Package: release.debian.org Severity: normal Tags: buster User: release.debian....@packages.debian.org Usertags: pu
[ Reason ] node-node-forge signature verification code is lenient in checking the digest algorithm structure. This can allow a crafted structure that steals padding bytes and uses unchecked portion of the PKCS#1 encoded message to forge a signature when a low public exponent is being used. The issue has been addressed in `node-forge` version 1.3.0. [ Impact ] medium vulnerability [ Tests ] New test added [ Risks ] Low risk, test passed [ Checklist ] [X] *all* changes are documented in the d/changelog [X] I reviewed all changes and I approve them [X] attach debdiff against the package in (old)stable [X] the issue is verified as fixed in unstable [ Changes ] Better checks [ Other info ] Upstream patch applied without any change except indentation Cheers, Yadd
diff --git a/debian/changelog b/debian/changelog index bd1ee3d..a11ea65 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +node-node-forge (0.8.1~dfsg-1+deb10u1) buster; urgency=medium + + * Team upload + * Fix signature verification + (Closes: CVE-2022-24771, CVE-2022-24772, CVE-2022-24773) + + -- Yadd <y...@debian.org> Wed, 23 Mar 2022 11:28:00 +0100 + node-node-forge (0.8.1~dfsg-1) unstable; urgency=medium [ upstream ] diff --git a/debian/patches/CVE-2022-24773.patch b/debian/patches/CVE-2022-24773.patch new file mode 100644 index 0000000..9f36228 --- /dev/null +++ b/debian/patches/CVE-2022-24773.patch @@ -0,0 +1,658 @@ +Description: fix signature verification issues (CVE-2022-24771, CVE-2022-24772, CVE-2022-24773) + **SECURITY**: Three RSA PKCS#1 v1.5 signature verification issues were + reported by Moosa Yahyazadeh (moosa-yahyaza...@uiowa.edu): + . + - Leniency in checking `digestAlgorithm` structure can lead to signature + forgery. + - The code is lenient in checking the digest algorithm structure. This can + allow a crafted structure that steals padding bytes and uses unchecked + portion of the PKCS#1 encoded message to forge a signature when a low + public exponent is being used. + - Failing to check tailing garbage bytes can lead to signature forgery. + - The code does not check for tailing garbage bytes after decoding a + `DigestInfo` ASN.1 structure. This can allow padding bytes to be removed + and garbage data added to forge a signature when a low public exponent is + being used. + - Leniency in checking type octet. + - `DigestInfo` is not properly checked for proper ASN.1 structure. This can + lead to successful verification with signatures that contain invalid + structures but a valid digest. + . + For more information, please see "Bleichenbacher's RSA signature forgery based + on implementation error" by Hal Finney: + https://mailarchive.ietf.org/arch/msg/openpgp/5rnE9ZRN1AokBVj3VqblGlP63QE/ + . + Fixed with the following: + . + - [asn1] `fromDer` is now more strict and will default to ensuring all + input bytes are parsed or throw an error. A new option `parseAllBytes` + can disable this behavior. + - **NOTE**: The previous behavior is being changed since it can lead + to security issues with crafted inputs. It is possible that code + doing custom DER parsing may need to adapt to this new behavior and + optional flag. + - [rsa] Add and use a validator to check for proper structure of parsed + ASN.1 `RSASSA-PKCS-v1_5` `DigestInfo` data. Additionally check that + the hash algorithm identifier is a known value. An invalid + `DigestInfo` or algorithm identifier will now cause an error to be + thrown. + - [oid] Added `1.2.840.113549.2.2` / `md2` for hash algorithm checking. + - [tests] Tests were added for all of the reported issues. A private + verify option was added to assist in checking multiple possible + failures in the test data. +Author: David I. Lehn <dl...@digitalbazaar.com> +Origin: upstream, https://github.com/digitalbazaar/forge/commit/3f0b49a0 +Bug: + https://github.com/digitalbazaar/forge/security/advisories/GHSA-cfm4-qjh2-4765 + https://github.com/digitalbazaar/forge/security/advisories/GHSA-x4jg-mjrx-434g + https://github.com/digitalbazaar/forge/security/advisories/GHSA-2r2c-g63r-vccr +Forwarded: not-needed +Reviewed-By: Yadd <y...@debian.org> +Last-Update: 2022-03-23 + +--- a/lib/asn1.js ++++ b/lib/asn1.js +@@ -411,6 +411,8 @@ + * @param [options] object with options or boolean strict flag + * [strict] true to be strict when checking value lengths, false to + * allow truncated values (default: true). ++ * [parseAllBytes] true to ensure all bytes are parsed ++ * (default: true) + * [decodeBitStrings] true to attempt to decode the content of + * BIT STRINGs (not OCTET STRINGs) using strict mode. Note that + * without schema support to understand the data context this can +@@ -418,24 +420,31 @@ + * flag will be deprecated or removed as soon as schema support is + * available. (default: true) + * ++ * @throws Will throw an error for various malformed input conditions. ++ * + * @return the parsed asn1 object. + */ + asn1.fromDer = function(bytes, options) { + if(options === undefined) { + options = { + strict: true, ++ parseAllBytes: true, + decodeBitStrings: true + }; + } + if(typeof options === 'boolean') { + options = { + strict: options, ++ parseAllBytes: true, + decodeBitStrings: true + }; + } + if(!('strict' in options)) { + options.strict = true; + } ++ if(!('parseAllBytes' in options)) { ++ options.parseAllBytes = true; ++ } + if(!('decodeBitStrings' in options)) { + options.decodeBitStrings = true; + } +@@ -445,7 +454,15 @@ + bytes = forge.util.createBuffer(bytes); + } + +- return _fromDer(bytes, bytes.length(), 0, options); ++ var byteCount = bytes.length(); ++ var value = _fromDer(bytes, bytes.length(), 0, options); ++ if(options.parseAllBytes && bytes.length() !== 0) { ++ var error = new Error('Unparsed DER bytes remain after ASN.1 parsing.'); ++ error.byteCount = byteCount; ++ error.remaining = bytes.length(); ++ throw error; ++ } ++ return value; + }; + + /** +@@ -566,7 +583,6 @@ + start = bytes.length(); + var subOptions = { + // enforce strict mode to avoid parsing ASN.1 from plain data +- verbose: options.verbose, + strict: true, + decodeBitStrings: true + }; +@@ -615,6 +631,7 @@ + } + } else { + value = bytes.getBytes(length); ++ remaining -= length; + } + } + +@@ -1391,7 +1408,16 @@ + } + rval += '0x' + forge.util.bytesToHex(obj.value); + } else if(obj.type === asn1.Type.UTF8) { +- rval += forge.util.decodeUtf8(obj.value); ++ try { ++ rval += forge.util.decodeUtf8(obj.value); ++ } catch(e) { ++ if(e.message === 'URI malformed') { ++ rval += ++ '0x' + forge.util.bytesToHex(obj.value) + ' (malformed UTF8)'; ++ } else { ++ throw e; ++ } ++ } + } else if(obj.type === asn1.Type.PRINTABLESTRING || + obj.type === asn1.Type.IA5String) { + rval += obj.value; +--- a/lib/oids.js ++++ b/lib/oids.js +@@ -43,6 +43,10 @@ + _IN('2.16.840.1.101.3.4.2.1', 'sha256'); + _IN('2.16.840.1.101.3.4.2.2', 'sha384'); + _IN('2.16.840.1.101.3.4.2.3', 'sha512'); ++_IN('2.16.840.1.101.3.4.2.4', 'sha224'); ++_IN('2.16.840.1.101.3.4.2.5', 'sha512-224'); ++_IN('2.16.840.1.101.3.4.2.6', 'sha512-256'); ++_IN('1.2.840.113549.2.2', 'md2'); + _IN('1.2.840.113549.2.5', 'md5'); + + // pkcs#7 content types +--- a/lib/rsa.js ++++ b/lib/rsa.js +@@ -265,6 +265,40 @@ + }] + }; + ++// validator for a DigestInfo structure ++var digestInfoValidator = { ++ name: 'DigestInfo', ++ tagClass: asn1.Class.UNIVERSAL, ++ type: asn1.Type.SEQUENCE, ++ constructed: true, ++ value: [{ ++ name: 'DigestInfo.DigestAlgorithm', ++ tagClass: asn1.Class.UNIVERSAL, ++ type: asn1.Type.SEQUENCE, ++ constructed: true, ++ value: [{ ++ name: 'DigestInfo.DigestAlgorithm.algorithmIdentifier', ++ tagClass: asn1.Class.UNIVERSAL, ++ type: asn1.Type.OID, ++ constructed: false, ++ capture: 'algorithmIdentifier' ++ }, { ++ // NULL paramters ++ name: 'DigestInfo.DigestAlgorithm.parameters', ++ tagClass: asn1.Class.UNIVERSAL, ++ type: asn1.Type.NULL, ++ constructed: false ++ }] ++ }, { ++ // digest ++ name: 'DigestInfo.digest', ++ tagClass: asn1.Class.UNIVERSAL, ++ type: asn1.Type.OCTETSTRING, ++ constructed: false, ++ capture: 'digest' ++ }] ++}; ++ + /** + * Wrap digest in DigestInfo object. + * +@@ -1092,15 +1126,27 @@ + * a Forge PSS object for RSASSA-PSS, + * 'NONE' or null for none, DigestInfo will not be expected, but + * PKCS#1 v1.5 padding will still be used. ++ * @param options optional verify options ++ * _parseAllDigestBytes testing flag to control parsing of all ++ * digest bytes. Unsupported and not for general usage. ++ * (default: true) + * + * @return true if the signature was verified, false if not. + */ +- key.verify = function(digest, signature, scheme) { ++ key.verify = function(digest, signature, scheme, options) { + if(typeof scheme === 'string') { + scheme = scheme.toUpperCase(); + } else if(scheme === undefined) { + scheme = 'RSASSA-PKCS1-V1_5'; + } ++ if(options === undefined) { ++ options = { ++ _parseAllDigestBytes: true ++ }; ++ } ++ if(!('_parseAllDigestBytes' in options)) { ++ options._parseAllDigestBytes = true; ++ } + + if(scheme === 'RSASSA-PKCS1-V1_5') { + scheme = { +@@ -1108,9 +1154,41 @@ + // remove padding + d = _decodePkcs1_v1_5(d, key, true); + // d is ASN.1 BER-encoded DigestInfo +- var obj = asn1.fromDer(d); ++ var obj = asn1.fromDer(d, { ++ parseAllBytes: options._parseAllDigestBytes ++ }); ++ ++ // validate DigestInfo ++ var capture = {}; ++ var errors = []; ++ if(!asn1.validate(obj, digestInfoValidator, capture, errors)) { ++ var error = new Error( ++ 'ASN.1 object does not contain a valid RSASSA-PKCS1-v1_5 ' + ++ 'DigestInfo value.'); ++ error.errors = errors; ++ throw error; ++ } ++ // check hash algorithm identifier ++ // see PKCS1-v1-5DigestAlgorithms in RFC 8017 ++ // FIXME: add support to vaidator for strict value choices ++ var oid = asn1.derToOid(capture.algorithmIdentifier); ++ if(!(oid === forge.oids.md2 || ++ oid === forge.oids.md5 || ++ oid === forge.oids.sha1 || ++ oid === forge.oids.sha224 || ++ oid === forge.oids.sha256 || ++ oid === forge.oids.sha384 || ++ oid === forge.oids.sha512 || ++ oid === forge.oids['sha512-224'] || ++ oid === forge.oids['sha512-256'])) { ++ var error = new Error( ++ 'Unknown RSASSA-PKCS1-v1_5 DigestAlgorithm identifier.'); ++ error.oid = oid; ++ throw error; ++ } ++ + // compare the given digest to the decrypted one +- return digest === obj.value[1].value; ++ return digest === capture.digest; + } + }; + } else if(scheme === 'NONE' || scheme === 'NULL' || scheme === null) { +--- a/tests/unit/rsa.js ++++ b/tests/unit/rsa.js +@@ -1,5 +1,6 @@ + var ASSERT = require('assert'); + var FORGE = require('../../lib/forge'); ++var JSBN = require('../../lib/jsbn'); + var MD = require('../../lib/md.all'); + var MGF = require('../../lib/mgf'); + var PKI = require('../../lib/pki'); +@@ -773,5 +774,373 @@ + }); + } + })(); ++ ++ describe('signature verification', function() { ++ ++ // NOTE: Tests in this section, and associated fixes, are largely derived ++ // from a detailed vulnerability report provided by Moosa Yahyazadeh ++ // (moosa-yahyaza...@uiowa.edu). ++ ++ // params for tests ++ ++ // public modulus / 256 bytes ++ var N = new JSBN.BigInteger( ++ 'E932AC92252F585B3A80A4DD76A897C8B7652952FE788F6EC8DD640587A1EE56' + ++ '47670A8AD4C2BE0F9FA6E49C605ADF77B5174230AF7BD50E5D6D6D6D28CCF0A8' + ++ '86A514CC72E51D209CC772A52EF419F6A953F3135929588EBE9B351FCA61CED7' + ++ '8F346FE00DBB6306E5C2A4C6DFC3779AF85AB417371CF34D8387B9B30AE46D7A' + ++ '5FF5A655B8D8455F1B94AE736989D60A6F2FD5CADBFFBD504C5A756A2E6BB5CE' + ++ 'CC13BCA7503F6DF8B52ACE5C410997E98809DB4DC30D943DE4E812A47553DCE5' + ++ '4844A78E36401D13F77DC650619FED88D8B3926E3D8E319C80C744779AC5D6AB' + ++ 'E252896950917476ECE5E8FC27D5F053D6018D91B502C4787558A002B9283DA7', ++ 16); ++ ++ // private exponent ++ var d = new JSBN.BigInteger( ++ '009b771db6c374e59227006de8f9c5ba85cf98c63754505f9f30939803afc149' + ++ '8eda44b1b1e32c7eb51519edbd9591ea4fce0f8175ca528e09939e48f37088a0' + ++ '7059c36332f74368c06884f718c9f8114f1b8d4cb790c63b09d46778bfdc4134' + ++ '8fb4cd9feab3d24204992c6dd9ea824fbca591cd64cf68a233ad0526775c9848' + ++ 'fafa31528177e1f8df9181a8b945081106fd58bd3d73799b229575c4f3b29101' + ++ 'a03ee1f05472b3615784d9244ce0ed639c77e8e212ab52abddf4a928224b6b6f' + ++ '74b7114786dd6071bd9113d7870c6b52c0bc8b9c102cfe321dac357e030ed6c5' + ++ '80040ca41c13d6b4967811807ef2a225983ea9f88d67faa42620f42a4f5bdbe0' + ++ '3b', ++ 16); ++ ++ // public exponent ++ var e = new JSBN.BigInteger('3'); ++ ++ // hash function ++ // H = SHA-256 (OID = 0x608648016503040201) ++ ++ // message ++ var m = 'hello world!'; ++ ++ // to-be-signed RSA PKCS#1 v1.5 signature scheme input structure ++ // I ++ ++ // signature value obtained by I^d mod N ++ // S ++ ++ function _checkBadTailingGarbage(publicKey, S) { ++ var md = MD.sha256.create(); ++ md.update(m); ++ ++ ASSERT.throws(function() { ++ publicKey.verify(md.digest().getBytes(), S); ++ }, ++ /^Error: Unparsed DER bytes remain after ASN.1 parsing.$/); ++ } ++ ++ function _checkBadDigestInfo(publicKey, S, skipTailingGarbage) { ++ var md = MD.sha256.create(); ++ md.update(m); ++ ++ ASSERT.throws(function() { ++ publicKey.verify(md.digest().getBytes(), S, undefined, { ++ _parseAllDigestBytes: !skipTailingGarbage ++ }); ++ }, ++ /^Error: ASN.1 object does not contain a valid RSASSA-PKCS1-v1_5 DigestInfo value.$/); ++ } ++ ++ it('should check DigestInfo structure', function() { ++ var publicKey = RSA.setPublicKey(N, e); ++ // 0xff bytes stolen from padding ++ // unchecked portion of PKCS#1 encoded message used to forge a ++ // signature when low public exponent is being used. ++ // See "Bleichenbacher's RSA signature forgery based on implementation ++ // error" by Hal Finney ++ // https://mailarchive.ietf.org/arch/msg/openpgp/5rnE9ZRN1AokBVj3VqblGlP63QE/ ++ ++ // 91 garbage byte injected as the value of a TLV replaced digest ++ // algorithm structure ++ var I = UTIL.binary.hex.decode( ++ '0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0030' + ++ '7f065b8888888888888888888888888888888888888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888880420' + ++ '7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9'); ++ var S = UTIL.binary.hex.decode( ++ 'e7410e05bdc38d1c72fab784be41df3d3de2ae83894d9ec86cb5fe343d5dc7d4' + ++ '5df2a36fc60363faf32f0d37ab457648af40a48a6c53ae7af0575e92cb1ffc23' + ++ '6d55e1325af8c71b3ac313f2630fb498b8e1546093aca1ed56026a96cb525d99' + ++ '1159a2d6ccbfd5ef63ae718f8ace2469e357ccf3f6a048bbf9760f5fb36b9dd3' + ++ '8fb330eab504f05078b83f5d8bd95dce8fccc6b46babd56f678300f2b39083e5' + ++ '3e04e79f503358a6222f8dd66b561fea3a51ecf3be16c9e2ea6ba8aaed9fbe6b' + ++ 'a510ff752e4529385f759d4d6120b15f65534248ed5bbb1307a7d0a983832969' + ++ '7f5fbae91f48e478dcbb77190f0d173b6cb8b1299cf4202570d25d11a7862b47'); ++ ++ _checkBadDigestInfo(publicKey, S); ++ }); ++ ++ it('should check tailing garbage and DigestInfo [1]', function() { ++ var publicKey = RSA.setPublicKey(N, e); ++ // bytes stolen from padding and unchecked tailing bytes used to forge ++ // a signature when low public exponent is used ++ ++ // 204 tailing garbage bytes injected after DigestInfo structure ++ var I = UTIL.binary.hex.decode( ++ '000100302f300b060960864801650304020104207509e5bda0c762d2bac7f90d' + ++ '758b5b2263fa01ccbc542ab5e3df163be08e6ca9888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888888888'); ++ var S = UTIL.binary.hex.decode( ++ 'c2ad2fa23c246ee98c453d69023e7ec05956b48bd0e287341ba9d342ad49b0ff' + ++ 'f2bcbb9adc50f1ccbfc54106305cc74a88db89ff94901a08359893a08426373e' + ++ '7949a8794798233445af6c48bc6ccbe278bdeb62c31e40c3bf0014af2faadcc9' + ++ 'ed7885756789a5b95c2a355fbb3f04412f42e0f9ed335ab51af8f091a62aaaaf' + ++ '6577422220917daaece3ca2f4e66dc4e0574356762592052b406768c31c25cf4' + ++ 'c1754e6da9dc3440e238c4f9b25cccc174dd1b17b027e0f9ce2763b86f0e6871' + ++ '690ddd018d2e774bc968c9c6e907a000daf5044ba31a0b9eefbd7b4b1ec466d2' + ++ '0bc1dd3f020cb1091af6b476416da3024ea046b09fbbbc4d2355da9a2bc6ddb9'); ++ ++ _checkBadTailingGarbage(publicKey, S); ++ _checkBadDigestInfo(publicKey, S, true); ++ }); ++ ++ it('should check tailing garbage and DigestInfo [2]', function() { ++ var publicKey = RSA.setPublicKey(N, e); ++ // bytes stolen from padding and unchecked tailing bytes used to forge ++ // a signature when low public exponent is used ++ ++ // 215 tailing garbage bytes injected after DigestInfo structure ++ // unchecked digest algorithm structure ++ // combined with earlier issue ++ var I = UTIL.binary.hex.decode( ++ '0001003024010004207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542a' + ++ 'b5e3df163be08e6ca98888888888888888888888888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888888888' + ++ '8888888888888888888888888888888888888888888888888888888888888888'); ++ var S = UTIL.binary.hex.decode( ++ 'a7c5812d7fc0eef766a481aac18c8c48483daf9b5ffb6614bd98ebe4ecb746dd' + ++ '493cf5dd2cbe16ecaa0b52109b744930eda49316605fc823fd57a68b5b2c62e8' + ++ 'c1b158b26e1547a2e33cdd79427d7c513f07d02261ffe43db197d8cddca2b5b4' + ++ '3c1df85aaed6e91aadd44a46bff7f5c70f1acc1a193917e3908444632f30e69c' + ++ 'fe95d8036d3b6ad318eefd3952804f16613c969e6d13604bb4e723dfad24c42c' + ++ '8d9b5b16a9f5a4b40dcf17b167d319017740f9cc0836436c14d51c3d8a697f1f' + ++ 'a2b65196deb5c21b1559c7dea7f598007fa7320909825009f8bf376491c298d8' + ++ '155a382e967042db952e995d14b2f961e1b22f911d1b77895def1c7ef229c87e'); ++ ++ _checkBadTailingGarbage(publicKey, S); ++ _checkBadDigestInfo(publicKey, S, true); ++ }); ++ ++ it('should check tailing garbage and DigestInfo [e=3]', function() { ++ // signature forged without knowledge of private key for given message ++ // and low exponent e=3 ++ ++ // test data computed from a script ++ var N = new JSBN.BigInteger( ++ '2943851338959486749023220128247883872673446416188780128906858510' + ++ '0507839535636256317277708295678804401391394313946142335874609638' + ++ '6660819509361141525748702240343825617847432837639613499808068190' + ++ '7802897559477710338828027239284411238090037450817022107555351764' + ++ '1170327441791034393719271744724924194371070527213991317221667249' + ++ '0779727008421990374037994805699108447010306443226160454080397152' + ++ '7839457232809919202392450307767317822761454935119120485180507635' + ++ '9472439160130994385433568113626206477097769842080459156024112389' + ++ '4062006872333417793816670825914214968706669312685485046743622307' + ++ '25756397511775557878046572472650613407143'); ++ var e = new JSBN.BigInteger('3'); ++ var publicKey = RSA.setPublicKey(N, e); ++ ++ var S = UTIL.binary.hex.decode( ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '00000000000000000000002853ccc2cd32a8d430dd3bde37e70782ac82cdb7bc' + ++ 'e3c044219b50aefd689c20d3b840299f28e2fde6c67c8a7f9e528ac222fae947' + ++ 'a6dee0d812e3c3b3452171717396e8bedc3132d92d8317e3593642640d1431ef'); ++ ++ _checkBadTailingGarbage(publicKey, S); ++ _checkBadDigestInfo(publicKey, S, true); ++ }); ++ ++ it('should check tailing garbage and DigestInfo [e=5]', function() { ++ // signature forged without knowledge of private key for given message ++ // and low exponent e=5 ++ ++ // test data computed from a script ++ var N = new JSBN.BigInteger( ++ '2943851338959486749023220128247883872673446416188780128906858510' + ++ '0507839535636256317277708295678804401391394313946142335874609638' + ++ '6660819509361141525748702240343825617847432837639613499808068190' + ++ '7802897559477710338828027239284411238090037450817022107555351764' + ++ '1170327441791034393719271744724924194371070527213991317221667249' + ++ '0779727008421990374037994805699108447010306443226160454080397152' + ++ '7839457232809919202392450307767317822761454935119120485180507635' + ++ '9472439160130994385433568113626206477097769842080459156024112389' + ++ '4062006872333417793816670825914214968706669312685485046743622307' + ++ '25756397511775557878046572472650613407143'); ++ var e = new JSBN.BigInteger('5'); ++ var publicKey = RSA.setPublicKey(N, e); ++ ++ var S = UTIL.binary.hex.decode( ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '000000000000000000000000005475fe2681d7125972bd2c2f2c7ab7b8003b03' + ++ 'd4a487d6dee07c14eb5212a9fe0071b93f84ba5bb4b0cfaf20c976b11d902013'); ++ ++ _checkBadTailingGarbage(publicKey, S); ++ _checkBadDigestInfo(publicKey, S, true); ++ }); ++ ++ it('should check tailing garbage and DigestInfo [e=17]', function() { ++ // signature forged without knowledge of private key for given message ++ // and low exponent e=17 ++ ++ // test data computed from a script ++ var N = new JSBN.BigInteger( ++ '9283656416612985262941143827717696579056959956800096804440022580' + ++ '8979605519224532102091105159037909758713334182004379540747102163' + ++ '0328875171430160513961779154294247563032373839871165519961382202' + ++ '8118288833646515747631246999476620608496831766892861810215014002' + ++ '6197665341672524640393361361575818164897153768964295647456396149' + ++ '0989544033629566558036444831495046301215543198107208071526376318' + ++ '9614817392787691228850316867637768748063173527415482321108924014' + ++ '0172719575883597580010690402077593789150581979877629529469651667' + ++ '0437057465296389148672556848624501468669295285428387365416747516' + ++ '1806526300547653933352115280843297169178217266705491556199868750' + ++ '3004910766820506445410432860104193197231996634882562129969319354' + ++ '2460060799067674344247887198933507132592770898312271636011037138' + ++ '9847292565155151851533347436854797090854109022697775636916157198' + ++ '8470890850961835279273782642105981947430594900197891694944702901' + ++ '0362775778664826653636547333219983468955600305523140183269580452' + ++ '7928125033990422010817859727072181449684606236639224708148897385' + ++ '6473081641220112881037032407068024585466913055187295801749427746' + ++ '8722193869883705529583737211815974801292292728082721785855274147' + ++ '9919792200010181565600099271483749952360303834740314188025547140' + ++ '4368096941701515529809239068018840617766710102093620675455198522' + ++ '9636814788735090951246816765035721775759652424641736739668936540' + ++ '4502328148572893125899985056273755530380627654934084609415976292' + ++ '9123186604266210829116435949633497856328752368587226250956046322' + ++ '5096226739991402761266388226652661345282274508037924611589455395' + ++ '6555120130786293751868059518231813715612891296160287687335835654' + ++ '3979850800254668550551247800296013251153132326459614458561196296' + ++ '9372672455541953777622436993987703564293487820434112162562492086' + ++ '8651475984366477254452308612460939500200990849949906321025068481' + ++ '9019640785570574553040761725312997166593985384222496507953730319' + ++ '8339986953399517682750248394628026225887174258267456078564070387' + ++ '3276539895054169432261639890044193773631304665663877617572725639' + ++ '9608670862191314058068741469812649057261850985814174869283757023' + ++ '5128900627675422927964369356691123905362222855545719945605604307' + ++ '2632528510813096225692258119794268564646732338755890857736163737' + ++ '9885700134409359441713832300526017978115395080312777381770201653' + ++ '4081581157881295739782000814998795398671806283018844936919299070' + ++ '5625387639000374694851356996772485803653791257029031861749956519' + ++ '3846941219138832785295572786934547608717304766525989212989524778' + ++ '5416834855450881318585909376917039'); ++ var e = new JSBN.BigInteger('17'); ++ var publicKey = RSA.setPublicKey(N, e); ++ ++ var S = UTIL.binary.hex.decode( ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '0000000000000000000000000000000000000000000000000000000000000000' + ++ '00000001eb90acbec1bf590ba1e50960db8381fb5bdc363d46379d09956560a6' + ++ '16b88616ce7fa4309dc45f47f5fa47d61bf66baa3d11732ce71768ded295f962'); ++ ++ _checkBadTailingGarbage(publicKey, S); ++ _checkBadDigestInfo(publicKey, S, true); ++ }); ++ ++ it('should check DigestInfo type octet [1]', function() { ++ var publicKey = RSA.setPublicKey(N, e); ++ // incorrect value for digest algorithm's type octet ++ // 0x0c instead of correct 0x06 ++ var I = UTIL.binary.hex.decode( ++ '0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffff0030310c0d060960864801650304020105000420' + ++ '7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9'); ++ var S = UTIL.binary.hex.decode( ++ 'd8298a199e1b6ac18f3c0067a004bd9ff7af87be6ad857d73cc3d24ef06195b8' + ++ '2aaddb0194f8e61fc31453b9163062255e8baf9c480200d0991a5f764f63d5f6' + ++ 'afd283b9cd6afe54f0b7f738707b4eb6b8807539bb627e74db87a50413ab18e5' + ++ '04e37975aad1edc612bc8ecad53b81ea249deb5a2acc27e6419c61ab9acec660' + ++ '8f5ae6a2985ba0b6f42d831bc6cce4b044864154b935cf179967d129e0ad8eda' + ++ '9bfbb638121c3ff13c64d439632e62250d4be928a3deb112ef76a025c5d91805' + ++ '1e601878eac0049fc9d82be9ae3475deb7ca515c830c20b91b7bedf2184fef66' + ++ 'aea0bde62ccd1659afbfd1342322b095309451b1a87e007e640e368fb68a13c9'); ++ ++ _checkBadDigestInfo(publicKey, S); ++ }); ++ ++ it('should check DigestInfo type octet [2]', function() { ++ var publicKey = RSA.setPublicKey(N, e); ++ // incorrect value for hash value's type octet ++ // 0x0a instead of correct 0x04 ++ var I = UTIL.binary.hex.decode( ++ '0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + ++ 'ffffffffffffffffffffffff003031300d060960864801650304020105000a20' + ++ '7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9'); ++ var S = UTIL.binary.hex.decode( ++ 'c1acdd3aef5f0439c254980295fc0d81b628df00726310a1041d79b5dd94c11d' + ++ '3bcaf0236763c77c25d9ab49522ed2a7d6ea3a4e483a29838acd48f2d60a7902' + ++ '75f4cd46e4b1d09c527a426ec373e8a21746ad3ea541d3b85ba4c303ff793ea8' + ++ 'a0a3458e93a7ec42ed66f675d7c299b0817ac95f7f45b2f48c09b3c070171f31' + ++ 'a33ac789da9943da5dabcda1c95b42531d45484ac1efde0fe0519077debb9318' + ++ '3e63de8f80d7f3cbfecb03cbb44ac4a2d56699e33fca0663b79ca627755fc4fc' + ++ '684b4ab358a0b4ac5b7e9d0cc18b6ab6300b40781502a1c03d34f31dd19d8119' + ++ '5f8a44bc03a2595a706f06f0cb39b8e3f4afe06675fe7439b057f1200a06f4fd'); ++ ++ _checkBadDigestInfo(publicKey, S); ++ }); ++ }); + }); + })(); diff --git a/debian/patches/series b/debian/patches/series index 339bf56..54baac9 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,2 +1,3 @@ 2001_webpack_shared_path.patch 2002_avoid_privacy_breach.patch +CVE-2022-24773.patch