Control: tags 862958 + pending Control: tags 863839 + pending # make RC severity due to otherwise regression from jessie Control: severity 862958 serious Control: severity 863839 serious
Dear maintainer, I've prepared an NMU for nss (versioned as 2:3.26.2-1.1) and uploaded it to DELAYED/2. Please feel free to tell me if I should delay it longer. Regards, Salvatore
diff -Nru nss-3.26.2/debian/changelog nss-3.26.2/debian/changelog --- nss-3.26.2/debian/changelog 2016-10-30 00:20:34.000000000 +0200 +++ nss-3.26.2/debian/changelog 2017-06-01 06:57:51.000000000 +0200 @@ -1,3 +1,13 @@ +nss (2:3.26.2-1.1) unstable; urgency=medium + + * Non-maintainer upload. + * CVE-2017-5461: Out-of-bounds write in Base64 encoding (Closes: #862958) + * CVE-2017-5462: DRBG flaw (Closes: #862958) + * CVE-2017-7502: Null pointer dereference when handling empty SSLv2 messages + (Closes: #863839) + + -- Salvatore Bonaccorso <car...@debian.org> Thu, 01 Jun 2017 06:57:51 +0200 + nss (2:3.26.2-1) unstable; urgency=medium * New upstream release. diff -Nru nss-3.26.2/debian/patches/CVE-2017-5461.patch nss-3.26.2/debian/patches/CVE-2017-5461.patch --- nss-3.26.2/debian/patches/CVE-2017-5461.patch 1970-01-01 01:00:00.000000000 +0100 +++ nss-3.26.2/debian/patches/CVE-2017-5461.patch 2017-06-01 06:57:51.000000000 +0200 @@ -0,0 +1,183 @@ + +# HG changeset patch +# User Franziskus Kiefer <franziskuskie...@gmail.com> +# Date 1489748381 -3600 +# Node ID 77a5bb81dbaac5b03266a64ff981c156b61c8931 +# Parent da15c12097edbe876620ed5da8378ee3269caea8 +Bug 1344380 - gtests for b64 bug and some fixes, r=ttaubert + +Differential Revision: https://nss-review.dev.mozaws.net/D256#inline-2146 + +--- a/nss/external_tests/util_gtest/manifest.mn ++++ b/nss/external_tests/util_gtest/manifest.mn +@@ -8,6 +8,7 @@ MODULE = nss + + CPPSRCS = \ + util_utf8_unittest.cc \ ++ util_b64_unittest.cc \ + $(NULL) + + INCLUDES += \ +--- /dev/null ++++ b/nss/external_tests/util_gtest/util_b64_unittest.cc +@@ -0,0 +1,79 @@ ++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim: set ts=2 et sw=2 tw=80: */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this file, ++ * You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#include <climits> ++#include <memory> ++#include "nssb64.h" ++ ++#include "gtest/gtest.h" ++#include "scoped_ptrs.h" ++ ++namespace nss_test { ++ ++class B64EncodeDecodeTest : public ::testing::Test { ++ public: ++ void TestDecodeStr(const std::string &str) { ++ ScopedSECItem tmp( ++ NSSBase64_DecodeBuffer(nullptr, nullptr, str.c_str(), str.size())); ++ ASSERT_TRUE(tmp); ++ char *out = NSSBase64_EncodeItem(nullptr, nullptr, 0, tmp.get()); ++ ASSERT_TRUE(out); ++ ASSERT_EQ(std::string(out), str); ++ PORT_Free(out); ++ } ++ bool TestEncodeItem(SECItem *item) { ++ bool rv = true; ++ char *out = NSSBase64_EncodeItem(nullptr, nullptr, 0, item); ++ rv = !!out; ++ if (out) { ++ ScopedSECItem tmp( ++ NSSBase64_DecodeBuffer(nullptr, nullptr, out, strlen(out))); ++ EXPECT_TRUE(tmp); ++ EXPECT_EQ(SECEqual, SECITEM_CompareItem(item, tmp.get())); ++ PORT_Free(out); ++ } ++ return rv; ++ } ++ bool TestFakeDecode(size_t str_len) { ++ std::string str(str_len, 'A'); ++ ScopedSECItem tmp( ++ NSSBase64_DecodeBuffer(nullptr, nullptr, str.c_str(), str.size())); ++ return !!tmp; ++ } ++ bool TestFakeEncode(size_t len) { ++ std::vector<uint8_t> data(len, 0x30); ++ SECItem tmp = {siBuffer, data.data(), ++ static_cast<unsigned int>(data.size())}; ++ return TestEncodeItem(&tmp); ++ } ++ ++ protected: ++}; ++ ++TEST_F(B64EncodeDecodeTest, DecEncTest) { TestDecodeStr("VGhpcyBpcyBOU1Mh"); } ++ ++TEST_F(B64EncodeDecodeTest, EncDecTest) { ++ uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}; ++ SECItem tmp = {siBuffer, data, sizeof(data)}; ++ TestEncodeItem(&tmp); ++} ++ ++TEST_F(B64EncodeDecodeTest, FakeDecTest) { EXPECT_TRUE(TestFakeDecode(100)); } ++ ++TEST_F(B64EncodeDecodeTest, FakeEncDecTest) { ++ EXPECT_TRUE(TestFakeEncode(100)); ++} ++ ++// These takes a while ... ++TEST_F(B64EncodeDecodeTest, LongFakeDecTest1) { ++ EXPECT_TRUE(TestFakeDecode(0x66666666)); ++} ++TEST_F(B64EncodeDecodeTest, LongFakeEncDecTest1) { TestFakeEncode(0x3fffffff); } ++TEST_F(B64EncodeDecodeTest, LongFakeEncDecTest2) { ++ EXPECT_FALSE(TestFakeEncode(0x40000000)); ++} ++ ++} // namespace nss_test +--- a/nss/lib/util/nssb64d.c ++++ b/nss/lib/util/nssb64d.c +@@ -373,7 +373,7 @@ pl_base64_decode_flush (PLBase64Decoder + static PRUint32 + PL_Base64MaxDecodedLength (PRUint32 size) + { +- return ((size * 3) / 4); ++ return size * 0.75; + } + + +--- a/nss/lib/util/nssb64e.c ++++ b/nss/lib/util/nssb64e.c +@@ -284,21 +284,29 @@ static PRUint32 + PL_Base64MaxEncodedLength (PRUint32 size, PRUint32 line_length) + { + PRUint32 tokens, tokens_per_line, full_lines, line_break_chars, remainder; ++ /* This is the maximum length we support. */ ++ if (size > 0x3fffffff) { ++ return 0; ++ } + + tokens = (size + 2) / 3; + +- if (line_length == 0) +- return tokens * 4; ++ if (line_length == 0) { ++ return tokens * 4; ++ } + +- if (line_length < 4) /* too small! */ +- line_length = 4; ++ ++ if (line_length < 4) { /* too small! */ ++ line_length = 4; ++ } + + tokens_per_line = line_length / 4; + full_lines = tokens / tokens_per_line; + remainder = (tokens - (full_lines * tokens_per_line)) * 4; + line_break_chars = full_lines * 2; +- if (remainder == 0) +- line_break_chars -= 2; ++ if (remainder == 0) { ++ line_break_chars -= 2; ++ } + + return (full_lines * tokens_per_line * 4) + line_break_chars + remainder; + } +@@ -454,13 +462,18 @@ PL_Base64EncodeBuffer (const unsigned ch + PRStatus status; + + PR_ASSERT(srclen > 0); +- if (srclen == 0) +- return dest; ++ if (srclen == 0) { ++ return dest; ++ } + + /* + * How much space could we possibly need for encoding this input? + */ + need_length = PL_Base64MaxEncodedLength (srclen, line_length); ++ if (need_length == 0) { ++ PORT_SetError(SEC_ERROR_INVALID_ARGS); ++ return NULL; ++ } + + /* + * Make sure we have at least that much, if output buffer provided. +@@ -643,6 +656,10 @@ NSSBase64_EncodeItem (PLArenaPool *arena + } + + max_out_len = PL_Base64MaxEncodedLength (inItem->len, 64); ++ if (max_out_len == 0) { ++ PORT_SetError(SEC_ERROR_INVALID_ARGS); ++ return NULL; ++ } + + if (arenaOpt != NULL) + mark = PORT_ArenaMark (arenaOpt); diff -Nru nss-3.26.2/debian/patches/CVE-2017-5462.patch nss-3.26.2/debian/patches/CVE-2017-5462.patch --- nss-3.26.2/debian/patches/CVE-2017-5462.patch 1970-01-01 01:00:00.000000000 +0100 +++ nss-3.26.2/debian/patches/CVE-2017-5462.patch 2017-06-01 06:57:51.000000000 +0200 @@ -0,0 +1,94 @@ + +# HG changeset patch +# User Franziskus Kiefer <franziskuskie...@gmail.com> +# Date 1491394302 -7200 +# Node ID 7248d38b76e569d2f89b20598fcdca595c3a2e6a +# Parent 6eb39ead39e0b3f6269fd9660a4426187f5302a8 +Bug 1345089 - add prng kat tests, r=ttaubert + +--- a/nss/lib/freebl/blapi.h ++++ b/nss/lib/freebl/blapi.h +@@ -1473,6 +1473,12 @@ FIPS186Change_ReduceModQForDSA(const uns + const unsigned char *q, + unsigned char *xj); + ++/* To allow NIST KAT tests */ ++extern SECStatus ++PRNGTEST_Instantiate_Kat(const PRUint8 *entropy, unsigned int entropy_len, ++ const PRUint8 *nonce, unsigned int nonce_len, ++ const PRUint8 *personal_string, unsigned int ps_len); ++ + /* + * The following functions are for FIPS poweron self test and FIPS algorithm + * testing. +--- a/nss/lib/freebl/drbg.c ++++ b/nss/lib/freebl/drbg.c +@@ -96,7 +96,8 @@ struct RNGContextStr { + * RNG_RandomUpdate. */ + PRUint8 additionalDataCache[PRNG_ADDITONAL_DATA_CACHE_SIZE]; + PRUint32 additionalAvail; +- PRBool isValid; /* false if RNG reaches an invalid state */ ++ PRBool isValid; /* false if RNG reaches an invalid state */ ++ PRBool isKatTest; /* true if running NIST PRNG KAT tests */ + }; + + typedef struct RNGContextStr RNGContext; +@@ -149,7 +150,7 @@ prng_Hash_df(PRUint8 *requested_bytes, u + + + /* +- * Hash_DRBG Instantiate NIST SP 800-80 10.1.1.2 ++ * Hash_DRBG Instantiate NIST SP 800-90 10.1.1.2 + * + * NOTE: bytes & len are entropy || nonce || personalization_string. In + * normal operation, NSS calculates them all together in a single call. +@@ -157,9 +158,11 @@ prng_Hash_df(PRUint8 *requested_bytes, u + static SECStatus + prng_instantiate(RNGContext *rng, const PRUint8 *bytes, unsigned int len) + { +- if (len < PRNG_SEEDLEN) { +- /* if the seedlen is to small, it's probably because we failed to get +- * enough random data */ ++ if (!rng->isKatTest && len < PRNG_SEEDLEN) { ++ /* If the seedlen is too small, it's probably because we failed to get ++ * enough random data. ++ * This is stricter than NIST SP800-90A requires. Don't enforce it for ++ * tests. */ + PORT_SetError(SEC_ERROR_NEED_RANDOM); + return SECFailure; + } +@@ -272,7 +275,7 @@ prng_reseed_test(RNGContext *rng, const + + #define PRNG_ADD_BITS_AND_CARRY(dest, dest_len, add, len, carry) \ + PRNG_ADD_BITS(dest, dest_len, add, len, carry) \ +- PRNG_ADD_CARRY_ONLY(dest, dest_len - len, carry) ++ PRNG_ADD_CARRY_ONLY(dest, dest_len - len - 1, carry) + + /* + * This function expands the internal state of the prng to fulfill any number +@@ -440,6 +443,7 @@ static PRStatus rng_init(void) + } + /* the RNG is in a valid state */ + globalrng->isValid = PR_TRUE; ++ globalrng->isKatTest = PR_FALSE; + + /* fetch one random value so that we can populate rng->oldV for our + * continous random number test. */ +@@ -684,6 +688,17 @@ RNG_RNGShutdown(void) + * entropy we may have previously collected. */ + RNGContext testContext; + ++SECStatus ++PRNGTEST_Instantiate_Kat(const PRUint8 *entropy, unsigned int entropy_len, ++ const PRUint8 *nonce, unsigned int nonce_len, ++ const PRUint8 *personal_string, unsigned int ps_len) ++{ ++ testContext.isKatTest = PR_TRUE; ++ return PRNGTEST_Instantiate(entropy, entropy_len, ++ nonce, nonce_len, ++ personal_string, ps_len); ++} ++ + /* + * Test vector API. Use NIST SP 800-90 general interface so one of the + * other NIST SP 800-90 algorithms may be used in the future. diff -Nru nss-3.26.2/debian/patches/CVE-2017-7502.patch nss-3.26.2/debian/patches/CVE-2017-7502.patch --- nss-3.26.2/debian/patches/CVE-2017-7502.patch 1970-01-01 01:00:00.000000000 +0100 +++ nss-3.26.2/debian/patches/CVE-2017-7502.patch 2017-06-01 06:57:51.000000000 +0200 @@ -0,0 +1,108 @@ + +# HG changeset patch +# User Tim Taubert <ttaub...@mozilla.com> +# Date 1483435195 -3600 +# Node ID 55ea60effd0d7c427f9b57a0bd43fb0fcbdae0e9 +# Parent 316fcf7c1ca35a1d1bb8e12605cca6f9af933bde +Bug 1328122 - Fix various ssl3_GatherData() issues r=mt,franziskus + +Differential Revision: https://nss-review.dev.mozaws.net/D135 + +--- a/nss/lib/ssl/ssl3gthr.c ++++ b/nss/lib/ssl/ssl3gthr.c +@@ -32,6 +32,7 @@ ssl3_InitGather(sslGather *gs) + gs->readOffset = 0; + gs->dtlsPacketOffset = 0; + gs->dtlsPacket.len = 0; ++ gs->rejectV2Records = PR_FALSE; + status = sslBuffer_Grow(&gs->buf, 4096); + return status; + } +@@ -147,8 +148,11 @@ ssl3_GatherData(sslSocket *ss, sslGather + switch (gs->state) { + case GS_HEADER: + /* Check for SSLv2 handshakes. Always assume SSLv3 on clients, +- * support SSLv2 handshakes only when ssl2gs != NULL. */ +- if (!ssl2gs || ssl3_isLikelyV3Hello(gs->hdr)) { ++ * support SSLv2 handshakes only when ssl2gs != NULL. ++ * Always assume v3 after we received the first record. */ ++ if (!ssl2gs || ++ ss->gs.rejectV2Records || ++ ssl3_isLikelyV3Hello(gs->hdr)) { + /* Should have an SSLv3 record header in gs->hdr. Extract + * the length of the following encrypted data, and then + * read in the rest of the SSL3 record into gs->inbuf. */ +@@ -171,7 +175,7 @@ ssl3_GatherData(sslSocket *ss, sslGather + /* This is the max length for an encrypted SSLv3+ fragment. */ + if (!v2HdrLength && + gs->remainder > (MAX_FRAGMENT_LENGTH + 2048)) { +- SSL3_SendAlert(ss, alert_fatal, unexpected_message); ++ SSL3_SendAlert(ss, alert_fatal, record_overflow); + gs->state = GS_INIT; + PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); + return SECFailure; +@@ -193,13 +197,28 @@ ssl3_GatherData(sslSocket *ss, sslGather + * many into the gs->hdr[] buffer. Copy them over into inbuf so + * that we can properly process the hello record later. */ + if (v2HdrLength) { ++ /* Reject v2 records that don't even carry enough data to ++ * resemble a valid ClientHello header. */ ++ if (gs->remainder < SSL_HL_CLIENT_HELLO_HBYTES) { ++ SSL3_SendAlert(ss, alert_fatal, illegal_parameter); ++ PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); ++ return SECFailure; ++ } ++ ++ PORT_Assert(lbp); + gs->inbuf.len = 5 - v2HdrLength; + PORT_Memcpy(lbp, gs->hdr + v2HdrLength, gs->inbuf.len); + gs->remainder -= gs->inbuf.len; + lbp += gs->inbuf.len; + } + +- break; /* End this case. Continue around the loop. */ ++ if (gs->remainder > 0) { ++ break; /* End this case. Continue around the loop. */ ++ } ++ ++ /* FALL THROUGH if (gs->remainder == 0) as we just received ++ * an empty record and there's really no point in calling ++ * ssl_DefRecv() with buf=NULL and len=0. */ + + case GS_DATA: + /* +@@ -207,6 +226,10 @@ ssl3_GatherData(sslSocket *ss, sslGather + */ + SSL_TRC(10, ("%d: SSL[%d]: got record of %d bytes", + SSL_GETPID(), ss->fd, gs->inbuf.len)); ++ ++ /* reject any v2 records from now on */ ++ ss->gs.rejectV2Records = PR_TRUE; ++ + gs->state = GS_INIT; + return 1; + } +--- a/nss/lib/ssl/ssldef.c ++++ b/nss/lib/ssl/ssldef.c +@@ -66,6 +66,8 @@ ssl_DefRecv(sslSocket *ss, unsigned char + PRFileDesc *lower = ss->fd->lower; + int rv; + ++ PORT_Assert(buf && len > 0); ++ + rv = lower->methods->recv(lower, (void *)buf, len, flags, ss->rTimeout); + if (rv < 0) { + DEFINE_ERROR +--- a/nss/lib/ssl/sslimpl.h ++++ b/nss/lib/ssl/sslimpl.h +@@ -451,6 +451,10 @@ struct sslGatherStr { + + /* the start of the buffered DTLS record in dtlsPacket */ + unsigned int dtlsPacketOffset; ++ ++ /* tracks whether we've seen a v3-type record before and must reject ++ * any further v2-type records. */ ++ PRBool rejectV2Records; + }; + + /* sslGather.state */ diff -Nru nss-3.26.2/debian/patches/series nss-3.26.2/debian/patches/series --- nss-3.26.2/debian/patches/series 2016-03-09 01:48:28.000000000 +0100 +++ nss-3.26.2/debian/patches/series 2017-06-01 06:57:51.000000000 +0200 @@ -3,3 +3,6 @@ 80_security_tools.patch 85_security_load.patch 38_hppa.patch +CVE-2017-5461.patch +CVE-2017-5462.patch +CVE-2017-7502.patch