Bug 1305970 - land NSS 0x295feaebef58, r=me
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Tue, 11 Oct 2016 14:33:41 +0200
changeset 317426 ce857155a4ee9cfcfa01ea736a1af711bd55ba0d
parent 317425 ffcf738fc20023b939afec0ced3be7b209573155
child 317427 c01dab3fd04152bb1a0b589c7a149dd6b17dccc7
push id82645
push userfranziskuskiefer@gmail.com
push dateTue, 11 Oct 2016 12:50:41 +0000
treeherdermozilla-inbound@ce857155a4ee [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1305970
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1305970 - land NSS 0x295feaebef58, r=me
security/nss/TAG-INFO
security/nss/automation/taskcluster/graph/src/context_hash.js
security/nss/automation/taskcluster/graph/src/image_builder.js
security/nss/automation/taskcluster/scripts/build.sh
security/nss/automation/taskcluster/scripts/run_scan_build.sh
security/nss/automation/taskcluster/scripts/run_tests.sh
security/nss/coreconf/arch.mk
security/nss/coreconf/coreconf.dep
security/nss/external_tests/der_gtest/der_private_key_import_unittest.cc
security/nss/external_tests/der_gtest/manifest.mn
security/nss/external_tests/ssl_gtest/ssl_agent_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_auth_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_hrr_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_version_unittest.cc
security/nss/lib/freebl/blapii.h
security/nss/lib/freebl/camellia.c
security/nss/lib/freebl/chacha20_vec.c
security/nss/lib/freebl/des.c
security/nss/lib/freebl/desblapi.c
security/nss/lib/freebl/ecl/curve25519_64.c
security/nss/lib/freebl/ecl/ecl-priv.h
security/nss/lib/freebl/md5.c
security/nss/lib/freebl/poly1305-donna-x64-sse2-incremental-source.c
security/nss/lib/freebl/sha_fast.c
security/nss/lib/freebl/sha_fast.h
security/nss/lib/pk11wrap/pk11pk12.c
security/nss/lib/ssl/dtlscon.c
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3ecc.c
security/nss/lib/ssl/ssl3ext.c
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/sslproto.h
security/nss/lib/ssl/tls13con.c
security/nss/lib/ssl/tls13con.h
security/nss/lib/util/secasn1d.c
security/nss/lib/util/secasn1e.c
security/nss/lib/util/utilpars.c
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-6b3812492e71
+295feaebef58
--- a/security/nss/automation/taskcluster/graph/src/context_hash.js
+++ b/security/nss/automation/taskcluster/graph/src/context_hash.js
@@ -31,10 +31,13 @@ function collectFilesInDirectory(dir) {
 export default function (context_path) {
   let root = path.join(__dirname, "../../../..");
   let dir = path.join(root, context_path);
   let files = collectFilesInDirectory(dir).sort();
   let hashes = files.map(file => {
     return sha256(file + "|" + fs.readFileSync(file, "utf-8"));
   });
 
-  return sha256(hashes.join(","));
+  // Generate a new prefix every month to ensure the image stays buildable.
+  let now = new Date();
+  let prefix = `${now.getUTCFullYear()}-${now.getUTCMonth() + 1}:`;
+  return sha256(prefix + hashes.join(","));
 }
--- a/security/nss/automation/taskcluster/graph/src/image_builder.js
+++ b/security/nss/automation/taskcluster/graph/src/image_builder.js
@@ -40,17 +40,17 @@ export async function buildTask({name, p
       HEAD_REF: process.env.NSS_HEAD_REVISION,
       PROJECT: process.env.TC_PROJECT,
       CONTEXT_PATH: path,
       HASH: hash
     },
     artifacts: {
       "public/image.tar": {
         type: "file",
-        expires: 24 * 365,
+        expires: 24 * 90,
         path: "/artifacts/image.tar"
       }
     },
     command: [
       "/bin/bash",
       "-c",
       "/home/worker/bin/build_image.sh"
     ],
--- a/security/nss/automation/taskcluster/scripts/build.sh
+++ b/security/nss/automation/taskcluster/scripts/build.sh
@@ -1,12 +1,10 @@
 #!/usr/bin/env bash
 
-set -v -e -x
-
 source $(dirname $0)/tools.sh
 
 if [[ $(id -u) -eq 0 ]]; then
     # Set compiler.
     switch_compilers
 
     # Drop privileges by re-running this script.
     exec su worker $0
--- a/security/nss/automation/taskcluster/scripts/run_scan_build.sh
+++ b/security/nss/automation/taskcluster/scripts/run_scan_build.sh
@@ -1,51 +1,52 @@
 #!/usr/bin/env bash
 
-set -v -e -x
+source $(dirname $0)/tools.sh
 
 if [ $(id -u) = 0 ]; then
-    source $(dirname $0)/tools.sh
 
     # Set compiler.
     switch_compilers
 
     # Drop privileges by re-running this script.
     exec su worker $0 $@
 fi
 
 # Clone NSPR if needed.
 if [ ! -d "nspr" ]; then
-    hg clone https://hg.mozilla.org/projects/nspr
+    hg_clone https://hg.mozilla.org/projects/nspr nspr default
 fi
 
 # Build.
-cd nss && make nss_build_all
+cd nss
+make nss_build_all
 
-# we run scan-build on these folders
-declare -a scan=("lib/ssl" "lib/freebl")
-# corresponds to the number of errors that are expected in the |scan| folder
-declare -a ignore=(0 0)
+# What we want to scan.
+# key: directory to scan
+# value: number of errors expected in that directory
+declare -A scan=( \
+        [lib/ssl]=0 \
+        [lib/freebl]=0 \
+        [lib/util]=0 \
+    )
 
-for i in "${scan[@]}"
-do
-   echo "cleaning $i ..."
-   find "$i" -name "*.OBJ" | xargs rm -fr
+# remove .OBJ directories to force a rebuild of just the select few
+for i in "${!scan[@]}"; do
+   find "$i" -name "*.OBJ" -exec rm -rf {} \+
 done
 
-# run scan-build
-scan-build -o /home/worker/artifacts/ make nss_build_all && cd ..
+# run scan-build (only building affected directories)
+scan-build -o /home/worker/artifacts make nss_build_all && cd ..
 
 # print errors we found
 set +v +x
 STATUS=0
-for i in "${!scan[@]}"
-do
-   n=$(grep -Rn "${scan[i]}" /home/worker/artifacts/*/report-*.html | wc -l)
-   if [ $n -ne ${ignore[$i]} ]; then
+for i in "${!scan[@]}"; do
+   n=$(grep -Rn "$i" /home/worker/artifacts/*/report-*.html | wc -l)
+   if [ $n -ne ${scan[$i]} ]; then
      STATUS=1
-     echo "$(date '+%T') WARNING - TEST-UNEXPECTED-FAIL: ${scan[$i]} contains $n scan-build errors"
+     echo "$(date '+%T') WARNING - TEST-UNEXPECTED-FAIL: $i contains $n scan-build errors"
    elif [ $n -ne 0 ]; then
-     echo "$(date '+%T') WARNING - TEST-UNEXPECTED-FAIL: ${scan[$i]} contains $n scan-build errors (nonfatal!)"
+     echo "$(date '+%T') WARNING - TEST-EXPECTED-FAIL: $i contains $n scan-build errors"
    fi
-
 done
 exit $STATUS
--- a/security/nss/automation/taskcluster/scripts/run_tests.sh
+++ b/security/nss/automation/taskcluster/scripts/run_tests.sh
@@ -1,12 +1,10 @@
 #!/usr/bin/env bash
 
-set -v -e -x
-
 source $(dirname $0)/tools.sh
 
 if [ $(id -u) = 0 ]; then
     # Set compiler.
     switch_compilers
 
     # Stupid Docker.
     echo "127.0.0.1 localhost.localdomain" >> /etc/hosts
--- a/security/nss/coreconf/arch.mk
+++ b/security/nss/coreconf/arch.mk
@@ -1,38 +1,30 @@
 #
 # 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/.
 
 #######################################################################
 # Master "Core Components" macros for getting the OS architecture     #
 # defines these symbols:
-# 64BIT_TAG
 # OS_ARCH	(from uname -r)
 # OS_TEST	(from uname -m)
 # OS_RELEASE	(from uname -v and/or -r)
 # OS_TARGET	User defined, or set to OS_ARCH
 # CPU_ARCH  	(from unmame -m or -p, ONLY on WINNT)
 # OS_CONFIG	OS_TARGET + OS_RELEASE
-# ASAN_TAG
-# OBJDIR_TAG
+# OBJDIR_TAG    (uses ASAN_TAG, GCOV_TAG, 64BIT_TAG)
 # OBJDIR_NAME
 #######################################################################
 
 #
 # Macros for getting the OS architecture
 #
 
-ifeq ($(USE_64), 1)
-	64BIT_TAG=_64
-else
-	64BIT_TAG=
-endif
-
 OS_ARCH := $(subst /,_,$(shell uname -s))
 
 #
 # Attempt to differentiate between sparc and x86 Solaris
 #
 
 OS_TEST := $(shell uname -m)
 ifeq ($(OS_TEST),i86pc)
@@ -253,65 +245,70 @@ endif
 
 #
 # This variable is used to get OS_CONFIG.mk.
 #
 
 OS_CONFIG = $(OS_TARGET)$(OS_RELEASE)
 
 #
-# Set Address Sanitizer prefix.
+# OBJDIR_TAG depends on the predefined variable BUILD_OPT,
+# to distinguish between debug and release builds.
 #
 
 ifeq ($(USE_ASAN), 1)
     ASAN_TAG = _ASAN
 else
     ASAN_TAG =
 endif
-
-#
-# OBJDIR_TAG depends on the predefined variable BUILD_OPT,
-# to distinguish between debug and release builds.
-#
+ifeq ($(USE_GCOV), 1)
+    GCOV_TAG = _GCOV
+else
+    GCOV_TAG =
+endif
+ifeq ($(USE_64), 1)
+    64BIT_TAG = _64
+else
+    64BIT_TAG =
+endif
+OBJDIR_TAG_BASE=$(ASAN_TAG)$(GCOV_TAG)$(64BIT_TAG)
 
 ifdef BUILD_OPT
-    OBJDIR_TAG = $(64BIT_TAG)$(ASAN_TAG)_OPT
+    OBJDIR_TAG = $(OBJDIR_TAG_BASE)_OPT
 else
     ifdef BUILD_IDG
-	OBJDIR_TAG = $(64BIT_TAG)$(ASAN_TAG)_IDG
+	OBJDIR_TAG = $(OBJDIR_TAG_BASE)_IDG
     else
-	OBJDIR_TAG = $(64BIT_TAG)$(ASAN_TAG)_DBG
+	OBJDIR_TAG = $(OBJDIR_TAG_BASE)_DBG
     endif
 endif
 
 #
 # The following flags are defined in the individual $(OS_CONFIG).mk
 # files.
 #
 # CPU_TAG is defined if the CPU is not the most common CPU.
 # COMPILER_TAG is defined if the compiler is not the default compiler.
 # IMPL_STRATEGY may be defined too.
 #
 
 ifdef CROSS_COMPILE
-OBJDIR_NAME = $(OS_TARGET)$(OS_RELEASE)$(CPU_TAG)$(LIBC_TAG)$(IMPL_STRATEGY)$(OBJDIR_TAG).OBJ
+    OBJDIR_NAME_COMPILER =
 else
-OBJDIR_NAME = $(OS_TARGET)$(OS_RELEASE)$(CPU_TAG)$(COMPILER_TAG)$(LIBC_TAG)$(IMPL_STRATEGY)$(OBJDIR_TAG).OBJ
+    OBJDIR_NAME_COMPILER = $(COMPILER_TAG)
 endif
+OBJDIR_NAME_BASE = $(OS_TARGET)$(OS_RELEASE)$(CPU_TAG)$(OBJDIR_NAME_COMPILER)$(LIBC_TAG)$(IMPL_STRATEGY)$(OBJDIR_TAG)
+OBJDIR_NAME = $(OBJDIR_NAME_BASE).OBJ
 
 
 ifeq (,$(filter-out WIN%,$(OS_TARGET)))
 ifndef BUILD_OPT
 #
 # Define USE_DEBUG_RTL if you want to use the debug runtime library
 # (RTL) in the debug build
 #
 ifdef USE_DEBUG_RTL
-    ifdef CROSS_COMPILE
-    OBJDIR_NAME = $(OS_TARGET)$(OS_RELEASE)$(CPU_TAG)$(IMPL_STRATEGY)$(OBJDIR_TAG).OBJD
-    else
-    OBJDIR_NAME = $(OS_TARGET)$(OS_RELEASE)$(CPU_TAG)$(COMPILER_TAG)$(IMPL_STRATEGY)$(OBJDIR_TAG).OBJD
-    endif
+    OBJDIR_NAME = $(OBJDIR_NAME_BASE).OBJD
 endif
 endif
 endif
 
 MK_ARCH = included
--- 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."
-
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/der_gtest/der_private_key_import_unittest.cc
@@ -0,0 +1,110 @@
+/* -*- 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 "nss.h"
+#include "pk11pub.h"
+#include "secutil.h"
+
+#include "gtest/gtest.h"
+#include "scoped_ptrs.h"
+
+namespace nss_test {
+
+const std::vector<uint8_t> kValidRSAKey = {
+    // 512-bit RSA private key (PKCS#8)
+    0x30, 0x82, 0x01, 0x54, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+    0x01, 0x3e, 0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
+    0xa2, 0x40, 0xce, 0xb5, 0x4e, 0x70, 0xdc, 0x14, 0x82, 0x5b, 0x58, 0x7d,
+    0x2f, 0x5d, 0xfd, 0x46, 0x3c, 0x4b, 0x82, 0x50, 0xb6, 0x96, 0x00, 0x4a,
+    0x1a, 0xca, 0xaf, 0xe4, 0x9b, 0xcf, 0x38, 0x4a, 0x46, 0xaa, 0x9f, 0xb4,
+    0xd9, 0xc7, 0xee, 0x88, 0xe9, 0xef, 0x0a, 0x31, 0x5f, 0x53, 0x86, 0x8f,
+    0x63, 0x68, 0x0b, 0x58, 0x34, 0x72, 0x49, 0xba, 0xed, 0xd9, 0x34, 0x15,
+    0x16, 0xc4, 0xca, 0xb7, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x34,
+    0xe6, 0xdc, 0x7e, 0xd0, 0xec, 0x8b, 0x55, 0x44, 0x8b, 0x73, 0xf6, 0x9d,
+    0x13, 0x10, 0x19, 0x6e, 0x5f, 0x50, 0x45, 0xf0, 0xc2, 0x47, 0xa5, 0xe1,
+    0xc6, 0x64, 0x43, 0x2d, 0x6a, 0x0a, 0xf7, 0xe7, 0xda, 0x40, 0xb8, 0x3a,
+    0xf0, 0x47, 0xdd, 0x01, 0xf5, 0xe0, 0xa9, 0x0e, 0x47, 0xc2, 0x24, 0xd7,
+    0xb5, 0x13, 0x3a, 0x35, 0x4d, 0x11, 0xaa, 0x50, 0x03, 0xb3, 0xe8, 0x54,
+    0x6c, 0x99, 0x01, 0x02, 0x21, 0x00, 0xcd, 0xb2, 0xd7, 0xa7, 0x43, 0x5b,
+    0xcb, 0x45, 0xe5, 0x0e, 0x86, 0xf6, 0xc1, 0x4e, 0x97, 0xed, 0x78, 0x1f,
+    0x09, 0x56, 0xcd, 0x26, 0xe6, 0xf7, 0x5e, 0xd9, 0xfc, 0x88, 0x12, 0x5f,
+    0x84, 0x07, 0x02, 0x21, 0x00, 0xc9, 0xee, 0x30, 0xaf, 0x6c, 0xb9, 0x5a,
+    0xc9, 0xc1, 0x14, 0x9e, 0xd8, 0x4b, 0x33, 0x38, 0x48, 0x17, 0x41, 0x35,
+    0x94, 0x09, 0xf3, 0x69, 0xc4, 0x97, 0xbe, 0x17, 0x7d, 0x95, 0x0f, 0xb7,
+    0xd1, 0x02, 0x21, 0x00, 0x8b, 0x0e, 0xf9, 0x8d, 0x61, 0x13, 0x20, 0x63,
+    0x9b, 0x0b, 0x6c, 0x20, 0x4a, 0xe4, 0xa7, 0xfe, 0xe8, 0xf3, 0x0a, 0x6c,
+    0x3c, 0xfa, 0xac, 0xaf, 0xd4, 0xd6, 0xc7, 0x4a, 0xf2, 0x28, 0xd2, 0x67,
+    0x02, 0x20, 0x6b, 0x0e, 0x1d, 0xbf, 0x93, 0x5b, 0xbd, 0x77, 0x43, 0x27,
+    0x24, 0x83, 0xb5, 0x72, 0xa5, 0x3f, 0x0b, 0x1d, 0x26, 0x43, 0xa2, 0xf6,
+    0xea, 0xb7, 0x30, 0x5f, 0xb6, 0x62, 0x7c, 0xf9, 0x85, 0x51, 0x02, 0x20,
+    0x3d, 0x22, 0x63, 0x15, 0x6b, 0x32, 0x41, 0x46, 0x44, 0x78, 0xb7, 0x13,
+    0xeb, 0x85, 0x4c, 0x4f, 0x6b, 0x3e, 0xf0, 0x52, 0xf0, 0x46, 0x3b, 0x65,
+    0xd8, 0x21, 0x7d, 0xae, 0xc0, 0x09, 0x98, 0x34};
+
+const std::vector<uint8_t> kInvalidLengthKey = {
+    0x30, 0x1b,        // SEQUENCE(len=27)
+    0x02, 0x01, 0x00,  // INT(len=1) = 0
+    0x30, 0x13,        // SEQUENCE(len=19)
+    0x06, 0x07,        // OID(len=7)
+    // dhPublicKey (1.2.840.10046.2.1)
+    0x2a, 0x86, 0x48, 0xce, 0x3e, 0x02, 0x01, 0x06, 0x08,  // OID(len=8)
+    // prime256v1 (1.2.840.10045.3.1.7) */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x04,
+    0x00  // OCTET STRING(len=0)
+};
+
+const std::vector<uint8_t> kInvalidZeroLengthKey = {
+    0x30, 0x1a,        // SEQUENCE(len=26)
+    0x02, 0x01, 0x00,  // INT(len=1) = 0
+    0x30, 0x13,        // SEQUENCE(len=19)
+    0x06, 0x07,        // OID(len=7)
+    // dhPublicKey (1.2.840.10046.2.1)
+    0x2a, 0x86, 0x48, 0xce, 0x3e, 0x02, 0x01, 0x06, 0x08,  // OID(len=8)
+    // prime256v1 (1.2.840.10045.3.1.7) */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x04,
+    0x00  // OCTET STRING(len=0)
+};
+
+class DERPrivateKeyImportTest : public ::testing::Test {
+ public:
+  bool ParsePrivateKey(const std::vector<uint8_t>& data) {
+    ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
+    EXPECT_TRUE(slot);
+
+    SECKEYPrivateKey* key = nullptr;
+    SECItem item = {siBuffer, const_cast<unsigned char*>(data.data()),
+                    (unsigned int)data.size()};
+
+    SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
+        slot.get(), &item, nullptr, nullptr, false, false, KU_ALL, &key,
+        nullptr);
+
+    EXPECT_EQ(rv == SECSuccess, key != nullptr);
+    SECKEY_DestroyPrivateKey(key);
+
+    return rv == SECSuccess;
+  }
+};
+
+TEST_F(DERPrivateKeyImportTest, ImportPrivateRSAKey) {
+  EXPECT_TRUE(ParsePrivateKey(kValidRSAKey));
+  EXPECT_FALSE(PORT_GetError());
+}
+
+TEST_F(DERPrivateKeyImportTest, ImportInvalidPrivateKey) {
+  EXPECT_FALSE(ParsePrivateKey(kInvalidLengthKey));
+  EXPECT_EQ(PORT_GetError(), SEC_ERROR_BAD_DER);
+}
+
+TEST_F(DERPrivateKeyImportTest, ImportZeroLengthPrivateKey) {
+  EXPECT_FALSE(ParsePrivateKey(kInvalidZeroLengthKey));
+  EXPECT_EQ(PORT_GetError(), SEC_ERROR_BAD_KEY);
+}
+
+}  // namespace nss_test
--- a/security/nss/external_tests/der_gtest/manifest.mn
+++ b/security/nss/external_tests/der_gtest/manifest.mn
@@ -3,16 +3,17 @@
 # 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 = \
       der_getint_unittest.cc \
+      der_private_key_import_unittest.cc \
       $(NULL)
 
 INCLUDES += -I$(CORE_DEPTH)/external_tests/google_test/gtest/include \
             -I$(CORE_DEPTH)/external_tests/common
 
 REQUIRES = nspr nss libdbm gtest
 
 PROGRAM = der_gtest
--- a/security/nss/external_tests/ssl_gtest/ssl_agent_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_agent_unittest.cc
@@ -3,49 +3,53 @@
 /* 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 "ssl.h"
 #include "sslerr.h"
 #include "sslproto.h"
 
+// This is an internal header, used to get TLS_1_3_DRAFT_VERSION.
+#include "ssl3prot.h"
+
 #include <memory>
 
 #include "databuffer.h"
 #include "tls_agent.h"
 #include "tls_connect.h"
 #include "tls_filter.h"
 #include "tls_parser.h"
 
 namespace nss_test {
 
+static const uint8_t kD13 = TLS_1_3_DRAFT_VERSION;
 // This is a 1-RTT ClientHello with ECDHE.
 const static uint8_t kCannedTls13ClientHello[] = {
     0x01, 0x00, 0x00, 0xcf, 0x03, 0x03, 0x6c, 0xb3, 0x46, 0x81, 0xc8, 0x1a,
     0xf9, 0xd2, 0x05, 0x97, 0x48, 0x7c, 0xa8, 0x31, 0x03, 0x1c, 0x06, 0xa8,
     0x62, 0xb1, 0x90, 0xd6, 0x21, 0x44, 0x7f, 0xc1, 0x9b, 0x87, 0x3e, 0xad,
     0x91, 0x85, 0x00, 0x00, 0x06, 0x13, 0x01, 0x13, 0x03, 0x13, 0x02, 0x01,
     0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x00, 0x06,
     0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00,
     0x0a, 0x00, 0x12, 0x00, 0x10, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x01,
     0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, 0x01, 0x04, 0x00, 0x28, 0x00,
     0x47, 0x00, 0x45, 0x00, 0x17, 0x00, 0x41, 0x04, 0x86, 0x4a, 0xb9, 0xdc,
     0x6a, 0x38, 0xa7, 0xce, 0xe7, 0xc2, 0x4f, 0xa6, 0x28, 0xb9, 0xdc, 0x65,
     0xbf, 0x73, 0x47, 0x3c, 0x9c, 0x65, 0x8c, 0x47, 0x6d, 0x57, 0x22, 0x8a,
     0xc2, 0xb3, 0xc6, 0x80, 0x72, 0x86, 0x08, 0x86, 0x8f, 0x52, 0xc5, 0xcb,
     0xbf, 0x2a, 0xb5, 0x59, 0x64, 0xcc, 0x0c, 0x49, 0x95, 0x36, 0xe4, 0xd9,
     0x2f, 0xd4, 0x24, 0x66, 0x71, 0x6f, 0x5d, 0x70, 0xe2, 0xa0, 0xea, 0x26,
-    0x00, 0x2b, 0x00, 0x03, 0x02, 0x7f, 0x10, 0x00, 0x0d, 0x00, 0x20, 0x00,
+    0x00, 0x2b, 0x00, 0x03, 0x02, 0x7f, kD13, 0x00, 0x0d, 0x00, 0x20, 0x00,
     0x1e, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02, 0x03, 0x08, 0x04, 0x08,
     0x05, 0x08, 0x06, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x01, 0x04,
     0x02, 0x05, 0x02, 0x06, 0x02, 0x02, 0x02};
 
 const static uint8_t kCannedTls13ServerHello[] = {
-    0x03, 0x04, 0x21, 0x12, 0xa7, 0xa7, 0x0d, 0x85, 0x8b, 0xb8, 0x0c, 0xbb,
+    0x7f, kD13, 0x21, 0x12, 0xa7, 0xa7, 0x0d, 0x85, 0x8b, 0xb8, 0x0c, 0xbb,
     0xdc, 0xa6, 0xfd, 0x97, 0xfe, 0x31, 0x26, 0x49, 0x2d, 0xa8, 0x6c, 0x7b,
     0x65, 0x30, 0x71, 0x00, 0x31, 0x03, 0x2b, 0x94, 0xe2, 0x16, 0x13, 0x01,
     0x00, 0x4d, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x28, 0x00, 0x45, 0x00, 0x17,
     0x00, 0x41, 0x04, 0x10, 0x97, 0x3d, 0x7a, 0xcf, 0xa2, 0x34, 0xe3, 0x69,
     0xc4, 0xdd, 0x1e, 0xf2, 0xd6, 0xc0, 0x9a, 0x3e, 0xf5, 0x41, 0xf3, 0x03,
     0x23, 0x94, 0xd2, 0x31, 0x85, 0xb7, 0xae, 0x5d, 0xfa, 0xc6, 0x9a, 0xd0,
     0xa5, 0x44, 0xa3, 0x3a, 0xe0, 0xbb, 0x61, 0xaa, 0x0a, 0x6f, 0xe8, 0xaf,
     0xdf, 0x86, 0xd8, 0x48, 0x36, 0x9c, 0x19, 0x70, 0x55, 0x84, 0xb0, 0x1c,
@@ -66,104 +70,85 @@ TEST_P(TlsAgentTest, EarlyCertificateVer
                  SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY);
 }
 
 TEST_P(TlsAgentTestClient, CannedHello) {
   DataBuffer buffer;
   EnsureInit();
   agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3,
                           SSL_LIBRARY_VERSION_TLS_1_3);
-  DataBuffer server_hello_inner(kCannedTls13ServerHello,
-                                sizeof(kCannedTls13ServerHello));
-  uint16_t wire_version =
-      mode_ == STREAM ? SSL_LIBRARY_VERSION_TLS_1_3
-                      : TlsVersionToDtlsVersion(SSL_LIBRARY_VERSION_TLS_1_3);
-  server_hello_inner.Write(0, wire_version, 2);
   DataBuffer server_hello;
-  MakeHandshakeMessage(kTlsHandshakeServerHello, server_hello_inner.data(),
-                       server_hello_inner.len(), &server_hello);
+  MakeHandshakeMessage(kTlsHandshakeServerHello, kCannedTls13ServerHello,
+                       sizeof(kCannedTls13ServerHello), &server_hello);
   MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
              server_hello.data(), server_hello.len(), &buffer);
   ProcessMessage(buffer, TlsAgent::STATE_CONNECTING);
 }
 
 TEST_P(TlsAgentTestClient, EncryptedExtensionsInClear) {
-  DataBuffer buffer;
-  DataBuffer server_hello_inner(kCannedTls13ServerHello,
-                                sizeof(kCannedTls13ServerHello));
-  server_hello_inner.Write(
-      0, mode_ == STREAM ? SSL_LIBRARY_VERSION_TLS_1_3
-                         : TlsVersionToDtlsVersion(SSL_LIBRARY_VERSION_TLS_1_3),
-      2);
   DataBuffer server_hello;
-  MakeHandshakeMessage(kTlsHandshakeServerHello, server_hello_inner.data(),
-                       server_hello_inner.len(), &server_hello);
+  MakeHandshakeMessage(kTlsHandshakeServerHello, kCannedTls13ServerHello,
+                       sizeof(kCannedTls13ServerHello), &server_hello);
   DataBuffer encrypted_extensions;
   MakeHandshakeMessage(kTlsHandshakeEncryptedExtensions, nullptr, 0,
                        &encrypted_extensions, 1);
   server_hello.Append(encrypted_extensions);
+  DataBuffer buffer;
   MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
              server_hello.data(), server_hello.len(), &buffer);
   EnsureInit();
   agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3,
                           SSL_LIBRARY_VERSION_TLS_1_3);
   ProcessMessage(buffer, TlsAgent::STATE_ERROR,
                  SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
 }
 
 TEST_F(TlsAgentStreamTestClient, EncryptedExtensionsInClearTwoPieces) {
-  DataBuffer buffer;
-  DataBuffer buffer2;
-  DataBuffer server_hello_inner(kCannedTls13ServerHello,
-                                sizeof(kCannedTls13ServerHello));
-  server_hello_inner.Write(0, SSL_LIBRARY_VERSION_TLS_1_3, 2);
   DataBuffer server_hello;
-  MakeHandshakeMessage(kTlsHandshakeServerHello, server_hello_inner.data(),
-                       server_hello_inner.len(), &server_hello);
+  MakeHandshakeMessage(kTlsHandshakeServerHello, kCannedTls13ServerHello,
+                       sizeof(kCannedTls13ServerHello), &server_hello);
   DataBuffer encrypted_extensions;
   MakeHandshakeMessage(kTlsHandshakeEncryptedExtensions, nullptr, 0,
                        &encrypted_extensions, 1);
   server_hello.Append(encrypted_extensions);
+  DataBuffer buffer;
   MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
              server_hello.data(), 20, &buffer);
 
+  DataBuffer buffer2;
   MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
              server_hello.data() + 20, server_hello.len() - 20, &buffer2);
 
   EnsureInit();
   agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3,
                           SSL_LIBRARY_VERSION_TLS_1_3);
   ProcessMessage(buffer, TlsAgent::STATE_CONNECTING);
   ProcessMessage(buffer2, TlsAgent::STATE_ERROR,
                  SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
 }
 
 TEST_F(TlsAgentDgramTestClient, EncryptedExtensionsInClearTwoPieces) {
-  DataBuffer buffer;
-  DataBuffer buffer2;
-  DataBuffer server_hello_inner(kCannedTls13ServerHello,
-                                sizeof(kCannedTls13ServerHello));
-  server_hello_inner.Write(
-      0, TlsVersionToDtlsVersion(SSL_LIBRARY_VERSION_TLS_1_3), 2);
   DataBuffer server_hello_frag1;
   MakeHandshakeMessageFragment(
-      kTlsHandshakeServerHello, server_hello_inner.data(),
-      server_hello_inner.len(), &server_hello_frag1, 0, 0, 20);
+      kTlsHandshakeServerHello, kCannedTls13ServerHello,
+      sizeof(kCannedTls13ServerHello), &server_hello_frag1, 0, 0, 20);
   DataBuffer server_hello_frag2;
-  MakeHandshakeMessageFragment(kTlsHandshakeServerHello,
-                               server_hello_inner.data() + 20,
-                               server_hello_inner.len(), &server_hello_frag2, 0,
-                               20, server_hello_inner.len() - 20);
+  MakeHandshakeMessageFragment(
+      kTlsHandshakeServerHello, kCannedTls13ServerHello + 20,
+      sizeof(kCannedTls13ServerHello), &server_hello_frag2, 0, 20,
+      sizeof(kCannedTls13ServerHello) - 20);
   DataBuffer encrypted_extensions;
   MakeHandshakeMessage(kTlsHandshakeEncryptedExtensions, nullptr, 0,
                        &encrypted_extensions, 1);
   server_hello_frag2.Append(encrypted_extensions);
+  DataBuffer buffer;
   MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
              server_hello_frag1.data(), server_hello_frag1.len(), &buffer);
 
+  DataBuffer buffer2;
   MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
              server_hello_frag2.data(), server_hello_frag2.len(), &buffer2, 1);
 
   EnsureInit();
   agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3,
                           SSL_LIBRARY_VERSION_TLS_1_3);
   ProcessMessage(buffer, TlsAgent::STATE_CONNECTING);
   ProcessMessage(buffer2, TlsAgent::STATE_ERROR,
--- a/security/nss/external_tests/ssl_gtest/ssl_auth_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_auth_unittest.cc
@@ -378,22 +378,25 @@ class BeforeFinished13 : public PacketFi
 
  private:
   TlsAgent* client_;
   TlsAgent* server_;
   VoidFunction before_finished_;
   size_t records_;
 };
 
+static SECStatus AuthCompleteBlock(TlsAgent*, PRBool, PRBool) {
+  return SECWouldBlock;
+}
+
 // This test uses an AuthCertificateCallback that blocks.  A filter is used to
 // split the server's first flight into two pieces.  Before the second piece is
 // processed by the client, SSL_AuthCertificateComplete() is called.
 TEST_F(TlsConnectDatagram13, AuthCompleteBeforeFinished) {
-  client_->SetAuthCertificateCallback(
-      [](TlsAgent*, PRBool, PRBool) -> SECStatus { return SECWouldBlock; });
+  client_->SetAuthCertificateCallback(AuthCompleteBlock);
   server_->SetPacketFilter(new BeforeFinished13(client_, server_, [this]() {
     EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
   }));
   Connect();
 }
 
 static void TriggerAuthComplete(PollTarget* target, Event event) {
   std::cerr << "client: call SSL_AuthCertificateComplete" << std::endl;
@@ -429,18 +432,17 @@ TEST_P(TlsConnectGenericPre13, ClientWri
 
   Connect();
   server_->SendData(10);
   Receive(10);
 }
 
 TEST_P(TlsConnectGenericPre13, AuthCompleteBeforeFinishedWithFalseStart) {
   client_->EnableFalseStart();
-  client_->SetAuthCertificateCallback(
-      [](TlsAgent*, PRBool, PRBool) -> SECStatus { return SECWouldBlock; });
+  client_->SetAuthCertificateCallback(AuthCompleteBlock);
   server_->SetPacketFilter(new BeforeFinished(
       client_, server_,
       []() {
         // Do nothing before CCS
       },
       [this]() {
         EXPECT_FALSE(client_->can_falsestart_hook_called());
         // AuthComplete before Finished still enables false start.
@@ -450,16 +452,84 @@ TEST_P(TlsConnectGenericPre13, AuthCompl
         client_->SendData(10);
       }));
 
   Connect();
   server_->SendData(10);
   Receive(10);
 }
 
+class EnforceNoActivity : public PacketFilter {
+ protected:
+  PacketFilter::Action Filter(const DataBuffer& input,
+                              DataBuffer* output) override {
+    std::cerr << "Unexpected packet: " << input << std::endl;
+    EXPECT_TRUE(false) << "should not send anything";
+    return KEEP;
+  }
+};
+
+// In this test, we want to make sure that the server completes its handshake,
+// but the client does not.  Because the AuthCertificate callback blocks and we
+// never call SSL_AuthCertificateComplete(), the client should never report that
+// it has completed the handshake.  Manually call Handshake(), alternating sides
+// between client and server, until the desired state is reached.
+TEST_P(TlsConnectGenericPre13, AuthCompleteDelayed) {
+  client_->SetAuthCertificateCallback(AuthCompleteBlock);
+
+  server_->StartConnect();
+  client_->StartConnect();
+  client_->Handshake();  // Send ClientHello
+  server_->Handshake();  // Send ServerHello
+  client_->Handshake();  // Send ClientKeyExchange and Finished
+  server_->Handshake();  // Send Finished
+  // The server should now report that it is connected
+  EXPECT_EQ(TlsAgent::STATE_CONNECTED, server_->state());
+
+  // The client should send nothing from here on.
+  client_->SetPacketFilter(new EnforceNoActivity());
+  client_->Handshake();
+  EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state());
+
+  // This should allow the handshake to complete now.
+  EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
+  client_->Handshake();  // Transition to connected
+  EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state());
+  EXPECT_EQ(TlsAgent::STATE_CONNECTED, server_->state());
+
+  // Remove this before closing or the close_notify alert will trigger it.
+  client_->SetPacketFilter(nullptr);
+}
+
+// TLS 1.3 handles a delayed AuthComplete callback differently since the
+// shape of the handshake is different.
+TEST_P(TlsConnectTls13, AuthCompleteDelayed) {
+  client_->SetAuthCertificateCallback(AuthCompleteBlock);
+
+  server_->StartConnect();
+  client_->StartConnect();
+  client_->Handshake();  // Send ClientHello
+  server_->Handshake();  // Send ServerHello
+  EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state());
+  EXPECT_EQ(TlsAgent::STATE_CONNECTING, server_->state());
+
+  // The client will send nothing until AuthCertificateComplete is called.
+  client_->SetPacketFilter(new EnforceNoActivity());
+  client_->Handshake();
+  EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state());
+
+  // This should allow the handshake to complete now.
+  client_->SetPacketFilter(nullptr);
+  EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
+  client_->Handshake();  // Send Finished
+  server_->Handshake();  // Transition to connected and send NewSessionTicket
+  EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state());
+  EXPECT_EQ(TlsAgent::STATE_CONNECTED, server_->state());
+}
+
 static const SSLExtraServerCertData ServerCertDataRsaPkcs1Decrypt = {
     ssl_auth_rsa_decrypt, nullptr, nullptr, nullptr};
 static const SSLExtraServerCertData ServerCertDataRsaPkcs1Sign = {
     ssl_auth_rsa_sign, nullptr, nullptr, nullptr};
 static const SSLExtraServerCertData ServerCertDataRsaPss = {
     ssl_auth_rsa_pss, nullptr, nullptr, nullptr};
 
 // Test RSA cert with usage=[signature, encipherment].
--- a/security/nss/external_tests/ssl_gtest/ssl_hrr_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_hrr_unittest.cc
@@ -4,16 +4,19 @@
  * 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 "secerr.h"
 #include "ssl.h"
 #include "sslerr.h"
 #include "sslproto.h"
 
+// This is internal, just to get TLS_1_3_DRAFT_VERSION.
+#include "ssl3prot.h"
+
 #include "gtest_utils.h"
 #include "scoped_ptrs.h"
 #include "tls_connect.h"
 #include "tls_filter.h"
 #include "tls_parser.h"
 
 namespace nss_test {
 
@@ -191,18 +194,17 @@ class HelloRetryRequestAgentTest : publi
     agent_->StartConnect();
   }
 
   void MakeCannedHrr(const uint8_t* body, size_t len, DataBuffer* hrr_record,
                      uint32_t seq_num = 0) const {
     DataBuffer hrr_data;
     hrr_data.Allocate(len + 4);
     size_t i = 0;
-    i = hrr_data.Write(i, static_cast<uint32_t>(SSL_LIBRARY_VERSION_TLS_1_3),
-                       2);
+    i = hrr_data.Write(i, 0x7f00 | TLS_1_3_DRAFT_VERSION, 2);
     i = hrr_data.Write(i, static_cast<uint32_t>(len), 2);
     if (len) {
       hrr_data.Write(i, body, len);
     }
     DataBuffer hrr;
     MakeHandshakeMessage(kTlsHandshakeHelloRetryRequest, hrr_data.data(),
                          hrr_data.len(), &hrr, seq_num);
     MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, hrr.data(),
--- a/security/nss/external_tests/ssl_gtest/ssl_version_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_version_unittest.cc
@@ -157,18 +157,24 @@ TEST_P(TlsConnectStream, ConnectTls10And
   // |version_|.
   client_->PrepareForRenegotiate();
   server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, test_version);
   // Reset version and cipher suite so that the preinfo callback
   // doesn't fail.
   server_->ResetPreliminaryInfo();
   server_->StartRenegotiate();
   Handshake();
-  client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
-  server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+  if (test_version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+    // In TLS 1.3, the server detects this problem.
+    client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT);
+    server_->CheckErrorCode(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
+  } else {
+    client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
+    server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+  }
 }
 
 TEST_P(TlsConnectStream, ConnectTls10AndClientRenegotiateHigher) {
   if (version_ == SSL_LIBRARY_VERSION_TLS_1_0) {
     return;
   }
   // Set the client so it will accept any version from 1.0
   // to |version_|.
@@ -184,18 +190,24 @@ TEST_P(TlsConnectStream, ConnectTls10And
   // |version_|.
   server_->PrepareForRenegotiate();
   server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, test_version);
   // Reset version and cipher suite so that the preinfo callback
   // doesn't fail.
   server_->ResetPreliminaryInfo();
   client_->StartRenegotiate();
   Handshake();
-  client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
-  server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+  if (test_version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+    // In TLS 1.3, the server detects this problem.
+    client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT);
+    server_->CheckErrorCode(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
+  } else {
+    client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
+    server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+  }
 }
 
 TEST_F(TlsConnectTest, Tls13RejectsRehandshakeClient) {
   client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   Connect();
--- a/security/nss/lib/freebl/blapii.h
+++ b/security/nss/lib/freebl/blapii.h
@@ -35,9 +35,27 @@ extern PRBool bl_parentForkedAfterC_Init
 #else
 
 #define SKIP_AFTER_FORK(x) x
 
 #endif
 
 SEC_END_PROTOS
 
+#if defined(NSS_X86_OR_X64)
+#define HAVE_UNALIGNED_ACCESS 1
+#endif
+
+#if defined(__clang__)
+#define HAVE_NO_SANITIZE_ATTR __has_attribute(no_sanitize)
+#else
+#define HAVE_NO_SANITIZE_ATTR 0
+#endif
+
+#if defined(HAVE_UNALIGNED_ACCESS) && HAVE_NO_SANITIZE_ATTR
+#define NO_SANITIZE_ALIGNMENT __attribute__((no_sanitize("alignment")))
+#else
+#define NO_SANITIZE_ALIGNMENT
+#endif
+
+#undef HAVE_NO_SANITIZE_ATTR
+
 #endif /* _BLAPII_H_ */
--- a/security/nss/lib/freebl/camellia.c
+++ b/security/nss/lib/freebl/camellia.c
@@ -29,17 +29,17 @@
 #define CAMELLIA_SIGMA5R (0xDE682D1DL)
 #define CAMELLIA_SIGMA6L (0xB05688C2L)
 #define CAMELLIA_SIGMA6R (0xB3E6C1FDL)
 
 /*
  *  macros
  */
 
-#if defined(SHA_ALLOW_UNALIGNED_ACCESS)
+#if defined(HAVE_UNALIGNED_ACCESS)
 
 /* require a CPU that allows unaligned access */
 
 #if defined(SHA_NEED_TMP_VARIABLE)
 #define CAMELLIA_NEED_TMP_VARIABLE 1
 #endif
 
 #define GETU32(p) SHA_HTONL(*((PRUint32 *)(p)))
--- a/security/nss/lib/freebl/chacha20_vec.c
+++ b/security/nss/lib/freebl/chacha20_vec.c
@@ -4,16 +4,17 @@
 
 /* This implementation is by Ted Krovetz and was submitted to SUPERCOP and
  * marked as public domain. It was been altered to allow for non-aligned inputs
  * and to allow the block counter to be passed in specifically. */
 
 #include <string.h>
 
 #include "chacha20.h"
+#include "blapii.h"
 
 #ifndef CHACHA_RNDS
 #define CHACHA_RNDS 20 /* 8 (high speed), 20 (conservative), 12 (middle) */
 #endif
 
 /* Architecture-neutral way to specify 16-byte vector of ints              */
 typedef unsigned vec __attribute__((vector_size(16)));
 
@@ -128,17 +129,17 @@ typedef unsigned vec __attribute__((vect
     b = b << 7 | b >> 25;
 
 #define WRITE_XOR(in, op, d, v0, v1, v2, v3)           \
     STORE(op + d + 0, LOAD(in + d + 0) ^ REVV_BE(v0)); \
     STORE(op + d + 4, LOAD(in + d + 4) ^ REVV_BE(v1)); \
     STORE(op + d + 8, LOAD(in + d + 8) ^ REVV_BE(v2)); \
     STORE(op + d + 12, LOAD(in + d + 12) ^ REVV_BE(v3));
 
-void
+void NO_SANITIZE_ALIGNMENT
 ChaCha20XOR(unsigned char *out, const unsigned char *in, unsigned int inlen,
             const unsigned char key[32], const unsigned char nonce[12],
             uint32_t counter)
 {
     unsigned iters, i, *op = (unsigned *)out, *ip = (unsigned *)in, *kp;
 #if defined(__ARM_NEON__)
     unsigned *np;
 #endif
--- a/security/nss/lib/freebl/des.c
+++ b/security/nss/lib/freebl/des.c
@@ -5,26 +5,20 @@
  *  Make key schedule from DES key.
  *  Encrypt/Decrypt one 8-byte block.
  *
  * 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 "des.h"
+#include "blapii.h"
 #include <stddef.h> /* for ptrdiff_t */
 /* #define USE_INDEXING 1 */
 
-/* Some processors automatically fix up unaligned memory access, so they can
- * read or write a HALF (4 bytes) at a time whether the address is 4-byte
- * aligned or not. */
-#if defined(NSS_X86_OR_X64)
-#define HAVE_UNALIGNED_ACCESS 1
-#endif
-
 /*
  * The tables below are the 8 sbox functions, with the 6-bit input permutation
  * and the 32-bit output permutation pre-computed.
  * They are shifted circularly to the left 3 bits, which removes 2 shifts
  * and an or from each round by reducing the number of sboxes whose
  * indices cross word broundaries from 2 to 1.
  */
 
@@ -556,17 +550,17 @@ DES_MakeSchedule(HALF *ks, const BYTE *k
     left ^= temp >> 8;                                   \
     right ^= temp = ((left << 2) ^ right) & 0xcccccccc;  \
     left ^= temp >> 2;                                   \
     right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
     left ^= temp << 16;                                  \
     right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f;  \
     left ^= temp << 4;
 
-void
+void NO_SANITIZE_ALIGNMENT
 DES_Do1Block(HALF *ks, const BYTE *inbuf, BYTE *outbuf)
 {
     register HALF left, right;
     register HALF temp;
 
 #if defined(HAVE_UNALIGNED_ACCESS)
     left = HALFPTR(inbuf)[0];
     right = HALFPTR(inbuf)[1];
--- a/security/nss/lib/freebl/desblapi.c
+++ b/security/nss/lib/freebl/desblapi.c
@@ -9,16 +9,17 @@
  * 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/. */
 
 #ifdef FREEBL_NO_DEPEND
 #include "stubs.h"
 #endif
 
 #include "des.h"
+#include "blapii.h"
 #include <stddef.h>
 #include "secerr.h"
 
 #if defined(NSS_X86_OR_X64)
 /* Intel X86 CPUs do unaligned loads and stores without complaint. */
 #define COPY8B(to, from, ptr) \
     HALFPTR(to)               \
     [0] = HALFPTR(from)[0];   \
@@ -49,34 +50,34 @@ DES_EDE3_ECB(DESContext *cx, BYTE *out, 
         len -= 8;
         in += 8;
         DES_Do1Block(cx->ks1, out, out);
         DES_Do1Block(cx->ks2, out, out);
         out += 8;
     }
 }
 
-static void
+static void NO_SANITIZE_ALIGNMENT
 DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
 {
     const BYTE *bufend = in + len;
     HALF vec[2];
 
     while (in != bufend) {
         COPY8BTOHALF(vec, in);
         in += 8;
         vec[0] ^= cx->iv[0];
         vec[1] ^= cx->iv[1];
         DES_Do1Block(cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
         COPY8BFROMHALF(out, cx->iv);
         out += 8;
     }
 }
 
-static void
+static void NO_SANITIZE_ALIGNMENT
 DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
 {
     const BYTE *bufend;
     HALF oldciphertext[2];
     HALF plaintext[2];
 
     for (bufend = in + len; in != bufend;) {
         oldciphertext[0] = cx->iv[0];
@@ -86,17 +87,17 @@ DES_CBCDe(DESContext *cx, BYTE *out, con
         DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
         plaintext[0] ^= oldciphertext[0];
         plaintext[1] ^= oldciphertext[1];
         COPY8BFROMHALF(out, plaintext);
         out += 8;
     }
 }
 
-static void
+static void NO_SANITIZE_ALIGNMENT
 DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
 {
     const BYTE *bufend = in + len;
     HALF vec[2];
 
     while (in != bufend) {
         COPY8BTOHALF(vec, in);
         in += 8;
@@ -105,17 +106,17 @@ DES_EDE3CBCEn(DESContext *cx, BYTE *out,
         DES_Do1Block(cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
         DES_Do1Block(cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv);
         DES_Do1Block(cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv);
         COPY8BFROMHALF(out, cx->iv);
         out += 8;
     }
 }
 
-static void
+static void NO_SANITIZE_ALIGNMENT
 DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
 {
     const BYTE *bufend;
     HALF oldciphertext[2];
     HALF plaintext[2];
 
     for (bufend = in + len; in != bufend;) {
         oldciphertext[0] = cx->iv[0];
--- a/security/nss/lib/freebl/ecl/curve25519_64.c
+++ b/security/nss/lib/freebl/ecl/curve25519_64.c
@@ -194,17 +194,17 @@ fsquare(felem *output, const felem *in)
     output[0] = mask51(t0);
     output[1] = mask_lower(t1);
     output[2] = mask51(t2);
     output[3] = mask51(t3);
     output[4] = mask51(t4);
 }
 
 /* Take a 32-byte number and expand it into polynomial form */
-static void
+static void NO_SANITIZE_ALIGNMENT
 fexpand(felem *output, const u8 *in)
 {
     output[0] = *((const uint64_t *)(in)) & MASK51;
     output[1] = (*((const uint64_t *)(in + 6)) >> 3) & MASK51;
     output[2] = (*((const uint64_t *)(in + 12)) >> 6) & MASK51;
     output[3] = (*((const uint64_t *)(in + 19)) >> 1) & MASK51;
     output[4] = (*((const uint64_t *)(in + 25)) >> 4) & MASK51;
 }
--- a/security/nss/lib/freebl/ecl/ecl-priv.h
+++ b/security/nss/lib/freebl/ecl/ecl-priv.h
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __ecl_priv_h_
 #define __ecl_priv_h_
 
 #include "ecl.h"
 #include "mpi.h"
 #include "mplogic.h"
+#include "../blapii.h"
 
 /* MAX_FIELD_SIZE_DIGITS is the maximum size of field element supported */
 /* the following needs to go away... */
 #if defined(MP_USE_LONG_LONG_DIGIT) || defined(MP_USE_LONG_DIGIT)
 #define ECL_SIXTY_FOUR_BIT
 #else
 #define ECL_THIRTY_TWO_BIT
 #endif
--- a/security/nss/lib/freebl/md5.c
+++ b/security/nss/lib/freebl/md5.c
@@ -8,16 +8,17 @@
 
 #include "prerr.h"
 #include "secerr.h"
 
 #include "prtypes.h"
 #include "prlong.h"
 
 #include "blapi.h"
+#include "blapii.h"
 
 #define MD5_HASH_LEN 16
 #define MD5_BUFFER_SIZE 64
 #define MD5_END_BUFFER (MD5_BUFFER_SIZE - 8)
 
 #define CV0_1 0x67452301
 #define CV0_2 0xefcdab89
 #define CV0_3 0x98badcfe
@@ -333,17 +334,17 @@ md5_prep_buffer_le(MD5Context *cx, const
     a = b + cls(a + G(b, c, d) + bufint + ti, s)
 
 #define HH(a, b, c, d, bufint, s, ti) \
     a = b + cls(a + H(b, c, d) + bufint + ti, s)
 
 #define II(a, b, c, d, bufint, s, ti) \
     a = b + cls(a + I(b, c, d) + bufint + ti, s)
 
-static void
+static void NO_SANITIZE_ALIGNMENT
 md5_compress(MD5Context *cx, const PRUint32 *wBuf)
 {
     PRUint32 a, b, c, d;
     PRUint32 tmp;
     a = cx->cv[0];
     b = cx->cv[1];
     c = cx->cv[2];
     d = cx->cv[3];
@@ -440,17 +441,17 @@ MD5_Update(MD5Context *cx, const unsigne
         /* Remaining input. */
         inputLen -= bytesToConsume;
         input += bytesToConsume;
     }
 
     /* Iterate over 64-byte chunks of the message. */
     while (inputLen >= MD5_BUFFER_SIZE) {
 #ifdef IS_LITTLE_ENDIAN
-#ifdef NSS_X86_OR_X64
+#ifdef HAVE_UNALIGNED_ACCESS
         /* x86 can handle arithmetic on non-word-aligned buffers */
         wBuf = (PRUint32 *)input;
 #else
         if ((ptrdiff_t)input & 0x3) {
             /* buffer not aligned, copy it to force alignment */
             memcpy(cx->inBuf, input, MD5_BUFFER_SIZE);
             wBuf = cx->u.w;
         } else {
--- a/security/nss/lib/freebl/poly1305-donna-x64-sse2-incremental-source.c
+++ b/security/nss/lib/freebl/poly1305-donna-x64-sse2-incremental-source.c
@@ -7,16 +7,17 @@
  * domain. It implements SIMD vectorization based on the algorithm described in
  * http://cr.yp.to/papers.html#neoncrypto. Unrolled to 2 powers, i.e. 64 byte
  * block size. */
 
 #include <emmintrin.h>
 #include <stdint.h>
 
 #include "poly1305.h"
+#include "blapii.h"
 
 #define ALIGN(x) __attribute__((aligned(x)))
 #define INLINE inline
 #define U8TO64_LE(m) (*(uint64_t *)(m))
 #define U8TO32_LE(m) (*(uint32_t *)(m))
 #define U64TO8_LE(m, v) (*(uint64_t *)(m)) = v
 
 typedef __m128i xmmi;
@@ -86,17 +87,17 @@ typedef struct poly1305_state_internal_t
 static poly1305_state_internal INLINE
     *
     poly1305_aligned_state(poly1305_state *state)
 {
     return (poly1305_state_internal *)(((uint64_t)state + 63) & ~63);
 }
 
 /* copy 0-63 bytes */
-static void INLINE
+static void INLINE NO_SANITIZE_ALIGNMENT
 poly1305_block_copy(uint8_t *dst, const uint8_t *src, size_t bytes)
 {
     size_t offset = src - dst;
     if (bytes & 32) {
         _mm_storeu_si128((xmmi *)(dst + 0), _mm_loadu_si128((xmmi *)(dst + offset + 0)));
         _mm_storeu_si128((xmmi *)(dst + 16), _mm_loadu_si128((xmmi *)(dst + offset + 16)));
         dst += 32;
     }
--- a/security/nss/lib/freebl/sha_fast.c
+++ b/security/nss/lib/freebl/sha_fast.c
@@ -110,17 +110,17 @@ SHA1_Update(SHA1Context *ctx, const unsi
         memcpy(ctx->B + lenB, dataIn, togo);
         len -= togo;
         dataIn += togo;
         lenB = (lenB + togo) & 63U;
         if (!lenB) {
             shaCompress(&ctx->H[H2X], ctx->W);
         }
     }
-#if !defined(SHA_ALLOW_UNALIGNED_ACCESS)
+#if !defined(HAVE_UNALIGNED_ACCESS)
     if ((ptrdiff_t)dataIn % sizeof(PRUint32)) {
         while (len >= 64U) {
             memcpy(ctx->B, dataIn, 64);
             len -= 64U;
             shaCompress(&ctx->H[H2X], ctx->W);
             dataIn += 64U;
         }
     } else
@@ -235,17 +235,17 @@ SHA1_EndRaw(SHA1Context *ctx, unsigned c
  * the optimizer from trying to reduce the use of the X array by the
  * creation of a MORE expensive W array on the stack. The result is
  * that all instructions use signed 8-bit offsets and not 32-bit offsets.
  *
  * The combination of this code and the -O3 optimizer flag on GCC 3.4.3
  * results in code that is 3 times faster than the previous NSS sha_fast
  * code on AMD64.
  */
-static void
+static void NO_SANITIZE_ALIGNMENT
 shaCompress(volatile SHA_HW_t *X, const PRUint32 *inbuf)
 {
     register SHA_HW_t A, B, C, D, E;
 
 #if defined(SHA_NEED_TMP_VARIABLE)
     register PRUint32 tmp;
 #endif
 
--- a/security/nss/lib/freebl/sha_fast.h
+++ b/security/nss/lib/freebl/sha_fast.h
@@ -1,16 +1,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/. */
 
 #ifndef _SHA_FAST_H_
 #define _SHA_FAST_H_
 
 #include "prlong.h"
+#include "blapii.h"
 
 #define SHA1_INPUT_LEN 64
 
 #if defined(IS_64) && !defined(__sparc)
 typedef PRUint64 SHA_HW_t;
 #define SHA1_USING_64_BIT 1
 #else
 typedef PRUint32 SHA_HW_t;
@@ -113,36 +114,32 @@ swap4b(PRUint32 value)
 
 #endif /* __GNUC__ */
 
 #if !defined(SHA_ROTL_IS_DEFINED)
 #define SHA_NEED_TMP_VARIABLE 1
 #define SHA_ROTL(X, n) (tmp = (X), ((tmp) << (n)) | ((tmp) >> (32 - (n))))
 #endif
 
-#if defined(NSS_X86_OR_X64)
-#define SHA_ALLOW_UNALIGNED_ACCESS 1
-#endif
-
 #if !defined(SHA_HTONL)
 #define SHA_MASK 0x00FF00FF
 #if defined(IS_LITTLE_ENDIAN)
 #undef SHA_NEED_TMP_VARIABLE
 #define SHA_NEED_TMP_VARIABLE 1
 #define SHA_HTONL(x) (tmp = (x), tmp = (tmp << 16) | (tmp >> 16), \
                       ((tmp & SHA_MASK) << 8) | ((tmp >> 8) & SHA_MASK))
 #else
 #define SHA_HTONL(x) (x)
 #endif
 #endif
 
 #define SHA_BYTESWAP(x) x = SHA_HTONL(x)
 
 #define SHA_STORE(n) ((PRUint32*)hashout)[n] = SHA_HTONL(ctx->H[n])
-#if defined(SHA_ALLOW_UNALIGNED_ACCESS)
+#if defined(HAVE_UNALIGNED_ACCESS)
 #define SHA_STORE_RESULT \
     SHA_STORE(0);        \
     SHA_STORE(1);        \
     SHA_STORE(2);        \
     SHA_STORE(3);        \
     SHA_STORE(4);
 
 #elif defined(IS_LITTLE_ENDIAN) || defined(SHA1_USING_64_BIT)
--- a/security/nss/lib/pk11wrap/pk11pk12.c
+++ b/security/nss/lib/pk11wrap/pk11pk12.c
@@ -228,26 +228,32 @@ PK11_ImportDERPrivateKeyInfoAndReturnKey
     if (!pki) {
         PORT_FreeArena(temparena, PR_FALSE);
         return rv;
     }
     pki->arena = temparena;
 
     rv = SEC_ASN1DecodeItem(pki->arena, pki, SECKEY_PrivateKeyInfoTemplate,
 		derPKI);
-    if (rv != SECSuccess || pki->privateKey.data == NULL) {
+    if (rv != SECSuccess) {
         /* If SEC_ASN1DecodeItem fails, we cannot assume anything about the
          * validity of the data in pki. The best we can do is free the arena
-         * and return. Do the same if SECKEYPrivateKeyInfo.privateKey is a
-         * zero-length octet string (i.e. NULL) to avoid trying to zero the
-         * corresponding SECItem.
-         */
+         * and return. */
         PORT_FreeArena(temparena, PR_TRUE);
         return rv;
     }
+    if (pki->privateKey.data == NULL) {
+        /* If SEC_ASN1DecodeItems succeeds but SECKEYPrivateKeyInfo.privateKey
+         * is a zero-length octet string, free the arena and return a failure
+         * to avoid trying to zero the corresponding SECItem in
+         * SECKEY_DestroyPrivateKeyInfo(). */
+        PORT_FreeArena(temparena, PR_TRUE);
+        PORT_SetError(SEC_ERROR_BAD_KEY);
+        return SECFailure;
+    }
 
     rv = PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname,
 		publicValue, isPerm, isPrivate, keyUsage, privk, wincx);
 
     /* this zeroes the key and frees the arena */
     SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE /*freeit*/);
     return rv;
 }
--- a/security/nss/lib/ssl/dtlscon.c
+++ b/security/nss/lib/ssl/dtlscon.c
@@ -994,41 +994,48 @@ dtls_SetMTU(sslSocket *ss, PRUint16 adve
  * DTLS hello_verify_request
  * Caller must hold Handshake and RecvBuf locks.
  */
 SECStatus
 dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 {
     int errCode = SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
     SECStatus rv;
-    PRInt32 temp;
+    SSL3ProtocolVersion temp;
     SSL3AlertDescription desc = illegal_parameter;
 
     SSL_TRC(3, ("%d: SSL3[%d]: handle hello_verify_request handshake",
                 SSL_GETPID(), ss->fd));
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     if (ss->ssl3.hs.ws != wait_server_hello) {
         errCode = SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST;
         desc = unexpected_message;
         goto alert_loser;
     }
 
-    /* The version */
-    temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
-    if (temp < 0) {
+    /* The version.
+     *
+     * RFC 4347 required that you verify that the server versions
+     * match (Section 4.2.1) in the HelloVerifyRequest and the
+     * ServerHello.
+     *
+     * RFC 6347 suggests (SHOULD) that servers always use 1.0 in
+     * HelloVerifyRequest and allows the versions not to match,
+     * especially when 1.2 is being negotiated.
+     *
+     * Therefore we do not do anything to enforce a match, just
+     * read and check that this value is sane.
+     */
+    rv = ssl_ClientReadVersion(ss, &b, &length, &temp);
+    if (rv != SECSuccess) {
         goto loser; /* alert has been sent */
     }
 
-    if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE &&
-        temp != SSL_LIBRARY_VERSION_DTLS_1_2_WIRE) {
-        goto alert_loser;
-    }
-
     /* Read the cookie.
      * IMPORTANT: The value of ss->ssl3.hs.cookie is only valid while the
      * HelloVerifyRequest message remains valid. */
     rv = ssl3_ConsumeHandshakeVariable(ss, &ss->ssl3.hs.cookie, 1, &b, &length);
     if (rv != SECSuccess) {
         goto loser; /* alert has been sent */
     }
     if (ss->ssl3.hs.cookie.len > DTLS_COOKIE_BYTES) {
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -221,44 +221,56 @@ ssl3_CheckCipherSuiteOrderConsistency()
     }
 }
 #endif
 
 /* This list of SSL3 compression methods is sorted in descending order of
  * precedence (desirability).  It only includes compression methods we
  * implement.
  */
-static const /*SSLCompressionMethod*/ PRUint8 compressions[] = {
+static const SSLCompressionMethod ssl_compression_methods[] = {
 #ifdef NSS_SSL_ENABLE_ZLIB
     ssl_compression_deflate,
 #endif
     ssl_compression_null
 };
 
-static const int compressionMethodsCount =
-    sizeof(compressions) / sizeof(compressions[0]);
+static const unsigned int ssl_compression_method_count =
+    PR_ARRAY_SIZE(ssl_compression_methods);
 
 /* compressionEnabled returns true iff the compression algorithm is enabled
  * for the given SSL socket. */
 static PRBool
-compressionEnabled(sslSocket *ss, SSLCompressionMethod compression)
-{
-    switch (compression) {
-        case ssl_compression_null:
-            return PR_TRUE; /* Always enabled */
+ssl_CompressionEnabled(sslSocket *ss, SSLCompressionMethod compression)
+{
+    SSL3ProtocolVersion version;
+
+    if (compression == ssl_compression_null) {
+        return PR_TRUE; /* Always enabled */
+    }
+    if (ss->sec.isServer) {
+        /* We can't easily check that the client didn't attempt TLS 1.3,
+         * so this will have to do. */
+        PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3);
+        version = ss->version;
+    } else {
+        version = ss->vrange.max;
+    }
+    if (version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+        return PR_FALSE;
+    }
 #ifdef NSS_SSL_ENABLE_ZLIB
-        case ssl_compression_deflate:
-            if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 && !IS_DTLS(ss)) {
-                return ss->opt.enableDeflate;
-            }
+    if (compression == ssl_compression_deflate) {
+        if (IS_DTLS(ss)) {
             return PR_FALSE;
+        }
+        return ss->opt.enableDeflate;
+    }
 #endif
-        default:
-            return PR_FALSE;
-    }
+    return PR_FALSE;
 }
 
 static const /*SSL3ClientCertificateType */ PRUint8 certificate_types[] = {
     ct_RSA_sign,
     ct_ECDSA_sign,
     ct_DSS_sign,
 };
 
@@ -1049,16 +1061,62 @@ ssl3_NegotiateVersion(sslSocket *ss, SSL
     }
 
     ss->version = PR_MIN(peerVersion, ss->vrange.max);
     PORT_Assert(ssl3_VersionIsSupported(ss->protocolVariant, ss->version));
 
     return SECSuccess;
 }
 
+/* Used by the client when the server produces a version number.
+ * This reads, validates, and normalizes the value. */
+SECStatus
+ssl_ClientReadVersion(sslSocket *ss, SSL3Opaque **b, unsigned int *len,
+                      SSL3ProtocolVersion *version)
+{
+    SSL3ProtocolVersion v;
+    PRInt32 temp;
+
+    temp = ssl3_ConsumeHandshakeNumber(ss, 2, b, len);
+    if (temp < 0) {
+        return SECFailure; /* alert has been sent */
+    }
+
+#ifdef TLS_1_3_DRAFT_VERSION
+    if (temp == SSL_LIBRARY_VERSION_TLS_1_3) {
+        (void)SSL3_SendAlert(ss, alert_fatal, protocol_version);
+        PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
+        return SECFailure;
+    }
+    if (temp == tls13_EncodeDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3)) {
+        v = SSL_LIBRARY_VERSION_TLS_1_3;
+    } else {
+        v = (SSL3ProtocolVersion)temp;
+    }
+#else
+    v = (SSL3ProtocolVersion)temp;
+#endif
+
+    if (IS_DTLS(ss)) {
+        /* If this fails, we get 0 back and the next check to fails. */
+        v = dtls_DTLSVersionToTLSVersion(v);
+    }
+
+    PORT_Assert(!SSL_ALL_VERSIONS_DISABLED(&ss->vrange));
+    if (ss->vrange.min > v || ss->vrange.max < v) {
+        (void)SSL3_SendAlert(ss, alert_fatal,
+                             (v > SSL_LIBRARY_VERSION_3_0) ? protocol_version
+                                                           : handshake_failure);
+        PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
+        return SECFailure;
+    }
+    *version = v;
+    return SECSuccess;
+}
+
 static SECStatus
 ssl3_GetNewRandom(SSL3Random *random)
 {
     SECStatus rv;
 
     rv = PK11_GenerateRandom(random->rand, SSL3_RANDOM_LENGTH);
     if (rv != SECSuccess) {
         ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
@@ -4862,23 +4920,31 @@ ssl3_SendClientHello(sslSocket *ss, sslC
     int length;
     int num_suites;
     int actual_count = 0;
     PRBool isTLS = PR_FALSE;
     PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE;
     PRInt32 total_exten_len = 0;
     unsigned paddingExtensionLen;
     unsigned numCompressionMethods;
+    PRUint16 version;
 
     SSL_TRC(3, ("%d: SSL3[%d]: send %s ClientHello handshake", SSL_GETPID(),
                 ss->fd, ssl_ClientHelloTypeName(type)));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
+    /* shouldn't get here if SSL3 is disabled, but ... */
+    if (SSL_ALL_VERSIONS_DISABLED(&ss->vrange)) {
+        PR_NOT_REACHED("No versions of SSL 3.0 or later are enabled");
+        PORT_SetError(SSL_ERROR_SSL_DISABLED);
+        return SECFailure;
+    }
+
     /* If we are responding to a HelloRetryRequest, don't reinitialize. We need
      * to maintain the handshake hashes. */
     if (ss->ssl3.hs.helloRetry) {
         PORT_Assert(type == client_hello_retry);
     } else {
         rv = ssl3_InitState(ss);
         if (rv != SECSuccess) {
             return rv; /* ssl3_InitState has set the error code. */
@@ -4959,17 +5025,17 @@ ssl3_SendClientHello(sslSocket *ss, sslC
         ** holds the private key still exists, is logged in, hasn't been
         ** removed, etc.
         */
         if (sidOK && !ssl3_ClientAuthTokenPresent(sid)) {
             sidOK = PR_FALSE;
         }
 
         if (sidOK) {
-            /* Set ss->version based on the session cache */
+            /* Set version based on the sid. */
             if (ss->firstHsDone) {
                 /*
                  * Windows SChannel compares the client_version inside the RSA
                  * EncryptedPreMasterSecret of a renegotiation with the
                  * client_version of the initial ClientHello rather than the
                  * ClientHello in the renegotiation. To work around this bug, we
                  * continue to use the client_version used in the initial
                  * ClientHello when renegotiating.
@@ -4977,36 +5043,32 @@ ssl3_SendClientHello(sslSocket *ss, sslC
                  * The client_version of the initial ClientHello is still
                  * available in ss->clientHelloVersion. Ensure that
                  * sid->version is bounded within
                  * [ss->vrange.min, ss->clientHelloVersion], otherwise we
                  * can't use sid.
                  */
                 if (sid->version >= ss->vrange.min &&
                     sid->version <= ss->clientHelloVersion) {
-                    ss->version = ss->clientHelloVersion;
+                    version = ss->clientHelloVersion;
                 } else {
                     sidOK = PR_FALSE;
                 }
             } else {
                 /*
                  * Check sid->version is OK first.
                  * Previously, we would cap the version based on sid->version,
                  * but that prevents negotiation of a higher version if the
                  * previous session was reduced (e.g., with version fallback)
                  */
                 if (sid->version < ss->vrange.min ||
                     sid->version > ss->vrange.max) {
                     sidOK = PR_FALSE;
                 } else {
-                    rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED,
-                                               PR_TRUE);
-                    if (rv != SECSuccess) {
-                        return rv; /* error code was set */
-                    }
+                    version = ss->vrange.max;
                 }
             }
         }
 
         if (!sidOK) {
             SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_not_ok);
             ss->sec.uncache(sid);
             ssl_FreeSID(sid);
@@ -5029,51 +5091,43 @@ ssl3_SendClientHello(sslSocket *ss, sslC
          * Windows SChannel compares the client_version inside the RSA
          * EncryptedPreMasterSecret of a renegotiation with the
          * client_version of the initial ClientHello rather than the
          * ClientHello in the renegotiation. To work around this bug, we
          * continue to use the client_version used in the initial
          * ClientHello when renegotiating.
          */
         if (ss->firstHsDone) {
-            ss->version = ss->clientHelloVersion;
+            version = ss->clientHelloVersion;
         } else {
-            rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED,
-                                       PR_TRUE);
-            if (rv != SECSuccess)
-                return rv; /* error code was set */
+            version = ss->vrange.max;
         }
 
         sid = ssl3_NewSessionID(ss, PR_FALSE);
         if (!sid) {
             return SECFailure; /* memory error is set */
         }
-    }
-
-    isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0);
+        /* ss->version isn't set yet, but the sid needs a sane value. */
+        sid->version = version;
+    }
+
+    isTLS = (version > SSL_LIBRARY_VERSION_3_0);
     ssl_GetSpecWriteLock(ss);
     cwSpec = ss->ssl3.cwSpec;
     if (cwSpec->mac_def->mac == mac_null) {
         /* SSL records are not being MACed. */
-        cwSpec->version = ss->version;
+        cwSpec->version = version;
     }
     ssl_ReleaseSpecWriteLock(ss);
 
     if (ss->sec.ci.sid != NULL) {
         ssl_FreeSID(ss->sec.ci.sid); /* decrement ref count, free if zero */
     }
     ss->sec.ci.sid = sid;
 
-    /* shouldn't get here if SSL3 is disabled, but ... */
-    if (SSL_ALL_VERSIONS_DISABLED(&ss->vrange)) {
-        PR_NOT_REACHED("No versions of SSL 3.0 or later are enabled");
-        PORT_SetError(SSL_ERROR_SSL_DISABLED);
-        return SECFailure;
-    }
-
     /* how many suites does our PKCS11 support (regardless of policy)? */
     num_suites = ssl3_config_match_init(ss);
     if (!num_suites)
         return SECFailure; /* ssl3_config_match_init has set error code. */
 
     /* HACK for SCSV in SSL 3.0.  On initial handshake, prepend SCSV,
      * only if TLS is disabled.
      */
@@ -5129,29 +5183,29 @@ ssl3_SendClientHello(sslSocket *ss, sslC
     if (!num_suites) {
         if (sid->u.ssl3.lock) {
             PR_RWLock_Unlock(sid->u.ssl3.lock);
         }
         return SECFailure; /* count_cipher_suites has set error code. */
     }
 
     fallbackSCSV = ss->opt.enableFallbackSCSV && (!requestingResume ||
-                                                  ss->version < sid->version);
+                                                  version < sid->version);
     /* make room for SCSV */
     if (ss->ssl3.hs.sendingSCSV) {
         ++num_suites;
     }
     if (fallbackSCSV) {
         ++num_suites;
     }
 
     /* count compression methods */
     numCompressionMethods = 0;
-    for (i = 0; i < compressionMethodsCount; i++) {
-        if (compressionEnabled(ss, compressions[i]))
+    for (i = 0; i < ssl_compression_method_count; i++) {
+        if (ssl_CompressionEnabled(ss, ssl_compression_methods[i]))
             numCompressionMethods++;
     }
 
     length = sizeof(SSL3ProtocolVersion) + SSL3_RANDOM_LENGTH +
              1 + (sid->version >= SSL_LIBRARY_VERSION_TLS_1_3
                       ? 0
                       : sid->u.ssl3.sessionIDLength) +
              2 + num_suites * sizeof(ssl3CipherSuite) +
@@ -5181,24 +5235,24 @@ ssl3_SendClientHello(sslSocket *ss, sslC
             PR_RWLock_Unlock(sid->u.ssl3.lock);
         }
         return rv; /* err set by ssl3_AppendHandshake* */
     }
 
     if (ss->firstHsDone) {
         /* The client hello version must stay unchanged to work around
          * the Windows SChannel bug described above. */
-        PORT_Assert(ss->version == ss->clientHelloVersion);
-    }
-    ss->clientHelloVersion = PR_MIN(ss->version, SSL_LIBRARY_VERSION_TLS_1_2);
+        PORT_Assert(version == ss->clientHelloVersion);
+    }
+    ss->clientHelloVersion = PR_MIN(version, SSL_LIBRARY_VERSION_TLS_1_2);
     if (IS_DTLS(ss)) {
-        PRUint16 version;
-
-        version = dtls_TLSVersionToDTLSVersion(ss->clientHelloVersion);
-        rv = ssl3_AppendHandshakeNumber(ss, version, 2);
+        PRUint16 dtlsVersion;
+
+        dtlsVersion = dtls_TLSVersionToDTLSVersion(ss->clientHelloVersion);
+        rv = ssl3_AppendHandshakeNumber(ss, dtlsVersion, 2);
     } else {
         rv = ssl3_AppendHandshakeNumber(ss, ss->clientHelloVersion, 2);
     }
     if (rv != SECSuccess) {
         if (sid->u.ssl3.lock) {
             PR_RWLock_Unlock(sid->u.ssl3.lock);
         }
         return rv; /* err set by ssl3_AppendHandshake* */
@@ -5314,20 +5368,20 @@ ssl3_SendClientHello(sslSocket *ss, sslC
 
     rv = ssl3_AppendHandshakeNumber(ss, numCompressionMethods, 1);
     if (rv != SECSuccess) {
         if (sid->u.ssl3.lock) {
             PR_RWLock_Unlock(sid->u.ssl3.lock);
         }
         return rv; /* err set by ssl3_AppendHandshake* */
     }
-    for (i = 0; i < compressionMethodsCount; i++) {
-        if (!compressionEnabled(ss, compressions[i]))
+    for (i = 0; i < ssl_compression_method_count; i++) {
+        if (!ssl_CompressionEnabled(ss, ssl_compression_methods[i]))
             continue;
-        rv = ssl3_AppendHandshakeNumber(ss, compressions[i], 1);
+        rv = ssl3_AppendHandshakeNumber(ss, ssl_compression_methods[i], 1);
         if (rv != SECSuccess) {
             if (sid->u.ssl3.lock) {
                 PR_RWLock_Unlock(sid->u.ssl3.lock);
             }
             return rv; /* err set by ssl3_AppendHandshake* */
         }
     }
 
@@ -5374,32 +5428,32 @@ ssl3_SendClientHello(sslSocket *ss, sslC
 
     if (ss->ssl3.hs.sendingSCSV) {
         /* Since we sent the SCSV, pretend we sent empty RI extension. */
         TLSExtensionData *xtnData = &ss->xtnData;
         xtnData->advertised[xtnData->numAdvertised++] =
             ssl_renegotiation_info_xtn;
     }
 
-    if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+    if (version >= SSL_LIBRARY_VERSION_TLS_1_3) {
         rv = tls13_MaybeDo0RTTHandshake(ss);
         if (rv != SECSuccess) {
             return SECFailure; /* error code set already. */
         }
     }
 
     /* On TLS (but not DTLS), if we sent 0-RTT, then we will have data in the
      * pending buffer. This just pushes a little of that out.  If we didn't do
      * that, we wouldn't send a ClientHello the first time and applications
      * would have to push SSL_ForceHandshake() twice. This should go away once
      * we have Finished stuffed in the ClientHello. */
     if (!IS_DTLS(ss) && ss->ssl3.hs.zeroRttState == ssl_0rtt_sent) {
         int sent;
 
-        PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
+        PORT_Assert(version >= SSL_LIBRARY_VERSION_TLS_1_3);
         PORT_Assert(ss->pendingBuf.len);
         sent = ssl_SendSavedWriteData(ss);
         if (sent < 0) {
             return SECFailure;
         }
     } else {
         PRInt32 flags = 0;
         if (!ss->firstHsDone && !IS_DTLS(ss)) {
@@ -6463,17 +6517,16 @@ ssl3_HandleServerHello(sslSocket *ss, SS
     PRInt32 temp; /* allow for consume number failure */
     PRBool suite_found = PR_FALSE;
     int i;
     int errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
     SECStatus rv;
     SECItem sidBytes = { siBuffer, NULL, 0 };
     PRBool isTLS = PR_FALSE;
     SSL3AlertDescription desc = illegal_parameter;
-    SSL3ProtocolVersion version;
 #ifndef TLS_1_3_DRAFT_VERSION
     SSL3ProtocolVersion downgradeCheckVersion;
 #endif
 
     SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello handshake",
                 SSL_GETPID(), ss->fd));
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
@@ -6494,59 +6547,33 @@ ssl3_HandleServerHello(sslSocket *ss, SS
         CERT_DestroyCertificate(ss->ssl3.clientCertificate);
         ss->ssl3.clientCertificate = NULL;
     }
     if (ss->ssl3.clientPrivateKey != NULL) {
         SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
         ss->ssl3.clientPrivateKey = NULL;
     }
 
-    temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
-    if (temp < 0) {
+    rv = ssl_ClientReadVersion(ss, &b, &length, &ss->version);
+    if (rv != SECSuccess) {
         goto loser; /* alert has been sent */
     }
-    version = tls13_DecodeDraftVersion((PRUint16)temp);
-
-    /* Try to translate DTLS versions. */
-    if (IS_DTLS(ss)) {
-        /* RFC 4347 required that you verify that the server versions
-         * match (Section 4.2.1) in the HelloVerifyRequest and the
-         * ServerHello.
-         *
-         * RFC 6347 suggests (SHOULD) that servers always use 1.0
-         * in HelloVerifyRequest and allows the versions not to match,
-         * especially when 1.2 is being negotiated.
-         *
-         * Therefore we do not check for matching here.
-         */
-        version = dtls_DTLSVersionToTLSVersion(version);
-        if (version == 0) { /* Insane version number */
-            goto alert_loser;
-        }
-    }
 
     /* We got a HelloRetryRequest, but the server didn't pick 1.3.  Scream. */
-    if (ss->ssl3.hs.helloRetry && version < SSL_LIBRARY_VERSION_TLS_1_3) {
+    if (ss->ssl3.hs.helloRetry && ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
         desc = illegal_parameter;
         errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
         goto alert_loser;
     }
 
-    rv = ssl3_NegotiateVersion(ss, version, PR_FALSE);
-    if (rv != SECSuccess) {
-        desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version
-                                                   : handshake_failure;
-        errCode = SSL_ERROR_UNSUPPORTED_VERSION;
-        goto alert_loser;
-    }
     /* Check that the server negotiated the same version as it did
      * in the first handshake. This isn't really the best place for
      * us to be getting this version number, but it's what we have.
      * (1294697). */
-    if (ss->firstHsDone && (version != ss->ssl3.crSpec->version)) {
+    if (ss->firstHsDone && (ss->version != ss->ssl3.crSpec->version)) {
         desc = illegal_parameter;
         errCode = SSL_ERROR_UNSUPPORTED_VERSION;
         goto alert_loser;
     }
     ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
     isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0);
 
     rv = ssl3_ConsumeHandshake(
@@ -6601,17 +6628,22 @@ ssl3_HandleServerHello(sslSocket *ss, SS
         }
     }
 
     /* find selected cipher suite in our list. */
     temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
     if (temp < 0) {
         goto loser; /* alert has been sent */
     }
-    ssl3_config_match_init(ss);
+    i = ssl3_config_match_init(ss);
+    PORT_Assert(i > 0);
+    if (i <= 0) {
+        errCode = PORT_GetError();
+        goto loser;
+    }
     for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
         ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
         if (temp == suite->cipher_suite) {
             SSLVersionRange vrange = { ss->version, ss->version };
             if (!config_match(suite, ss->ssl3.policy, &vrange, ss)) {
                 /* config_match already checks whether the cipher suite is
                  * acceptable for the version, but the check is repeated here
                  * in order to give a more precise error code. */
@@ -6643,19 +6675,19 @@ ssl3_HandleServerHello(sslSocket *ss, SS
 
     if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
         /* find selected compression method in our list. */
         temp = ssl3_ConsumeHandshakeNumber(ss, 1, &b, &length);
         if (temp < 0) {
             goto loser; /* alert has been sent */
         }
         suite_found = PR_FALSE;
-        for (i = 0; i < compressionMethodsCount; i++) {
-            if (temp == compressions[i]) {
-                if (!compressionEnabled(ss, compressions[i])) {
+        for (i = 0; i < ssl_compression_method_count; i++) {
+            if (temp == ssl_compression_methods[i]) {
+                if (!ssl_CompressionEnabled(ss, ssl_compression_methods[i])) {
                     break; /* failure */
                 }
                 suite_found = PR_TRUE;
                 break; /* success */
             }
         }
         if (!suite_found) {
             desc = handshake_failure;
@@ -8534,17 +8566,17 @@ ssl3_HandleClientHelloPart2(sslSocket *s
     if (sid)
         do {
             ssl3CipherSuiteCfg *suite;
 #ifdef PARANOID
             SSLVersionRange vrange = { ss->version, ss->version };
 #endif
 
             /* Check that the cached compression method is still enabled. */
-            if (!compressionEnabled(ss, sid->u.ssl3.compression))
+            if (!ssl_CompressionEnabled(ss, sid->u.ssl3.compression))
                 break;
 
             /* Check that the cached compression method is in the client's list */
             for (i = 0; i < comps->len; i++) {
                 if (comps->data[i] == sid->u.ssl3.compression)
                     break;
             }
             if (i == comps->len)
@@ -8615,22 +8647,22 @@ ssl3_HandleClientHelloPart2(sslSocket *s
 
     if (canOfferSessionTicket) {
         ssl3_RegisterServerHelloExtensionSender(ss,
                                                 ssl_session_ticket_xtn, ssl3_SendSessionTicketXtn);
     }
 
     /* Select a compression algorithm. */
     for (i = 0; i < comps->len; i++) {
-        if (!compressionEnabled(ss, comps->data[i]))
+        SSLCompressionMethod method = (SSLCompressionMethod)comps->data[i];
+        if (!ssl_CompressionEnabled(ss, method))
             continue;
-        for (j = 0; j < compressionMethodsCount; j++) {
-            if (comps->data[i] == compressions[j]) {
-                ss->ssl3.hs.compression =
-                    (SSLCompressionMethod)compressions[j];
+        for (j = 0; j < ssl_compression_method_count; j++) {
+            if (method == ssl_compression_methods[j]) {
+                ss->ssl3.hs.compression = ssl_compression_methods[j];
                 goto compression_found;
             }
         }
     }
     errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP;
     /* null compression must be supported */
     goto alert_loser;
 
@@ -11705,16 +11737,23 @@ ssl3_HandlePostHelloHandshakeMessage(ssl
             }
             if (ss->sec.isServer) {
                 (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
                 PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST);
                 return SECFailure;
             }
             rv = ssl3_HandleHelloRequest(ss);
             break;
+
+        case hello_retry_request:
+            /* This arrives here because - as a client - we haven't received a
+             * final decision on the version from the server. */
+            rv = tls13_HandleHelloRetryRequest(ss, b, length);
+            break;
+
         case hello_verify_request:
             if (!IS_DTLS(ss) || ss->sec.isServer) {
                 (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
                 PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST);
                 return SECFailure;
             }
             rv = dtls_HandleHelloVerifyRequest(ss, b, length);
             break;
--- a/security/nss/lib/ssl/ssl3ecc.c
+++ b/security/nss/lib/ssl/ssl3ecc.c
@@ -889,17 +889,17 @@ ssl_SendSupportedGroupsXtn(sslSocket *ss
     PRBool ec;
     PRBool ff = PR_FALSE;
 
     if (!ss)
         return 0;
 
     /* We only send FF supported groups if we require DH named groups
      * or if TLS 1.3 is a possibility. */
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+    if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) {
         ec = ssl_IsECCEnabled(ss);
         if (ss->opt.requireDHENamedGroups) {
             ff = ssl_IsDHEEnabled(ss);
         }
         if (!ec && !ff)
             return 0;
     } else {
         ec = ff = PR_TRUE;
--- a/security/nss/lib/ssl/ssl3ext.c
+++ b/security/nss/lib/ssl/ssl3ext.c
@@ -1219,17 +1219,17 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
     unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
     unsigned int computed_mac_length;
     unsigned char iv[AES_BLOCK_SIZE];
     SECItem ivItem;
     SECItem *srvName = NULL;
     PRUint32 srvNameLen = 0;
     CK_MECHANISM_TYPE msWrapMech = 0; /* dummy default value,
                                           * must be >= 0 */
-    ssl3CipherSpec *spec = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 ? ss->ssl3.cwSpec : ss->ssl3.pwSpec;
+    ssl3CipherSpec *spec;
     const sslServerCertType *certType;
     SECItem alpnSelection = { siBuffer, NULL, 0 };
 
     SSL_TRC(3, ("%d: SSL3[%d]: send session_ticket handshake",
                 SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
@@ -1244,16 +1244,21 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
     rv = PK11_GenerateRandom(iv, sizeof(iv));
     if (rv != SECSuccess)
         goto loser;
 
     rv = ssl3_GetSessionTicketKeys(ss, &aes_key, &mac_key);
     if (rv != SECSuccess)
         goto loser;
 
+    if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+        spec = ss->ssl3.cwSpec;
+    } else {
+        spec = ss->ssl3.pwSpec;
+    }
     if (spec->msItem.len && spec->msItem.data) {
         /* The master secret is available unwrapped. */
         ms_item.data = spec->msItem.data;
         ms_item.len = spec->msItem.len;
         ms_is_wrapped = PR_FALSE;
     } else {
         /* Extract the master secret wrapped. */
         sslSessionID sid;
@@ -1282,32 +1287,34 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
     }
 
     if (ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT &&
         ss->ssl3.nextProto.data) {
         alpnSelection = ss->ssl3.nextProto;
     }
 
     ciphertext_length =
-        sizeof(PRUint16)                                                                        /* ticket_version */
-        + sizeof(SSL3ProtocolVersion)                                                           /* ssl_version */
-        + sizeof(ssl3CipherSuite)                                                               /* ciphersuite */
-        + 1                                                                                     /* compression */
-        + 10                                                                                    /* cipher spec parameters */
-        + 1                                                                                     /* certType arguments */
-        + 1                                                                                     /* SessionTicket.ms_is_wrapped */
-        + 4                                                                                     /* msWrapMech */
-        + 2                                                                                     /* master_secret.length */
-        + ms_item.len                                                                           /* master_secret */
-        + 1                                                                                     /* client_auth_type */
-        + cert_length                                                                           /* cert */
-        + 1                                                                                     /* server name type */
-        + srvNameLen                                                                            /* name len + length field */
-        + 1                                                                                     /* extendedMasterSecretUsed */
-        + sizeof(ticket->ticket_lifetime_hint) + sizeof(ticket->flags) + 1 + alpnSelection.len; /* npn value + length field. */
+        sizeof(PRUint16)                       /* ticket_version */
+        + sizeof(SSL3ProtocolVersion)          /* ssl_version */
+        + sizeof(ssl3CipherSuite)              /* ciphersuite */
+        + 1                                    /* compression */
+        + 10                                   /* cipher spec parameters */
+        + 1                                    /* certType arguments */
+        + 1                                    /* SessionTicket.ms_is_wrapped */
+        + 4                                    /* msWrapMech */
+        + 2                                    /* master_secret.length */
+        + ms_item.len                          /* master_secret */
+        + 1                                    /* client_auth_type */
+        + cert_length                          /* cert */
+        + 1                                    /* server name type */
+        + srvNameLen                           /* name len + length field */
+        + 1                                    /* extendedMasterSecretUsed */
+        + sizeof(ticket->ticket_lifetime_hint) /* ticket lifetime hint */
+        + sizeof(ticket->flags)                /* ticket flags */
+        + 1 + alpnSelection.len;               /* npn value + length field. */
     padding_length = AES_BLOCK_SIZE -
                      (ciphertext_length %
                       AES_BLOCK_SIZE);
     ciphertext_length += padding_length;
 
     if (SECITEM_AllocItem(NULL, &plaintext_item, ciphertext_length) == NULL)
         goto loser;
 
@@ -2176,17 +2183,16 @@ ssl3_HandleParsedExtensions(sslSocket *s
         case client_hello:
             handlers = clientHelloHandlers;
             break;
         case new_session_ticket:
             PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
             handlers = newSessionTicketHandlers;
             break;
         case hello_retry_request:
-            PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
             handlers = helloRetryRequestHandlers;
             break;
         case encrypted_extensions:
             PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
         /* fall through */
         case server_hello:
             if (ss->version > SSL_LIBRARY_VERSION_3_0) {
                 handlers = serverHelloHandlersTLS;
@@ -2312,17 +2318,17 @@ ssl3_RegisterServerHelloExtensionSender(
 PRInt32
 ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
                                const ssl3HelloExtensionSender *sender)
 {
     PRInt32 total_exten_len = 0;
     int i;
 
     if (!sender) {
-        if (ss->version > SSL_LIBRARY_VERSION_3_0) {
+        if (ss->vrange.max > SSL_LIBRARY_VERSION_3_0) {
             sender = &clientHelloSendersTLS[0];
         } else {
             sender = &clientHelloSendersSSL3[0];
         }
     }
 
     for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) {
         if (sender->ex_sender) {
@@ -2685,17 +2691,17 @@ ssl3_ServerHandleSigAlgsXtn(sslSocket *s
 static PRInt32
 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
 {
     PRInt32 extension_length;
     PRUint8 buf[MAX_SIGNATURE_SCHEMES * 2];
     PRUint32 len;
     SECStatus rv;
 
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_2) {
+    if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_2) {
         return 0;
     }
 
     rv = ssl3_EncodeSigAlgs(ss, buf, sizeof(buf), &len);
     if (rv != SECSuccess) {
         return -1;
     }
 
@@ -3056,17 +3062,17 @@ tls13_EncodeKeyShareEntry(sslSocket *ss,
 }
 
 static PRInt32
 tls13_ClientSendKeyShareXtn(sslSocket *ss, PRBool append,
                             PRUint32 maxBytes)
 {
     PRUint32 extension_length;
 
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+    if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) {
         return 0;
     }
 
     /* Optimistically try to send an ECDHE key using the
      * preexisting key (in future will be keys) */
     SSL_TRC(3, ("%d: TLS13[%d]: send client key share xtn",
                 SSL_GETPID(), ss->fd));
 
@@ -3193,17 +3199,17 @@ tls13_ClientHandleKeyShareXtn(sslSocket 
 static SECStatus
 tls13_ClientHandleKeyShareXtnHrr(sslSocket *ss, PRUint16 ex_type, SECItem *data)
 {
     SECStatus rv;
     PRInt32 tmp;
     const sslNamedGroupDef *group;
 
     PORT_Assert(!ss->sec.isServer);
-    PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
+    PORT_Assert(ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3);
 
     SSL_TRC(3, ("%d: SSL3[%d]: handle key_share extension in HRR",
                 SSL_GETPID(), ss->fd));
 
     tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
     if (tmp < 0) {
         return SECFailure; /* error code already set */
     }
@@ -3344,19 +3350,22 @@ tls13_ClientSendPreSharedKeyXtn(sslSocke
 {
     PRInt32 extension_length;
     static const PRUint8 auth_modes[] = { tls13_psk_auth };
     static const unsigned long auth_modes_len = sizeof(auth_modes);
     static const PRUint8 ke_modes[] = { tls13_psk_dh_ke };
     static const unsigned long ke_modes_len = sizeof(ke_modes);
     NewSessionTicket *session_ticket;
 
+    /* We only set statelessResume on the client in TLS 1.3 code. */
     if (!ss->statelessResume)
         return 0;
 
+    PORT_Assert(ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3);
+
     session_ticket = &ss->sec.ci.sid->u.ssl3.locked.sessionTicket;
 
     extension_length =
         2 + 2 + 2 +                     /* Type + length + vector length */
         1 + ke_modes_len +              /* key exchange modes vector */
         1 + auth_modes_len +            /* auth modes vector */
         2 + session_ticket->ticket.len; /* identity length + ticket len */
 
@@ -3806,17 +3815,17 @@ tls13_ClientHandleSigAlgsXtn(sslSocket *
 static PRInt32
 tls13_ClientSendSupportedVersionsXtn(sslSocket *ss, PRBool append,
                                      PRUint32 maxBytes)
 {
     PRInt32 extensions_len;
     PRUint16 version;
     SECStatus rv;
 
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+    if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) {
         return 0;
     }
 
     SSL_TRC(3, ("%d: TLS13[%d]: send supported_versions extension",
                 SSL_GETPID(), ss->fd));
 
     /* Extension type, extension len fiels, vector len field,
      * length of the values. */
--- a/security/nss/lib/ssl/sslimpl.h
+++ b/security/nss/lib/ssl/sslimpl.h
@@ -1711,16 +1711,19 @@ extern void ssl3_InitSocketPolicy(sslSoc
 
 extern SECStatus ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache);
 extern SECStatus ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
                                              PRUint32 length,
                                              PRBool endOfRecord);
 
 extern void ssl3_DestroySSL3Info(sslSocket *ss);
 
+extern SECStatus ssl_ClientReadVersion(sslSocket *ss, SSL3Opaque **b,
+                                       PRUint32 *length,
+                                       SSL3ProtocolVersion *version);
 extern SECStatus ssl3_NegotiateVersion(sslSocket *ss,
                                        SSL3ProtocolVersion peerVersion,
                                        PRBool allowLargerPeerVersion);
 
 extern SECStatus ssl_GetPeerInfo(sslSocket *ss);
 
 /* ECDH functions */
 extern SECStatus ssl3_SendECDHClientKeyExchange(sslSocket *ss,
--- a/security/nss/lib/ssl/sslproto.h
+++ b/security/nss/lib/ssl/sslproto.h
@@ -26,17 +26,17 @@
 #define SSL_LIBRARY_VERSION_DTLS_1_3            SSL_LIBRARY_VERSION_TLS_1_3
 
 /* deprecated old name */
 #define SSL_LIBRARY_VERSION_3_1_TLS SSL_LIBRARY_VERSION_TLS_1_0
 
 /* The DTLS versions used in the spec */
 #define SSL_LIBRARY_VERSION_DTLS_1_0_WIRE       ((~0x0100) & 0xffff)
 #define SSL_LIBRARY_VERSION_DTLS_1_2_WIRE       ((~0x0102) & 0xffff)
-#define SSL_LIBRARY_VERSION_DTLS_1_3_WIRE       0x0304
+#define SSL_LIBRARY_VERSION_DTLS_1_3_WIRE       SSL_LIBRARY_VERSION_DTLS_1_3
 
 /* Certificate types */
 #define SSL_CT_X509_CERTIFICATE                 0x01
 #if 0 /* XXX Not implemented yet */
 #define SSL_PKCS6_CERTIFICATE                   0x02
 #endif
 #define SSL_AT_MD5_WITH_RSA_ENCRYPTION          0x01
 
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -84,18 +84,16 @@ static SECStatus tls13_ClientHandleFinis
                                             SSL3Opaque *b, PRUint32 length,
                                             const TLS13CombinedHash *hashes);
 static SECStatus tls13_ServerHandleFinished(sslSocket *ss,
                                             SSL3Opaque *b, PRUint32 length,
                                             const TLS13CombinedHash *hashes);
 static SECStatus tls13_SendNewSessionTicket(sslSocket *ss);
 static SECStatus tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b,
                                               PRUint32 length);
-static SECStatus tls13_HandleHelloRetryRequest(sslSocket *ss, SSL3Opaque *b,
-                                               PRUint32 length);
 static void
 tls13_CombineHashes(sslSocket *ss, const PRUint8 *hhash, unsigned int hlen,
                     TLS13CombinedHash *hashes);
 static SECStatus tls13_ComputeHandshakeHashes(sslSocket *ss,
                                               TLS13CombinedHash *hashes);
 static SECStatus tls13_ComputeEarlySecrets(sslSocket *ss, PRBool setup0Rtt);
 static SECStatus tls13_ComputeHandshakeSecrets(sslSocket *ss);
 static SECStatus tls13_ComputeApplicationSecrets(sslSocket *ss);
@@ -531,19 +529,16 @@ tls13_HandlePostHelloHandshakeMessage(ss
         SSL_TRC(3, ("%d: TLS13[%d]: %s successfully decrypted handshake after"
                     "failed 0-RTT",
                     SSL_GETPID(), ss->fd));
         ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_none;
     }
 
     /* TODO(ekr@rtfm.com): Would it be better to check all the states here? */
     switch (ss->ssl3.hs.msg_type) {
-        case hello_retry_request:
-            return tls13_HandleHelloRetryRequest(ss, b, length);
-
         case certificate:
             return tls13_HandleCertificate(ss, b, length);
 
         case certificate_request:
             return tls13_HandleCertificateRequest(ss, b, length);
 
         case certificate_verify:
             if (!hashesPtr) {
@@ -1604,30 +1599,36 @@ tls13_SendCertificateRequest(sslSocket *
     rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
 
     return SECSuccess;
 }
 
-static SECStatus
+SECStatus
 tls13_HandleHelloRetryRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 {
     SECStatus rv;
     PRInt32 tmp;
-    PRUint32 version;
+    SSL3ProtocolVersion version;
 
     SSL_TRC(3, ("%d: TLS13[%d]: handle hello retry request",
                 SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
-    /* Client */
+    if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) {
+        FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_HELLO_RETRY_REQUEST,
+                    unexpected_message);
+        return SECFailure;
+    }
+
+    /* Client only. */
     rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_HELLO_RETRY_REQUEST,
                               wait_server_hello);
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
     /* Fool me once, shame on you; fool me twice... */
     if (ss->ssl3.hs.helloRetry) {
@@ -1639,27 +1640,28 @@ tls13_HandleHelloRetryRequest(sslSocket 
     if (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent) {
         /* Oh well, back to the start. */
         tls13_SetNullCipherSpec(ss, &ss->ssl3.cwSpec);
         ss->ssl3.hs.zeroRttState = ssl_0rtt_ignored;
     } else {
         PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_none);
     }
 
-    tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
-    if (tmp < 0) {
-        return SECFailure; /* error code already set */
-    }
-    version = tls13_DecodeDraftVersion((PRUint16)tmp);
+    /* Version. */
+    rv = ssl_ClientReadVersion(ss, &b, &length, &version);
+    if (rv != SECSuccess) {
+        return SECFailure; /* alert already sent */
+    }
     if (version > ss->vrange.max || version < SSL_LIBRARY_VERSION_TLS_1_3) {
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST,
                     protocol_version);
         return SECFailure;
     }
 
+    /* Extensions. */
     tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
     if (tmp < 0) {
         return SECFailure; /* error code already set */
     }
     /* Extensions must be non-empty and use the remainder of the message.
      * This means that a HelloRetryRequest cannot be a no-op: we must have an
      * extension, it must be one that we understand and recognize as being valid
      * for HelloRetryRequest, and all the extensions we permit cause us to
@@ -1738,17 +1740,17 @@ tls13_HandleCertificateRequest(sslSocket
     certRequest->ca_list.arena = arena;
 
     rv = ssl_ParseSignatureSchemes(ss, arena,
                                    &certRequest->signatureSchemes,
                                    &certRequest->signatureSchemeCount,
                                    &b, &length);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST,
-                    illegal_parameter);
+                    decode_error);
         goto loser;
     }
 
     rv = ssl3_ParseCertificateRequestCAs(ss, &b, &length, arena,
                                          &certRequest->ca_list);
     if (rv != SECSuccess)
         goto loser; /* alert already sent */
 
@@ -2426,17 +2428,18 @@ tls13_SetupPendingCipherSpec(sslSocket *
     const ssl3BulkCipherDef *bulk = ssl_GetBulkCipherDef(
         ssl_LookupCipherSuiteDef(suite));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     ssl_GetSpecWriteLock(ss); /*******************************/
 
     pSpec = ss->ssl3.pwSpec;
-    pSpec->version = ss->version;
+    /* Version isn't set when we send 0-RTT data. */
+    pSpec->version = PR_MAX(SSL_LIBRARY_VERSION_TLS_1_3, ss->version);
 
     SSL_TRC(3, ("%d: TLS13[%d]: Set Pending Cipher Suite to 0x%04x",
                 SSL_GETPID(), ss->fd, suite));
     pSpec->cipher_def = bulk;
 
     ssl_ReleaseSpecWriteLock(ss); /*******************************/
     return SECSuccess;
 }
@@ -4197,33 +4200,24 @@ tls13_HandleEarlyApplicationData(sslSock
     PR_APPEND_LINK(&ed->link, &ss->ssl3.hs.bufferedEarlyData);
 
     origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */
 
     return SECSuccess;
 }
 
 PRUint16
-tls13_EncodeDraftVersion(PRUint16 version)
+tls13_EncodeDraftVersion(SSL3ProtocolVersion version)
 {
 #ifdef TLS_1_3_DRAFT_VERSION
-    return version == SSL_LIBRARY_VERSION_TLS_1_3 ? (0x7f00 | TLS_1_3_DRAFT_VERSION) : version;
-#else
-    return version;
+    if (version == SSL_LIBRARY_VERSION_TLS_1_3) {
+        return 0x7f00 | TLS_1_3_DRAFT_VERSION;
+    }
 #endif
-}
-
-PRUint16
-tls13_DecodeDraftVersion(PRUint16 version)
-{
-#ifdef TLS_1_3_DRAFT_VERSION
-    return version == (0x7f00 | TLS_1_3_DRAFT_VERSION) ? SSL_LIBRARY_VERSION_TLS_1_3 : version;
-#else
-    return version;
-#endif
+    return (PRUint16)version;
 }
 
 /* Pick the highest version we support that is also advertised. */
 SECStatus
 tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supported_versions)
 {
     PRUint16 version;
     /* Make a copy so we're nondestructive*/
--- a/security/nss/lib/ssl/tls13con.h
+++ b/security/nss/lib/ssl/tls13con.h
@@ -45,16 +45,18 @@ PRBool tls13_AllowPskCipher(const sslSoc
 PRBool tls13_PskSuiteEnabled(sslSocket *ss);
 SECStatus tls13_HandleClientHelloPart2(sslSocket *ss,
                                        const SECItem *suites,
                                        sslSessionID *sid);
 SECStatus tls13_HandleServerHelloPart2(sslSocket *ss);
 SECStatus tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
                                                 PRUint32 length,
                                                 SSL3Hashes *hashesPtr);
+SECStatus tls13_HandleHelloRetryRequest(sslSocket *ss, SSL3Opaque *b,
+                                        PRUint32 length);
 void tls13_DestroyKeyShareEntry(TLS13KeyShareEntry *entry);
 void tls13_DestroyKeyShares(PRCList *list);
 SECStatus tls13_CreateKeyShare(sslSocket *ss, const sslNamedGroupDef *groupDef);
 void tls13_DestroyEarlyData(PRCList *list);
 void tls13_CipherSpecAddRef(ssl3CipherSpec *spec);
 void tls13_CipherSpecRelease(ssl3CipherSpec *spec);
 void tls13_DestroyCipherSpecs(PRCList *list);
 PRBool tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message);
@@ -63,14 +65,14 @@ SECStatus tls13_ProtectRecord(sslSocket 
                               SSL3ContentType type,
                               const SSL3Opaque *pIn,
                               PRUint32 contentLen,
                               sslBuffer *wrBuf);
 PRInt32 tls13_Read0RttData(sslSocket *ss, void *buf, PRInt32 len);
 SECStatus tls13_HandleEndOfEarlyData(sslSocket *ss);
 SECStatus tls13_HandleEarlyApplicationData(sslSocket *ss, sslBuffer *origBuf);
 PRBool tls13_ClientAllow0Rtt(sslSocket *ss, const sslSessionID *sid);
-PRUint16 tls13_EncodeDraftVersion(PRUint16 version);
+PRUint16 tls13_EncodeDraftVersion(SSL3ProtocolVersion version);
 PRUint16 tls13_DecodeDraftVersion(PRUint16 version);
 SECStatus tls13_NegotiateVersion(sslSocket *ss,
                                  const TLSExtension *supported_versions);
 
 #endif /* __tls13con_h_ */
--- a/security/nss/lib/util/secasn1d.c
+++ b/security/nss/lib/util/secasn1d.c
@@ -1080,18 +1080,19 @@ sec_asn1d_prepare_for_contents(sec_asn1d
      */
     if (state->explicit) {
         state->place = afterExplicit;
         state = sec_asn1d_push_state(state->top,
                                      SEC_ASN1GetSubtemplate(state->theTemplate,
                                                             state->dest,
                                                             PR_FALSE),
                                      state->dest, PR_TRUE);
-        if (state != NULL)
-            state = sec_asn1d_init_state_based_on_template(state);
+        if (state != NULL) {
+            (void)sec_asn1d_init_state_based_on_template(state);
+        }
         return;
     }
 
     /*
      * For GROUP (SET OF, SEQUENCE OF), even if we know the length here
      * we cannot tell how many items we will end up with ... so push a
      * state that can keep track of "children" (the individual members
      * of the group; we will allocate as we go and put them all together
@@ -1112,17 +1113,17 @@ sec_asn1d_prepare_for_contents(sec_asn1d
             state = sec_asn1d_push_state(state->top, subt, NULL, PR_TRUE);
             if (state != NULL) {
                 if (!state->top->filter_only)
                     state->allocate = PR_TRUE; /* XXX propogate this? */
                 /*
                  * Do the "before" field notification for next in group.
                  */
                 sec_asn1d_notify_before(state->top, state->dest, state->depth);
-                state = sec_asn1d_init_state_based_on_template(state);
+                (void)sec_asn1d_init_state_based_on_template(state);
             }
         } else {
             /*
              * A group of zero; we are done.
              * Set state to afterGroup and let that code plant the NULL.
              */
             state->place = afterGroup;
         }
@@ -1137,17 +1138,17 @@ sec_asn1d_prepare_for_contents(sec_asn1d
             state->place = duringSequence;
             state = sec_asn1d_push_state(state->top, state->theTemplate + 1,
                                          state->dest, PR_TRUE);
             if (state != NULL) {
                 /*
                  * Do the "before" field notification.
                  */
                 sec_asn1d_notify_before(state->top, state->dest, state->depth);
-                state = sec_asn1d_init_state_based_on_template(state);
+                (void)sec_asn1d_init_state_based_on_template(state);
             }
             break;
 
         case SEC_ASN1_SET: /* XXX SET is not really implemented */
             /*
              * XXX A plain SET requires special handling; scanning of a
              * template to see where a field should go (because by definition,
              * they are not in any particular order, and you have to look at
@@ -1363,17 +1364,17 @@ sec_asn1d_prepare_for_contents(sec_asn1d
                         sub = NULL;     /* so just do enough to quiet it. */
                         break;
                 }
 
                 state->place = duringConstructedString;
                 state = sec_asn1d_push_state(state->top, sub, item, PR_TRUE);
                 if (state != NULL) {
                     state->substring = PR_TRUE; /* XXX propogate? */
-                    state = sec_asn1d_init_state_based_on_template(state);
+                    (void)sec_asn1d_init_state_based_on_template(state);
                 }
             } else if (state->indefinite) {
                 /*
                  * An indefinite-length string *must* be constructed!
                  */
                 PORT_SetError(SEC_ERROR_BAD_DER);
                 state->top->status = decodeError;
             } else {
--- a/security/nss/lib/util/secasn1e.c
+++ b/security/nss/lib/util/secasn1e.c
@@ -754,17 +754,17 @@ sec_asn1e_write_header(sec_asn1e_state *
         state = sec_asn1e_push_state(state->top, &state->theTemplate[indx],
                                      (char *)state->src - state->theTemplate->offset,
                                      PR_TRUE);
         if (state) {
             /*
              * Do the "before" field notification.
              */
             sec_asn1e_notify_before(state->top, state->src, state->depth);
-            state = sec_asn1e_init_state_based_on_template(state);
+            (void)sec_asn1e_init_state_based_on_template(state);
         }
         return;
     }
 
     /* The !isString test below is apparently intended to ensure that all
     ** constructed types receive indefinite length encoding.
     */
     indefinite = (PRBool)(state->top->streaming && state->may_stream &&
@@ -836,18 +836,19 @@ sec_asn1e_write_header(sec_asn1e_state *
      * An EXPLICIT is nothing but an outer header, which we have already
      * written.  Now we need to do the inner header and contents.
      */
     if (state->isExplicit) {
         const SEC_ASN1Template *subt =
             SEC_ASN1GetSubtemplate(state->theTemplate, state->src, PR_TRUE);
         state->place = afterContents;
         state = sec_asn1e_push_state(state->top, subt, state->src, PR_TRUE);
-        if (state != NULL)
-            state = sec_asn1e_init_state_based_on_template(state);
+        if (state != NULL) {
+            (void)sec_asn1e_init_state_based_on_template(state);
+        }
         return;
     }
 
     switch (state->underlying_kind) {
         case SEC_ASN1_SET_OF:
         case SEC_ASN1_SEQUENCE_OF:
             /*
              * We need to push a child to handle each member.
@@ -863,35 +864,36 @@ sec_asn1e_write_header(sec_asn1e_state *
                      */
                     state->place = afterContents;
                     return;
                 }
                 state->place = duringGroup;
                 subt = SEC_ASN1GetSubtemplate(state->theTemplate, state->src,
                                               PR_TRUE);
                 state = sec_asn1e_push_state(state->top, subt, *group, PR_TRUE);
-                if (state != NULL)
-                    state = sec_asn1e_init_state_based_on_template(state);
+                if (state != NULL) {
+                    (void)sec_asn1e_init_state_based_on_template(state);
+                }
             }
             break;
 
         case SEC_ASN1_SEQUENCE:
         case SEC_ASN1_SET:
             /*
              * We need to push a child to handle the individual fields.
              */
             state->place = duringSequence;
             state = sec_asn1e_push_state(state->top, state->theTemplate + 1,
                                          state->src, PR_TRUE);
             if (state != NULL) {
                 /*
                  * Do the "before" field notification.
                  */
                 sec_asn1e_notify_before(state->top, state->src, state->depth);
-                state = sec_asn1e_init_state_based_on_template(state);
+                (void)sec_asn1e_init_state_based_on_template(state);
             }
             break;
 
         default:
             /*
              * I think we do not need to do anything else.
              * XXX Correct?
              */
--- a/security/nss/lib/util/utilpars.c
+++ b/security/nss/lib/util/utilpars.c
@@ -774,17 +774,16 @@ nssutil_mkRootFlags(PRBool hasRootCerts,
     if (hasRootCerts) {
         PORT_Strcat(flags, "hasRootCerts");
         first = PR_FALSE;
     }
     if (hasRootTrust) {
         if (!first)
             PORT_Strcat(flags, ",");
         PORT_Strcat(flags, "hasRootTrust");
-        first = PR_FALSE;
     }
     return flags;
 }
 
 /* now make a full slot string */
 char *
 NSSUTIL_MkSlotString(unsigned long slotID, unsigned long defaultFlags,
                      unsigned long timeout, unsigned char askpw_in,
@@ -977,17 +976,16 @@ nssutil_mkNSSFlags(PRBool internal, PRBo
             PORT_Strcat(flags, ",");
         PORT_Strcat(flags, "moduleDBOnly");
         first = PR_FALSE;
     }
     if (isCritical) {
         if (!first)
             PORT_Strcat(flags, ",");
         PORT_Strcat(flags, "critical");
-        first = PR_FALSE;
     }
     return flags;
 }
 
 /* construct the NSS cipher flags */
 static char *
 nssutil_mkCipherFlags(unsigned long ssl0, unsigned long ssl1)
 {