Merge ~athos-ribeiro/ubuntu/+source/nss:lp1959126-upstream-3.68.2 into ubuntu/+source/nss:ubuntu/devel

Proposed by Athos Ribeiro
Status: Merged
Merged at revision: e7ce70b8a296c4b8875570711405bbee45fe3468
Proposed branch: ~athos-ribeiro/ubuntu/+source/nss:lp1959126-upstream-3.68.2
Merge into: ubuntu/+source/nss:ubuntu/devel
Diff against target: 1147 lines (+350/-421)
16 files modified
debian/changelog (+8/-0)
debian/patches/series (+0/-1)
dev/null (+0/-282)
nss/.hg_archival.txt (+3/-3)
nss/gtests/certdb_gtest/decode_certs_unittest.cc (+13/-0)
nss/gtests/mozpkix_gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp (+71/-1)
nss/lib/cryptohi/secvfy.c (+121/-71)
nss/lib/mozpkix/include/pkix-test/pkixtestutil.h (+8/-0)
nss/lib/mozpkix/include/pkix/pkixutil.h (+14/-0)
nss/lib/mozpkix/lib/pkixocsp.cpp (+55/-37)
nss/lib/mozpkix/lib/pkixverify.cpp (+1/-8)
nss/lib/mozpkix/test-lib/pkixtestutil.cpp (+45/-12)
nss/lib/nss/nss.h (+2/-2)
nss/lib/pkcs7/certread.c (+5/-0)
nss/lib/softoken/softkver.h (+2/-2)
nss/lib/util/nssutil.h (+2/-2)
Reviewer Review Type Date Requested Status
Lucas Kanashiro (community) Approve
Canonical Server Pending
Review via email: mp+415883@code.launchpad.net

Description of the change

This MP updates nss from 3.68 to 3.68.2. Note that this new version is not available in Debian, which is already in 3.7x. We decided to remain in 3.68.2 due to the fact that it is an LTS release and is more suitable for jammy.

This new version includes two bug fixes. One of them was already applied in our delta (hence the dropped patch). It also adds support to SHA-2 hashes in CertIDs in OCSP responses.

There are no symbol changes for this new version and no transition should be required.

a PPA with the proposed changes is available at:
https://launchpad.net/~athos-ribeiro/+archive/ubuntu/lp1959126-nss-jammy/+packages

This package has no dep8 tests.

To post a comment you must log in.
Revision history for this message
Lucas Kanashiro (lucaskanashiro) wrote :

Thanks Athos. The update looks good, the package in the PPA installs/upgrades fine, nothing suspicious showed up in the build logs, and according to upstream no rebuild of reverse dependencies is needed indeed.

The only thing that we could do to improve the changelog entry, in my opinion, is mentioning the fix of the CVE-2021-43527 which according to the upstream is a critical issue:

https://www.mozilla.org/en-US/security/advisories/mfsa2021-51/

This is not a blocker, it is just a plus. Feel free to ignore this if you believe it is not needed. Also let me know if you need a sponsor for this upload.

review: Approve
Revision history for this message
Lucas Kanashiro (lucaskanashiro) wrote :

I overlooked the CVE number, it was already fixed in the previous release :) no need to mention it again, sorry for the noise.

Revision history for this message
Lucas Kanashiro (lucaskanashiro) wrote :

Package uploaded as requested by Athos:

$ dput ubuntu ../nss_3.68.2-0ubuntu1_source.changes
Checking signature on .changes
gpg: ../nss_3.68.2-0ubuntu1_source.changes: Valid signature from F823A2729883C97C
Checking signature on .dsc
gpg: ../nss_3.68.2-0ubuntu1.dsc: Valid signature from F823A2729883C97C
Uploading to ubuntu (via ftp to upload.ubuntu.com):
  Uploading nss_3.68.2-0ubuntu1.dsc: done.
  Uploading nss_3.68.2.orig.tar.gz: done.
  Uploading nss_3.68.2-0ubuntu1.debian.tar.xz: done.
  Uploading nss_3.68.2-0ubuntu1_source.buildinfo: done.
  Uploading nss_3.68.2-0ubuntu1_source.changes: done.
Successfully uploaded packages.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index dcda4b0..2bfdd70 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,11 @@
6+nss (2:3.68.2-0ubuntu1) jammy; urgency=medium
7+
8+ * New upstream release. (LP: #1959126)
9+ * d/p/CVE-2021-43527.patch: drop patch applied upstream.
10+ [ Fixed in 3.68.1 ]
11+
12+ -- Athos Ribeiro <athos.ribeiro@canonical.com> Mon, 21 Feb 2022 14:55:42 -0300
13+
14 nss (2:3.68-1ubuntu2) jammy; urgency=medium
15
16 * SECURITY UPDATE: heap overflow when verifying DSA/RSA-PSS DER-encoded
17diff --git a/debian/patches/CVE-2021-43527.patch b/debian/patches/CVE-2021-43527.patch
18deleted file mode 100644
19index a663236..0000000
20--- a/debian/patches/CVE-2021-43527.patch
21+++ /dev/null
22@@ -1,282 +0,0 @@
23-Description: fix heap overflow when verifying DSA/RSA-PSS DER-encoded signatures
24-Origin: Provided by Mozilla
25-
26-diff --git a/nss/lib/cryptohi/secvfy.c b/nss/lib/cryptohi/secvfy.c
27---- a/nss/lib/cryptohi/secvfy.c
28-+++ b/nss/lib/cryptohi/secvfy.c
29-@@ -164,6 +164,37 @@
30- PR_FALSE /*XXX: unsafeAllowMissingParameters*/);
31- }
32-
33-+static unsigned int
34-+checkedSignatureLen(const SECKEYPublicKey *pubk)
35-+{
36-+ unsigned int sigLen = SECKEY_SignatureLen(pubk);
37-+ if (sigLen == 0) {
38-+ /* Error set by SECKEY_SignatureLen */
39-+ return sigLen;
40-+ }
41-+ unsigned int maxSigLen;
42-+ switch (pubk->keyType) {
43-+ case rsaKey:
44-+ case rsaPssKey:
45-+ maxSigLen = (RSA_MAX_MODULUS_BITS + 7) / 8;
46-+ break;
47-+ case dsaKey:
48-+ maxSigLen = DSA_MAX_SIGNATURE_LEN;
49-+ break;
50-+ case ecKey:
51-+ maxSigLen = 2 * MAX_ECKEY_LEN;
52-+ break;
53-+ default:
54-+ PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
55-+ return 0;
56-+ }
57-+ if (sigLen > maxSigLen) {
58-+ PORT_SetError(SEC_ERROR_INVALID_KEY);
59-+ return 0;
60-+ }
61-+ return sigLen;
62-+}
63-+
64- /*
65- * decode the ECDSA or DSA signature from it's DER wrapping.
66- * The unwrapped/raw signature is placed in the buffer pointed
67-@@ -174,38 +205,38 @@
68- unsigned int len)
69- {
70- SECItem *dsasig = NULL; /* also used for ECDSA */
71-- SECStatus rv = SECSuccess;
72-
73-- if ((algid != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
74-- (algid != SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
75-- if (sig->len != len) {
76-- PORT_SetError(SEC_ERROR_BAD_DER);
77-- return SECFailure;
78-+ /* Safety: Ensure algId is as expected and that signature size is within maxmimums */
79-+ if (algid == SEC_OID_ANSIX9_DSA_SIGNATURE) {
80-+ if (len > DSA_MAX_SIGNATURE_LEN) {
81-+ goto loser;
82- }
83--
84-- PORT_Memcpy(dsig, sig->data, sig->len);
85-- return SECSuccess;
86-+ } else if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
87-+ if (len > MAX_ECKEY_LEN * 2) {
88-+ goto loser;
89-+ }
90-+ } else {
91-+ goto loser;
92- }
93-
94-- if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
95-- if (len > MAX_ECKEY_LEN * 2) {
96-- PORT_SetError(SEC_ERROR_BAD_DER);
97-- return SECFailure;
98-- }
99-+ /* Decode and pad to length */
100-+ dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len);
101-+ if (dsasig == NULL) {
102-+ goto loser;
103- }
104-- dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len);
105--
106-- if ((dsasig == NULL) || (dsasig->len != len)) {
107-- rv = SECFailure;
108-- } else {
109-- PORT_Memcpy(dsig, dsasig->data, dsasig->len);
110-+ if (dsasig->len != len) {
111-+ SECITEM_FreeItem(dsasig, PR_TRUE);
112-+ goto loser;
113- }
114-
115-- if (dsasig != NULL)
116-- SECITEM_FreeItem(dsasig, PR_TRUE);
117-- if (rv == SECFailure)
118-- PORT_SetError(SEC_ERROR_BAD_DER);
119-- return rv;
120-+ PORT_Memcpy(dsig, dsasig->data, len);
121-+ SECITEM_FreeItem(dsasig, PR_TRUE);
122-+
123-+ return SECSuccess;
124-+
125-+loser:
126-+ PORT_SetError(SEC_ERROR_BAD_DER);
127-+ return SECFailure;
128- }
129-
130- const SEC_ASN1Template hashParameterTemplate[] =
131-@@ -281,7 +312,7 @@
132- sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
133- const SECItem *param, SECOidTag *encalgp, SECOidTag *hashalg)
134- {
135-- int len;
136-+ unsigned int len;
137- PLArenaPool *arena;
138- SECStatus rv;
139- SECItem oid;
140-@@ -466,48 +497,52 @@
141- cx->pkcs1RSADigestInfo = NULL;
142- rv = SECSuccess;
143- if (sig) {
144-- switch (type) {
145-- case rsaKey:
146-- rv = recoverPKCS1DigestInfo(hashAlg, &cx->hashAlg,
147-- &cx->pkcs1RSADigestInfo,
148-- &cx->pkcs1RSADigestInfoLen,
149-- cx->key,
150-- sig, wincx);
151-- break;
152-- case rsaPssKey:
153-- sigLen = SECKEY_SignatureLen(key);
154-- if (sigLen == 0) {
155-- /* error set by SECKEY_SignatureLen */
156-- rv = SECFailure;
157-+ rv = SECFailure;
158-+ if (type == rsaKey) {
159-+ rv = recoverPKCS1DigestInfo(hashAlg, &cx->hashAlg,
160-+ &cx->pkcs1RSADigestInfo,
161-+ &cx->pkcs1RSADigestInfoLen,
162-+ cx->key,
163-+ sig, wincx);
164-+ } else {
165-+ sigLen = checkedSignatureLen(key);
166-+ /* Check signature length is within limits */
167-+ if (sigLen == 0) {
168-+ /* error set by checkedSignatureLen */
169-+ rv = SECFailure;
170-+ goto loser;
171-+ }
172-+ if (sigLen > sizeof(cx->u)) {
173-+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
174-+ rv = SECFailure;
175-+ goto loser;
176-+ }
177-+ switch (type) {
178-+ case rsaPssKey:
179-+ if (sig->len != sigLen) {
180-+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
181-+ rv = SECFailure;
182-+ goto loser;
183-+ }
184-+ PORT_Memcpy(cx->u.buffer, sig->data, sigLen);
185-+ rv = SECSuccess;
186- break;
187-- }
188-- if (sig->len != sigLen) {
189-- PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
190-+ case ecKey:
191-+ case dsaKey:
192-+ /* decodeECorDSASignature will check sigLen == sig->len after padding */
193-+ rv = decodeECorDSASignature(encAlg, sig, cx->u.buffer, sigLen);
194-+ break;
195-+ default:
196-+ /* Unreachable */
197- rv = SECFailure;
198-- break;
199-- }
200-- PORT_Memcpy(cx->u.buffer, sig->data, sigLen);
201-- break;
202-- case dsaKey:
203-- case ecKey:
204-- sigLen = SECKEY_SignatureLen(key);
205-- if (sigLen == 0) {
206-- /* error set by SECKEY_SignatureLen */
207-- rv = SECFailure;
208-- break;
209-- }
210-- rv = decodeECorDSASignature(encAlg, sig, cx->u.buffer, sigLen);
211-- break;
212-- default:
213-- rv = SECFailure;
214-- PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
215-- break;
216-+ goto loser;
217-+ }
218-+ }
219-+ if (rv != SECSuccess) {
220-+ goto loser;
221- }
222- }
223-
224-- if (rv)
225-- goto loser;
226--
227- /* check hash alg again, RSA may have changed it.*/
228- if (HASH_GetHashTypeByOidTag(cx->hashAlg) == HASH_AlgNULL) {
229- /* error set by HASH_GetHashTypeByOidTag */
230-@@ -650,11 +685,16 @@
231- switch (cx->key->keyType) {
232- case ecKey:
233- case dsaKey:
234-- dsasig.data = cx->u.buffer;
235-- dsasig.len = SECKEY_SignatureLen(cx->key);
236-+ dsasig.len = checkedSignatureLen(cx->key);
237- if (dsasig.len == 0) {
238- return SECFailure;
239- }
240-+ if (dsasig.len > sizeof(cx->u)) {
241-+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
242-+ return SECFailure;
243-+ }
244-+ dsasig.data = cx->u.buffer;
245-+
246- if (sig) {
247- rv = decodeECorDSASignature(cx->encAlg, sig, dsasig.data,
248- dsasig.len);
249-@@ -686,8 +726,13 @@
250- }
251-
252- rsasig.data = cx->u.buffer;
253-- rsasig.len = SECKEY_SignatureLen(cx->key);
254-+ rsasig.len = checkedSignatureLen(cx->key);
255- if (rsasig.len == 0) {
256-+ /* Error set by checkedSignatureLen */
257-+ return SECFailure;
258-+ }
259-+ if (rsasig.len > sizeof(cx->u)) {
260-+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
261- return SECFailure;
262- }
263- if (sig) {
264-@@ -749,7 +794,6 @@
265- SECStatus rv;
266- VFYContext *cx;
267- SECItem dsasig; /* also used for ECDSA */
268--
269- rv = SECFailure;
270-
271- cx = vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
272-@@ -757,19 +801,25 @@
273- switch (key->keyType) {
274- case rsaKey:
275- rv = verifyPKCS1DigestInfo(cx, digest);
276-+ /* Error (if any) set by verifyPKCS1DigestInfo */
277- break;
278-- case dsaKey:
279- case ecKey:
280-+ case dsaKey:
281- dsasig.data = cx->u.buffer;
282-- dsasig.len = SECKEY_SignatureLen(cx->key);
283-+ dsasig.len = checkedSignatureLen(cx->key);
284- if (dsasig.len == 0) {
285-+ /* Error set by checkedSignatureLen */
286-+ rv = SECFailure;
287- break;
288- }
289-- if (PK11_Verify(cx->key, &dsasig, (SECItem *)digest, cx->wincx) !=
290-- SECSuccess) {
291-+ if (dsasig.len > sizeof(cx->u)) {
292- PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
293-- } else {
294-- rv = SECSuccess;
295-+ rv = SECFailure;
296-+ break;
297-+ }
298-+ rv = PK11_Verify(cx->key, &dsasig, (SECItem *)digest, cx->wincx);
299-+ if (rv != SECSuccess) {
300-+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
301- }
302- break;
303- default:
304-
305diff --git a/debian/patches/series b/debian/patches/series
306index 64788bc..bac12de 100644
307--- a/debian/patches/series
308+++ b/debian/patches/series
309@@ -7,4 +7,3 @@ disable_fips_enabled_read.patch
310 set-tls1.2-as-minimum.patch
311 fix-ftbfs-s390x.patch
312 fix-ftbfs-glibc-invalid-oob-error.patch
313-CVE-2021-43527.patch
314diff --git a/nss/.hg_archival.txt b/nss/.hg_archival.txt
315index 9a2c8a2..807d9fe 100644
316--- a/nss/.hg_archival.txt
317+++ b/nss/.hg_archival.txt
318@@ -1,4 +1,4 @@
319 repo: 9949429068caa6bb8827a8ceeaa7c605d722f47f
320-node: 3680dc580194cbe3bb1004d2f7741eebc3066d2c
321-branch: NSS_3_68_BRANCH
322-tag: NSS_3_68_RTM
323+node: 78d2f4a3339fa41c274c5ea189f8060da9d3a463
324+branch: NSS_3_68_2_BRANCH
325+tag: NSS_3_68_2_RTM
326diff --git a/nss/gtests/certdb_gtest/decode_certs_unittest.cc b/nss/gtests/certdb_gtest/decode_certs_unittest.cc
327index 405194e..3317ae8 100644
328--- a/nss/gtests/certdb_gtest/decode_certs_unittest.cc
329+++ b/nss/gtests/certdb_gtest/decode_certs_unittest.cc
330@@ -26,3 +26,16 @@ TEST_F(DecodeCertsTest, EmptyCertPackage) {
331 sizeof(emptyCertPackage)));
332 EXPECT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
333 }
334+
335+TEST_F(DecodeCertsTest, EmptySignedData) {
336+ // This represents a PKCS#7 ContentInfo of contentType
337+ // 1.2.840.113549.1.7.2 (signedData) with missing content.
338+ unsigned char emptySignedData[] = {0x30, 0x80, 0x06, 0x09, 0x2a, 0x86,
339+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
340+ 0x02, 0x00, 0x00, 0x05, 0x00};
341+
342+ EXPECT_EQ(nullptr,
343+ CERT_DecodeCertFromPackage(reinterpret_cast<char*>(emptySignedData),
344+ sizeof(emptySignedData)));
345+ EXPECT_EQ(SEC_ERROR_BAD_DER, PR_GetError());
346+}
347diff --git a/nss/gtests/mozpkix_gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp b/nss/gtests/mozpkix_gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp
348index 58336df..c7e8236 100644
349--- a/nss/gtests/mozpkix_gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp
350+++ b/nss/gtests/mozpkix_gtest/pkixocsp_VerifyEncodedOCSPResponse.cpp
351@@ -217,9 +217,13 @@ public:
352 const TestSignatureAlgorithm& signatureAlgorithm,
353 /*optional*/ const ByteString* certs = nullptr,
354 /*optional*/ OCSPResponseExtension* singleExtensions = nullptr,
355- /*optional*/ OCSPResponseExtension* responseExtensions = nullptr)
356+ /*optional*/ OCSPResponseExtension* responseExtensions = nullptr,
357+ /*optional*/ DigestAlgorithm certIDHashAlgorithm = DigestAlgorithm::sha1,
358+ /*optional*/ ByteString certIDHashAlgorithmEncoded = ByteString())
359 {
360 OCSPResponseContext context(certID, producedAt);
361+ context.certIDHashAlgorithm = certIDHashAlgorithm;
362+ context.certIDHashAlgorithmEncoded = certIDHashAlgorithmEncoded;
363 if (signerName) {
364 context.signerNameDER = CNToDERName(signerName);
365 EXPECT_FALSE(ENCODING_FAILED(context.signerNameDER));
366@@ -466,6 +470,72 @@ TEST_F(pkixocsp_VerifyEncodedResponse_successful, ct_extension)
367 trustDomain.signedCertificateTimestamps);
368 }
369
370+struct CertIDHashAlgorithm
371+{
372+ DigestAlgorithm hashAlgorithm;
373+ ByteString encodedHashAlgorithm;
374+ Result expectedResult;
375+};
376+
377+// python DottedOIDToCode.py --alg id-sha1 1.3.14.3.2.26
378+static const uint8_t alg_id_sha1[] = {
379+ 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a
380+};
381+// python DottedOIDToCode.py --alg id-sha256 2.16.840.1.101.3.4.2.1
382+static const uint8_t alg_id_sha256[] = {
383+ 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
384+};
385+static const uint8_t not_an_encoded_hash_oid[] = {
386+ 0x01, 0x02, 0x03, 0x04
387+};
388+
389+static const CertIDHashAlgorithm CERTID_HASH_ALGORITHMS[] = {
390+ { DigestAlgorithm::sha1, ByteString(), Success },
391+ { DigestAlgorithm::sha256, ByteString(), Success },
392+ { DigestAlgorithm::sha384, ByteString(), Success },
393+ { DigestAlgorithm::sha512, ByteString(), Success },
394+ { DigestAlgorithm::sha256, BytesToByteString(alg_id_sha1),
395+ Result::ERROR_OCSP_MALFORMED_RESPONSE },
396+ { DigestAlgorithm::sha1, BytesToByteString(alg_id_sha256),
397+ Result::ERROR_OCSP_MALFORMED_RESPONSE },
398+ { DigestAlgorithm::sha1, BytesToByteString(not_an_encoded_hash_oid),
399+ Result::ERROR_OCSP_MALFORMED_RESPONSE },
400+};
401+
402+class pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm
403+ : public pkixocsp_VerifyEncodedResponse_successful
404+ , public ::testing::WithParamInterface<CertIDHashAlgorithm>
405+{
406+};
407+
408+TEST_P(pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm, CertIDHashAlgorithm)
409+{
410+ ByteString responseString(
411+ CreateEncodedOCSPSuccessfulResponse(
412+ OCSPResponseContext::good, *endEntityCertID, byKey,
413+ *rootKeyPair, oneDayBeforeNow,
414+ oneDayBeforeNow, &oneDayAfterNow,
415+ sha256WithRSAEncryption(),
416+ nullptr,
417+ nullptr,
418+ nullptr,
419+ GetParam().hashAlgorithm,
420+ GetParam().encodedHashAlgorithm));
421+ Input response;
422+ ASSERT_EQ(Success,
423+ response.Init(responseString.data(), responseString.length()));
424+ bool expired;
425+ ASSERT_EQ(GetParam().expectedResult,
426+ VerifyEncodedOCSPResponse(trustDomain, *endEntityCertID,
427+ Now(), END_ENTITY_MAX_LIFETIME_IN_DAYS,
428+ response, expired));
429+ ASSERT_FALSE(expired);
430+}
431+
432+INSTANTIATE_TEST_SUITE_P(pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm,
433+ pkixocsp_VerifyEncodedResponse_CertIDHashAlgorithm,
434+ testing::ValuesIn(CERTID_HASH_ALGORITHMS));
435+
436 ///////////////////////////////////////////////////////////////////////////////
437 // indirect responses (signed by a delegated OCSP responder cert)
438
439diff --git a/nss/lib/cryptohi/secvfy.c b/nss/lib/cryptohi/secvfy.c
440index 2540a54..1754584 100644
441--- a/nss/lib/cryptohi/secvfy.c
442+++ b/nss/lib/cryptohi/secvfy.c
443@@ -164,6 +164,37 @@ verifyPKCS1DigestInfo(const VFYContext *cx, const SECItem *digest)
444 PR_FALSE /*XXX: unsafeAllowMissingParameters*/);
445 }
446
447+static unsigned int
448+checkedSignatureLen(const SECKEYPublicKey *pubk)
449+{
450+ unsigned int sigLen = SECKEY_SignatureLen(pubk);
451+ if (sigLen == 0) {
452+ /* Error set by SECKEY_SignatureLen */
453+ return sigLen;
454+ }
455+ unsigned int maxSigLen;
456+ switch (pubk->keyType) {
457+ case rsaKey:
458+ case rsaPssKey:
459+ maxSigLen = (RSA_MAX_MODULUS_BITS + 7) / 8;
460+ break;
461+ case dsaKey:
462+ maxSigLen = DSA_MAX_SIGNATURE_LEN;
463+ break;
464+ case ecKey:
465+ maxSigLen = 2 * MAX_ECKEY_LEN;
466+ break;
467+ default:
468+ PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
469+ return 0;
470+ }
471+ if (sigLen > maxSigLen) {
472+ PORT_SetError(SEC_ERROR_INVALID_KEY);
473+ return 0;
474+ }
475+ return sigLen;
476+}
477+
478 /*
479 * decode the ECDSA or DSA signature from it's DER wrapping.
480 * The unwrapped/raw signature is placed in the buffer pointed
481@@ -174,38 +205,38 @@ decodeECorDSASignature(SECOidTag algid, const SECItem *sig, unsigned char *dsig,
482 unsigned int len)
483 {
484 SECItem *dsasig = NULL; /* also used for ECDSA */
485- SECStatus rv = SECSuccess;
486
487- if ((algid != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
488- (algid != SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
489- if (sig->len != len) {
490- PORT_SetError(SEC_ERROR_BAD_DER);
491- return SECFailure;
492+ /* Safety: Ensure algId is as expected and that signature size is within maxmimums */
493+ if (algid == SEC_OID_ANSIX9_DSA_SIGNATURE) {
494+ if (len > DSA_MAX_SIGNATURE_LEN) {
495+ goto loser;
496 }
497-
498- PORT_Memcpy(dsig, sig->data, sig->len);
499- return SECSuccess;
500- }
501-
502- if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
503+ } else if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
504 if (len > MAX_ECKEY_LEN * 2) {
505- PORT_SetError(SEC_ERROR_BAD_DER);
506- return SECFailure;
507+ goto loser;
508 }
509- }
510- dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len);
511-
512- if ((dsasig == NULL) || (dsasig->len != len)) {
513- rv = SECFailure;
514 } else {
515- PORT_Memcpy(dsig, dsasig->data, dsasig->len);
516+ goto loser;
517 }
518
519- if (dsasig != NULL)
520+ /* Decode and pad to length */
521+ dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len);
522+ if (dsasig == NULL) {
523+ goto loser;
524+ }
525+ if (dsasig->len != len) {
526 SECITEM_FreeItem(dsasig, PR_TRUE);
527- if (rv == SECFailure)
528- PORT_SetError(SEC_ERROR_BAD_DER);
529- return rv;
530+ goto loser;
531+ }
532+
533+ PORT_Memcpy(dsig, dsasig->data, len);
534+ SECITEM_FreeItem(dsasig, PR_TRUE);
535+
536+ return SECSuccess;
537+
538+loser:
539+ PORT_SetError(SEC_ERROR_BAD_DER);
540+ return SECFailure;
541 }
542
543 const SEC_ASN1Template hashParameterTemplate[] =
544@@ -281,7 +312,7 @@ SECStatus
545 sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
546 const SECItem *param, SECOidTag *encalgp, SECOidTag *hashalg)
547 {
548- int len;
549+ unsigned int len;
550 PLArenaPool *arena;
551 SECStatus rv;
552 SECItem oid;
553@@ -466,48 +497,52 @@ vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
554 cx->pkcs1RSADigestInfo = NULL;
555 rv = SECSuccess;
556 if (sig) {
557- switch (type) {
558- case rsaKey:
559- rv = recoverPKCS1DigestInfo(hashAlg, &cx->hashAlg,
560- &cx->pkcs1RSADigestInfo,
561- &cx->pkcs1RSADigestInfoLen,
562- cx->key,
563- sig, wincx);
564- break;
565- case rsaPssKey:
566- sigLen = SECKEY_SignatureLen(key);
567- if (sigLen == 0) {
568- /* error set by SECKEY_SignatureLen */
569- rv = SECFailure;
570+ rv = SECFailure;
571+ if (type == rsaKey) {
572+ rv = recoverPKCS1DigestInfo(hashAlg, &cx->hashAlg,
573+ &cx->pkcs1RSADigestInfo,
574+ &cx->pkcs1RSADigestInfoLen,
575+ cx->key,
576+ sig, wincx);
577+ } else {
578+ sigLen = checkedSignatureLen(key);
579+ /* Check signature length is within limits */
580+ if (sigLen == 0) {
581+ /* error set by checkedSignatureLen */
582+ rv = SECFailure;
583+ goto loser;
584+ }
585+ if (sigLen > sizeof(cx->u)) {
586+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
587+ rv = SECFailure;
588+ goto loser;
589+ }
590+ switch (type) {
591+ case rsaPssKey:
592+ if (sig->len != sigLen) {
593+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
594+ rv = SECFailure;
595+ goto loser;
596+ }
597+ PORT_Memcpy(cx->u.buffer, sig->data, sigLen);
598+ rv = SECSuccess;
599 break;
600- }
601- if (sig->len != sigLen) {
602- PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
603- rv = SECFailure;
604+ case ecKey:
605+ case dsaKey:
606+ /* decodeECorDSASignature will check sigLen == sig->len after padding */
607+ rv = decodeECorDSASignature(encAlg, sig, cx->u.buffer, sigLen);
608 break;
609- }
610- PORT_Memcpy(cx->u.buffer, sig->data, sigLen);
611- break;
612- case dsaKey:
613- case ecKey:
614- sigLen = SECKEY_SignatureLen(key);
615- if (sigLen == 0) {
616- /* error set by SECKEY_SignatureLen */
617+ default:
618+ /* Unreachable */
619 rv = SECFailure;
620- break;
621- }
622- rv = decodeECorDSASignature(encAlg, sig, cx->u.buffer, sigLen);
623- break;
624- default:
625- rv = SECFailure;
626- PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
627- break;
628+ goto loser;
629+ }
630+ }
631+ if (rv != SECSuccess) {
632+ goto loser;
633 }
634 }
635
636- if (rv)
637- goto loser;
638-
639 /* check hash alg again, RSA may have changed it.*/
640 if (HASH_GetHashTypeByOidTag(cx->hashAlg) == HASH_AlgNULL) {
641 /* error set by HASH_GetHashTypeByOidTag */
642@@ -650,11 +685,16 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
643 switch (cx->key->keyType) {
644 case ecKey:
645 case dsaKey:
646- dsasig.data = cx->u.buffer;
647- dsasig.len = SECKEY_SignatureLen(cx->key);
648+ dsasig.len = checkedSignatureLen(cx->key);
649 if (dsasig.len == 0) {
650 return SECFailure;
651 }
652+ if (dsasig.len > sizeof(cx->u)) {
653+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
654+ return SECFailure;
655+ }
656+ dsasig.data = cx->u.buffer;
657+
658 if (sig) {
659 rv = decodeECorDSASignature(cx->encAlg, sig, dsasig.data,
660 dsasig.len);
661@@ -686,8 +726,13 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
662 }
663
664 rsasig.data = cx->u.buffer;
665- rsasig.len = SECKEY_SignatureLen(cx->key);
666+ rsasig.len = checkedSignatureLen(cx->key);
667 if (rsasig.len == 0) {
668+ /* Error set by checkedSignatureLen */
669+ return SECFailure;
670+ }
671+ if (rsasig.len > sizeof(cx->u)) {
672+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
673 return SECFailure;
674 }
675 if (sig) {
676@@ -749,7 +794,6 @@ vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key,
677 SECStatus rv;
678 VFYContext *cx;
679 SECItem dsasig; /* also used for ECDSA */
680-
681 rv = SECFailure;
682
683 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
684@@ -757,19 +801,25 @@ vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key,
685 switch (key->keyType) {
686 case rsaKey:
687 rv = verifyPKCS1DigestInfo(cx, digest);
688+ /* Error (if any) set by verifyPKCS1DigestInfo */
689 break;
690- case dsaKey:
691 case ecKey:
692+ case dsaKey:
693 dsasig.data = cx->u.buffer;
694- dsasig.len = SECKEY_SignatureLen(cx->key);
695+ dsasig.len = checkedSignatureLen(cx->key);
696 if (dsasig.len == 0) {
697+ /* Error set by checkedSignatureLen */
698+ rv = SECFailure;
699 break;
700 }
701- if (PK11_Verify(cx->key, &dsasig, (SECItem *)digest, cx->wincx) !=
702- SECSuccess) {
703+ if (dsasig.len > sizeof(cx->u)) {
704+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
705+ rv = SECFailure;
706+ break;
707+ }
708+ rv = PK11_Verify(cx->key, &dsasig, (SECItem *)digest, cx->wincx);
709+ if (rv != SECSuccess) {
710 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
711- } else {
712- rv = SECSuccess;
713 }
714 break;
715 default:
716diff --git a/nss/lib/mozpkix/include/pkix-test/pkixtestutil.h b/nss/lib/mozpkix/include/pkix-test/pkixtestutil.h
717index 55c4354..70c0fee 100644
718--- a/nss/lib/mozpkix/include/pkix-test/pkixtestutil.h
719+++ b/nss/lib/mozpkix/include/pkix-test/pkixtestutil.h
720@@ -349,6 +349,14 @@ class OCSPResponseContext final {
721 OCSPResponseContext(const CertID& certID, std::time_t time);
722
723 const CertID& certID;
724+ // What digest algorithm to use to produce issuerNameHash and issuerKeyHash.
725+ // Defaults to sha1.
726+ DigestAlgorithm certIDHashAlgorithm;
727+ // If non-empty, the sequence of bytes to use for hashAlgorithm when encoding
728+ // this response. If empty, the sequence of bytes corresponding to
729+ // certIDHashAlgorithm will be used. Defaults to empty.
730+ ByteString certIDHashAlgorithmEncoded;
731+
732 // TODO(bug 980538): add a way to specify what certificates are included.
733
734 // The fields below are in the order that they appear in an OCSP response.
735diff --git a/nss/lib/mozpkix/include/pkix/pkixutil.h b/nss/lib/mozpkix/include/pkix/pkixutil.h
736index ca5b5a2..b224aa1 100644
737--- a/nss/lib/mozpkix/include/pkix/pkixutil.h
738+++ b/nss/lib/mozpkix/include/pkix/pkixutil.h
739@@ -259,6 +259,20 @@ Result CheckSubjectPublicKeyInfo(Input subjectPublicKeyInfo,
740 #else
741 #error Unsupported compiler for MOZILLA_PKIX_UNREACHABLE_DEFAULT.
742 #endif
743+
744+inline size_t DigestAlgorithmToSizeInBytes(DigestAlgorithm digestAlgorithm) {
745+ switch (digestAlgorithm) {
746+ case DigestAlgorithm::sha1:
747+ return 160 / 8;
748+ case DigestAlgorithm::sha256:
749+ return 256 / 8;
750+ case DigestAlgorithm::sha384:
751+ return 384 / 8;
752+ case DigestAlgorithm::sha512:
753+ return 512 / 8;
754+ MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
755+ }
756+}
757 }
758 } // namespace mozilla::pkix
759
760diff --git a/nss/lib/mozpkix/lib/pkixocsp.cpp b/nss/lib/mozpkix/lib/pkixocsp.cpp
761index a811544..d725e55 100644
762--- a/nss/lib/mozpkix/lib/pkixocsp.cpp
763+++ b/nss/lib/mozpkix/lib/pkixocsp.cpp
764@@ -28,12 +28,6 @@
765 #include "mozpkix/pkixcheck.h"
766 #include "mozpkix/pkixutil.h"
767
768-namespace {
769-
770-const size_t SHA1_DIGEST_LENGTH = 160 / 8;
771-
772-} // namespace
773-
774 namespace mozilla { namespace pkix {
775
776 // These values correspond to the tag values in the ASN.1 CertStatus
777@@ -181,10 +175,12 @@ static inline Result MatchCertID(Reader& input,
778 const Context& context,
779 /*out*/ bool& match);
780 static Result MatchKeyHash(TrustDomain& trustDomain,
781+ DigestAlgorithm hashAlgorithm,
782 Input issuerKeyHash,
783 Input issuerSubjectPublicKeyInfo,
784 /*out*/ bool& match);
785 static Result KeyHash(TrustDomain& trustDomain,
786+ DigestAlgorithm hashAlgorithm,
787 Input subjectPublicKeyInfo,
788 /*out*/ uint8_t* hashBuf, size_t hashBufSize);
789
790@@ -213,7 +209,7 @@ MatchResponderID(TrustDomain& trustDomain,
791 if (rv != Success) {
792 return rv;
793 }
794- return MatchKeyHash(trustDomain, keyHash,
795+ return MatchKeyHash(trustDomain, DigestAlgorithm::sha1, keyHash,
796 potentialSignerSubjectPublicKeyInfo, match);
797 }
798
799@@ -741,36 +737,36 @@ MatchCertID(Reader& input, const Context& context, /*out*/ bool& match)
800 return Success;
801 }
802
803- // TODO: support SHA-2 hashes.
804-
805- if (hashAlgorithm != DigestAlgorithm::sha1) {
806- // Again, not interested in this response. Consume input, return success.
807- input.SkipToEnd();
808- return Success;
809- }
810-
811- if (issuerNameHash.GetLength() != SHA1_DIGEST_LENGTH) {
812+ size_t hashAlgorithmLength = DigestAlgorithmToSizeInBytes(hashAlgorithm);
813+ if (issuerNameHash.GetLength() != hashAlgorithmLength) {
814 return Result::ERROR_OCSP_MALFORMED_RESPONSE;
815 }
816
817 // From http://tools.ietf.org/html/rfc6960#section-4.1.1:
818 // "The hash shall be calculated over the DER encoding of the
819 // issuer's name field in the certificate being checked."
820- uint8_t hashBuf[SHA1_DIGEST_LENGTH];
821+ uint8_t hashBuf[MAX_DIGEST_SIZE_IN_BYTES];
822+ if (hashAlgorithmLength > sizeof(hashBuf)) {
823+ return Result::FATAL_ERROR_LIBRARY_FAILURE;
824+ }
825 rv = context.trustDomain.DigestBuf(context.certID.issuer,
826- DigestAlgorithm::sha1, hashBuf,
827- sizeof(hashBuf));
828+ hashAlgorithm, hashBuf,
829+ hashAlgorithmLength);
830+ if (rv != Success) {
831+ return rv;
832+ }
833+ Input computed;
834+ rv = computed.Init(hashBuf, hashAlgorithmLength);
835 if (rv != Success) {
836 return rv;
837 }
838- Input computed(hashBuf);
839 if (!InputsAreEqual(computed, issuerNameHash)) {
840 // Again, not interested in this response. Consume input, return success.
841 input.SkipToEnd();
842 return Success;
843 }
844
845- return MatchKeyHash(context.trustDomain, issuerKeyHash,
846+ return MatchKeyHash(context.trustDomain, hashAlgorithm, issuerKeyHash,
847 context.certID.issuerSubjectPublicKeyInfo, match);
848 }
849
850@@ -784,30 +780,53 @@ MatchCertID(Reader& input, const Context& context, /*out*/ bool& match)
851 // -- BIT STRING subjectPublicKey [excluding
852 // -- the tag, length, and number of unused
853 // -- bits] in the responder's certificate)
854+//
855+// From https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1:
856+// CertID ::= SEQUENCE {
857+// hashAlgorithm AlgorithmIdentifier,
858+// issuerNameHash OCTET STRING, -- Hash of issuer's DN
859+// issuerKeyHash OCTET STRING, -- Hash of issuer's public key
860+// serialNumber CertificateSerialNumber }
861+// ...
862+// o hashAlgorithm is the hash algorithm used to generate the
863+// issuerNameHash and issuerKeyHash values.
864+// ...
865+// o issuerKeyHash is the hash of the issuer's public key. The hash
866+// shall be calculated over the value (excluding tag and length) of
867+// the subject public key field in the issuer's certificate.
868 static Result
869-MatchKeyHash(TrustDomain& trustDomain, Input keyHash,
870- const Input subjectPublicKeyInfo, /*out*/ bool& match)
871+MatchKeyHash(TrustDomain& trustDomain, DigestAlgorithm hashAlgorithm,
872+ Input keyHash, const Input subjectPublicKeyInfo,
873+ /*out*/ bool& match)
874 {
875- if (keyHash.GetLength() != SHA1_DIGEST_LENGTH) {
876+ size_t hashLength = DigestAlgorithmToSizeInBytes(hashAlgorithm);
877+ if (keyHash.GetLength() != hashLength) {
878 return Result::ERROR_OCSP_MALFORMED_RESPONSE;
879 }
880- uint8_t hashBuf[SHA1_DIGEST_LENGTH];
881- Result rv = KeyHash(trustDomain, subjectPublicKeyInfo, hashBuf,
882- sizeof hashBuf);
883+ uint8_t hashBuf[MAX_DIGEST_SIZE_IN_BYTES];
884+ if (hashLength > MAX_DIGEST_SIZE_IN_BYTES) {
885+ return Result::FATAL_ERROR_LIBRARY_FAILURE;
886+ }
887+ Result rv = KeyHash(trustDomain, hashAlgorithm, subjectPublicKeyInfo,
888+ hashBuf, hashLength);
889+ if (rv != Success) {
890+ return rv;
891+ }
892+ Input computed;
893+ rv = computed.Init(hashBuf, hashLength);
894 if (rv != Success) {
895 return rv;
896 }
897- Input computed(hashBuf);
898 match = InputsAreEqual(computed, keyHash);
899 return Success;
900 }
901
902-// TODO(bug 966856): support SHA-2 hashes
903 Result
904-KeyHash(TrustDomain& trustDomain, const Input subjectPublicKeyInfo,
905- /*out*/ uint8_t* hashBuf, size_t hashBufSize)
906+KeyHash(TrustDomain& trustDomain, DigestAlgorithm hashAlgorithm,
907+ const Input subjectPublicKeyInfo, /*out*/ uint8_t* hashBuf,
908+ size_t hashBufSize)
909 {
910- if (!hashBuf || hashBufSize != SHA1_DIGEST_LENGTH) {
911+ if (!hashBuf || hashBufSize != DigestAlgorithmToSizeInBytes(hashAlgorithm)) {
912 return Result::FATAL_ERROR_LIBRARY_FAILURE;
913 }
914
915@@ -840,8 +859,8 @@ KeyHash(TrustDomain& trustDomain, const Input subjectPublicKeyInfo,
916 return rv;
917 }
918
919- return trustDomain.DigestBuf(subjectPublicKey, DigestAlgorithm::sha1,
920- hashBuf, hashBufSize);
921+ return trustDomain.DigestBuf(subjectPublicKey, hashAlgorithm, hashBuf,
922+ hashBufSize);
923 }
924
925 Result
926@@ -921,8 +940,6 @@ CreateEncodedOCSPRequest(TrustDomain& trustDomain, const struct CertID& certID,
927 // and thus more likely to fit within the 255 byte limit for OCSP GET that
928 // is specified in RFC 5019 Section 5.
929
930- // Bug 966856: Add the id-pkix-ocsp-pref-sig-algs extension.
931-
932 // Since we don't know whether the OCSP responder supports anything other
933 // than SHA-1, we have no choice but to use SHA-1 for issuerNameHash and
934 // issuerKeyHash.
935@@ -986,7 +1003,8 @@ CreateEncodedOCSPRequest(TrustDomain& trustDomain, const struct CertID& certID,
936 // reqCert.issuerKeyHash (OCTET STRING)
937 *d++ = 0x04;
938 *d++ = hashLen;
939- rv = KeyHash(trustDomain, certID.issuerSubjectPublicKeyInfo, d, hashLen);
940+ rv = KeyHash(trustDomain, DigestAlgorithm::sha1,
941+ certID.issuerSubjectPublicKeyInfo, d, hashLen);
942 if (rv != Success) {
943 return rv;
944 }
945diff --git a/nss/lib/mozpkix/lib/pkixverify.cpp b/nss/lib/mozpkix/lib/pkixverify.cpp
946index 8ceb2c1..bec570d 100644
947--- a/nss/lib/mozpkix/lib/pkixverify.cpp
948+++ b/nss/lib/mozpkix/lib/pkixverify.cpp
949@@ -43,14 +43,7 @@ DigestSignedData(TrustDomain& trustDomain,
950 return Result::ERROR_BAD_DER;
951 }
952
953- size_t digestLen;
954- switch (signedDigest.digestAlgorithm) {
955- case DigestAlgorithm::sha512: digestLen = 512 / 8; break;
956- case DigestAlgorithm::sha384: digestLen = 384 / 8; break;
957- case DigestAlgorithm::sha256: digestLen = 256 / 8; break;
958- case DigestAlgorithm::sha1: digestLen = 160 / 8; break;
959- MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
960- }
961+ size_t digestLen = DigestAlgorithmToSizeInBytes(signedDigest.digestAlgorithm);
962 assert(digestLen <= sizeof(digestBuf));
963
964 rv = trustDomain.DigestBuf(signedData.data, signedDigest.digestAlgorithm,
965diff --git a/nss/lib/mozpkix/test-lib/pkixtestutil.cpp b/nss/lib/mozpkix/test-lib/pkixtestutil.cpp
966index b1b89c0..306f7a0 100644
967--- a/nss/lib/mozpkix/test-lib/pkixtestutil.cpp
968+++ b/nss/lib/mozpkix/test-lib/pkixtestutil.cpp
969@@ -156,6 +156,8 @@ OCSPResponseExtension::OCSPResponseExtension()
970
971 OCSPResponseContext::OCSPResponseContext(const CertID& aCertID, time_t time)
972 : certID(aCertID)
973+ , certIDHashAlgorithm(DigestAlgorithm::sha1)
974+ , certIDHashAlgorithmEncoded(ByteString())
975 , responseStatus(successful)
976 , skipResponseBytes(false)
977 , producedAt(time)
978@@ -184,25 +186,26 @@ static ByteString CertID(OCSPResponseContext& context);
979 static ByteString CertStatus(OCSPResponseContext& context);
980
981 static ByteString
982-SHA1(const ByteString& toHash)
983+HASH(const ByteString& toHash, DigestAlgorithm digestAlgorithm)
984 {
985- uint8_t digestBuf[20];
986+ uint8_t digestBuf[MAX_DIGEST_SIZE_IN_BYTES];
987 Input input;
988 if (input.Init(toHash.data(), toHash.length()) != Success) {
989 abort();
990 }
991- Result rv = TestDigestBuf(input, DigestAlgorithm::sha1, digestBuf,
992- sizeof(digestBuf));
993+ size_t digestLen = DigestAlgorithmToSizeInBytes(digestAlgorithm);
994+ assert(digestLen <= sizeof(digestBuf));
995+ Result rv = TestDigestBuf(input, digestAlgorithm, digestBuf, digestLen);
996 if (rv != Success) {
997 abort();
998 }
999- return ByteString(digestBuf, sizeof(digestBuf));
1000+ return ByteString(digestBuf, digestLen);
1001 }
1002
1003 static ByteString
1004-HashedOctetString(const ByteString& bytes)
1005+HashedOctetString(const ByteString& bytes, DigestAlgorithm digestAlgorithm)
1006 {
1007- ByteString digest(SHA1(bytes));
1008+ ByteString digest(HASH(bytes, digestAlgorithm));
1009 if (ENCODING_FAILED(digest)) {
1010 return ByteString();
1011 }
1012@@ -993,7 +996,7 @@ ResponderID(OCSPResponseContext& context)
1013 ByteString
1014 KeyHash(const ByteString& subjectPublicKey)
1015 {
1016- return HashedOctetString(subjectPublicKey);
1017+ return HashedOctetString(subjectPublicKey, DigestAlgorithm::sha1);
1018 }
1019
1020 // SingleResponse ::= SEQUENCE {
1021@@ -1050,7 +1053,7 @@ CertID(OCSPResponseContext& context)
1022 {
1023 ByteString issuerName(context.certID.issuer.UnsafeGetData(),
1024 context.certID.issuer.GetLength());
1025- ByteString issuerNameHash(HashedOctetString(issuerName));
1026+ ByteString issuerNameHash(HashedOctetString(issuerName, context.certIDHashAlgorithm));
1027 if (ENCODING_FAILED(issuerNameHash)) {
1028 return ByteString();
1029 }
1030@@ -1074,8 +1077,8 @@ CertID(OCSPResponseContext& context)
1031 != Success) {
1032 return ByteString();
1033 }
1034- issuerKeyHash = KeyHash(ByteString(subjectPublicKey.UnsafeGetData(),
1035- subjectPublicKey.GetLength()));
1036+ issuerKeyHash = HashedOctetString(ByteString(subjectPublicKey.UnsafeGetData(),
1037+ subjectPublicKey.GetLength()), context.certIDHashAlgorithm);
1038 if (ENCODING_FAILED(issuerKeyHash)) {
1039 return ByteString();
1040 }
1041@@ -1089,9 +1092,39 @@ CertID(OCSPResponseContext& context)
1042 static const uint8_t alg_id_sha1[] = {
1043 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a
1044 };
1045+ // python DottedOIDToCode.py --alg id-sha256 2.16.840.1.101.3.4.2.1
1046+ static const uint8_t alg_id_sha256[] = {
1047+ 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
1048+ };
1049+ // python DottedOIDToCode.py --alg id-sha384 2.16.840.1.101.3.4.2.2
1050+ static const uint8_t alg_id_sha384[] = {
1051+ 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
1052+ };
1053+ // python DottedOIDToCode.py --alg id-sha512 2.16.840.1.101.3.4.2.3
1054+ static const uint8_t alg_id_sha512[] = {
1055+ 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
1056+ };
1057
1058 ByteString value;
1059- value.append(alg_id_sha1, sizeof(alg_id_sha1));
1060+ if (!context.certIDHashAlgorithmEncoded.empty()) {
1061+ value.append(context.certIDHashAlgorithmEncoded);
1062+ } else {
1063+ switch (context.certIDHashAlgorithm) {
1064+ case DigestAlgorithm::sha1:
1065+ value.append(alg_id_sha1, sizeof(alg_id_sha1));
1066+ break;
1067+ case DigestAlgorithm::sha256:
1068+ value.append(alg_id_sha256, sizeof(alg_id_sha256));
1069+ break;
1070+ case DigestAlgorithm::sha384:
1071+ value.append(alg_id_sha384, sizeof(alg_id_sha384));
1072+ break;
1073+ case DigestAlgorithm::sha512:
1074+ value.append(alg_id_sha512, sizeof(alg_id_sha512));
1075+ break;
1076+ MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
1077+ }
1078+ }
1079 value.append(issuerNameHash);
1080 value.append(issuerKeyHash);
1081 value.append(serialNumber);
1082diff --git a/nss/lib/nss/nss.h b/nss/lib/nss/nss.h
1083index 5d372e7..c87fa1e 100644
1084--- a/nss/lib/nss/nss.h
1085+++ b/nss/lib/nss/nss.h
1086@@ -22,10 +22,10 @@
1087 * The format of the version string should be
1088 * "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
1089 */
1090-#define NSS_VERSION "3.68" _NSS_CUSTOMIZED
1091+#define NSS_VERSION "3.68.2" _NSS_CUSTOMIZED
1092 #define NSS_VMAJOR 3
1093 #define NSS_VMINOR 68
1094-#define NSS_VPATCH 0
1095+#define NSS_VPATCH 2
1096 #define NSS_VBUILD 0
1097 #define NSS_BETA PR_FALSE
1098
1099diff --git a/nss/lib/pkcs7/certread.c b/nss/lib/pkcs7/certread.c
1100index 3091f99..15094f2 100644
1101--- a/nss/lib/pkcs7/certread.c
1102+++ b/nss/lib/pkcs7/certread.c
1103@@ -139,6 +139,11 @@ SEC_ReadPKCS7Certs(SECItem *pkcs7Item, CERTImportCertificateFunc f, void *arg)
1104 goto done;
1105 }
1106
1107+ if (contentInfo.content.signedData == NULL) {
1108+ PORT_SetError(SEC_ERROR_BAD_DER);
1109+ goto done;
1110+ }
1111+
1112 rv = SECSuccess;
1113
1114 certs = contentInfo.content.signedData->certificates;
1115diff --git a/nss/lib/softoken/softkver.h b/nss/lib/softoken/softkver.h
1116index 349373e..f3506b6 100644
1117--- a/nss/lib/softoken/softkver.h
1118+++ b/nss/lib/softoken/softkver.h
1119@@ -17,10 +17,10 @@
1120 * The format of the version string should be
1121 * "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
1122 */
1123-#define SOFTOKEN_VERSION "3.68" SOFTOKEN_ECC_STRING
1124+#define SOFTOKEN_VERSION "3.68.2" SOFTOKEN_ECC_STRING
1125 #define SOFTOKEN_VMAJOR 3
1126 #define SOFTOKEN_VMINOR 68
1127-#define SOFTOKEN_VPATCH 0
1128+#define SOFTOKEN_VPATCH 2
1129 #define SOFTOKEN_VBUILD 0
1130 #define SOFTOKEN_BETA PR_FALSE
1131
1132diff --git a/nss/lib/util/nssutil.h b/nss/lib/util/nssutil.h
1133index 21cdbf6..28e0f1e 100644
1134--- a/nss/lib/util/nssutil.h
1135+++ b/nss/lib/util/nssutil.h
1136@@ -19,10 +19,10 @@
1137 * The format of the version string should be
1138 * "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
1139 */
1140-#define NSSUTIL_VERSION "3.68"
1141+#define NSSUTIL_VERSION "3.68.2"
1142 #define NSSUTIL_VMAJOR 3
1143 #define NSSUTIL_VMINOR 68
1144-#define NSSUTIL_VPATCH 0
1145+#define NSSUTIL_VPATCH 2
1146 #define NSSUTIL_VBUILD 0
1147 #define NSSUTIL_BETA PR_FALSE
1148

Subscribers

People subscribed via source and target branches