From 740954d747ac56b76a6e1ae12a057c9548843436 Mon Sep 17 00:00:00 2001 From: "David I. Lehn" Date: Tue, 29 Mar 2022 20:01:31 -0400 Subject: [PATCH] Allow optional DigestAlgorithm parameters. RFC 3447 and RFC 8017 allow for optional `DigestAlgorithm` `NULL` parameters for `sha*` algorithms and require `NULL` paramters for `md2` and `md5` algorithms. --- CHANGELOG.md | 7 +++++++ lib/rsa.js | 12 ++++++++++++ tests/unit/rsa.js | 11 ++++++++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2987c54b..f0d08cca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ Forge ChangeLog =============== +## 1.3.1 - 2022-03-xx + +### Fixes +- RFC 3447 and RFC 8017 allow for optional `DigestAlgorithm` `NULL` parameters + for `sha*` algorithms and require `NULL` paramters for `md2` and `md5` + algorithms. + ## 1.3.0 - 2022-03-17 ### Security diff --git a/lib/rsa.js b/lib/rsa.js index 86a7557e..5c73209f 100644 --- a/lib/rsa.js +++ b/lib/rsa.js @@ -286,6 +286,8 @@ var digestInfoValidator = { name: 'DigestInfo.DigestAlgorithm.parameters', tagClass: asn1.Class.UNIVERSAL, type: asn1.Type.NULL, + // captured only to check existence for md2 and md5 + capture: 'parameters', optional: true, constructed: false }] @@ -1188,6 +1190,16 @@ pki.setRsaPublicKey = pki.rsa.setPublicKey = function(n, e) { throw error; } + // special check for md2 and md5 that NULL parameters exist + if(oid === forge.oids.md2 || oid === forge.oids.md5) { + if(!('parameters' in capture)) { + throw new Error( + 'ASN.1 object does not contain a valid RSASSA-PKCS1-v1_5 ' + + 'DigestInfo value. ' + + 'Missing algorithm identifer NULL parameters.'); + } + } + // compare the given digest to the decrypted one return digest === capture.digest; } diff --git a/tests/unit/rsa.js b/tests/unit/rsa.js index 1cd9e072..b1c1b64a 100644 --- a/tests/unit/rsa.js +++ b/tests/unit/rsa.js @@ -845,6 +845,15 @@ var UTIL = require('../../lib/util'); /^Error: ASN.1 object does not contain a valid RSASSA-PKCS1-v1_5 DigestInfo value.$/); } + function _checkGoodDigestInfo(publicKey, S, skipTailingGarbage) { + var md = MD.sha256.create(); + md.update(m); + + ASSERT.ok(publicKey.verify(md.digest().getBytes(), S, undefined, { + _parseAllDigestBytes: !skipTailingGarbage + })); + } + it('should check DigestInfo structure', function() { var publicKey = RSA.setPublicKey(N, e); // 0xff bytes stolen from padding @@ -904,7 +913,7 @@ var UTIL = require('../../lib/util'); '0bc1dd3f020cb1091af6b476416da3024ea046b09fbbbc4d2355da9a2bc6ddb9'); _checkBadTailingGarbage(publicKey, S); - _checkBadDigestInfo(publicKey, S, true); + _checkGoodDigestInfo(publicKey, S, true); }); it('should check tailing garbage and DigestInfo [2]', function() {