Bug 1344368 - Upgrade ESR52 to NSS 3.28.4. a=jcristau
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 05 Apr 2017 17:54:07 -0400
changeset 578271 845da34e5bd820476bba0ba77f41fa65fdc7b958
parent 578270 da44c5cfab2eba8418b496bfef1a25beed58fcfb
child 578272 0f966927bd55bbb2229f1a492f6f21a8d3a95a94
push id58939
push userbmo:cku@mozilla.com
push dateTue, 16 May 2017 04:17:59 +0000
reviewersjcristau
bugs1344368
milestone52.0.3
Bug 1344368 - Upgrade ESR52 to NSS 3.28.4. a=jcristau
old-configure.in
security/nss/TAG-INFO
security/nss/coreconf/coreconf.dep
security/nss/gtests/util_gtest/manifest.mn
security/nss/gtests/util_gtest/util_b64_unittest.cc
security/nss/gtests/util_gtest/util_gtest.gyp
security/nss/lib/freebl/blapi.h
security/nss/lib/freebl/drbg.c
security/nss/lib/nss/nss.h
security/nss/lib/softoken/softkver.h
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/sslsock.c
security/nss/lib/ssl/tls13con.c
security/nss/lib/util/nssb64d.c
security/nss/lib/util/nssb64e.c
security/nss/lib/util/nssutil.h
--- a/old-configure.in
+++ b/old-configure.in
@@ -2118,17 +2118,17 @@ dnl = If NSS was not detected in the sys
 dnl = use the one in the source tree (mozilla/security/nss)
 dnl ========================================================
 
 MOZ_ARG_WITH_BOOL(system-nss,
 [  --with-system-nss       Use system installed NSS],
     _USE_SYSTEM_NSS=1 )
 
 if test -n "$_USE_SYSTEM_NSS"; then
-    AM_PATH_NSS(3.28.3, [MOZ_SYSTEM_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
+    AM_PATH_NSS(3.28.4, [MOZ_SYSTEM_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
 fi
 
 if test -n "$MOZ_SYSTEM_NSS"; then
    NSS_LIBS="$NSS_LIBS -lcrmf"
 else
    NSS_CFLAGS="-I${DIST}/include/nss"
 fi
 
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-NSS_3_28_3_RTM
+NSS_3_28_4_RTM
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/security/nss/gtests/util_gtest/manifest.mn
+++ b/security/nss/gtests/util_gtest/manifest.mn
@@ -2,16 +2,17 @@
 # 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/.
 CORE_DEPTH = ../..
 DEPTH      = ../..
 MODULE = nss
 
 CPPSRCS = \
+	util_b64_unittest.cc \
 	util_utf8_unittest.cc \
 	$(NULL)
 
 INCLUDES += \
 	-I$(CORE_DEPTH)/gtests/google_test/gtest/include \
 	-I$(CORE_DEPTH)/gtests/common \
 	$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/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/security/nss/gtests/util_gtest/util_gtest.gyp
+++ b/security/nss/gtests/util_gtest/util_gtest.gyp
@@ -6,16 +6,17 @@
     '../../coreconf/config.gypi',
     '../common/gtest.gypi',
   ],
   'targets': [
     {
       'target_name': 'util_gtest',
       'type': 'executable',
       'sources': [
+        'util_b64_unittest.cc',
         'util_utf8_unittest.cc',
         '<(DEPTH)/gtests/common/gtests.cc'
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
         '<(DEPTH)/lib/util/util.gyp:nssutil',
       ]
--- a/security/nss/lib/freebl/blapi.h
+++ b/security/nss/lib/freebl/blapi.h
@@ -1464,16 +1464,22 @@ FIPS186Change_GenerateX(unsigned char *X
  *        q, DSA_SUBPRIME_LEN bytes
  * Output: xj, DSA_SUBPRIME_LEN bytes
  */
 extern SECStatus
 FIPS186Change_ReduceModQForDSA(const unsigned char *w,
                                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.
  */
 extern SECStatus
 PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len,
                      const PRUint8 *nonce, unsigned int nonce_len,
                      const PRUint8 *personal_string, unsigned int ps_len);
--- a/security/nss/lib/freebl/drbg.c
+++ b/security/nss/lib/freebl/drbg.c
@@ -94,17 +94,18 @@ struct RNGContextStr {
                                               * save the rest of the rng output for
                                               * another partial block */
     PRUint8 dataAvail;                       /* # bytes of output available in our cache,
                                               * [0...SHA256_LENGTH] */
     /* store additional data that has been shovelled off to us by
      * 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;
 static RNGContext *globalrng = NULL;
 static RNGContext theGlobalRng;
 
 /*
  * The next several functions are derived from the NIST SP 800-90
@@ -145,27 +146,29 @@ prng_Hash_df(PRUint8 *requested_bytes, u
                    no_of_bytes_to_return);
         requested_bytes += hash_return_len;
         no_of_bytes_to_return -= hash_return_len;
     }
     return SECSuccess;
 }
 
 /*
- * 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.
  */
 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;
     }
     prng_Hash_df(V(rng), VSize(rng), bytes, len, NULL, 0);
     rng->V_type = prngCGenerateType;
     prng_Hash_df(rng->C, sizeof rng->C, rng->V_Data, sizeof rng->V_Data, NULL, 0);
     PRNG_RESET_RESEED_COUNT(rng)
     return SECSuccess;
@@ -267,17 +270,17 @@ prng_reseed_test(RNGContext *rng, const 
             carry += dest[k1] + add[k2];                             \
             dest[k1] = (PRUint8)carry;                               \
             carry >>= 8;                                             \
         }                                                            \
     }
 
 #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
  * of bytes we need for this request. We only use this call if we need more
  * than can be supplied by a single call to SHA256_HashBuf.
  *
  * This function is specified in NIST SP 800-90 section 10.1.1.4, Hashgen
  */
@@ -436,16 +439,17 @@ rng_init(void)
             return PR_FAILURE;
         }
 
         if (rv != SECSuccess) {
             return PR_FAILURE;
         }
         /* 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. */
         prng_generateNewBytes(globalrng, bytes, SHA256_LENGTH, NULL, 0);
 
         /* Fetch more entropy into the PRNG */
         RNG_SystemInfoForRNG();
     }
@@ -691,16 +695,27 @@ RNG_RNGShutdown(void)
 /*
  * Test case interface. used by fips testing and power on self test
  */
 /* make sure the test context is separate from the global context, This
   * allows us to test the internal random number generator without losing
   * 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.
  */
 SECStatus
 PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len,
                      const PRUint8 *nonce, unsigned int nonce_len,
                      const PRUint8 *personal_string, unsigned int ps_len)
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -17,20 +17,20 @@
 
 /*
  * NSS's major version, minor version, patch level, build number, and whether
  * this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define NSS_VERSION "3.28.3" _NSS_CUSTOMIZED
+#define NSS_VERSION "3.28.4" _NSS_CUSTOMIZED
 #define NSS_VMAJOR 3
 #define NSS_VMINOR 28
-#define NSS_VPATCH 3
+#define NSS_VPATCH 4
 #define NSS_VBUILD 0
 #define NSS_BETA PR_FALSE
 
 #ifndef RC_INVOKED
 
 #include "seccomon.h"
 
 typedef struct NSSInitParametersStr NSSInitParameters;
--- a/security/nss/lib/softoken/softkver.h
+++ b/security/nss/lib/softoken/softkver.h
@@ -16,16 +16,16 @@
 
 /*
  * Softoken's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define SOFTOKEN_VERSION "3.28.3" SOFTOKEN_ECC_STRING
+#define SOFTOKEN_VERSION "3.28.4" SOFTOKEN_ECC_STRING
 #define SOFTOKEN_VMAJOR 3
 #define SOFTOKEN_VMINOR 28
-#define SOFTOKEN_VPATCH 3
+#define SOFTOKEN_VPATCH 4
 #define SOFTOKEN_VBUILD 0
 #define SOFTOKEN_BETA PR_FALSE
 
 #endif /* _SOFTKVER_H_ */
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -13289,18 +13289,16 @@ ssl3_DestroySSL3Info(sslSocket *ss)
     if (ss->ssl3.hs.exporterSecret)
         PK11_FreeSymKey(ss->ssl3.hs.exporterSecret);
 
     ss->ssl3.hs.zeroRttState = ssl_0rtt_none;
     /* Destroy TLS 1.3 buffered early data. */
     tls13_DestroyEarlyData(&ss->ssl3.hs.bufferedEarlyData);
 
     ss->ssl3.initialized = PR_FALSE;
-
-    SECITEM_FreeItem(&ss->xtnData.nextProto, PR_FALSE);
 }
 
 #define MAP_NULL(x) (((x) != 0) ? (x) : SEC_OID_NULL_CIPHER)
 
 SECStatus
 ssl3_ApplyNSSPolicy(void)
 {
     unsigned i;
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -3699,28 +3699,28 @@ ssl_NewSocket(PRBool makeLocks, SSLProto
     for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
         ss->namedGroupPreferences[i] = &ssl_named_groups[i];
     }
     ss->additionalShares = 0;
     PR_INIT_CLIST(&ss->ssl3.hs.remoteExtensions);
     PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight);
     PR_INIT_CLIST(&ss->ssl3.hs.cipherSpecs);
     PR_INIT_CLIST(&ss->ssl3.hs.bufferedEarlyData);
+    ssl3_InitExtensionData(&ss->xtnData);
     if (makeLocks) {
         rv = ssl_MakeLocks(ss);
         if (rv != SECSuccess)
             goto loser;
     }
     rv = ssl_CreateSecurityInfo(ss);
     if (rv != SECSuccess)
         goto loser;
     rv = ssl3_InitGather(&ss->gs);
     if (rv != SECSuccess)
         goto loser;
-    ssl3_InitExtensionData(&ss->xtnData);
     return ss;
 
 loser:
     ssl_DestroySocketContents(ss);
     ssl_DestroyLocks(ss);
     PORT_Free(ss);
     return NULL;
 }
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -2848,16 +2848,19 @@ tls13_DestroyKeyShareEntry(TLS13KeyShare
     PORT_ZFree(offer, sizeof(*offer));
 }
 
 void
 tls13_DestroyKeyShares(PRCList *list)
 {
     PRCList *cur_p;
 
+    /* The list must be initialized. */
+    PORT_Assert(PR_LIST_HEAD(list));
+
     while (!PR_CLIST_IS_EMPTY(list)) {
         cur_p = PR_LIST_TAIL(list);
         PR_REMOVE_LINK(cur_p);
         tls13_DestroyKeyShareEntry((TLS13KeyShareEntry *)cur_p);
     }
 }
 
 void
--- a/security/nss/lib/util/nssb64d.c
+++ b/security/nss/lib/util/nssb64d.c
@@ -365,17 +365,17 @@ pl_base64_decode_flush(PLBase64Decoder *
 
 /*
  * The maximum space needed to hold the output of the decoder given
  * input data of length "size".
  */
 static PRUint32
 PL_Base64MaxDecodedLength(PRUint32 size)
 {
-    return ((size * 3) / 4);
+    return size * 0.75;
 }
 
 /*
  * A distinct internal creation function for the buffer version to use.
  * (It does not want to specify an output_fn, and we want the normal
  * Create function to require that.)  If more common initialization
  * of the decoding context needs to be done, it should be done *here*.
  */
--- a/security/nss/lib/util/nssb64e.c
+++ b/security/nss/lib/util/nssb64e.c
@@ -277,30 +277,38 @@ pl_base64_encode_flush(PLBase64Encoder *
  * line_length bytes (we will add it at nearest lower multiple of 4).
  * There is no trailing CRLF.
  */
 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)
+    if (line_length == 0) {
         return tokens * 4;
+    }
 
-    if (line_length < 4) /* too small! */
+    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)
+    if (remainder == 0) {
         line_break_chars -= 2;
+    }
 
     return (full_lines * tokens_per_line * 4) + line_break_chars + remainder;
 }
 
 /*
  * A distinct internal creation function for the buffer version to use.
  * (It does not want to specify an output_fn, and we want the normal
  * Create function to require that.)  All common initialization of the
@@ -442,23 +450,28 @@ PL_Base64EncodeBuffer(const unsigned cha
                       PRUint32 line_length, char *dest, PRUint32 maxdestlen,
                       PRUint32 *output_destlen)
 {
     PRUint32 need_length;
     PLBase64Encoder *data = NULL;
     PRStatus status;
 
     PR_ASSERT(srclen > 0);
-    if (srclen == 0)
+    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.
      */
     if (dest != NULL) {
         PR_ASSERT(maxdestlen >= need_length);
         if (maxdestlen < need_length) {
             PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
@@ -626,16 +639,20 @@ NSSBase64_EncodeItem(PLArenaPool *arenaO
 
     PORT_Assert(inItem != NULL && inItem->data != NULL && inItem->len != 0);
     if (inItem == NULL || inItem->data == NULL || inItem->len == 0) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return NULL;
     }
 
     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);
 
     if (out_string == NULL) {
         if (arenaOpt != NULL)
             out_string = PORT_ArenaAlloc(arenaOpt, max_out_len + 1);
         else
--- a/security/nss/lib/util/nssutil.h
+++ b/security/nss/lib/util/nssutil.h
@@ -14,20 +14,20 @@
 
 /*
  * NSS utilities's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
  */
-#define NSSUTIL_VERSION "3.28.3"
+#define NSSUTIL_VERSION "3.28.4"
 #define NSSUTIL_VMAJOR 3
 #define NSSUTIL_VMINOR 28
-#define NSSUTIL_VPATCH 3
+#define NSSUTIL_VPATCH 4
 #define NSSUTIL_VBUILD 0
 #define NSSUTIL_BETA PR_FALSE
 
 SEC_BEGIN_PROTOS
 
 /*
  * Returns a const string of the UTIL library version.
  */