Bug 1414735 - Upgrade Firefox to NSS 3.35, r=franziskus UPGRADE_NSS_RELEASE
authorMartin Thomson <martin.thomson@gmail.com>
Tue, 07 Nov 2017 12:24:58 +1100
changeset 443749 996440f4c25776f30092caa38051e25d6008faca
parent 443715 5a38089c03751d5b123b41645167d5858c3a6a5f
child 443750 653c66220a5f3c59f2119bb7cea3e722fee6c47c
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfranziskus
bugs1414735
milestone58.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 1414735 - Upgrade Firefox to NSS 3.35, r=franziskus UPGRADE_NSS_RELEASE MozReview-Commit-ID: 6hDnHCWVeWz
old-configure.in
security/manager/ssl/nsNSSIOLayer.cpp
security/nss/TAG-INFO
security/nss/automation/abi-check/expected-report-libnss3.so.txt
security/nss/automation/abi-check/expected-report-libssl3.so.txt
security/nss/automation/abi-check/previous-nss-release
security/nss/cmd/tstclnt/tstclnt.c
security/nss/coreconf/coreconf.dep
security/nss/gtests/common/util.h
security/nss/gtests/pk11_gtest/manifest.mn
security/nss/gtests/pk11_gtest/pk11_gtest.gyp
security/nss/gtests/ssl_gtest/libssl_internals.c
security/nss/gtests/ssl_gtest/manifest.mn
security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc
security/nss/gtests/ssl_gtest/ssl_gtest.gyp
security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc
security/nss/gtests/ssl_gtest/ssl_record_unittest.cc
security/nss/gtests/ssl_gtest/tls_agent.cc
security/nss/gtests/ssl_gtest/tls_filter.cc
security/nss/gtests/ssl_gtest/tls_filter.h
security/nss/lib/freebl/poly1305.h
security/nss/lib/nss/nss.h
security/nss/lib/softoken/pkcs11.c
security/nss/lib/softoken/pkcs11c.c
security/nss/lib/softoken/softkver.h
security/nss/lib/softoken/softoknt.h
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3ecc.c
security/nss/lib/ssl/ssl3exthandle.c
security/nss/lib/ssl/ssl3gthr.c
security/nss/lib/ssl/ssl3prot.h
security/nss/lib/ssl/sslexp.h
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/sslinfo.c
security/nss/lib/ssl/sslsock.c
security/nss/lib/ssl/tls13con.c
security/nss/lib/ssl/tls13con.h
security/nss/lib/ssl/tls13exthandle.c
security/nss/lib/ssl/tls13exthandle.h
security/nss/lib/util/nssutil.h
security/nss/lib/util/pkcs11uri.c
security/nss/lib/util/secport.c
security/nss/tests/ssl_gtests/ssl_gtests.sh
--- a/old-configure.in
+++ b/old-configure.in
@@ -1910,17 +1910,17 @@ dnl = If NSS was not detected in the sys
 dnl = use the one in the source tree (mozilla/security/nss)
 dnl ========================================================
 
 MOZ_ARG_WITH_BOOL(system-nss,
 [  --with-system-nss       Use system installed NSS],
     _USE_SYSTEM_NSS=1 )
 
 if test -n "$_USE_SYSTEM_NSS"; then
-    AM_PATH_NSS(3.34, [MOZ_SYSTEM_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
+    AM_PATH_NSS(3.35, [MOZ_SYSTEM_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
 fi
 
 if test -n "$MOZ_SYSTEM_NSS"; then
    NSS_LIBS="$NSS_LIBS -lcrmf"
 else
    NSS_CFLAGS="-I${DIST}/include/nss"
    case "${OS_ARCH}" in
         # Only few platforms have been tested with GYP
--- a/security/manager/ssl/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/nsNSSIOLayer.cpp
@@ -70,17 +70,17 @@ namespace {
 // does not impact other normal sockets not using the flags.)
 //
 // Their current definitions are:
 //
 // bits 0-2 (mask 0x07) specify the max tls version
 //          0 means no override 1->4 are 1.0, 1.1, 1.2, 1.3, 4->7 unused
 // bits 3-5 (mask 0x38) specify the tls fallback limit
 //          0 means no override, values 1->4 match prefs
-// bit    6 (mask 0x40) specifies use of SSL_AltServerHelloType on handshake
+// bit    6 (mask 0x40) specifies use of SSL_AltHandshakeType on handshake
 
 enum {
   kTLSProviderFlagMaxVersion10   = 0x01,
   kTLSProviderFlagMaxVersion11   = 0x02,
   kTLSProviderFlagMaxVersion12   = 0x03,
   kTLSProviderFlagMaxVersion13   = 0x04,
 };
 
@@ -89,17 +89,17 @@ static uint32_t getTLSProviderFlagMaxVer
   return (flags & 0x07);
 }
 
 static uint32_t getTLSProviderFlagFallbackLimit(uint32_t flags)
 {
   return (flags & 0x38) >> 3;
 }
 
-static bool getTLSProviderFlagAltServerHello(uint32_t flags)
+static bool getTLSProviderFlagAltHandshake(uint32_t flags)
 {
   return (flags & 0x40);
 }
 
 #define MAX_ALPN_LENGTH 255
 
 void
 getSiteKey(const nsACString& hostName, uint16_t port,
@@ -2596,23 +2596,23 @@ nsSSLIOLayerSetOptions(PRFileDesc* fd, b
       range.max = SSL_LIBRARY_VERSION_TLS_1_3;
     } else {
       MOZ_LOG(gPIPNSSLog, LogLevel::Error,
               ("[%p] nsSSLIOLayerSetOptions: unknown version flags %d\n",
                fd, versionFlags));
     }
   }
 
-  // enabling alternative server hello
-  if (getTLSProviderFlagAltServerHello(infoObject->GetProviderTlsFlags())) {
+  // enabling alternative handshake
+  if (getTLSProviderFlagAltHandshake(infoObject->GetProviderTlsFlags())) {
     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
-            ("[%p] nsSSLIOLayerSetOptions: Use AltServerHello\n", fd));
-    if (SECSuccess != SSL_UseAltServerHelloType(fd, PR_TRUE)) {
+            ("[%p] nsSSLIOLayerSetOptions: Use AltHandshake\n", fd));
+    if (SECSuccess != SSL_UseAltHandshakeType(fd, PR_TRUE)) {
           MOZ_LOG(gPIPNSSLog, LogLevel::Error,
-                  ("[%p] nsSSLIOLayerSetOptions: Use AltServerHello failed\n", fd));
+                  ("[%p] nsSSLIOLayerSetOptions: Use AltHandshake failed\n", fd));
           // continue on default path
     }
   }
 
   if ((infoObject->GetProviderFlags() & nsISocketProvider::BE_CONSERVATIVE) &&
       (range.max > SSL_LIBRARY_VERSION_TLS_1_2)) {
     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
             ("[%p] nsSSLIOLayerSetOptions: range.max limited to 1.2 due to BE_CONSERVATIVE flag\n",
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-NSS_3_34_BETA1
+de7e5e67e878
--- a/security/nss/automation/abi-check/expected-report-libnss3.so.txt
+++ b/security/nss/automation/abi-check/expected-report-libnss3.so.txt
@@ -1,11 +0,0 @@
-Functions changes summary: 0 Removed, 0 Changed, 4 Added functions
-Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
-
-4 Added functions:
-
-  'function SECItem* SEC_CreateSignatureAlgorithmParameters(SECItem*, SECOidTag, SECOidTag, const SECItem*, const SECKEYPrivateKey*)'    {SEC_CreateSignatureAlgorithmParameters@@NSS_3.34}
-  'function SECStatus SEC_DerSignDataWithAlgorithmID(SECItem*, const unsigned char*, int, SECKEYPrivateKey*, SECAlgorithmID*)'    {SEC_DerSignDataWithAlgorithmID@@NSS_3.34}
-  'function SECStatus SEC_SignDataWithAlgorithmID(SECItem*, const unsigned char*, int, SECKEYPrivateKey*, SECAlgorithmID*)'    {SEC_SignDataWithAlgorithmID@@NSS_3.34}
-  'function void SGN_NewContextWithAlgorithmID(SECAlgorithmID*, SECKEYPrivateKey*)'    {SGN_NewContextWithAlgorithmID@@NSS_3.34}
-
-
--- a/security/nss/automation/abi-check/expected-report-libssl3.so.txt
+++ b/security/nss/automation/abi-check/expected-report-libssl3.so.txt
@@ -1,15 +0,0 @@
-Functions changes summary: 0 Removed, 1 Changed, 0 Added function
-Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
-
-1 function with some indirect sub-type change:
-
-  [C]'function SECStatus SSL_GetChannelInfo(SSLChannelInfo*, PRUintn)' at sslinfo.c:26:1 has some indirect sub-type changes:
-    parameter 1 of type 'SSLChannelInfo*' has sub-type changes:
-      in pointed to type 'typedef SSLChannelInfo' at sslt.h:288:1:
-        underlying type 'struct SSLChannelInfoStr' at sslt.h:229:1 changed:
-          type size changed from 896 to 960 bits
-          2 data member insertions:
-            'SSLNamedGroup SSLChannelInfoStr::originalKeaGroup', at offset 864 (in bits) at sslt.h:281:1
-            'PRBool SSLChannelInfoStr::resumed', at offset 896 (in bits) at sslt.h:284:1
-
-
--- a/security/nss/automation/abi-check/previous-nss-release
+++ b/security/nss/automation/abi-check/previous-nss-release
@@ -1,1 +1,1 @@
-NSS_3_33_BRANCH
+NSS_3_34_BRANCH
--- a/security/nss/cmd/tstclnt/tstclnt.c
+++ b/security/nss/cmd/tstclnt/tstclnt.c
@@ -247,17 +247,17 @@ PrintParameterUsage(void)
     fprintf(stderr, "%-20s Require the use of FFDHE supported groups [RFC7919]\n", "-H");
     fprintf(stderr, "%-20s Read from a file instead of stdin\n", "-A");
     fprintf(stderr, "%-20s Allow 0-RTT data (TLS 1.3 only)\n", "-Z");
     fprintf(stderr, "%-20s Disconnect and reconnect up to N times total\n", "-L");
     fprintf(stderr, "%-20s Comma separated list of enabled groups for TLS key exchange.\n"
                     "%-20s The following values are valid:\n"
                     "%-20s P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192\n",
             "-I", "", "");
-    fprintf(stderr, "%-20s Enable alternate content type for TLS 1.3 ServerHello\n", "-X alt-server-hello");
+    fprintf(stderr, "%-20s Enable alternative TLS 1.3 handshake\n", "-X alt-server-hello");
 }
 
 static void
 Usage(const char *progName)
 {
     PrintUsageHeader(progName);
     PrintParameterUsage();
     exit(1);
@@ -1178,17 +1178,17 @@ run_client(void)
             SECU_PrintError(progName, "error enabling 0-RTT");
             error = 1;
             goto done;
         }
     }
 
     /* Alternate ServerHello content type (TLS 1.3 only) */
     if (enableAltServerHello) {
-        rv = SSL_UseAltServerHelloType(s, PR_TRUE);
+        rv = SSL_UseAltHandshakeType(s, PR_TRUE);
         if (rv != SECSuccess) {
             SECU_PrintError(progName, "error enabling alternate ServerHello type");
             error = 1;
             goto done;
         }
     }
 
     /* require the use of fixed finite-field DH groups */
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/security/nss/gtests/common/util.h
+++ b/security/nss/gtests/common/util.h
@@ -5,17 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef util_h__
 #define util_h__
 
 #include <cassert>
 #include <vector>
 
-std::vector<uint8_t> hex_string_to_bytes(std::string s) {
+static inline std::vector<uint8_t> hex_string_to_bytes(std::string s) {
   std::vector<uint8_t> bytes;
   for (size_t i = 0; i < s.length(); i += 2) {
     bytes.push_back(std::stoul(s.substr(i, 2), nullptr, 16));
   }
   return bytes;
 }
 
 #endif  // util_h__
--- a/security/nss/gtests/pk11_gtest/manifest.mn
+++ b/security/nss/gtests/pk11_gtest/manifest.mn
@@ -6,16 +6,17 @@ CORE_DEPTH = ../..
 DEPTH      = ../..
 MODULE = nss
 
 CPPSRCS = \
       pk11_aeskeywrap_unittest.cc \
       pk11_chacha20poly1305_unittest.cc \
       pk11_curve25519_unittest.cc \
       pk11_ecdsa_unittest.cc \
+      pk11_encrypt_derive_unittest.cc \
       pk11_export_unittest.cc \
       pk11_pbkdf2_unittest.cc \
       pk11_prf_unittest.cc \
       pk11_prng_unittest.cc \
       pk11_rsapss_unittest.cc \
       pk11_der_private_key_import_unittest.cc \
       $(NULL)
 
--- a/security/nss/gtests/pk11_gtest/pk11_gtest.gyp
+++ b/security/nss/gtests/pk11_gtest/pk11_gtest.gyp
@@ -11,16 +11,17 @@
       'target_name': 'pk11_gtest',
       'type': 'executable',
       'sources': [
         'pk11_aeskeywrap_unittest.cc',
         'pk11_aes_gcm_unittest.cc',
         'pk11_chacha20poly1305_unittest.cc',
         'pk11_curve25519_unittest.cc',
         'pk11_ecdsa_unittest.cc',
+        'pk11_encrypt_derive_unittest.cc',
         'pk11_pbkdf2_unittest.cc',
         'pk11_prf_unittest.cc',
         'pk11_prng_unittest.cc',
         'pk11_rsapss_unittest.cc',
         'pk11_der_private_key_import_unittest.cc',
         '<(DEPTH)/gtests/common/gtests.cc'
       ],
       'dependencies': [
--- a/security/nss/gtests/ssl_gtest/libssl_internals.c
+++ b/security/nss/gtests/ssl_gtest/libssl_internals.c
@@ -35,22 +35,22 @@ SECStatus SSLInt_UpdateSSLv2ClientRandom
   }
 
   ssl3_InitState(ss);
   ssl3_RestartHandshakeHashes(ss);
 
   // Ensure we don't overrun hs.client_random.
   rnd_len = PR_MIN(SSL3_RANDOM_LENGTH, rnd_len);
 
-  // Zero the client_random struct.
-  PORT_Memset(&ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH);
+  // Zero the client_random.
+  PORT_Memset(ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH);
 
   // Copy over the challenge bytes.
   size_t offset = SSL3_RANDOM_LENGTH - rnd_len;
-  PORT_Memcpy(&ss->ssl3.hs.client_random.rand[offset], rnd, rnd_len);
+  PORT_Memcpy(ss->ssl3.hs.client_random + offset, rnd, rnd_len);
 
   // Rehash the SSLv2 client hello message.
   return ssl3_UpdateHandshakeHashes(ss, msg, msg_len);
 }
 
 PRBool SSLInt_ExtensionNegotiated(PRFileDesc *fd, PRUint16 ext) {
   sslSocket *ss = ssl_FindSocket(fd);
   return (PRBool)(ss && ssl3_ExtensionNegotiated(ss, ext));
--- a/security/nss/gtests/ssl_gtest/manifest.mn
+++ b/security/nss/gtests/ssl_gtest/manifest.mn
@@ -9,16 +9,17 @@ MODULE = nss
 # These sources have access to libssl internals
 CSRCS = \
       libssl_internals.c \
       $(NULL)
 
 CPPSRCS = \
       ssl_0rtt_unittest.cc \
       ssl_agent_unittest.cc \
+      ssl_alths_unittest.cc \
       ssl_auth_unittest.cc \
       ssl_cert_ext_unittest.cc \
       ssl_ciphersuite_unittest.cc \
       ssl_damage_unittest.cc \
       ssl_dhe_unittest.cc \
       ssl_drop_unittest.cc \
       ssl_ecdh_unittest.cc \
       ssl_ems_unittest.cc \
--- a/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc
@@ -1074,20 +1074,16 @@ TEST_P(TlsBogusExtensionTest13, AddBogus
 
 TEST_P(TlsBogusExtensionTest13, AddBogusExtensionHelloRetryRequest) {
   static const std::vector<SSLNamedGroup> groups = {ssl_grp_ec_secp384r1};
   server_->ConfigNamedGroups(groups);
 
   Run(kTlsHandshakeHelloRetryRequest);
 }
 
-TEST_P(TlsBogusExtensionTest13, AddVersionExtensionServerHello) {
-  Run(kTlsHandshakeServerHello, ssl_tls13_supported_versions_xtn);
-}
-
 TEST_P(TlsBogusExtensionTest13, AddVersionExtensionEncryptedExtensions) {
   Run(kTlsHandshakeEncryptedExtensions, ssl_tls13_supported_versions_xtn);
 }
 
 TEST_P(TlsBogusExtensionTest13, AddVersionExtensionCertificate) {
   Run(kTlsHandshakeCertificate, ssl_tls13_supported_versions_xtn);
 }
 
--- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
+++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
@@ -10,16 +10,17 @@
     {
       'target_name': 'ssl_gtest',
       'type': 'executable',
       'sources': [
         'libssl_internals.c',
         'selfencrypt_unittest.cc',
         'ssl_0rtt_unittest.cc',
         'ssl_agent_unittest.cc',
+        'ssl_alths_unittest.cc',
         'ssl_auth_unittest.cc',
         'ssl_cert_ext_unittest.cc',
         'ssl_ciphersuite_unittest.cc',
         'ssl_damage_unittest.cc',
         'ssl_dhe_unittest.cc',
         'ssl_drop_unittest.cc',
         'ssl_ecdh_unittest.cc',
         'ssl_ems_unittest.cc',
--- a/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc
@@ -6,17 +6,16 @@
 
 #include <functional>
 #include <memory>
 #include <vector>
 #include "secerr.h"
 #include "ssl.h"
 #include "sslerr.h"
 #include "sslproto.h"
-#include "ssl3prot.h"
 
 extern "C" {
 // This is not something that should make you happy.
 #include "libssl_internals.h"
 }
 
 #include "gtest_utils.h"
 #include "scoped_ptrs.h"
@@ -99,19 +98,19 @@ class HelloTruncator : public TlsHandsha
 };
 
 // Verify that when NSS reports that an alert is sent, it is actually sent.
 TEST_P(TlsConnectGeneric, CaptureAlertServer) {
   client_->SetPacketFilter(std::make_shared<HelloTruncator>());
   auto alert_recorder = std::make_shared<TlsAlertRecorder>();
   server_->SetPacketFilter(alert_recorder);
 
-  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
+  ConnectExpectAlert(server_, kTlsAlertDecodeError);
   EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
-  EXPECT_EQ(kTlsAlertIllegalParameter, alert_recorder->description());
+  EXPECT_EQ(kTlsAlertDecodeError, alert_recorder->description());
 }
 
 TEST_P(TlsConnectGenericPre13, CaptureAlertClient) {
   server_->SetPacketFilter(std::make_shared<HelloTruncator>());
   auto alert_recorder = std::make_shared<TlsAlertRecorder>();
   client_->SetPacketFilter(alert_recorder);
 
   ConnectExpectAlert(client_, kTlsAlertDecodeError);
@@ -302,52 +301,16 @@ TEST_F(TlsConnectStreamTls13, Tls13Faile
 TEST_F(TlsConnectStreamTls13, NegotiateShortHeaders) {
   client_->SetShortHeadersEnabled();
   server_->SetShortHeadersEnabled();
   client_->ExpectShortHeaders();
   server_->ExpectShortHeaders();
   Connect();
 }
 
-TEST_F(TlsConnectStreamTls13, ClientAltHandshakeType) {
-  client_->SetAltHandshakeTypeEnabled();
-  auto filter = std::make_shared<TlsHeaderRecorder>();
-  server_->SetPacketFilter(filter);
-  Connect();
-  ASSERT_EQ(kTlsHandshakeType, filter->header(0)->content_type());
-}
-
-TEST_F(TlsConnectStreamTls13, ServerAltHandshakeType) {
-  server_->SetAltHandshakeTypeEnabled();
-  auto filter = std::make_shared<TlsHeaderRecorder>();
-  server_->SetPacketFilter(filter);
-  Connect();
-  ASSERT_EQ(kTlsHandshakeType, filter->header(0)->content_type());
-}
-
-TEST_F(TlsConnectStreamTls13, BothAltHandshakeType) {
-  client_->SetAltHandshakeTypeEnabled();
-  server_->SetAltHandshakeTypeEnabled();
-  auto header_filter = std::make_shared<TlsHeaderRecorder>();
-  auto sh_filter = std::make_shared<TlsInspectorRecordHandshakeMessage>(
-      kTlsHandshakeServerHello);
-  std::vector<std::shared_ptr<PacketFilter>> filters = {header_filter,
-                                                        sh_filter};
-  auto chained = std::make_shared<ChainedPacketFilter>(filters);
-  server_->SetPacketFilter(chained);
-  header_filter->SetAgent(server_.get());
-  header_filter->EnableDecryption();
-  Connect();
-  ASSERT_EQ(kTlsAltHandshakeType, header_filter->header(0)->content_type());
-  ASSERT_EQ(kTlsHandshakeType, header_filter->header(1)->content_type());
-  uint32_t ver;
-  ASSERT_TRUE(sh_filter->buffer().Read(0, 2, &ver));
-  ASSERT_EQ((uint32_t)(0x7a00 | TLS_1_3_DRAFT_VERSION), ver);
-}
-
 INSTANTIATE_TEST_CASE_P(
     GenericStream, TlsConnectGeneric,
     ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
                        TlsConnectTestBase::kTlsVAll));
 INSTANTIATE_TEST_CASE_P(
     GenericDatagram, TlsConnectGeneric,
     ::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram,
                        TlsConnectTestBase::kTlsV11Plus));
--- a/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc
@@ -5,16 +5,18 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nss.h"
 #include "ssl.h"
 #include "sslimpl.h"
 
 #include "databuffer.h"
 #include "gtest_utils.h"
+#include "tls_connect.h"
+#include "tls_filter.h"
 
 namespace nss_test {
 
 const static size_t kMacSize = 20;
 
 class TlsPaddingTest
     : public ::testing::Test,
       public ::testing::WithParamInterface<std::tuple<size_t, bool>> {
@@ -46,18 +48,18 @@ class TlsPaddingTest
   }
 
   void Unpad(bool expect_success) {
     std::cerr << "Content length=" << plaintext_len_
               << " padding length=" << pad_len_
               << " total length=" << plaintext_.len() << std::endl;
     std::cerr << "Plaintext: " << plaintext_ << std::endl;
     sslBuffer s;
-    s.buf = const_cast<unsigned char *>(
-        static_cast<const unsigned char *>(plaintext_.data()));
+    s.buf = const_cast<unsigned char*>(
+        static_cast<const unsigned char*>(plaintext_.data()));
     s.len = plaintext_.len();
     SECStatus rv = ssl_RemoveTLSCBCPadding(&s, kMacSize);
     if (expect_success) {
       EXPECT_EQ(SECSuccess, rv);
       EXPECT_EQ(plaintext_len_, static_cast<size_t>(s.len));
     } else {
       EXPECT_EQ(SECFailure, rv);
     }
@@ -94,16 +96,85 @@ TEST_P(TlsPaddingTest, FirstByteOfPadWro
 TEST_P(TlsPaddingTest, LastByteOfPadWrong) {
   if (pad_len_) {
     plaintext_.Write(plaintext_.len() - 2,
                      plaintext_.data()[plaintext_.len() - 1] + 1, 1);
     Unpad(false);
   }
 }
 
+class RecordReplacer : public TlsRecordFilter {
+ public:
+  RecordReplacer(size_t size)
+      : TlsRecordFilter(), enabled_(false), size_(size) {}
+
+  PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
+                                    const DataBuffer& data,
+                                    DataBuffer* changed) override {
+    if (!enabled_) {
+      return KEEP;
+    }
+
+    EXPECT_EQ(kTlsApplicationDataType, header.content_type());
+    changed->Allocate(size_);
+
+    for (size_t i = 0; i < size_; ++i) {
+      changed->data()[i] = i & 0xff;
+    }
+
+    enabled_ = false;
+    return CHANGE;
+  }
+
+  void Enable() { enabled_ = true; }
+
+ private:
+  bool enabled_;
+  size_t size_;
+};
+
+TEST_F(TlsConnectStreamTls13, LargeRecord) {
+  EnsureTlsSetup();
+
+  const size_t record_limit = 16384;
+  auto replacer = std::make_shared<RecordReplacer>(record_limit);
+  client_->SetTlsRecordFilter(replacer);
+  replacer->EnableDecryption();
+  Connect();
+
+  replacer->Enable();
+  client_->SendData(10);
+  WAIT_(server_->received_bytes() == record_limit, 2000);
+  ASSERT_EQ(record_limit, server_->received_bytes());
+}
+
+TEST_F(TlsConnectStreamTls13, TooLargeRecord) {
+  EnsureTlsSetup();
+
+  const size_t record_limit = 16384;
+  auto replacer = std::make_shared<RecordReplacer>(record_limit + 1);
+  client_->SetTlsRecordFilter(replacer);
+  replacer->EnableDecryption();
+  Connect();
+
+  replacer->Enable();
+  ExpectAlert(server_, kTlsAlertRecordOverflow);
+  client_->SendData(10);  // This is expanded.
+
+  uint8_t buf[record_limit + 2];
+  PRInt32 rv = PR_Read(server_->ssl_fd(), buf, sizeof(buf));
+  EXPECT_GT(0, rv);
+  EXPECT_EQ(SSL_ERROR_RX_RECORD_TOO_LONG, PORT_GetError());
+
+  // Read the server alert.
+  rv = PR_Read(client_->ssl_fd(), buf, sizeof(buf));
+  EXPECT_GT(0, rv);
+  EXPECT_EQ(SSL_ERROR_RECORD_OVERFLOW_ALERT, PORT_GetError());
+}
+
 const static size_t kContentSizesArr[] = {
     1, kMacSize - 1, kMacSize, 30, 31, 32, 36, 256, 257, 287, 288};
 
 auto kContentSizes = ::testing::ValuesIn(kContentSizesArr);
 const static bool kTrueFalseArr[] = {true, false};
 auto kTrueFalse = ::testing::ValuesIn(kTrueFalseArr);
 
 INSTANTIATE_TEST_CASE_P(TlsPadding, TlsPaddingTest,
--- a/security/nss/gtests/ssl_gtest/tls_agent.cc
+++ b/security/nss/gtests/ssl_gtest/tls_agent.cc
@@ -382,17 +382,17 @@ void TlsAgent::SetShortHeadersEnabled() 
 
   SECStatus rv = SSLInt_EnableShortHeaders(ssl_fd());
   EXPECT_EQ(SECSuccess, rv);
 }
 
 void TlsAgent::SetAltHandshakeTypeEnabled() {
   EXPECT_TRUE(EnsureTlsSetup());
 
-  SECStatus rv = SSL_UseAltServerHelloType(ssl_fd(), true);
+  SECStatus rv = SSL_UseAltHandshakeType(ssl_fd(), PR_TRUE);
   EXPECT_EQ(SECSuccess, rv);
 }
 
 void TlsAgent::SetVersionRange(uint16_t minver, uint16_t maxver) {
   vrange_.min = minver;
   vrange_.max = maxver;
 
   if (ssl_fd()) {
--- a/security/nss/gtests/ssl_gtest/tls_filter.cc
+++ b/security/nss/gtests/ssl_gtest/tls_filter.cc
@@ -358,16 +358,25 @@ PacketFilter::Action TlsInspectorReplace
   if (header.handshake_type() == handshake_type_) {
     *output = buffer_;
     return CHANGE;
   }
 
   return KEEP;
 }
 
+PacketFilter::Action TlsRecordRecorder::FilterRecord(
+    const TlsRecordHeader& header, const DataBuffer& input,
+    DataBuffer* output) {
+  if (!filter_ || (header.content_type() == ct_)) {
+    records_.push_back({header, input});
+  }
+  return KEEP;
+}
+
 PacketFilter::Action TlsConversationRecorder::FilterRecord(
     const TlsRecordHeader& header, const DataBuffer& input,
     DataBuffer* output) {
   buffer_.Append(input);
   return KEEP;
 }
 
 PacketFilter::Action TlsHeaderRecorder::FilterRecord(
--- a/security/nss/gtests/ssl_gtest/tls_filter.h
+++ b/security/nss/gtests/ssl_gtest/tls_filter.h
@@ -58,16 +58,21 @@ class TlsRecordHeader : public TlsVersio
   // Return the offset of the end of the write.
   size_t Write(DataBuffer* buffer, size_t offset, const DataBuffer& body) const;
 
  private:
   uint8_t content_type_;
   uint64_t sequence_number_;
 };
 
+struct TlsRecord {
+  const TlsRecordHeader header;
+  const DataBuffer buffer;
+};
+
 // Abstract filter that operates on entire (D)TLS records.
 class TlsRecordFilter : public PacketFilter {
  public:
   TlsRecordFilter() : agent_(nullptr), count_(0), cipher_spec_() {}
 
   void SetAgent(const TlsAgent* agent) { agent_ = agent; }
   const TlsAgent* agent() const { return agent_; }
 
@@ -216,16 +221,38 @@ class TlsInspectorReplaceHandshakeMessag
                                                const DataBuffer& input,
                                                DataBuffer* output);
 
  private:
   uint8_t handshake_type_;
   DataBuffer buffer_;
 };
 
+class TlsRecordRecorder : public TlsRecordFilter {
+ public:
+  TlsRecordRecorder(uint8_t ct) : filter_(true), ct_(ct), records_() {}
+  TlsRecordRecorder()
+      : filter_(false),
+        ct_(content_handshake),  // dummy (<optional> is C++14)
+        records_() {}
+  virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
+                                            const DataBuffer& input,
+                                            DataBuffer* output);
+
+  size_t count() const { return records_.size(); }
+  void Clear() { records_.clear(); }
+
+  const TlsRecord& record(size_t i) const { return records_[i]; }
+
+ private:
+  bool filter_;
+  uint8_t ct_;
+  std::vector<TlsRecord> records_;
+};
+
 // Make a copy of the complete conversation.
 class TlsConversationRecorder : public TlsRecordFilter {
  public:
   TlsConversationRecorder(DataBuffer& buffer) : buffer_(buffer) {}
 
   virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
                                             const DataBuffer& input,
                                             DataBuffer* output);
@@ -242,21 +269,26 @@ class TlsHeaderRecorder : public TlsReco
                                             DataBuffer* output);
   const TlsRecordHeader* header(size_t index);
 
  private:
   std::vector<TlsRecordHeader> headers_;
 };
 
 // Runs multiple packet filters in series.
+typedef std::initializer_list<std::shared_ptr<PacketFilter>>
+    ChainedPacketFilterInit;
+
+// Runs multiple packet filters in series.
 class ChainedPacketFilter : public PacketFilter {
  public:
   ChainedPacketFilter() {}
   ChainedPacketFilter(const std::vector<std::shared_ptr<PacketFilter>> filters)
       : filters_(filters.begin(), filters.end()) {}
+  ChainedPacketFilter(ChainedPacketFilterInit il) : filters_(il) {}
   virtual ~ChainedPacketFilter() {}
 
   virtual PacketFilter::Action Filter(const DataBuffer& input,
                                       DataBuffer* output);
 
   // Takes ownership of the filter.
   void Add(std::shared_ptr<PacketFilter> filter) { filters_.push_back(filter); }
 
--- a/security/nss/lib/freebl/poly1305.h
+++ b/security/nss/lib/freebl/poly1305.h
@@ -3,16 +3,18 @@
  *
  * 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 FREEBL_POLY1305_H_
 #define FREEBL_POLY1305_H_
 
+#include "stddef.h"
+
 typedef unsigned char poly1305_state[512];
 
 /* Poly1305Init sets up |state| so that it can be used to calculate an
  * authentication tag with the one-time key |key|. Note that |key| is a
  * one-time key and therefore there is no `reset' method because that would
  * enable several messages to be authenticated with the same key. */
 extern void Poly1305Init(poly1305_state* state, const unsigned char key[32]);
 
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -17,19 +17,19 @@
 
 /*
  * NSS's major version, minor version, patch level, build number, and whether
  * this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define NSS_VERSION "3.34" _NSS_CUSTOMIZED " Beta"
+#define NSS_VERSION "3.35" _NSS_CUSTOMIZED " Beta"
 #define NSS_VMAJOR 3
-#define NSS_VMINOR 34
+#define NSS_VMINOR 35
 #define NSS_VPATCH 0
 #define NSS_VBUILD 0
 #define NSS_BETA PR_TRUE
 
 #ifndef RC_INVOKED
 
 #include "seccomon.h"
 
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -416,21 +416,30 @@ static const struct mechanismList mechan
     { CKM_IDEA_ECB, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
     { CKM_IDEA_CBC, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
     { CKM_IDEA_MAC, { 16, 16, CKF_SN_VR }, PR_TRUE },
     { CKM_IDEA_MAC_GENERAL, { 16, 16, CKF_SN_VR }, PR_TRUE },
     { CKM_IDEA_CBC_PAD, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
 #endif
     /* --------------------- Secret Key Operations ------------------------ */
     { CKM_GENERIC_SECRET_KEY_GEN, { 1, 32, CKF_GENERATE }, PR_TRUE },
-    { CKM_CONCATENATE_BASE_AND_KEY, { 1, 32, CKF_GENERATE }, PR_FALSE },
-    { CKM_CONCATENATE_BASE_AND_DATA, { 1, 32, CKF_GENERATE }, PR_FALSE },
-    { CKM_CONCATENATE_DATA_AND_BASE, { 1, 32, CKF_GENERATE }, PR_FALSE },
-    { CKM_XOR_BASE_AND_DATA, { 1, 32, CKF_GENERATE }, PR_FALSE },
+    { CKM_CONCATENATE_BASE_AND_KEY, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_CONCATENATE_BASE_AND_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_CONCATENATE_DATA_AND_BASE, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_XOR_BASE_AND_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
     { CKM_EXTRACT_KEY_FROM_KEY, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_DES3_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_DES3_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_AES_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_AES_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_CAMELLIA_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_CAMELLIA_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_SEED_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_SEED_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+
     /* ---------------------- SSL Key Derivations ------------------------- */
     { CKM_SSL3_PRE_MASTER_KEY_GEN, { 48, 48, CKF_GENERATE }, PR_FALSE },
     { CKM_SSL3_MASTER_KEY_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
     { CKM_SSL3_MASTER_KEY_DERIVE_DH, { 8, 128, CKF_DERIVE }, PR_FALSE },
     { CKM_SSL3_KEY_AND_MAC_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
     { CKM_SSL3_MD5_MAC, { 0, 16, CKF_DERIVE }, PR_FALSE },
     { CKM_SSL3_SHA1_MAC, { 0, 20, CKF_DERIVE }, PR_FALSE },
     { CKM_MD5_KEY_DERIVATION, { 0, 16, CKF_DERIVE }, PR_FALSE },
--- a/security/nss/lib/softoken/pkcs11c.c
+++ b/security/nss/lib/softoken/pkcs11c.c
@@ -1519,18 +1519,17 @@ NSC_DecryptUpdate(CK_SESSION_HANDLE hSes
             rv = (*context->update)(context->cipherInfo, pPart, &padoutlen,
                                     maxout, context->padBuf, context->blockSize);
             if (rv != SECSuccess)
                 return sftk_MapDecryptError(PORT_GetError());
             pPart += padoutlen;
             maxout -= padoutlen;
         }
         /* now save the final block for the next decrypt or the final */
-        PORT_Memcpy(context->padBuf, &pEncryptedPart[ulEncryptedPartLen -
-                                                     context->blockSize],
+        PORT_Memcpy(context->padBuf, &pEncryptedPart[ulEncryptedPartLen - context->blockSize],
                     context->blockSize);
         context->padDataLength = context->blockSize;
         ulEncryptedPartLen -= context->padDataLength;
     }
 
     /* do it: NOTE: this assumes buf size in is >= buf size out! */
     rv = (*context->update)(context->cipherInfo, pPart, &outlen,
                             maxout, pEncryptedPart, ulEncryptedPartLen);
@@ -6237,16 +6236,53 @@ sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_UL
     else if (kdf == CKD_SHA512_KDF)
         return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
                                            SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH);
     else
         return CKR_MECHANISM_INVALID;
 }
 
 /*
+ *  Handle the derive from a block encryption cipher
+ */
+CK_RV
+sftk_DeriveEncrypt(SFTKCipher encrypt, void *cipherInfo,
+                   int blockSize, SFTKObject *key, CK_ULONG keySize,
+                   unsigned char *data, CK_ULONG len)
+{
+    /* large enough for a 512-bit key */
+    unsigned char tmpdata[SFTK_MAX_DERIVE_KEY_SIZE];
+    SECStatus rv;
+    unsigned int outLen;
+    CK_RV crv;
+
+    if ((len % blockSize) != 0) {
+        return CKR_MECHANISM_PARAM_INVALID;
+    }
+    if (len > SFTK_MAX_DERIVE_KEY_SIZE) {
+        return CKR_MECHANISM_PARAM_INVALID;
+    }
+    if (keySize && (len < keySize)) {
+        return CKR_MECHANISM_PARAM_INVALID;
+    }
+    if (keySize == 0) {
+        keySize = len;
+    }
+
+    rv = (*encrypt)(cipherInfo, &tmpdata, &outLen, len, data, len);
+    if (rv != SECSuccess) {
+        crv = sftk_MapCryptError(PORT_GetError());
+        return crv;
+    }
+
+    crv = sftk_forceAttribute(key, CKA_VALUE, tmpdata, keySize);
+    return crv;
+}
+
+/*
  * SSL Key generation given pre master secret
  */
 #define NUM_MIXERS 9
 static const char *const mixers[NUM_MIXERS] = {
     "A",
     "BB",
     "CCC",
     "DDDD",
@@ -6894,16 +6930,182 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
             }
             MD5_DestroyContext(md5, PR_TRUE);
             SHA1_DestroyContext(sha, PR_TRUE);
             sftk_FreeObject(key);
             key = NULL;
             break;
         }
 
+        case CKM_DES3_ECB_ENCRYPT_DATA:
+        case CKM_DES3_CBC_ENCRYPT_DATA: {
+            void *cipherInfo;
+            unsigned char des3key[MAX_DES3_KEY_SIZE];
+            CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr;
+            int mode;
+            unsigned char *iv;
+            unsigned char *data;
+            CK_ULONG len;
+
+            if (mechanism == CKM_DES3_ECB_ENCRYPT_DATA) {
+                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
+                                pMechanism->pParameter;
+                mode = NSS_DES_EDE3;
+                iv = NULL;
+                data = stringPtr->pData;
+                len = stringPtr->ulLen;
+            } else {
+                mode = NSS_DES_EDE3_CBC;
+                desEncryptPtr =
+                    (CK_DES_CBC_ENCRYPT_DATA_PARAMS *)
+                        pMechanism->pParameter;
+                iv = desEncryptPtr->iv;
+                data = desEncryptPtr->pData;
+                len = desEncryptPtr->length;
+            }
+            if (att->attrib.ulValueLen == 16) {
+                PORT_Memcpy(des3key, att->attrib.pValue, 16);
+                PORT_Memcpy(des3key + 16, des3key, 8);
+            } else if (att->attrib.ulValueLen == 24) {
+                PORT_Memcpy(des3key, att->attrib.pValue, 24);
+            } else {
+                crv = CKR_KEY_SIZE_RANGE;
+                break;
+            }
+            cipherInfo = DES_CreateContext(des3key, iv, mode, PR_TRUE);
+            PORT_Memset(des3key, 0, 24);
+            if (cipherInfo == NULL) {
+                crv = CKR_HOST_MEMORY;
+                break;
+            }
+            crv = sftk_DeriveEncrypt((SFTKCipher)DES_Encrypt,
+                                     cipherInfo, 8, key, keySize,
+                                     data, len);
+            DES_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+        }
+
+        case CKM_AES_ECB_ENCRYPT_DATA:
+        case CKM_AES_CBC_ENCRYPT_DATA: {
+            void *cipherInfo;
+            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
+            int mode;
+            unsigned char *iv;
+            unsigned char *data;
+            CK_ULONG len;
+
+            if (mechanism == CKM_AES_ECB_ENCRYPT_DATA) {
+                mode = NSS_AES;
+                iv = NULL;
+                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
+                data = stringPtr->pData;
+                len = stringPtr->ulLen;
+            } else {
+                aesEncryptPtr =
+                    (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)pMechanism->pParameter;
+                mode = NSS_AES_CBC;
+                iv = aesEncryptPtr->iv;
+                data = aesEncryptPtr->pData;
+                len = aesEncryptPtr->length;
+            }
+
+            cipherInfo = AES_CreateContext((unsigned char *)att->attrib.pValue,
+                                           iv, mode, PR_TRUE,
+                                           att->attrib.ulValueLen, 16);
+            if (cipherInfo == NULL) {
+                crv = CKR_HOST_MEMORY;
+                break;
+            }
+            crv = sftk_DeriveEncrypt((SFTKCipher)AES_Encrypt,
+                                     cipherInfo, 16, key, keySize,
+                                     data, len);
+            AES_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+        }
+
+        case CKM_CAMELLIA_ECB_ENCRYPT_DATA:
+        case CKM_CAMELLIA_CBC_ENCRYPT_DATA: {
+            void *cipherInfo;
+            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
+            int mode;
+            unsigned char *iv;
+            unsigned char *data;
+            CK_ULONG len;
+
+            if (mechanism == CKM_CAMELLIA_ECB_ENCRYPT_DATA) {
+                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
+                                pMechanism->pParameter;
+                aesEncryptPtr = NULL;
+                mode = NSS_CAMELLIA;
+                data = stringPtr->pData;
+                len = stringPtr->ulLen;
+                iv = NULL;
+            } else {
+                stringPtr = NULL;
+                aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
+                                    pMechanism->pParameter;
+                mode = NSS_CAMELLIA_CBC;
+                iv = aesEncryptPtr->iv;
+                data = aesEncryptPtr->pData;
+                len = aesEncryptPtr->length;
+            }
+
+            cipherInfo = Camellia_CreateContext((unsigned char *)att->attrib.pValue,
+                                                iv, mode, PR_TRUE,
+                                                att->attrib.ulValueLen);
+            if (cipherInfo == NULL) {
+                crv = CKR_HOST_MEMORY;
+                break;
+            }
+            crv = sftk_DeriveEncrypt((SFTKCipher)Camellia_Encrypt,
+                                     cipherInfo, 16, key, keySize,
+                                     data, len);
+            Camellia_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+        }
+
+        case CKM_SEED_ECB_ENCRYPT_DATA:
+        case CKM_SEED_CBC_ENCRYPT_DATA: {
+            void *cipherInfo;
+            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
+            int mode;
+            unsigned char *iv;
+            unsigned char *data;
+            CK_ULONG len;
+
+            if (mechanism == CKM_SEED_ECB_ENCRYPT_DATA) {
+                mode = NSS_SEED;
+                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
+                                pMechanism->pParameter;
+                aesEncryptPtr = NULL;
+                data = stringPtr->pData;
+                len = stringPtr->ulLen;
+                iv = NULL;
+            } else {
+                mode = NSS_SEED_CBC;
+                aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
+                                    pMechanism->pParameter;
+                iv = aesEncryptPtr->iv;
+                data = aesEncryptPtr->pData;
+                len = aesEncryptPtr->length;
+            }
+
+            cipherInfo = SEED_CreateContext((unsigned char *)att->attrib.pValue,
+                                            iv, mode, PR_TRUE);
+            if (cipherInfo == NULL) {
+                crv = CKR_HOST_MEMORY;
+                break;
+            }
+            crv = sftk_DeriveEncrypt((SFTKCipher)SEED_Encrypt,
+                                     cipherInfo, 16, key, keySize,
+                                     data, len);
+            SEED_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+        }
+
         case CKM_CONCATENATE_BASE_AND_KEY: {
             SFTKObject *newKey;
 
             crv = sftk_DeriveSensitiveCheck(sourceKey, key);
             if (crv != CKR_OK)
                 break;
 
             session = sftk_SessionFromHandle(hSession);
--- a/security/nss/lib/softoken/softkver.h
+++ b/security/nss/lib/softoken/softkver.h
@@ -12,16 +12,16 @@
 
 /*
  * Softoken's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define SOFTOKEN_VERSION "3.34" SOFTOKEN_ECC_STRING " Beta"
+#define SOFTOKEN_VERSION "3.35" SOFTOKEN_ECC_STRING " Beta"
 #define SOFTOKEN_VMAJOR 3
-#define SOFTOKEN_VMINOR 34
+#define SOFTOKEN_VMINOR 35
 #define SOFTOKEN_VPATCH 0
 #define SOFTOKEN_VBUILD 0
 #define SOFTOKEN_BETA PR_TRUE
 
 #endif /* _SOFTKVER_H_ */
--- a/security/nss/lib/softoken/softoknt.h
+++ b/security/nss/lib/softoken/softoknt.h
@@ -4,16 +4,19 @@
  * 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 _SOFTOKNT_H_
 #define _SOFTOKNT_H_
 
 #define NSS_SOFTOKEN_DEFAULT_CHUNKSIZE 2048
+#define DES_BLOCK_SIZE 8     /* bytes */
+#define MAX_DES3_KEY_SIZE 24 /* DES_BLOCK_SIZE * 3 */
+#define SFTK_MAX_DERIVE_KEY_SIZE 64
 
 /*
  * FIPS 140-2 auditing
  */
 typedef enum {
     NSS_AUDIT_ERROR = 3,   /* errors */
     NSS_AUDIT_WARNING = 2, /* warning messages */
     NSS_AUDIT_INFO = 1     /* informational messages */
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -1,9 +1,8 @@
-
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /*
  * SSL3 Protocol
  *
  * 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/. */
 
@@ -1042,16 +1041,29 @@ Null_Cipher(void *ctx, unsigned char *ou
     }
     return SECSuccess;
 }
 
 /*
  * SSL3 Utility functions
  */
 
+static void
+ssl_SetSpecVersions(sslSocket *ss, ssl3CipherSpec *spec)
+{
+    spec->version = ss->version;
+    if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+        tls13_SetSpecRecordVersion(ss, spec);
+    } else if (IS_DTLS(ss)) {
+        spec->recordVersion = dtls_TLSVersionToDTLSVersion(ss->version);
+    } else {
+        spec->recordVersion = ss->version;
+    }
+}
+
 /* allowLargerPeerVersion controls whether the function will select the
  * highest enabled SSL version or fail when peerVersion is greater than the
  * highest enabled version.
  *
  * If allowLargerPeerVersion is true, peerVersion is the peer's highest
  * enabled version rather than the peer's selected version.
  */
 SECStatus
@@ -1091,49 +1103,48 @@ ssl_ClientReadVersion(sslSocket *ss, PRU
     }
 
 #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) || (ss->opt.enableAltHandshaketype &&
-                                                                          (temp == tls13_EncodeAltDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3)))) {
+    if (temp == tls13_EncodeDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3)) {
+        v = SSL_LIBRARY_VERSION_TLS_1_3;
+    } else if (temp == tls13_EncodeAltDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3)) {
+        if (!ss->opt.enableAltHandshaketype || IS_DTLS(ss)) {
+            (void)SSL3_SendAlert(ss, alert_fatal, protocol_version);
+            PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
+            return SECFailure;
+        }
+        ss->ssl3.hs.altHandshakeType = PR_TRUE;
         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)
+ssl3_GetNewRandom(SSL3Random random)
 {
     SECStatus rv;
 
-    rv = PK11_GenerateRandom(random->rand, SSL3_RANDOM_LENGTH);
+    rv = PK11_GenerateRandom(random, SSL3_RANDOM_LENGTH);
     if (rv != SECSuccess) {
         ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
     }
     return rv;
 }
 
 /* Called by ssl3_SendServerKeyExchange and ssl3_SendCertificateVerify */
 SECStatus
@@ -1447,19 +1458,19 @@ ssl3_ComputeDHKeyHash(sslSocket *ss, SSL
         hashBuf = buf;
     } else {
         hashBuf = PORT_Alloc(bufLen);
         if (!hashBuf) {
             return SECFailure;
         }
     }
 
-    memcpy(hashBuf, &ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH);
+    memcpy(hashBuf, ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH);
     pBuf = hashBuf + SSL3_RANDOM_LENGTH;
-    memcpy(pBuf, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH);
+    memcpy(pBuf, ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH);
     pBuf += SSL3_RANDOM_LENGTH;
     pBuf = ssl_EncodeUintX(dh_p.len, 2, pBuf);
     memcpy(pBuf, dh_p.data, dh_p.len);
     pBuf += dh_p.len;
     pBuf = ssl_EncodeUintX(dh_g.len, 2, pBuf);
     memcpy(pBuf, dh_g.data, dh_g.len);
     pBuf += dh_g.len;
     pBuf = ssl_EncodeUintX(yLen, 2, pBuf);
@@ -1575,17 +1586,17 @@ ssl3_SetupPendingCipherSpec(sslSocket *s
 
     /* This hack provides maximal interoperability with SSL 3 servers. */
     cwSpec = ss->ssl3.cwSpec;
     if (cwSpec->mac_def->mac == mac_null) {
         /* SSL records are not being MACed. */
         cwSpec->version = ss->version;
     }
 
-    pwSpec->version = ss->version;
+    ssl_SetSpecVersions(ss, ss->ssl3.pwSpec);
     isTLS = (PRBool)(pwSpec->version > SSL_LIBRARY_VERSION_3_0);
 
     SSL_TRC(3, ("%d: SSL3[%d]: Set XXX Pending Cipher Suite to 0x%04x",
                 SSL_GETPID(), ss->fd, suite));
 
     suite_def = ssl_LookupCipherSuiteDef(suite);
     if (suite_def == NULL) {
         ssl_ReleaseSpecWriteLock(ss);
@@ -1770,61 +1781,58 @@ ssl3_InitCompressionContext(ssl3CipherSp
 }
 
 /* ssl3_BuildRecordPseudoHeader writes the SSL/TLS pseudo-header (the data
  * which is included in the MAC or AEAD additional data) to |out| and returns
  * its length. See https://tools.ietf.org/html/rfc5246#section-6.2.3.3 for the
  * definition of the AEAD additional data.
  *
  * TLS pseudo-header includes the record's version field, SSL's doesn't. Which
- * pseudo-header defintiion to use should be decided based on the version of
+ * pseudo-header definition to use should be decided based on the version of
  * the protocol that was negotiated when the cipher spec became current, NOT
  * based on the version value in the record itself, and the decision is passed
  * to this function as the |includesVersion| argument. But, the |version|
  * argument should be the record's version value.
  */
-static unsigned int
-ssl3_BuildRecordPseudoHeader(unsigned char *out,
+static SECStatus
+ssl3_BuildRecordPseudoHeader(PRUint8 *out, DTLSEpoch epoch,
                              sslSequenceNumber seq_num,
                              SSL3ContentType type,
                              PRBool includesVersion,
                              SSL3ProtocolVersion version,
                              PRBool isDTLS,
                              int length)
 {
-    out[0] = (unsigned char)(seq_num >> 56);
-    out[1] = (unsigned char)(seq_num >> 48);
+    if (isDTLS) {
+        out[0] = (unsigned char)(epoch >> 8);
+        out[1] = (unsigned char)(epoch >> 0);
+    } else {
+        out[0] = (unsigned char)(seq_num >> 56);
+        out[1] = (unsigned char)(seq_num >> 48);
+    }
     out[2] = (unsigned char)(seq_num >> 40);
     out[3] = (unsigned char)(seq_num >> 32);
     out[4] = (unsigned char)(seq_num >> 24);
     out[5] = (unsigned char)(seq_num >> 16);
     out[6] = (unsigned char)(seq_num >> 8);
     out[7] = (unsigned char)(seq_num >> 0);
     out[8] = type;
 
     /* SSL3 MAC doesn't include the record's version field. */
     if (!includesVersion) {
         out[9] = MSB(length);
         out[10] = LSB(length);
         return 11;
     }
-
     /* TLS MAC and AEAD additional data include version. */
-    if (isDTLS) {
-        SSL3ProtocolVersion dtls_version;
-
-        dtls_version = dtls_TLSVersionToDTLSVersion(version);
-        out[9] = MSB(dtls_version);
-        out[10] = LSB(dtls_version);
-    } else {
-        out[9] = MSB(version);
-        out[10] = LSB(version);
-    }
+    out[9] = MSB(version);
+    out[10] = LSB(version);
     out[11] = MSB(length);
     out[12] = LSB(length);
+    PRINT_BUF(50, (NULL, "Pseudoheader", out, 13));
     return 13;
 }
 
 static SECStatus
 ssl3_AESGCM(ssl3KeyMaterial *keys,
             PRBool doDecrypt,
             unsigned char *out,
             int *outlen,
@@ -2368,17 +2376,16 @@ ssl3_ClientAuthTokenPresent(sslSessionID
     return isPresent;
 }
 
 /* Caller must hold the spec read lock. */
 SECStatus
 ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec,
                               PRBool isServer,
                               PRBool isDTLS,
-                              PRBool capRecordVersion,
                               SSL3ContentType type,
                               const PRUint8 *pIn,
                               PRUint32 contentLen,
                               sslBuffer *wrBuf)
 {
     const ssl3BulkCipherDef *cipher_def;
     SECStatus rv;
     PRUint32 macLen = 0;
@@ -2425,18 +2432,18 @@ ssl3_CompressMACEncryptRecord(ssl3Cipher
                                 &outlen, wrBuf->space - ivLen, pIn, contentLen);
         if (rv != SECSuccess)
             return rv;
         pIn = wrBuf->buf + ivLen;
         contentLen = outlen;
     }
 
     pseudoHeaderLen = ssl3_BuildRecordPseudoHeader(
-        pseudoHeader, cwSpec->write_seq_num, type,
-        cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->version,
+        pseudoHeader, cwSpec->epoch, cwSpec->write_seq_num, type,
+        cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->recordVersion,
         isDTLS, contentLen);
     PORT_Assert(pseudoHeaderLen <= sizeof(pseudoHeader));
     if (cipher_def->type == type_aead) {
         const int nonceLen = cipher_def->explicit_nonce_size;
         const int tagLen = cipher_def->tag_size;
 
         if (nonceLen + contentLen + tagLen > wrBuf->space) {
             PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
@@ -2537,24 +2544,22 @@ ssl3_CompressMACEncryptRecord(ssl3Cipher
             wrBuf->len += cipherBytesPart2;
         }
     }
 
     return SECSuccess;
 }
 
 SECStatus
-ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec,
-                  PRBool capRecordVersion, SSL3ContentType type,
+ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSL3ContentType type,
                   const PRUint8 *pIn, PRUint32 contentLen, sslBuffer *wrBuf)
 {
     const ssl3BulkCipherDef *cipher_def = cwSpec->cipher_def;
     PRUint16 headerLen;
     sslBuffer protBuf;
-    SSL3ProtocolVersion version = cwSpec->version;
     PRBool isTLS13;
     PRUint8 *ptr = wrBuf->buf;
     SECStatus rv;
 
     if (ss->ssl3.hs.shortHeaders) {
         PORT_Assert(!IS_DTLS(ss));
         PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
         headerLen = TLS13_RECORD_HEADER_LENGTH_SHORT;
@@ -2578,17 +2583,17 @@ ssl_ProtectRecord(sslSocket *ss, ssl3Cip
 #ifdef UNSAFE_FUZZER_MODE
     rv = Null_Cipher(NULL, protBuf.buf, (int *)&protBuf.len, protBuf.space,
                      pIn, contentLen);
 #else
     if (isTLS13) {
         rv = tls13_ProtectRecord(ss, cwSpec, type, pIn, contentLen, &protBuf);
     } else {
         rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer,
-                                           IS_DTLS(ss), capRecordVersion, type,
+                                           IS_DTLS(ss), type,
                                            pIn, contentLen, &protBuf);
     }
 #endif
     if (rv != SECSuccess) {
         return SECFailure; /* error was set */
     }
 
     PORT_Assert(protBuf.len <= MAX_FRAGMENT_LENGTH + (isTLS13 ? 256 : 1024));
@@ -2602,35 +2607,27 @@ ssl_ProtectRecord(sslSocket *ss, ssl3Cip
         if (isTLS13 && cipher_def->calg != ssl_calg_null) {
             *ptr++ = content_application_data;
         } else
 #endif
         {
             *ptr++ = type;
         }
 
+        ptr = ssl_EncodeUintX(cwSpec->recordVersion, 2, ptr);
         if (IS_DTLS(ss)) {
-            version = isTLS13 ? SSL_LIBRARY_VERSION_TLS_1_1 : version;
-            version = dtls_TLSVersionToDTLSVersion(version);
-
-            ptr = ssl_EncodeUintX(version, 2, ptr);
-            ptr = ssl_EncodeUintX(cwSpec->write_seq_num, 8, ptr);
-        } else {
-            if (capRecordVersion || isTLS13) {
-                version = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0, version);
-            }
-            ptr = ssl_EncodeUintX(version, 2, ptr);
+            ptr = ssl_EncodeUintX(cwSpec->epoch, 2, ptr);
+            ptr = ssl_EncodeUintX(cwSpec->write_seq_num, 6, ptr);
         }
         (void)ssl_EncodeUintX(protBuf.len, 2, ptr);
     }
     ++cwSpec->write_seq_num;
 
     return SECSuccess;
 }
-
 /* Process the plain text before sending it.
  * Returns the number of bytes of plaintext that were successfully sent
  *  plus the number of bytes of plaintext that were copied into the
  *  output (write) buffer.
  * Returns SECFailure on a hard IO error, memory error, or crypto error.
  * Does NOT return SECWouldBlock.
  *
  * Notes on the use of the private ssl flags:
@@ -2641,65 +2638,43 @@ ssl_ProtectRecord(sslSocket *ss, ssl3Cip
  *    then buffer remaining bytes of ciphertext into pending buf,
  *    and continue to do that for all succssive records until all
  *    bytes are used.
  * ssl_SEND_FLAG_FORCE_INTO_BUFFER
  *    As above, except this suppresses all write attempts, and forces
  *    all ciphertext into the pending ciphertext buffer.
  * ssl_SEND_FLAG_USE_EPOCH (for DTLS)
  *    Forces the use of the provided epoch
- * ssl_SEND_FLAG_CAP_RECORD_VERSION
- *    Caps the record layer version number of TLS ClientHello to { 3, 1 }
- *    (TLS 1.0). Some TLS 1.0 servers (which seem to use F5 BIG-IP) ignore
- *    ClientHello.client_version and use the record layer version number
- *    (TLSPlaintext.version) instead when negotiating protocol versions. In
- *    addition, if the record layer version number of ClientHello is { 3, 2 }
- *    (TLS 1.1) or higher, these servers reset the TCP connections. Lastly,
- *    some F5 BIG-IP servers hang if a record containing a ClientHello has a
- *    version greater than { 3, 1 } and a length greater than 255. Set this
- *    flag to work around such servers.
  */
 PRInt32
 ssl3_SendRecord(sslSocket *ss,
                 ssl3CipherSpec *cwSpec, /* non-NULL for DTLS retransmits */
                 SSL3ContentType type,
                 const PRUint8 *pIn, /* input buffer */
                 PRInt32 nIn,        /* bytes of input */
                 PRInt32 flags)
 {
     sslBuffer *wrBuf = &ss->sec.writeBuf;
     SECStatus rv;
     PRInt32 totalSent = 0;
-    PRBool capRecordVersion;
     ssl3CipherSpec *spec;
 
     SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d",
                 SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type),
                 nIn));
     PRINT_BUF(50, (ss, "Send record (plain text)", pIn, nIn));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
     if (ss->ssl3.fatalAlertSent) {
         SSL_TRC(3, ("%d: SSL3[%d] Suppress write, fatal alert already sent",
                     SSL_GETPID(), ss->fd));
         return SECFailure;
     }
 
-    capRecordVersion = ((flags & ssl_SEND_FLAG_CAP_RECORD_VERSION) != 0);
-
-    if (capRecordVersion) {
-        /* ssl_SEND_FLAG_CAP_RECORD_VERSION can only be used with the
-         * TLS initial ClientHello. */
-        PORT_Assert(!IS_DTLS(ss));
-        PORT_Assert(!ss->firstHsDone);
-        PORT_Assert(type == content_handshake);
-        PORT_Assert(ss->ssl3.hs.ws == wait_server_hello);
-    }
-
     if (ss->ssl3.initialized == PR_FALSE) {
         /* This can happen on a server if the very first incoming record
         ** looks like a defective ssl3 record (e.g. too long), and we're
         ** trying to send an alert.
         */
         PR_ASSERT(type == content_alert);
         ssl3_InitState(ss);
     }
@@ -2740,29 +2715,29 @@ ssl3_SendRecord(sslSocket *ss,
                 SSL_DBG(("%d: SSL3[%d]: SendRecord, tried to get %d bytes",
                          SSL_GETPID(), ss->fd, spaceNeeded));
                 goto spec_locked_loser; /* sslBuffer_Grow set error code. */
             }
         }
 
         if (numRecords == 2) {
             sslBuffer secondRecord;
-            rv = ssl_ProtectRecord(ss, ss->ssl3.cwSpec, capRecordVersion, type,
+            rv = ssl_ProtectRecord(ss, ss->ssl3.cwSpec, type,
                                    pIn, 1, wrBuf);
             if (rv != SECSuccess)
                 goto spec_locked_loser;
 
             PRINT_BUF(50, (ss, "send (encrypted) record data [1/2]:",
                            wrBuf->buf, wrBuf->len));
 
             secondRecord.buf = wrBuf->buf + wrBuf->len;
             secondRecord.len = 0;
             secondRecord.space = wrBuf->space - wrBuf->len;
 
-            rv = ssl_ProtectRecord(ss, ss->ssl3.cwSpec, capRecordVersion, type,
+            rv = ssl_ProtectRecord(ss, ss->ssl3.cwSpec, type,
                                    pIn + 1, contentLen - 1, &secondRecord);
             if (rv == SECSuccess) {
                 PRINT_BUF(50, (ss, "send (encrypted) record data [2/2]:",
                                secondRecord.buf, secondRecord.len));
                 wrBuf->len += secondRecord.len;
             }
         } else {
             if (cwSpec) {
@@ -2771,18 +2746,17 @@ ssl3_SendRecord(sslSocket *ss,
                 PORT_Assert(IS_DTLS(ss) &&
                             (type == content_handshake ||
                              type == content_change_cipher_spec));
                 spec = cwSpec;
             } else {
                 spec = ss->ssl3.cwSpec;
             }
 
-            rv = ssl_ProtectRecord(ss, spec, !IS_DTLS(ss) && capRecordVersion,
-                                   type, pIn, contentLen, wrBuf);
+            rv = ssl_ProtectRecord(ss, spec, type, pIn, contentLen, wrBuf);
             if (rv == SECSuccess) {
                 PRINT_BUF(50, (ss, "send (encrypted) record data:",
                                wrBuf->buf, wrBuf->len));
             }
         }
 
     spec_locked_loser:
         ssl_ReleaseSpecReadLock(ss); /************************************/
@@ -2975,40 +2949,33 @@ ssl3_FlushHandshake(sslSocket *ss, PRInt
  * This function returns SECSuccess or SECFailure, never SECWouldBlock.
  * Always set sendBuf.len to 0, even when returning SECFailure.
  *
  * Called from ssl3_FlushHandshake
  */
 static SECStatus
 ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
 {
-    static const PRInt32 allowedFlags = ssl_SEND_FLAG_FORCE_INTO_BUFFER |
-                                        ssl_SEND_FLAG_CAP_RECORD_VERSION;
+    static const PRInt32 allowedFlags = ssl_SEND_FLAG_FORCE_INTO_BUFFER;
     PRInt32 count = -1;
     SECStatus rv;
-    SSL3ContentType ct = content_handshake;
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
     if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
         return SECSuccess;
 
     /* only these flags are allowed */
     PORT_Assert(!(flags & ~allowedFlags));
     if ((flags & ~allowedFlags) != 0) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
-    /* Maybe send the first message with alt handshake type. */
-    if (ss->ssl3.hs.altHandshakeType) {
-        ct = content_alt_handshake;
-        ss->ssl3.hs.altHandshakeType = PR_FALSE;
-    }
-    count = ssl3_SendRecord(ss, NULL, ct,
+    count = ssl3_SendRecord(ss, NULL, content_handshake,
                             ss->sec.ci.sendBuf.buf,
                             ss->sec.ci.sendBuf.len, flags);
     if (count < 0) {
         int err = PORT_GetError();
         PORT_Assert(err != PR_WOULD_BLOCK_ERROR);
         if (err == PR_WOULD_BLOCK_ERROR) {
             PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         }
@@ -3407,45 +3374,59 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffe
  * Called from ssl3_HandleServerHelloDone,
  *             ssl3_HandleClientHello,
  * and         ssl3_HandleFinished
  *
  * Acquires and releases spec write lock, to protect switching the current
  * and pending write spec pointers.
  */
 
-static SECStatus
-ssl3_SendChangeCipherSpecs(sslSocket *ss)
+SECStatus
+ssl3_SendChangeCipherSpecsInt(sslSocket *ss)
 {
     PRUint8 change = change_cipher_spec_choice;
-    ssl3CipherSpec *pwSpec;
     SECStatus rv;
-    PRInt32 sent;
 
     SSL_TRC(3, ("%d: SSL3[%d]: send change_cipher_spec record",
                 SSL_GETPID(), ss->fd));
 
+    rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
+    if (rv != SECSuccess) {
+        return SECFailure; /* error code set by ssl3_FlushHandshake */
+    }
+
+    if (!IS_DTLS(ss)) {
+        PRInt32 sent;
+        sent = ssl3_SendRecord(ss, NULL, content_change_cipher_spec,
+                               &change, 1, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
+        if (sent < 0) {
+            return SECFailure; /* error code set by ssl3_SendRecord */
+        }
+    } else {
+        SECStatus rv;
+        rv = dtls_QueueMessage(ss, content_change_cipher_spec, &change, 1);
+        if (rv != SECSuccess) {
+            return SECFailure;
+        }
+    }
+    return SECSuccess;
+}
+
+static SECStatus
+ssl3_SendChangeCipherSpecs(sslSocket *ss)
+{
+    ssl3CipherSpec *pwSpec;
+    SECStatus rv;
+
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
-    rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
-    if (rv != SECSuccess) {
-        return rv; /* error code set by ssl3_FlushHandshake */
-    }
-    if (!IS_DTLS(ss)) {
-        sent = ssl3_SendRecord(ss, NULL, content_change_cipher_spec, &change, 1,
-                               ssl_SEND_FLAG_FORCE_INTO_BUFFER);
-        if (sent < 0) {
-            return (SECStatus)sent; /* error code set by ssl3_SendRecord */
-        }
-    } else {
-        rv = dtls_QueueMessage(ss, content_change_cipher_spec, &change, 1);
-        if (rv != SECSuccess) {
-            return rv;
-        }
+    rv = ssl3_SendChangeCipherSpecsInt(ss);
+    if (rv != SECSuccess) {
+        return rv; /* Error code set. */
     }
 
     /* swap the pending and current write specs. */
     ssl_GetSpecWriteLock(ss); /**************************************/
     pwSpec = ss->ssl3.pwSpec;
 
     ss->ssl3.pwSpec = ss->ssl3.cwSpec;
     ss->ssl3.cwSpec = pwSpec;
@@ -3659,18 +3640,16 @@ ssl3_ComputeMasterSecretFinish(sslSocket
  **
  ** Called from: ssl3_ComputeMasterSecret
  */
 static SECStatus
 ssl3_ComputeMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
                             PK11SymKey **msp)
 {
     ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
-    unsigned char *cr = (unsigned char *)&ss->ssl3.hs.client_random;
-    unsigned char *sr = (unsigned char *)&ss->ssl3.hs.server_random;
     PRBool isTLS = (PRBool)(pwSpec->version > SSL_LIBRARY_VERSION_3_0);
     PRBool isTLS12 =
         (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
     /*
      * Whenever isDH is true, we need to use CKM_TLS_MASTER_KEY_DERIVE_DH
      * which, unlike CKM_TLS_MASTER_KEY_DERIVE, converts arbitrary size
      * data into a 48-byte value, and does not expect to return the version.
      */
@@ -3709,19 +3688,19 @@ ssl3_ComputeMasterSecretInt(sslSocket *s
         keyFlags = 0;
     }
 
     if (!isDH) {
         pms_version_ptr = &pms_version;
     }
 
     master_params.pVersion = pms_version_ptr;
-    master_params.RandomInfo.pClientRandom = cr;
+    master_params.RandomInfo.pClientRandom = ss->ssl3.hs.client_random;
     master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
-    master_params.RandomInfo.pServerRandom = sr;
+    master_params.RandomInfo.pServerRandom = ss->ssl3.hs.server_random;
     master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
     if (isTLS12) {
         master_params.prfHashMechanism = ssl3_GetPrfHashMechanism(ss);
         master_params_len = sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS);
     } else {
         /* prfHashMechanism is not relevant with this PRF */
         master_params_len = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
     }
@@ -3861,19 +3840,17 @@ ssl3_DeriveMasterSecret(sslSocket *ss, P
  * Caller MUST hold the specWriteLock, and SSL3HandshakeLock.
  * ssl3_InitPendingCipherSpec does that.
  *
  */
 static SECStatus
 ssl3_DeriveConnectionKeys(sslSocket *ss)
 {
     ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
-    unsigned char *cr = (unsigned char *)&ss->ssl3.hs.client_random;
-    unsigned char *sr = (unsigned char *)&ss->ssl3.hs.server_random;
-    PRBool isTLS = (PRBool)(pwSpec->version > SSL_LIBRARY_VERSION_3_0);
+    PRBool isTLS = (PRBool)(ss->version > SSL_LIBRARY_VERSION_3_0);
     PRBool isTLS12 =
         (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
     const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def;
     PK11SlotInfo *slot = NULL;
     PK11SymKey *symKey = NULL;
     void *pwArg = ss->pkcs11PinArg;
     int keySize;
     CK_TLS12_KEY_MAT_PARAMS key_material_params; /* may be used as a
@@ -3904,19 +3881,19 @@ ssl3_DeriveConnectionKeys(sslSocket *ss)
         pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
         /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */
         key_material_params.ulIVSizeInBits = 0;
         memset(pwSpec->client.write_iv, 0, cipher_def->iv_size);
         memset(pwSpec->server.write_iv, 0, cipher_def->iv_size);
     }
 
     key_material_params.bIsExport = PR_FALSE;
-    key_material_params.RandomInfo.pClientRandom = cr;
+    key_material_params.RandomInfo.pClientRandom = ss->ssl3.hs.client_random;
     key_material_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
-    key_material_params.RandomInfo.pServerRandom = sr;
+    key_material_params.RandomInfo.pServerRandom = ss->ssl3.hs.server_random;
     key_material_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
     key_material_params.pReturnedKeyMaterial = &returnedKeys;
 
     returnedKeys.pIVClient = pwSpec->client.write_iv;
     returnedKeys.pIVServer = pwSpec->server.write_iv;
     keySize = cipher_def->key_size;
 
     if (skipKeysAndIVs) {
@@ -4342,17 +4319,17 @@ ssl3_ConsumeHandshake(sslSocket *ss, voi
  *
  * On error, an alert has been sent, and a generic error code has been set.
  */
 SECStatus
 ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRUint32 *num, PRUint32 bytes,
                             PRUint8 **b, PRUint32 *length)
 {
     PRUint8 *buf = *b;
-    int i;
+    PRUint32 i;
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     *num = 0;
     if (bytes > *length || bytes > sizeof(*num)) {
         return ssl3_DecodeError(ss);
     }
@@ -4934,16 +4911,28 @@ ssl_ClientHelloTypeName(sslClientHelloTy
         CHTYPE(renegotiation); /* TLS <= 1.2 only */
     }
     PORT_Assert(0);
     return NULL;
 }
 #undef CHTYPE
 #endif
 
+PR_STATIC_ASSERT(SSL3_SESSIONID_BYTES == SSL3_RANDOM_LENGTH);
+static void
+ssl_MakeFakeSid(sslSocket *ss, PRUint8 *buf)
+{
+    PRUint8 x = 0x5a;
+    int i;
+    for (i = 0; i < SSL3_SESSIONID_BYTES; ++i) {
+        x += ss->ssl3.hs.client_random[i];
+        buf[i] = x;
+    }
+}
+
 /* Called from ssl3_HandleHelloRequest(),
  *             ssl3_RedoHandshake()
  *             ssl_BeginClientHandshake (when resuming ssl3 session)
  *             dtls_HandleHelloVerifyRequest(with resending=PR_TRUE)
  *
  * The |type| argument indicates what is going on here:
  * - client_hello_initial is set for the very first ClientHello
  * - client_hello_retry indicates that this is a second attempt after receiving
@@ -4952,17 +4941,17 @@ ssl_ClientHelloTypeName(sslClientHelloTy
  * - client_hello_renegotiation is used to renegotiate (in TLS <1.3)
  */
 SECStatus
 ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
 {
     sslSessionID *sid;
     ssl3CipherSpec *cwSpec;
     SECStatus rv;
-    int i;
+    unsigned int i;
     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 numCompressionMethods;
     PRUint16 version;
@@ -5245,21 +5234,24 @@ ssl3_SendClientHello(sslSocket *ss, sslC
     /* count compression methods */
     numCompressionMethods = 0;
     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) +
+             1 + /* session id length */
              2 + num_suites * sizeof(ssl3CipherSuite) +
              1 + numCompressionMethods + total_exten_len;
+    if (sid->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+        length += sid->u.ssl3.sessionIDLength;
+    } else if (ss->opt.enableAltHandshaketype && !IS_DTLS(ss)) {
+        length += SSL3_SESSIONID_BYTES;
+    }
     if (IS_DTLS(ss)) {
         length += 1 + ss->ssl3.hs.cookie.len;
     }
 
     if (total_exten_len > 0) {
         ssl3_CalculatePaddingExtLen(ss, length);
         if (ss->xtnData.paddingLen) {
             total_exten_len += 4 + ss->xtnData.paddingLen;
@@ -5293,38 +5285,45 @@ ssl3_SendClientHello(sslSocket *ss, sslC
         if (sid->u.ssl3.lock) {
             PR_RWLock_Unlock(sid->u.ssl3.lock);
         }
         return rv; /* err set by ssl3_AppendHandshake* */
     }
 
     /* Generate a new random if this is the first attempt. */
     if (type == client_hello_initial) {
-        rv = ssl3_GetNewRandom(&ss->ssl3.hs.client_random);
+        rv = ssl3_GetNewRandom(ss->ssl3.hs.client_random);
         if (rv != SECSuccess) {
             if (sid->u.ssl3.lock) {
                 PR_RWLock_Unlock(sid->u.ssl3.lock);
             }
             return rv; /* err set by GetNewRandom. */
         }
     }
-    rv = ssl3_AppendHandshake(ss, &ss->ssl3.hs.client_random,
+    rv = ssl3_AppendHandshake(ss, ss->ssl3.hs.client_random,
                               SSL3_RANDOM_LENGTH);
     if (rv != SECSuccess) {
         if (sid->u.ssl3.lock) {
             PR_RWLock_Unlock(sid->u.ssl3.lock);
         }
         return rv; /* err set by ssl3_AppendHandshake* */
     }
 
-    if (sid->version < SSL_LIBRARY_VERSION_TLS_1_3)
+    if (sid->version < SSL_LIBRARY_VERSION_TLS_1_3) {
         rv = ssl3_AppendHandshakeVariable(
             ss, sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength, 1);
-    else
+    } else if (ss->opt.enableAltHandshaketype && !IS_DTLS(ss)) {
+        /* We're faking session resumption, so rather than create new
+         * randomness, just mix up the client random a little. */
+        PRUint8 buf[SSL3_SESSIONID_BYTES];
+        ssl_MakeFakeSid(ss, buf);
+        rv = ssl3_AppendHandshakeVariable(ss, buf, SSL3_SESSIONID_BYTES, 1);
+    } else {
         rv = ssl3_AppendHandshakeNumber(ss, 0, 1);
+    }
     if (rv != SECSuccess) {
         if (sid->u.ssl3.lock) {
             PR_RWLock_Unlock(sid->u.ssl3.lock);
         }
         return rv; /* err set by ssl3_AppendHandshake* */
     }
 
     if (IS_DTLS(ss)) {
@@ -5458,19 +5457,16 @@ 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;
     }
 
     flags = 0;
-    if (!ss->firstHsDone && !IS_DTLS(ss)) {
-        flags |= ssl_SEND_FLAG_CAP_RECORD_VERSION;
-    }
     rv = ssl3_FlushHandshake(ss, flags);
     if (rv != SECSuccess) {
         return rv; /* error code set by ssl3_FlushHandshake */
     }
 
     if (version >= SSL_LIBRARY_VERSION_TLS_1_3) {
         rv = tls13_MaybeDo0RTTHandshake(ss);
         if (rv != SECSuccess) {
@@ -6551,52 +6547,96 @@ done:
     if (buf.data)
         PORT_Free(buf.data);
     return rv;
 }
 
 /* Once a cipher suite has been selected, make sure that the necessary secondary
  * information is properly set. */
 SECStatus
-ssl3_SetCipherSuite(sslSocket *ss, ssl3CipherSuite chosenSuite,
-                    PRBool initHashes)
-{
-    ss->ssl3.hs.cipher_suite = chosenSuite;
-    ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef(chosenSuite);
+ssl3_SetupCipherSuite(sslSocket *ss, PRBool initHashes)
+{
+    ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
     if (!ss->ssl3.hs.suite_def) {
         PORT_Assert(0);
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
 
     ss->ssl3.hs.kea_def = &kea_defs[ss->ssl3.hs.suite_def->key_exchange_alg];
     ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_cipher_suite;
 
     if (!initHashes) {
         return SECSuccess;
     }
-    /* Now we've have a cipher suite, initialize the handshake hashes. */
+    /* Now we have a cipher suite, initialize the handshake hashes. */
     return ssl3_InitHandshakeHashes(ss);
 }
 
+/* Once a cipher suite has been selected, make sure that the necessary secondary
+ * information is properly set. */
+SECStatus
+ssl3_SetCipherSuite(sslSocket *ss, ssl3CipherSuite chosenSuite,
+                    PRBool initHashes)
+{
+    ss->ssl3.hs.cipher_suite = chosenSuite;
+    return ssl3_SetupCipherSuite(ss, initHashes);
+}
+
+SECStatus
+ssl_ClientSetCipherSuite(sslSocket *ss, SSL3ProtocolVersion version,
+                         ssl3CipherSuite suite, PRBool initHashes)
+{
+    int i;
+
+    i = ssl3_config_match_init(ss);
+    PORT_Assert(i > 0);
+    if (i <= 0) {
+        return SECFailure;
+    }
+    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
+        ssl3CipherSuiteCfg *suiteCfg = &ss->cipherSuites[i];
+        if (suite == suiteCfg->cipher_suite) {
+            SSLVersionRange vrange = { version, version };
+            if (!config_match(suiteCfg, 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. */
+                if (!ssl3_CipherSuiteAllowedForVersionRange(suite, &vrange)) {
+                    PORT_SetError(SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION);
+                } else {
+                    PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
+                }
+                return SECFailure;
+            }
+            break;
+        }
+    }
+    if (i >= ssl_V3_SUITES_IMPLEMENTED) {
+        PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
+        return SECFailure;
+    }
+
+    ss->ssl3.hs.cipher_suite = (ssl3CipherSuite)suite;
+    return ssl3_SetupCipherSuite(ss, initHashes);
+}
+
 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
  * ssl3 ServerHello message.
  * Caller must hold Handshake and RecvBuf locks.
  */
 static SECStatus
 ssl3_HandleServerHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
 {
-    PRUint32 temp;
-    PRBool suite_found = PR_FALSE;
-    int i;
+    PRUint32 cipher;
     int errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
     SECStatus rv;
     SECItem sidBytes = { siBuffer, NULL, 0 };
-    PRBool isTLS = PR_FALSE;
     SSL3AlertDescription desc = illegal_parameter;
+    TLSExtension *versionExtension;
 #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));
@@ -6617,21 +6657,101 @@ ssl3_HandleServerHello(sslSocket *ss, PR
         CERT_DestroyCertificate(ss->ssl3.clientCertificate);
         ss->ssl3.clientCertificate = NULL;
     }
     if (ss->ssl3.clientPrivateKey != NULL) {
         SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
         ss->ssl3.clientPrivateKey = NULL;
     }
 
+    /* Note that if we are doing the alternative handshake for TLS 1.3, this
+     * will set the version to TLS 1.2.  We will amend that once all other
+     * fields have been read. */
     rv = ssl_ClientReadVersion(ss, &b, &length, &ss->version);
     if (rv != SECSuccess) {
         goto loser; /* alert has been sent */
     }
 
+    rv = ssl3_ConsumeHandshake(
+        ss, ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH, &b, &length);
+    if (rv != SECSuccess) {
+        goto loser; /* alert has been sent */
+    }
+
+    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+        rv = ssl3_ConsumeHandshakeVariable(ss, &sidBytes, 1, &b, &length);
+        if (rv != SECSuccess) {
+            goto loser; /* alert has been sent */
+        }
+        if (sidBytes.len > SSL3_SESSIONID_BYTES) {
+            if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_0)
+                desc = decode_error;
+            goto alert_loser; /* malformed. */
+        }
+    }
+
+    /* Read the cipher suite. */
+    rv = ssl3_ConsumeHandshakeNumber(ss, &cipher, 2, &b, &length);
+    if (rv != SECSuccess) {
+        goto loser; /* alert has been sent */
+    }
+
+    /* Compression method. */
+    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+        PRUint32 compression;
+        rv = ssl3_ConsumeHandshakeNumber(ss, &compression, 1, &b, &length);
+        if (rv != SECSuccess) {
+            goto loser; /* alert has been sent */
+        }
+        if (compression != ssl_compression_null) {
+            desc = illegal_parameter;
+            errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
+            goto alert_loser;
+        }
+    }
+
+    /* Parse extensions. */
+    if (length != 0) {
+        PRUint32 extensionLength;
+        rv = ssl3_ConsumeHandshakeNumber(ss, &extensionLength, 2, &b, &length);
+        if (rv != SECSuccess) {
+            goto loser; /* alert already sent */
+        }
+        if (extensionLength != length) {
+            desc = decode_error;
+            goto alert_loser;
+        }
+        rv = ssl3_ParseExtensions(ss, &b, &length);
+        if (rv != SECSuccess) {
+            goto alert_loser; /* malformed */
+        }
+    }
+
+    /* Update the version based on the extension, as necessary. */
+    versionExtension = ssl3_FindExtension(ss, ssl_tls13_supported_versions_xtn);
+    if (versionExtension) {
+        rv = ssl_ClientReadVersion(ss, &versionExtension->data.data,
+                                   &versionExtension->data.len,
+                                   &ss->version);
+        if (rv != SECSuccess) {
+            errCode = PORT_GetError();
+            goto loser; /* An alert is sent by ssl_ClientReadVersion */
+        }
+    }
+
+    PORT_Assert(!SSL_ALL_VERSIONS_DISABLED(&ss->vrange));
+    /* Check that the version is within the configured range. */
+    if (ss->vrange.min > ss->version || ss->vrange.max < ss->version) {
+        desc = (ss->version > SSL_LIBRARY_VERSION_3_0)
+                   ? protocol_version
+                   : handshake_failure;
+        errCode = SSL_ERROR_UNSUPPORTED_VERSION;
+        goto alert_loser;
+    }
+
     /* The server didn't pick 1.3 although we either received a
      * HelloRetryRequest, or we prepared to send early app data. */
     if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
         if (ss->ssl3.hs.helloRetry) {
             /* SSL3_SendAlert() will uncache the SID. */
             desc = illegal_parameter;
             errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
             goto alert_loser;
@@ -6648,24 +6768,16 @@ ssl3_HandleServerHello(sslSocket *ss, PR
      * 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 && (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(
-        ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* alert has been sent */
-    }
 
 #ifndef TLS_1_3_DRAFT_VERSION
     /* Check the ServerHello.random per
      * [draft-ietf-tls-tls13-11 Section 6.3.1.1].
      *
      * TLS 1.3 clients receiving a TLS 1.2 or below ServerHello MUST check
      * that the top eight octets are not equal to either of these values.
      * TLS 1.2 clients SHOULD also perform this check if the ServerHello
@@ -6675,136 +6787,73 @@ ssl3_HandleServerHello(sslSocket *ss, PR
      * Disable this test during the TLS 1.3 draft version period.
      */
     downgradeCheckVersion = ss->ssl3.downgradeCheckVersion ? ss->ssl3.downgradeCheckVersion
                                                            : ss->vrange.max;
 
     if (downgradeCheckVersion >= SSL_LIBRARY_VERSION_TLS_1_2 &&
         downgradeCheckVersion > ss->version) {
         /* Both sections use the same sentinel region. */
-        unsigned char *downgrade_sentinel =
-            ss->ssl3.hs.server_random.rand +
+        PRUint8 *downgrade_sentinel =
+            ss->ssl3.hs.server_random +
             SSL3_RANDOM_LENGTH - sizeof(tls13_downgrade_random);
         if (!PORT_Memcmp(downgrade_sentinel,
                          tls13_downgrade_random,
                          sizeof(tls13_downgrade_random)) ||
             !PORT_Memcmp(downgrade_sentinel,
                          tls12_downgrade_random,
                          sizeof(tls12_downgrade_random))) {
             desc = illegal_parameter;
             errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
             goto alert_loser;
         }
     }
 #endif
 
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        rv = ssl3_ConsumeHandshakeVariable(ss, &sidBytes, 1, &b, &length);
-        if (rv != SECSuccess) {
-            goto loser; /* alert has been sent */
-        }
-        if (sidBytes.len > SSL3_SESSIONID_BYTES) {
-            if (isTLS)
-                desc = decode_error;
-            goto alert_loser; /* malformed. */
-        }
-    }
-
-    /* find selected cipher suite in our list. */
-    rv = ssl3_ConsumeHandshakeNumber(ss, &temp, 2, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* alert has been sent */
-    }
-    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. */
-                if (!ssl3_CipherSuiteAllowedForVersionRange(temp, &vrange)) {
-                    desc = handshake_failure;
-                    errCode = SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION;
-                    goto alert_loser;
-                }
-
-                break; /* failure */
-            }
-
-            suite_found = PR_TRUE;
-            break; /* success */
-        }
-    }
-    if (!suite_found) {
+    /* Finally, now all the version-related checks have passed. */
+    ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
+    /* Update the write cipher spec to match the version. */
+    if (!ss->firstHsDone) {
+        ssl_GetSpecWriteLock(ss);
+        ssl_SetSpecVersions(ss, ss->ssl3.cwSpec);
+        ssl_ReleaseSpecWriteLock(ss);
+    }
+
+    /* Check that the session ID is as expected. */
+    if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+        PRUint8 buf[SSL3_SESSIONID_BYTES];
+        unsigned int expectedSidLen;
+        if (ss->ssl3.hs.altHandshakeType) {
+            expectedSidLen = SSL3_SESSIONID_BYTES;
+            ssl_MakeFakeSid(ss, buf);
+        } else {
+            expectedSidLen = 0;
+        }
+        if (sidBytes.len != expectedSidLen ||
+            PORT_Memcmp(buf, sidBytes.data, expectedSidLen) != 0) {
+            desc = illegal_parameter;
+            errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
+            goto alert_loser;
+        }
+    }
+
+    /* Set compression (to be removed soon), and cipher suite. */
+    ss->ssl3.hs.compression = ssl_compression_null;
+    rv = ssl_ClientSetCipherSuite(ss, ss->version, cipher,
+                                  PR_TRUE /* init hashes */);
+    if (rv != SECSuccess) {
         desc = handshake_failure;
-        errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
-        goto alert_loser;
-    }
-
-    rv = ssl3_SetCipherSuite(ss, (ssl3CipherSuite)temp, PR_TRUE);
-    if (rv != SECSuccess) {
-        desc = internal_error;
         errCode = PORT_GetError();
         goto alert_loser;
     }
 
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        /* find selected compression method in our list. */
-        rv = ssl3_ConsumeHandshakeNumber(ss, &temp, 1, &b, &length);
-        if (rv != SECSuccess) {
-            goto loser; /* alert has been sent */
-        }
-        suite_found = PR_FALSE;
-        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;
-            errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP;
-            goto alert_loser;
-        }
-        ss->ssl3.hs.compression = (SSLCompressionMethod)temp;
-    } else {
-        ss->ssl3.hs.compression = ssl_compression_null;
-    }
-
-    /* Note that if !isTLS and the extra stuff is not extensions, we
-     * do NOT goto alert_loser.
-     * There are some old SSL 3.0 implementations that do send stuff
-     * after the end of the server hello, and we deliberately ignore
-     * such stuff in the interest of maximal interoperability (being
-     * "generous in what you accept").
-     * Update: Starting in NSS 3.12.6, we handle the renegotiation_info
-     * extension in SSL 3.0.
-     */
-    if (length != 0) {
-        SECItem extensions;
-        rv = ssl3_ConsumeHandshakeVariable(ss, &extensions, 2, &b, &length);
-        if (rv != SECSuccess || length != 0) {
-            if (isTLS)
-                goto alert_loser;
-        } else {
-            rv = ssl3_HandleExtensions(ss, &extensions.data,
-                                       &extensions.len, server_hello);
-            if (rv != SECSuccess)
-                goto alert_loser;
-        }
+    rv = ssl3_HandleParsedExtensions(ss, server_hello);
+    ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions);
+    if (rv != SECSuccess) {
+        goto alert_loser;
     }
 
     if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
         rv = tls13_HandleServerHelloPart2(ss);
         if (rv != SECSuccess) {
             errCode = PORT_GetError();
             goto loser;
         }
@@ -7087,21 +7136,21 @@ ssl_HandleDHServerKeyExchange(sslSocket 
     SECKEYPublicKey *peerKey = NULL;
 
     rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length);
     if (rv != SECSuccess) {
         goto loser; /* malformed. */
     }
 
     rv = NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &minDH);
-    if (rv != SECSuccess) {
+    if (rv != SECSuccess || minDH <= 0) {
         minDH = SSL_DH_MIN_P_BITS;
     }
     dh_p_bits = SECKEY_BigIntegerBitLength(&dh_p);
-    if (dh_p_bits < minDH) {
+    if (dh_p_bits < (unsigned)minDH) {
         errCode = SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY;
         goto alert_loser;
     }
     rv = ssl3_ConsumeHandshakeVariable(ss, &dh_g, 2, &b, &length);
     if (rv != SECSuccess) {
         goto loser; /* malformed. */
     }
     /* Abort if dh_g is 0, 1, or obviously too big. */
@@ -7923,16 +7972,17 @@ ssl3_NewSessionID(sslSocket *ss, PRBool 
     sid->version = ss->version;
     sid->sigScheme = ssl_sig_none;
 
     sid->u.ssl3.keys.resumable = PR_TRUE;
     sid->u.ssl3.policy = SSL_ALLOWED;
     sid->u.ssl3.clientWriteKey = NULL;
     sid->u.ssl3.serverWriteKey = NULL;
     sid->u.ssl3.keys.extendedMasterSecretUsed = PR_FALSE;
+    sid->u.ssl3.altHandshakeType = ss->ssl3.hs.altHandshakeType;
 
     if (is_server) {
         SECStatus rv;
         int pid = SSL_GETPID();
 
         sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES;
         sid->u.ssl3.sessionID[0] = (pid >> 8) & 0xff;
         sid->u.ssl3.sessionID[1] = pid & 0xff;
@@ -8027,18 +8077,18 @@ ssl3_KEASupportsTickets(const ssl3KEADef
 ** cipher suites. Therefore, we refuse to negotiate export cipher suites
 ** with any client that indicates support for TLS 1.1 or higher when we
 ** (the server) have TLS 1.1 support enabled.
 */
 SECStatus
 ssl3_NegotiateCipherSuite(sslSocket *ss, const SECItem *suites,
                           PRBool initHashes)
 {
-    int j;
-    int i;
+    unsigned int j;
+    unsigned int i;
 
     for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
         ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
         SSLVersionRange vrange = { ss->version, ss->version };
         if (!config_match(suite, ss->ssl3.policy, &vrange, ss)) {
             continue;
         }
         for (i = 0; i + 1 < suites->len; i += 2) {
@@ -8339,17 +8389,17 @@ ssl3_HandleClientHello(sslSocket *ss, PR
         ss->clientHelloVersion = version =
             dtls_DTLSVersionToTLSVersion((SSL3ProtocolVersion)tmp);
     } else {
         ss->clientHelloVersion = version = (SSL3ProtocolVersion)tmp;
     }
 
     /* Grab the client random data. */
     rv = ssl3_ConsumeHandshake(
-        ss, &ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH, &b, &length);
+        ss, ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH, &b, &length);
     if (rv != SECSuccess) {
         goto loser; /* malformed */
     }
 
     /* Grab the client's SID, if present. */
     rv = ssl3_ConsumeHandshakeVariable(ss, &sidBytes, 1, &b, &length);
     if (rv != SECSuccess) {
         goto loser; /* malformed */
@@ -8379,24 +8429,25 @@ ssl3_HandleClientHello(sslSocket *ss, PR
      * we are restarting a previous session until extensions have been
      * parsed, since we might have received a SessionTicket extension.
      * Note: we allow extensions even when negotiating SSL3 for the sake
      * of interoperability (and backwards compatibility).
      */
 
     if (length) {
         /* Get length of hello extensions */
-        PRUint32 extension_length;
-        rv = ssl3_ConsumeHandshakeNumber(ss, &extension_length, 2, &b, &length);
+        PRUint32 extensionLength;
+        rv = ssl3_ConsumeHandshakeNumber(ss, &extensionLength, 2, &b, &length);
         if (rv != SECSuccess) {
             goto loser; /* alert already sent */
         }
-        if (extension_length != length) {
-            ssl3_DecodeError(ss); /* send alert */
-            goto loser;
+        if (extensionLength != length) {
+            errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
+            desc = decode_error;
+            goto alert_loser;
         }
 
         rv = ssl3_ParseExtensions(ss, &b, &length);
         if (rv != SECSuccess) {
             goto loser; /* malformed */
         }
     }
 
@@ -8417,27 +8468,44 @@ ssl3_HandleClientHello(sslSocket *ss, PR
                                    PR_TRUE);
         if (rv != SECSuccess) {
             desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version
                                                        : handshake_failure;
             errCode = SSL_ERROR_UNSUPPORTED_VERSION;
             goto alert_loser;
         }
     }
+
+    if (ss->firstHsDone && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+        desc = unexpected_message;
+        errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
+        goto alert_loser;
+    }
+
     isTLS13 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
     ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
-
-    /* You can't resume TLS 1.3 like this. */
-    if (isTLS13 && sidBytes.len) {
-        goto alert_loser;
+    /* Update the write spec to match the selected version. */
+    if (!ss->firstHsDone) {
+        ssl_GetSpecWriteLock(ss);
+        ssl_SetSpecVersions(ss, ss->ssl3.cwSpec);
+        ssl_ReleaseSpecWriteLock(ss);
+    }
+
+    if (ss->ssl3.hs.altHandshakeType) {
+        rv = SECITEM_CopyItem(NULL, &ss->ssl3.hs.fakeSid, &sidBytes);
+        if (rv != SECSuccess) {
+            desc = internal_error;
+            errCode = PORT_GetError();
+            goto alert_loser;
+        }
     }
 
     /* Generate the Server Random now so it is available
      * when we process the ClientKeyShare in TLS 1.3 */
-    rv = ssl3_GetNewRandom(&ss->ssl3.hs.server_random);
+    rv = ssl3_GetNewRandom(ss->ssl3.hs.server_random);
     if (rv != SECSuccess) {
         errCode = SSL_ERROR_GENERATE_RANDOM_FAILURE;
         goto loser;
     }
 
 #ifndef TLS_1_3_DRAFT_VERSION
     /*
      * [draft-ietf-tls-tls13-11 Section 6.3.1.1].
@@ -8453,18 +8521,18 @@ ssl3_HandleClientHello(sslSocket *ss, PR
      *
      * 44 4F 57 4E 47 52 44 00
      *
      * TODO(ekr@rtfm.com): Note this change was not added in the SSLv2
      * compat processing code since that will most likely be removed before
      * we ship the final version of TLS 1.3. Bug 1306672.
      */
     if (ss->vrange.max > ss->version) {
-        unsigned char *downgrade_sentinel =
-            ss->ssl3.hs.server_random.rand +
+        PRUint8 *downgrade_sentinel =
+            ss->ssl3.hs.server_random +
             SSL3_RANDOM_LENGTH - sizeof(tls13_downgrade_random);
 
         switch (ss->vrange.max) {
             case SSL_LIBRARY_VERSION_TLS_1_3:
                 PORT_Memcpy(downgrade_sentinel,
                             tls13_downgrade_random,
                             sizeof(tls13_downgrade_random));
                 break;
@@ -8477,16 +8545,17 @@ ssl3_HandleClientHello(sslSocket *ss, PR
                 /* Do not change random. */
                 break;
         }
     }
 #endif
 
     /* Now parse the rest of the extensions. */
     rv = ssl3_HandleParsedExtensions(ss, client_hello);
+    ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions);
     if (rv != SECSuccess) {
         goto loser; /* malformed */
     }
 
     /* If the ClientHello version is less than our maximum version, check for a
      * TLS_FALLBACK_SCSV and reject the connection if found. */
     if (ss->vrange.max > ss->version) {
         for (i = 0; i + 1 < suites.len; i += 2) {
@@ -8517,26 +8586,18 @@ ssl3_HandleClientHello(sslSocket *ss, PR
                 PRUint8 *b2 = (PRUint8 *)emptyRIext;
                 PRUint32 L2 = sizeof emptyRIext;
                 (void)ssl3_HandleExtensions(ss, &b2, &L2, client_hello);
                 break;
             }
         }
     }
 
-    /* This is a second check for TLS 1.3 and re-handshake to stop us
-     * from re-handshake up to TLS 1.3, so it happens after version
-     * negotiation. */
-    if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
-        if (ss->firstHsDone) {
-            desc = unexpected_message;
-            errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
-            goto alert_loser;
-        }
-    } else {
+    /* The check for renegotiation in TLS 1.3 is earlier. */
+    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
         if (ss->firstHsDone &&
             (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_REQUIRES_XTN ||
              ss->opt.enableRenegotiation == SSL_RENEGOTIATE_TRANSITIONAL) &&
             !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
             desc = no_renegotiation;
             level = alert_warning;
             errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
             goto alert_loser;
@@ -8617,25 +8678,16 @@ ssl3_HandleClientHello(sslSocket *ss, PR
             sid = NULL;
         }
     }
 
     if (IS_DTLS(ss)) {
         ssl3_DisableNonDTLSSuites(ss);
     }
 
-#ifdef PARANOID
-    /* Look for a matching cipher suite. */
-    j = ssl3_config_match_init(ss);
-    if (j <= 0) {                  /* no ciphers are working/supported by PK11 */
-        errCode = PORT_GetError(); /* error code is already set. */
-        goto alert_loser;
-    }
-#endif
-
     if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
         rv = tls13_HandleClientHelloPart2(ss, &suites, sid);
     } else {
         rv = ssl3_HandleClientHelloPart2(ss, &suites, &comps, sid);
     }
     if (rv != SECSuccess) {
         errCode = PORT_GetError();
         goto loser;
@@ -8657,17 +8709,17 @@ ssl3_HandleClientHelloPart2(sslSocket *s
                             sslSessionID *sid)
 {
     PRBool haveSpecWriteLock = PR_FALSE;
     PRBool haveXmitBufLock = PR_FALSE;
     int errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
     SSL3AlertDescription desc = illegal_parameter;
     SECStatus rv;
     unsigned int i;
-    int j;
+    unsigned int j;
 
     /* If we already have a session for this client, be sure to pick the
     ** same cipher suite and compression method we picked before.
     ** This is not a loop, despite appearances.
     */
     if (sid)
         do {
             ssl3CipherSuiteCfg *suite;
@@ -8689,17 +8741,17 @@ ssl3_HandleClientHelloPart2(sslSocket *s
 
             suite = ss->cipherSuites;
             /* Find the entry for the cipher suite used in the cached session. */
             for (j = ssl_V3_SUITES_IMPLEMENTED; j > 0; --j, ++suite) {
                 if (suite->cipher_suite == sid->u.ssl3.cipherSuite)
                     break;
             }
             PORT_Assert(j > 0);
-            if (j <= 0)
+            if (j == 0)
                 break;
 #ifdef PARANOID
             /* Double check that the cached cipher suite is still enabled,
              * implemented, and allowed by policy.  Might have been disabled.
              * The product policy won't change during the process lifetime.
              * Implemented ("isPresent") shouldn't change for servers.
              */
             if (!config_match(suite, ss->ssl3.policy, &vrange, ss))
@@ -8726,18 +8778,17 @@ ssl3_HandleClientHelloPart2(sslSocket *s
                     goto compression_found;
                 }
             }
         } while (0);
 /* START A NEW SESSION */
 
 #ifndef PARANOID
     /* Look for a matching cipher suite. */
-    j = ssl3_config_match_init(ss);
-    if (j <= 0) { /* no ciphers are working/supported by PK11 */
+    if (ssl3_config_match_init(ss) <= 0) {
         desc = internal_error;
         errCode = PORT_GetError(); /* error code is already set. */
         goto alert_loser;
     }
 #endif
 
     rv = ssl3_NegotiateCipherSuite(ss, suites, PR_TRUE);
     if (rv != SECSuccess) {
@@ -9119,16 +9170,21 @@ ssl3_HandleV2ClientHello(sslSocket *ss, 
     if (rv != SECSuccess) {
         /* send back which ever alert client will understand. */
         desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version
                                                    : handshake_failure;
         errCode = SSL_ERROR_UNSUPPORTED_VERSION;
         goto alert_loser;
     }
     ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
+    if (!ss->firstHsDone) {
+        ssl_GetSpecWriteLock(ss);
+        ssl_SetSpecVersions(ss, ss->ssl3.cwSpec);
+        ssl_ReleaseSpecWriteLock(ss);
+    }
 
     /* if we get a non-zero SID, just ignore it. */
     if (length != total) {
         SSL_DBG(("%d: SSL3[%d]: bad v2 client hello message, len=%d should=%d",
                  SSL_GETPID(), ss->fd, length, total));
         desc = illegal_parameter;
         errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
         goto alert_loser;
@@ -9141,22 +9197,21 @@ ssl3_HandleV2ClientHello(sslSocket *ss, 
         rand_length > SSL_MAX_CHALLENGE_BYTES) {
         desc = illegal_parameter;
         errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO;
         goto alert_loser;
     }
 
     PORT_Assert(SSL_MAX_CHALLENGE_BYTES == SSL3_RANDOM_LENGTH);
 
-    PORT_Memset(&ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH);
-    PORT_Memcpy(
-        &ss->ssl3.hs.client_random.rand[SSL3_RANDOM_LENGTH - rand_length],
-        random, rand_length);
-
-    PRINT_BUF(60, (ss, "client random:", &ss->ssl3.hs.client_random.rand[0],
+    PORT_Memset(ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH);
+    PORT_Memcpy(&ss->ssl3.hs.client_random[SSL3_RANDOM_LENGTH - rand_length],
+                random, rand_length);
+
+    PRINT_BUF(60, (ss, "client random:", ss->ssl3.hs.client_random,
                    SSL3_RANDOM_LENGTH));
     i = ssl3_config_match_init(ss);
     if (i <= 0) {
         errCode = PORT_GetError(); /* error code is already set. */
         goto alert_loser;
     }
 
     /* Select a cipher suite.
@@ -9298,68 +9353,82 @@ ssl3_SendServerHello(sslSocket *ss)
 
     sid = ss->sec.ci.sid;
 
     extensions_len = ssl3_CallHelloExtensionSenders(
         ss, PR_FALSE, maxBytes, &ss->xtnData.serverHelloSenders[0]);
     if (extensions_len > 0)
         extensions_len += 2; /* Add sizeof total extension length */
 
-    /* TLS 1.3 doesn't use the session_id or compression_method
-     * fields in the ServerHello. */
     length = sizeof(SSL3ProtocolVersion) + SSL3_RANDOM_LENGTH;
+
+    /* Adjust for session ID.  In TLS 1.3 proper it isn't even present.  In the
+     * alternative TLS 1.3 handshake, it is copied from the client. */
     if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        length += 1 + ((sid == NULL) ? 0 : sid->u.ssl3.sessionIDLength);
+        length += 1; /* Session ID Length */
+        if (sid) {
+            length += sid->u.ssl3.sessionIDLength;
+        }
+    } else if (ss->ssl3.hs.altHandshakeType) {
+        length += 1 + ss->ssl3.hs.fakeSid.len;
     }
     length += sizeof(ssl3CipherSuite);
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        length += 1; /* Compression */
+    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 ||
+        ss->ssl3.hs.altHandshakeType) {
+        length += 1; /* Compression. */
     }
     length += extensions_len;
 
     rv = ssl3_AppendHandshakeHeader(ss, server_hello, length);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
 
     if (IS_DTLS(ss) && ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
         version = dtls_TLSVersionToDTLSVersion(ss->version);
-    } else {
-        version = ss->ssl3.hs.altHandshakeType ? tls13_EncodeAltDraftVersion(ss->version) : tls13_EncodeDraftVersion(ss->version);
+    } else if (ss->ssl3.hs.altHandshakeType) {
+        version = SSL_LIBRARY_VERSION_TLS_1_2;
+    } else {
+        version = tls13_EncodeDraftVersion(ss->version);
     }
 
     rv = ssl3_AppendHandshakeNumber(ss, version, 2);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
     /* Random already generated in ssl3_HandleClientHello */
     rv = ssl3_AppendHandshake(
-        ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH);
+        ss, ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
 
     if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
         if (sid) {
             rv = ssl3_AppendHandshakeVariable(
                 ss, sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength, 1);
         } else {
             rv = ssl3_AppendHandshakeNumber(ss, 0, 1);
         }
-        if (rv != SECSuccess) {
-            return rv; /* err set by AppendHandshake. */
-        }
+    } else if (ss->ssl3.hs.altHandshakeType) {
+        rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.hs.fakeSid.data,
+                                          ss->ssl3.hs.fakeSid.len, 1);
+        SECITEM_FreeItem(&ss->ssl3.hs.fakeSid, PR_FALSE);
+    }
+    if (rv != SECSuccess) {
+        return SECFailure; /* err set by AppendHandshake. */
     }
 
     rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.cipher_suite, 2);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
-    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.compression, 1);
+    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 ||
+        ss->ssl3.hs.altHandshakeType) {
+        rv = ssl3_AppendHandshakeNumber(ss, ssl_compression_null, 1);
         if (rv != SECSuccess) {
             return rv; /* err set by AppendHandshake. */
         }
     }
     if (extensions_len) {
         PRInt32 sent_len;
 
         extensions_len -= 2;
@@ -9611,22 +9680,22 @@ ssl3_EncodeSigAlgs(const sslSocket *ss, 
 }
 
 static SECStatus
 ssl3_SendCertificateRequest(sslSocket *ss)
 {
     PRBool isTLS12;
     const PRUint8 *certTypes;
     SECStatus rv;
-    int length;
+    PRUint32 length;
     SECItem *names;
     unsigned int calen;
     unsigned int nnames;
     SECItem *name;
-    int i;
+    unsigned int i;
     int certTypesLength;
     PRUint8 sigAlgs[MAX_SIGNATURE_SCHEMES * 2];
     unsigned int sigAlgsLength = 0;
 
     SSL_TRC(3, ("%d: SSL3[%d]: send certificate_request handshake",
                 SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
@@ -10834,50 +10903,51 @@ ssl3_AuthCertificate(sslSocket *ss)
         if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
             /* These are filled in in tls13_HandleCertificateVerify and
              * tls13_HandleServerKeyShare. */
             ss->sec.authType = ss->ssl3.hs.kea_def->authKeyType;
             ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
         }
         if (pubKey) {
             KeyType pubKeyType;
-            PRInt32 minKey;
+            PRUint32 minKey;
+            PRInt32 optval;
             /* This partly fixes Bug 124230 and may cause problems for
              * callers which depend on the old (wrong) behavior. */
             ss->sec.authKeyBits = SECKEY_PublicKeyStrengthInBits(pubKey);
             pubKeyType = SECKEY_GetPublicKeyType(pubKey);
             minKey = ss->sec.authKeyBits;
             switch (pubKeyType) {
                 case rsaKey:
                 case rsaPssKey:
                 case rsaOaepKey:
                     rv =
-                        NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minKey);
-                    if (rv !=
-                        SECSuccess) {
-                        minKey =
-                            SSL_RSA_MIN_MODULUS_BITS;
+                        NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &optval);
+                    if (rv == SECSuccess && optval > 0) {
+                        minKey = (PRUint32)optval;
+                    } else {
+                        minKey = SSL_RSA_MIN_MODULUS_BITS;
                     }
                     break;
                 case dsaKey:
                     rv =
-                        NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &minKey);
-                    if (rv !=
-                        SECSuccess) {
-                        minKey =
-                            SSL_DSA_MIN_P_BITS;
+                        NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &optval);
+                    if (rv == SECSuccess && optval > 0) {
+                        minKey = (PRUint32)optval;
+                    } else {
+                        minKey = SSL_DSA_MIN_P_BITS;
                     }
                     break;
                 case dhKey:
                     rv =
-                        NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &minKey);
-                    if (rv !=
-                        SECSuccess) {
-                        minKey =
-                            SSL_DH_MIN_P_BITS;
+                        NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &optval);
+                    if (rv == SECSuccess && optval > 0) {
+                        minKey = (PRUint32)optval;
+                    } else {
+                        minKey = SSL_DH_MIN_P_BITS;
                     }
                     break;
                 default:
                     break;
             }
 
             /* Too small: not good enough. Send a fatal alert. */
             /* We aren't checking EC here on the understanding that we only
@@ -11188,17 +11258,17 @@ ssl3_RecordKeyLog(sslSocket *ss, const c
 
     /* There could be multiple, concurrent writers to the
      * keylog, so we have to do everything in a single call to
      * fwrite. */
 
     strcpy(buf, label);
     offset = strlen(label);
     buf[offset++] += ' ';
-    hexEncode(buf + offset, ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
+    hexEncode(buf + offset, ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH);
     offset += SSL3_RANDOM_LENGTH * 2;
     buf[offset++] = ' ';
     hexEncode(buf + offset, keyData->data, keyData->len);
     offset += keyData->len * 2;
     buf[offset++] = '\n';
 
     PORT_Assert(offset == len);
 
@@ -11557,16 +11627,17 @@ ssl3_FillInCachedSID(sslSocket *ss, sslS
 
     if (ss->xtnData.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT &&
         ss->xtnData.nextProto.data) {
         if (SECITEM_CopyItem(
                 NULL, &sid->u.ssl3.alpnSelection, &ss->xtnData.nextProto) != SECSuccess) {
             return SECFailure; /* error already set. */
         }
     }
+    sid->u.ssl3.altHandshakeType = ss->ssl3.hs.altHandshakeType;
 
     ssl_GetSpecReadLock(ss); /*************************************/
 
     /* Copy the master secret (wrapped or unwrapped) into the sid */
     if (ss->ssl3.crSpec->msItem.len && ss->ssl3.crSpec->msItem.data) {
         sid->u.ssl3.keys.wrapped_master_secret_len =
             ss->ssl3.crSpec->msItem.len;
         memcpy(sid->u.ssl3.keys.wrapped_master_secret,
@@ -12371,17 +12442,17 @@ ssl3_UnprotectRecord(sslSocket *ss, SSL3
         /* XXX For many AEAD ciphers, the plaintext is shorter than the
          * ciphertext by a fixed byte count, but it is not true in general.
          * Each AEAD cipher should provide a function that returns the
          * plaintext length for a given ciphertext. */
         unsigned int decryptedLen =
             cText->buf->len - cipher_def->explicit_nonce_size -
             cipher_def->tag_size;
         headerLen = ssl3_BuildRecordPseudoHeader(
-            header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
+            header, crSpec->epoch, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
             rType, isTLS, cText->version, IS_DTLS(ss), decryptedLen);
         PORT_Assert(headerLen <= sizeof(header));
         rv = crSpec->aead(
             ss->sec.isServer ? &crSpec->client : &crSpec->server,
             PR_TRUE,                /* do decrypt */
             plaintext->buf,         /* out */
             (int *)&plaintext->len, /* outlen */
             plaintext->space,       /* maxout */
@@ -12420,17 +12491,18 @@ ssl3_UnprotectRecord(sslSocket *ss, SSL3
             } else {
                 good &= SECStatusToMask(ssl_RemoveTLSCBCPadding(
                     plaintext, macSize));
             }
         }
 
         /* compute the MAC */
         headerLen = ssl3_BuildRecordPseudoHeader(
-            header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
+            header, crSpec->epoch,
+            IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num,
             rType, isTLS, cText->version, IS_DTLS(ss),
             plaintext->len - crSpec->mac_size);
         PORT_Assert(headerLen <= sizeof(header));
         if (cipher_def->type == type_block) {
             rv = ssl3_ComputeRecordMACConstantTime(
                 crSpec, (PRBool)(!ss->sec.isServer), header, headerLen,
                 plaintext->buf, plaintext->len, originalLen,
                 hash, &hashBytes);
@@ -12611,21 +12683,36 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Cip
     if (rv != SECSuccess) {
         ssl_ReleaseSpecReadLock(ss); /***************************/
 
         SSL_DBG(("%d: SSL3[%d]: decryption failed", SSL_GETPID(), ss->fd));
 
         /* Clear the temp buffer used for decompression upon failure. */
         sslBuffer_Clear(&temp_buf);
 
+        /* Zero the input so that we don't process it again. */
+        databuf->len = 0;
+
+        /* Ignore a CCS if the alternative handshake is negotiated.  Note that
+         * this will fail if the server fails to negotiate the alternative
+         * handshake type in a 0-RTT session that is resumed from a session that
+         * did negotiate it.  We don't care about that corner case right now. */
+        if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 &&
+            cText->type == content_change_cipher_spec &&
+            ss->ssl3.hs.ws != idle_handshake &&
+            ss->ssl3.hs.altHandshakeType &&
+            cText->buf->len == 1 &&
+            cText->buf->buf[0] == change_cipher_spec_choice) {
+            /* Ignore the error. */
+            return SECSuccess;
+        }
         if (IS_DTLS(ss) ||
             (ss->sec.isServer &&
              ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_trial)) {
             /* Silently drop the packet */
-            databuf->len = 0; /* Needed to ensure data not left around */
             return SECSuccess;
         } else {
             int errCode = PORT_GetError();
             SSL3_SendAlert(ss, alert_fatal, alert);
             /* Reset the error code in case SSL3_SendAlert called
              * PORT_SetError(). */
             PORT_SetError(errCode);
             return SECFailure;
@@ -12704,17 +12791,17 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Cip
         }
 
         sslBuffer_Clear(&temp_buf);
     }
 
     /*
     ** Having completed the decompression, check the length again.
     */
-    if (isTLS && databuf->len > (MAX_FRAGMENT_LENGTH + 1024)) {
+    if (isTLS && databuf->len > MAX_FRAGMENT_LENGTH) {
         SSL3_SendAlert(ss, alert_fatal, record_overflow);
         PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
         return SECFailure;
     }
 
     /* Application data records are processed by the caller of this
     ** function, not by this function.
     */
@@ -12854,17 +12941,37 @@ ssl3_InitState(sslSocket *ss)
 
     ssl_InitSecState(&ss->sec);
 
     ssl_GetSpecWriteLock(ss);
     ss->ssl3.crSpec = ss->ssl3.cwSpec = &ss->ssl3.specs[0];
     ss->ssl3.prSpec = ss->ssl3.pwSpec = &ss->ssl3.specs[1];
     ssl3_InitCipherSpec(ss->ssl3.crSpec);
     ssl3_InitCipherSpec(ss->ssl3.prSpec);
-    ss->ssl3.crSpec->version = ss->ssl3.prSpec->version = ss->vrange.max;
+    ss->ssl3.crSpec->version = ss->vrange.max;
+    if (IS_DTLS(ss)) {
+        ss->ssl3.crSpec->recordVersion = SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
+    } else {
+        /* For new connections, cap the record layer version number of TLS
+         * ClientHello to { 3, 1 } (TLS 1.0). Some TLS 1.0 servers (which seem
+         * to use F5 BIG-IP) ignore ClientHello.client_version and use the
+         * record layer version number (TLSPlaintext.version) instead when
+         * negotiating protocol versions. In addition, if the record layer
+         * version number of ClientHello is { 3, 2 } (TLS 1.1) or higher, these
+         * servers reset the TCP connections. Lastly, some F5 BIG-IP servers
+         * hang if a record containing a ClientHello has a version greater than
+         * { 3, 1 } and a length greater than 255. Set this flag to work around
+         * such servers.
+         *
+         * We bump the version up when we settle on a version.  Before producing
+         * an initial ServerHello, or when processing it.
+         */
+        ss->ssl3.crSpec->recordVersion = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0,
+                                                ss->vrange.max);
+    }
     ssl_ReleaseSpecWriteLock(ss);
 
     ss->ssl3.hs.sendingSCSV = PR_FALSE;
     ss->ssl3.hs.preliminaryInfo = 0;
     ss->ssl3.hs.ws = (ss->sec.isServer) ? wait_client_hello : wait_server_hello;
 
     ssl3_ResetExtensionData(&ss->xtnData);
     PR_INIT_CLIST(&ss->ssl3.hs.remoteExtensions);
@@ -13223,16 +13330,17 @@ ssl3_DestroySSL3Info(sslSocket *ss)
         sslBuffer_Clear(&ss->ssl3.hs.messages);
     }
 
     /* free the SSL3Buffer (msg_body) */
     PORT_Free(ss->ssl3.hs.msg_body.buf);
 
     SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE);
     SECITEM_FreeItem(&ss->ssl3.hs.srvVirtName, PR_FALSE);
+    SECITEM_FreeItem(&ss->ssl3.hs.fakeSid, PR_FALSE);
 
     if (ss->ssl3.hs.certificateRequest) {
         PORT_FreeArena(ss->ssl3.hs.certificateRequest->arena, PR_FALSE);
         ss->ssl3.hs.certificateRequest = NULL;
     }
 
     /* free up the CipherSpecs */
     ssl3_DestroyCipherSpec(&ss->ssl3.specs[0], PR_TRUE /*freeSrvName*/);
--- a/security/nss/lib/ssl/ssl3ecc.c
+++ b/security/nss/lib/ssl/ssl3ecc.c
@@ -106,17 +106,17 @@ ssl_ECPubKey2NamedGroup(const SECKEYPubl
 
     return NULL;
 }
 
 /* Caller must set hiLevel error code. */
 static SECStatus
 ssl3_ComputeECDHKeyHash(SSLHashType hashAlg,
                         SECItem ec_params, SECItem server_ecpoint,
-                        SSL3Random *client_rand, SSL3Random *server_rand,
+                        PRUint8 *client_rand, PRUint8 *server_rand,
                         SSL3Hashes *hashes)
 {
     PRUint8 *hashBuf;
     PRUint8 *pBuf;
     SECStatus rv = SECSuccess;
     unsigned int bufLen;
     /*
      * We only support named curves (the appropriate checks are made before this
@@ -592,18 +592,18 @@ ssl3_HandleECDHServerKeyExchange(sslSock
     /* failures after this point are not malformed handshakes. */
     /* TLS: send decrypt_error if signature failed. */
     desc = isTLS ? decrypt_error : handshake_failure;
 
     /*
      *  check to make sure the hash is signed by right guy
      */
     rv = ssl3_ComputeECDHKeyHash(hashAlg, ec_params, ec_point,
-                                 &ss->ssl3.hs.client_random,
-                                 &ss->ssl3.hs.server_random,
+                                 ss->ssl3.hs.client_random,
+                                 ss->ssl3.hs.server_random,
                                  &hashes);
 
     if (rv != SECSuccess) {
         errCode =
             ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
         goto alert_loser;
     }
     rv = ssl3_VerifySignedHashes(ss, sigScheme, &hashes, &signature);
@@ -706,18 +706,18 @@ ssl3_SendECDHServerKeyExchange(sslSocket
     if (ss->ssl3.pwSpec->version == SSL_LIBRARY_VERSION_TLS_1_2) {
         hashAlg = ssl_SignatureSchemeToHashType(ss->ssl3.hs.signatureScheme);
     } else {
         /* Use ssl_hash_none to represent the MD5+SHA1 combo. */
         hashAlg = ssl_hash_none;
     }
     rv = ssl3_ComputeECDHKeyHash(hashAlg, ec_params,
                                  pubKey->u.ec.publicValue,
-                                 &ss->ssl3.hs.client_random,
-                                 &ss->ssl3.hs.server_random,
+                                 ss->ssl3.hs.client_random,
+                                 ss->ssl3.hs.server_random,
                                  &hashes);
     if (rv != SECSuccess) {
         ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
         goto loser;
     }
 
     isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
 
--- a/security/nss/lib/ssl/ssl3exthandle.c
+++ b/security/nss/lib/ssl/ssl3exthandle.c
@@ -797,17 +797,17 @@ ssl3_ClientHandleStatusRequestXtn(const 
     }
 
     /* Keep track of negotiated extensions. */
     xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
     return SECSuccess;
 }
 
 PRUint32 ssl_ticket_lifetime = 2 * 24 * 60 * 60; /* 2 days in seconds */
-#define TLS_EX_SESS_TICKET_VERSION (0x0106)
+#define TLS_EX_SESS_TICKET_VERSION (0x0107)
 
 /*
  * Called from ssl3_SendNewSessionTicket, tls13_SendNewSessionTicket
  */
 SECStatus
 ssl3_EncodeSessionTicket(sslSocket *ss,
                          const NewSessionTicket *ticket,
                          SECItem *ticket_data)
@@ -889,16 +889,17 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
         + 2                                    /* master_secret.length */
         + ms_item.len                          /* master_secret */
         + 1                                    /* client_auth_type */
         + cert_length                          /* cert */
         + 2 + srvName->len                     /* name len + length field */
         + 1                                    /* extendedMasterSecretUsed */
         + sizeof(ticket->ticket_lifetime_hint) /* ticket lifetime hint */
         + sizeof(ticket->flags)                /* ticket flags */
+        + 1                                    /* alt handshake type */
         + 1 + alpnSelection->len               /* alpn value + length field */
         + 4;                                   /* maxEarlyData */
 
     if (SECITEM_AllocItem(NULL, &plaintext_item, plaintext_length) == NULL)
         goto loser;
 
     plaintext = plaintext_item;
 
@@ -1035,16 +1036,21 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
     if (rv != SECSuccess)
         goto loser;
     if (alpnSelection->len) {
         rv = ssl3_AppendToItem(&plaintext, alpnSelection->data,
                                alpnSelection->len);
         if (rv != SECSuccess)
             goto loser;
     }
+    /* Alternative handshake type. */
+    rv = ssl3_AppendNumberToItem(
+        &plaintext, ss->sec.ci.sid->u.ssl3.altHandshakeType, 1);
+    if (rv != SECSuccess)
+        goto loser;
 
     rv = ssl3_AppendNumberToItem(&plaintext, ssl_max_early_data_size, 4);
     if (rv != SECSuccess)
         goto loser;
 
     /* Check that we are totally full. */
     PORT_Assert(plaintext.len == 0);
 
@@ -1301,16 +1307,24 @@ ssl_ParseSessionTicket(sslSocket *ss, co
     rv = ssl3_ExtConsumeHandshakeVariable(ss, &parsedTicket->alpnSelection, 1,
                                           &buffer, &len);
     PORT_Assert(parsedTicket->alpnSelection.len < 256);
     if (rv != SECSuccess) {
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
 
+    rv = ssl3_ExtConsumeHandshakeNumber(ss, &temp, 1, &buffer, &len);
+    if (rv != SECSuccess) {
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        return SECFailure;
+    }
+    PORT_Assert(temp == PR_TRUE || temp == PR_FALSE);
+    parsedTicket->altHandshakeType = temp;
+
     rv = ssl3_ExtConsumeHandshakeNumber(ss, &temp, 4, &buffer, &len);
     if (rv != SECSuccess) {
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
     parsedTicket->maxEarlyData = temp;
 
 #ifndef UNSAFE_FUZZER_MODE
@@ -1365,16 +1379,17 @@ ssl_CreateSIDFromTicket(sslSocket *ss, c
     PORT_Memcpy(sid->u.ssl3.keys.wrapped_master_secret,
                 parsedTicket->master_secret, parsedTicket->ms_length);
     sid->u.ssl3.keys.wrapped_master_secret_len = parsedTicket->ms_length;
     sid->u.ssl3.masterWrapMech = parsedTicket->msWrapMech;
     sid->u.ssl3.keys.msIsWrapped = parsedTicket->ms_is_wrapped;
     sid->u.ssl3.masterValid = PR_TRUE;
     sid->u.ssl3.keys.resumable = PR_TRUE;
     sid->u.ssl3.keys.extendedMasterSecretUsed = parsedTicket->extendedMasterSecretUsed;
+    sid->u.ssl3.altHandshakeType = parsedTicket->altHandshakeType;
 
     /* Copy over client cert from session ticket if there is one. */
     if (parsedTicket->peer_cert.data != NULL) {
         PORT_Assert(!sid->peerCert);
         sid->peerCert = CERT_NewTempCertificate(ss->dbHandle,
                                                 &parsedTicket->peer_cert,
                                                 NULL, PR_FALSE, PR_TRUE);
         if (!sid->peerCert) {
--- a/security/nss/lib/ssl/ssl3gthr.c
+++ b/security/nss/lib/ssl/ssl3gthr.c
@@ -390,17 +390,18 @@ dtls_GatherData(sslSocket *ss, sslGather
  */
 int
 ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
 {
     int rv;
     SSL3Ciphertext cText;
     PRBool keepGoing = PR_TRUE;
 
-    SSL_TRC(30, ("ssl3_GatherCompleteHandshake"));
+    SSL_TRC(30, ("%d: SSL3[%d]: ssl3_GatherCompleteHandshake",
+                 SSL_GETPID(), ss->fd));
 
     /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake,
      * which requires the 1stHandshakeLock, which must be acquired before the
      * RecvBufLock.
      */
     PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
 
@@ -503,17 +504,16 @@ ssl3_GatherCompleteHandshake(sslSocket *
                 } else {
                     cText.type = (SSL3ContentType)ss->gs.hdr[0];
                     cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
                 }
 
                 if (IS_DTLS(ss)) {
                     sslSequenceNumber seq_num;
 
-                    cText.version = dtls_DTLSVersionToTLSVersion(cText.version);
                     /* DTLS sequence number */
                     PORT_Memcpy(&seq_num, &ss->gs.hdr[3], sizeof(seq_num));
                     cText.seq_num = PR_ntohll(seq_num);
                 }
 
                 cText.buf = &ss->gs.inbuf;
                 rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
             }
--- a/security/nss/lib/ssl/ssl3prot.h
+++ b/security/nss/lib/ssl/ssl3prot.h
@@ -146,19 +146,17 @@ typedef enum {
     certificate_status = 22,
     next_proto = 67
 } SSL3HandshakeType;
 
 typedef struct {
     PRUint8 empty;
 } SSL3HelloRequest;
 
-typedef struct {
-    PRUint8 rand[SSL3_RANDOM_LENGTH];
-} SSL3Random;
+typedef PRUint8 SSL3Random[SSL3_RANDOM_LENGTH];
 
 typedef struct {
     PRUint8 id[32];
     PRUint8 length;
 } SSL3SessionID;
 
 typedef struct {
     SSL3ProtocolVersion client_version;
--- a/security/nss/lib/ssl/sslexp.h
+++ b/security/nss/lib/ssl/sslexp.h
@@ -17,21 +17,20 @@ SEC_BEGIN_PROTOS
  * future NSS versions. Code that uses these functions needs to safeguard
  * against the function not being available. */
 
 #define SSL_EXPERIMENTAL_API(name, arglist, args)                   \
     (SSL_GetExperimentalAPI(name)                                   \
          ? ((SECStatus(*) arglist)SSL_GetExperimentalAPI(name))args \
          : SECFailure)
 
-/* Allow the ServerHello to be record type 24. Experiment to test:
- * https://github.com/tlswg/tls13-spec/pull/1051
+/* Make the TLS 1.3 handshake mimic TLS 1.2 session resumption.
  * This will either become part of the standard or be disabled
  * after we have tested it.
  */
-#define SSL_UseAltServerHelloType(fd, enable)                \
-    SSL_EXPERIMENTAL_API("SSL_UseAltServerHelloType",        \
+#define SSL_UseAltHandshakeType(fd, enable)                  \
+    SSL_EXPERIMENTAL_API("SSL_UseAltHandshakeType",          \
                          (PRFileDesc * _fd, PRBool _enable), \
                          (fd, enable))
 
 SEC_END_PROTOS
 
 #endif /* __sslexp_h_ */
--- a/security/nss/lib/ssl/sslimpl.h
+++ b/security/nss/lib/ssl/sslimpl.h
@@ -224,18 +224,16 @@ struct sslSocketOpsStr {
     int (*getpeername)(sslSocket *, PRNetAddr *);
     int (*getsockname)(sslSocket *, PRNetAddr *);
 };
 
 /* Flags interpreted by ssl send functions. */
 #define ssl_SEND_FLAG_FORCE_INTO_BUFFER 0x40000000
 #define ssl_SEND_FLAG_NO_BUFFER 0x20000000
 #define ssl_SEND_FLAG_NO_RETRANSMIT 0x08000000 /* DTLS only */
-#define ssl_SEND_FLAG_CAP_RECORD_VERSION \
-    0x04000000 /* TLS only */
 #define ssl_SEND_FLAG_MASK 0x7f000000
 
 /*
 ** A buffer object.
 */
 struct sslBufferStr {
     unsigned char *buf;
     unsigned int len;
@@ -495,16 +493,17 @@ struct ssl3CipherSpecStr {
     SSLDestroy destroyCompressContext;
     void *compressContext;
     SSLDestroy destroyDecompressContext;
     void *decompressContext;
     PK11SymKey *master_secret;
     sslSequenceNumber write_seq_num;
     sslSequenceNumber read_seq_num;
     SSL3ProtocolVersion version;
+    SSL3ProtocolVersion recordVersion;
     ssl3KeyMaterial client;
     ssl3KeyMaterial server;
     SECItem msItem;
     DTLSEpoch epoch;
     DTLSRecvdRecords recvdRecords;
     /* The number of 0-RTT bytes that can be sent or received in TLS 1.3. This
      * will be zero for everything but 0-RTT. */
     PRUint32 earlyDataRemaining;
@@ -604,16 +603,18 @@ struct sslSessionIDStr {
             ** (used only in client).
             */
             SECItem signedCertTimestamps;
 
             /* The NPN/ALPN value negotiated in the original connection.
              * Used for TLS 1.3. */
             SECItem alpnSelection;
 
+            PRBool altHandshakeType;
+
             /* This lock is lazily initialized by CacheSID when a sid is first
              * cached. Before then, there is no need to lock anything because
              * the sid isn't being shared by anything.
              */
             PRRWLock *lock;
 
             /* The lock must be held while reading or writing these members
              * because they change while the sid is cached.
@@ -881,17 +882,18 @@ typedef struct SSL3HandshakeStateStr {
     ssl3CipherSuite zeroRttSuite;   /* The cipher suite we used for 0-RTT. */
     PRCList bufferedEarlyData;      /* Buffered TLS 1.3 early data
                                      * on server.*/
     PRBool helloRetry;              /* True if HelloRetryRequest has been sent
                                      * or received. */
     ssl3KEADef kea_def_mutable;     /* Used to hold the writable kea_def
                                      * we use for TLS 1.3 */
     PRBool shortHeaders;            /* Assigned if we are doing short headers. */
-    PRBool altHandshakeType;        /* Assigned if we are doing the wrapped handshake. */
+    PRBool altHandshakeType;        /* Alternative ServerHello content type. */
+    SECItem fakeSid;                /* ... (server) the SID the client used. */
 } SSL3HandshakeState;
 
 /*
 ** This is the "ssl3" struct, as in "ss->ssl3".
 ** note:
 ** usually,   crSpec == cwSpec and prSpec == pwSpec.
 ** Sometimes, crSpec == pwSpec and prSpec == cwSpec.
 ** But there are never more than 2 actual specs.
@@ -1017,16 +1019,17 @@ typedef struct SessionTicketStr {
     PRUint8 master_secret[48];
     PRBool extendedMasterSecretUsed;
     ClientAuthenticationType client_auth_type;
     SECItem peer_cert;
     PRUint32 timestamp;
     PRUint32 flags;
     SECItem srvName; /* negotiated server name */
     SECItem alpnSelection;
+    PRBool altHandshakeType;
     PRUint32 maxEarlyData;
 } SessionTicket;
 
 /*
  * SSL2 buffers used in SSL3.
  *     writeBuf in the SecurityInfo maintained by sslsecur.c is used
  *              to hold the data just about to be passed to the kernel
  *     sendBuf in the ConnectInfo maintained by sslcon.c is used
@@ -1648,16 +1651,20 @@ extern SECStatus ssl3_HandleHandshakeMes
 extern void ssl3_DestroySSL3Info(sslSocket *ss);
 
 extern SECStatus ssl_ClientReadVersion(sslSocket *ss, PRUint8 **b,
                                        PRUint32 *length,
                                        SSL3ProtocolVersion *version);
 extern SECStatus ssl3_NegotiateVersion(sslSocket *ss,
                                        SSL3ProtocolVersion peerVersion,
                                        PRBool allowLargerPeerVersion);
+extern SECStatus ssl_ClientSetCipherSuite(sslSocket *ss,
+                                          SSL3ProtocolVersion version,
+                                          ssl3CipherSuite suite,
+                                          PRBool initHashes);
 
 extern SECStatus ssl_GetPeerInfo(sslSocket *ss);
 
 /* ECDH functions */
 extern SECStatus ssl3_SendECDHClientKeyExchange(sslSocket *ss,
                                                 SECKEYPublicKey *svrPubKey);
 extern SECStatus ssl3_HandleECDHServerKeyExchange(sslSocket *ss,
                                                   PRUint8 *b, PRUint32 length);
@@ -1821,16 +1828,17 @@ SECStatus ssl_GetCertificateRequestCAs(s
                                        SECItem **namesp, unsigned int *nnamesp);
 SECStatus ssl3_ParseCertificateRequestCAs(sslSocket *ss, PRUint8 **b,
                                           PRUint32 *length, PLArenaPool *arena,
                                           CERTDistNames *ca_list);
 SECStatus ssl3_CompleteHandleCertificateRequest(
     sslSocket *ss, const SSLSignatureScheme *signatureSchemes,
     unsigned int signatureSchemeCount, CERTDistNames *ca_list);
 SECStatus ssl3_SendServerHello(sslSocket *ss);
+SECStatus ssl3_SendChangeCipherSpecsInt(sslSocket *ss);
 SECStatus ssl3_ComputeHandshakeHashes(sslSocket *ss,
                                       ssl3CipherSpec *spec,
                                       SSL3Hashes *hashes,
                                       PRUint32 sender);
 SECStatus ssl_CreateECDHEphemeralKeyPair(const sslSocket *ss,
                                          const sslNamedGroupDef *ecGroup,
                                          sslEphemeralKeyPair **keyPair);
 SECStatus ssl_CreateStaticECDHEKey(sslSocket *ss,
--- a/security/nss/lib/ssl/sslinfo.c
+++ b/security/nss/lib/ssl/sslinfo.c
@@ -463,19 +463,19 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd,
     if (hasContext) {
         valLen += 2 /* PRUint16 length */ + contextLen;
     }
     val = PORT_Alloc(valLen);
     if (!val) {
         return SECFailure;
     }
     i = 0;
-    PORT_Memcpy(val + i, &ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
+    PORT_Memcpy(val + i, ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH);
     i += SSL3_RANDOM_LENGTH;
-    PORT_Memcpy(val + i, &ss->ssl3.hs.server_random.rand, SSL3_RANDOM_LENGTH);
+    PORT_Memcpy(val + i, ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH);
     i += SSL3_RANDOM_LENGTH;
     if (hasContext) {
         val[i++] = contextLen >> 8;
         val[i++] = contextLen;
         PORT_Memcpy(val + i, context, contextLen);
         i += contextLen;
     }
     PORT_Assert(i == valLen);
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -3870,17 +3870,17 @@ SSL_CanBypass(CERTCertificate *cert, SEC
     {                      \
         "SSL_" #n, SSL_##n \
     }
 struct {
     const char *const name;
     void *function;
 } ssl_experimental_functions[] = {
 #ifndef SSL_DISABLE_EXPERIMENTAL_API
-    EXP(UseAltServerHelloType),
+    EXP(UseAltHandshakeType),
 #endif
     { "", NULL }
 };
 #undef EXP
 #undef PUB
 
 void *
 SSL_GetExperimentalAPI(const char *name)
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -128,19 +128,16 @@ const char keylogLabelClientTrafficSecre
 const char keylogLabelServerTrafficSecret[] = "SERVER_TRAFFIC_SECRET_0";
 const char keylogLabelExporterSecret[] = "EXPORTER_SECRET";
 
 #define TRAFFIC_SECRET(ss, dir, name) ((ss->sec.isServer ^            \
                                         (dir == CipherSpecWrite))     \
                                            ? ss->ssl3.hs.client##name \
                                            : ss->ssl3.hs.server##name)
 
-const SSL3ProtocolVersion kTlsRecordVersion = SSL_LIBRARY_VERSION_TLS_1_0;
-const SSL3ProtocolVersion kDtlsRecordVersion = SSL_LIBRARY_VERSION_TLS_1_1;
-
 /* Belt and suspenders in case we ever add a TLS 1.4. */
 PR_STATIC_ASSERT(SSL_LIBRARY_VERSION_MAX_SUPPORTED <=
                  SSL_LIBRARY_VERSION_TLS_1_3);
 
 /* Use this instead of FATAL_ERROR when no alert shall be sent. */
 #define LOG_ERROR(ss, prError)                                                     \
     do {                                                                           \
         SSL_TRC(3, ("%d: TLS13[%d]: fatal error %d in %s (%s:%d)",                 \
@@ -1723,17 +1720,19 @@ tls13_HandleHelloRetryRequest(sslSocket 
         ssl_ReleaseSpecWriteLock(ss);
     } else {
         PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_none);
     }
 
     /* Version. */
     rv = ssl_ClientReadVersion(ss, &b, &length, &version);
     if (rv != SECSuccess) {
-        return SECFailure; /* alert already sent */
+        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST,
+                    protocol_version);
+        return SECFailure;
     }
     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. */
@@ -1936,16 +1935,23 @@ tls13_SendServerHelloSequence(sslSocket 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
     rv = ssl3_SendServerHello(ss);
     if (rv != SECSuccess) {
         return rv; /* err code is set. */
     }
 
+    if (ss->ssl3.hs.altHandshakeType) {
+        rv = ssl3_SendChangeCipherSpecsInt(ss);
+        if (rv != SECSuccess) {
+            return rv;
+        }
+    }
+
     rv = tls13_SendEncryptedServerSequence(ss);
     if (rv != SECSuccess) {
         err = PORT_GetError();
     }
     /* Even if we get an error, since the ServerHello was successfully
      * serialized, we should give it a chance to reach the network.  This gives
      * the client a chance to perform the key exchange and decrypt the alert
      * we're about to send. */
@@ -2699,37 +2705,71 @@ tls13_DeriveTrafficKeys(sslSocket *ss, s
         *prkp = NULL;
     }
     return SECSuccess;
 
 loser:
     return SECFailure;
 }
 
-static SECStatus
-tls13_SetupPendingCipherSpec(sslSocket *ss)
+void
+tls13_SetSpecRecordVersion(sslSocket *ss, ssl3CipherSpec *spec)
 {
-    ssl3CipherSpec *pSpec;
+    const SSL3ProtocolVersion kTlsRecordVersion = SSL_LIBRARY_VERSION_TLS_1_0;
+    const SSL3ProtocolVersion kTlsAltRecordVersion = SSL_LIBRARY_VERSION_TLS_1_2;
+    const SSL3ProtocolVersion kDtlsRecordVersion = SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
+
+    /* Set the record version. */
+    if (IS_DTLS(ss)) {
+        spec->recordVersion = kDtlsRecordVersion;
+    } else if (spec->epoch == TrafficKeyEarlyApplicationData) {
+        /* For early data, the previous session determines the record type that
+         * is used (and not what this session might negotiate). */
+        if (ss->sec.ci.sid && ss->sec.ci.sid->u.ssl3.altHandshakeType) {
+            spec->recordVersion = kTlsAltRecordVersion;
+        } else {
+            spec->recordVersion = kTlsRecordVersion;
+        }
+    } else if (ss->ssl3.hs.altHandshakeType) {
+        spec->recordVersion = kTlsAltRecordVersion;
+    } else {
+        spec->recordVersion = kTlsRecordVersion;
+    }
+    SSL_TRC(10, ("%d: TLS13[%d]: Set record version to 0x%04x",
+                 SSL_GETPID(), ss->fd, spec->recordVersion));
+}
+
+static SECStatus
+tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
+{
     ssl3CipherSuite suite = ss->ssl3.hs.cipher_suite;
-    const ssl3BulkCipherDef *bulk = ssl_GetBulkCipherDef(
-        ssl_LookupCipherSuiteDef(suite));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
-    ssl_GetSpecWriteLock(ss); /*******************************/
-
-    pSpec = ss->ssl3.pwSpec;
     /* Version isn't set when we send 0-RTT data. */
-    pSpec->version = PR_MAX(SSL_LIBRARY_VERSION_TLS_1_3, ss->version);
+    spec->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); /*******************************/
+
+    spec->cipher_def = ssl_GetBulkCipherDef(ssl_LookupCipherSuiteDef(suite));
+    switch (spec->cipher_def->calg) {
+        case ssl_calg_aes_gcm:
+            spec->aead = tls13_AESGCM;
+            break;
+        case ssl_calg_chacha20:
+            spec->aead = tls13_ChaCha20Poly1305;
+            break;
+        default:
+            PORT_Assert(0);
+            return SECFailure;
+            break;
+    }
+
+    tls13_SetSpecRecordVersion(ss, spec);
     return SECSuccess;
 }
 
 /* Install a new cipher spec for this direction. */
 static SECStatus
 tls13_SetCipherSpec(sslSocket *ss, TrafficKeyType type,
                     CipherSpecDirection direction, PRBool deleteSecret)
 {
@@ -2749,39 +2789,16 @@ tls13_SetCipherSpec(sslSocket *ss, Traff
     if (!spec) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         return SECFailure;
     }
     spec->refCt = 1;
     PR_APPEND_LINK(&spec->link, &ss->ssl3.hs.cipherSpecs);
     ss->ssl3.pwSpec = ss->ssl3.prSpec = spec;
 
-    rv = tls13_SetupPendingCipherSpec(ss);
-    if (rv != SECSuccess)
-        return SECFailure;
-
-    switch (spec->cipher_def->calg) {
-        case calg_aes_gcm:
-            spec->aead = tls13_AESGCM;
-            break;
-        case calg_chacha20:
-            spec->aead = tls13_ChaCha20Poly1305;
-            break;
-        default:
-            PORT_Assert(0);
-            return SECFailure;
-            break;
-    }
-
-    rv = tls13_DeriveTrafficKeys(ss, spec, type, direction,
-                                 deleteSecret);
-    if (rv != SECSuccess) {
-        return SECFailure;
-    }
-
     /* We use the epoch for cipher suite identification, so increment
      * it in both TLS and DTLS. */
     if ((*specp)->epoch == PR_UINT16_MAX) {
         return SECFailure;
     }
     spec->epoch = (PRUint16)type;
 
     if (!IS_DTLS(ss)) {
@@ -2789,16 +2806,27 @@ tls13_SetCipherSpec(sslSocket *ss, Traff
     } else {
         /* The sequence number has the high 16 bits as the epoch. */
         spec->read_seq_num = spec->write_seq_num =
             (sslSequenceNumber)spec->epoch << 48;
 
         dtls_InitRecvdRecords(&spec->recvdRecords);
     }
 
+    /* This depends on spec having a valid direction and epoch. */
+    rv = tls13_SetupPendingCipherSpec(ss, spec);
+    if (rv != SECSuccess)
+        return SECFailure;
+
+    rv = tls13_DeriveTrafficKeys(ss, spec, type, direction,
+                                 deleteSecret);
+    if (rv != SECSuccess) {
+        return SECFailure;
+    }
+
     if (type == TrafficKeyEarlyApplicationData) {
         spec->earlyDataRemaining =
             ss->sec.ci.sid->u.ssl3.locked.sessionTicket.max_early_data_size;
     }
 
     /* Now that we've set almost everything up, finally cut over. */
     ssl_GetSpecWriteLock(ss);
     tls13_CipherSpecRelease(*specp); /* May delete old cipher. */
@@ -3740,16 +3768,24 @@ tls13_SendClientSecondRound(sslSocket *s
         return SECWouldBlock;
     }
 
     if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) {
         rv = tls13_SendEndOfEarlyData(ss);
         if (rv != SECSuccess) {
             return SECFailure; /* Error code already set. */
         }
+    } else if (ss->ssl3.hs.zeroRttState == ssl_0rtt_none &&
+               ss->ssl3.hs.altHandshakeType) {
+        ssl_GetXmitBufLock(ss); /*******************************/
+        rv = ssl3_SendChangeCipherSpecsInt(ss);
+        ssl_ReleaseXmitBufLock(ss); /*******************************/
+        if (rv != SECSuccess) {
+            return rv;
+        }
     }
 
     rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake,
                              CipherSpecWrite, PR_FALSE);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SSL_ERROR_INIT_CIPHER_SUITE_FAILURE, internal_error);
         return SECFailure;
     }
@@ -4041,17 +4077,18 @@ static const struct {
     { ssl_tls13_pre_shared_key_xtn, ExtensionSendClear },
     { ssl_tls13_early_data_xtn, ExtensionSendEncrypted },
     { ssl_next_proto_nego_xtn, ExtensionNotUsed },
     { ssl_renegotiation_info_xtn, ExtensionNotUsed },
     { ssl_signed_cert_timestamp_xtn, ExtensionSendCertificate },
     { ssl_cert_status_xtn, ExtensionSendCertificate },
     { ssl_tls13_ticket_early_data_info_xtn, ExtensionNewSessionTicket },
     { ssl_tls13_cookie_xtn, ExtensionSendHrr },
-    { ssl_tls13_short_header_xtn, ExtensionSendClear }
+    { ssl_tls13_short_header_xtn, ExtensionSendClear },
+    { ssl_tls13_supported_versions_xtn, ExtensionSendClear }
 };
 
 PRBool
 tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message)
 {
     unsigned int i;
 
     PORT_Assert((message == client_hello) ||
@@ -4234,19 +4271,18 @@ tls13_UnprotectRecord(sslSocket *ss, SSL
         SSL_TRC(3,
                 ("%d: TLS13[%d]: record has invalid exterior content type=%d",
                  SSL_GETPID(), ss->fd, cText->type));
         /* Do we need a better error here? */
         PORT_SetError(SSL_ERROR_BAD_MAC_READ);
         return SECFailure;
     }
 
-    /* Check the version number in the record */
-    if ((IS_DTLS(ss) && cText->version != kDtlsRecordVersion) ||
-        (!IS_DTLS(ss) && cText->version != kTlsRecordVersion)) {
+    /* Check the version number in the record. */
+    if (cText->version != crSpec->recordVersion) {
         /* Do we need a better error here? */
         SSL_TRC(3,
                 ("%d: TLS13[%d]: record has bogus version",
                  SSL_GETPID(), ss->fd));
         return SECFailure;
     }
 
     /* Decrypt */
@@ -4359,36 +4395,50 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss
     SSL_TRC(3, ("%d: TLS13[%d]: in 0-RTT mode", SSL_GETPID(), ss->fd));
 
     /* Set the ALPN data as if it was negotiated. We check in the ServerHello
      * handler that the server negotiates the same value. */
     if (ss->sec.ci.sid->u.ssl3.alpnSelection.len) {
         ss->xtnData.nextProtoState = SSL_NEXT_PROTO_EARLY_VALUE;
         rv = SECITEM_CopyItem(NULL, &ss->xtnData.nextProto,
                               &ss->sec.ci.sid->u.ssl3.alpnSelection);
-        if (rv != SECSuccess)
-            return rv;
+        if (rv != SECSuccess) {
+            return SECFailure;
+        }
+    }
+
+    /* If the alternative handshake type option is enabled and the last session
+     * had the alternative handshake type, then send CCS. */
+    if (ss->opt.enableAltHandshaketype &&
+        ss->sec.ci.sid->u.ssl3.altHandshakeType) {
+        ssl_GetXmitBufLock(ss);
+        rv = ssl3_SendChangeCipherSpecsInt(ss);
+        ssl_ReleaseXmitBufLock(ss);
+        if (rv != SECSuccess) {
+            return SECFailure;
+        }
     }
 
     /* Cipher suite already set in tls13_SetupClientHello. */
     ss->ssl3.hs.preliminaryInfo = 0;
 
     rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
                             kHkdfLabelClient,
                             kHkdfLabelEarlyTrafficSecret,
                             keylogLabelClientEarlyTrafficSecret,
                             NULL,
                             &ss->ssl3.hs.clientEarlyTrafficSecret);
-    if (rv != SECSuccess)
+    if (rv != SECSuccess) {
         return SECFailure;
+    }
 
     rv = tls13_SetCipherSpec(ss, TrafficKeyEarlyApplicationData,
                              CipherSpecWrite, PR_TRUE);
     if (rv != SECSuccess) {
-        return rv;
+        return SECFailure;
     }
 
     return SECSuccess;
 }
 
 PRInt32
 tls13_Read0RttData(sslSocket *ss, void *buf, PRInt32 len)
 {
@@ -4499,17 +4549,17 @@ tls13_EncodeDraftVersion(SSL3ProtocolVer
     return (PRUint16)version;
 }
 
 PRUint16
 tls13_EncodeAltDraftVersion(SSL3ProtocolVersion version)
 {
 #ifdef TLS_1_3_DRAFT_VERSION
     if (version == SSL_LIBRARY_VERSION_TLS_1_3) {
-        return 0x7a00 | TLS_1_3_DRAFT_VERSION;
+        return 0x7e02;
     }
 #endif
     return (PRUint16)version;
 }
 
 /* Pick the highest version we support that is also advertised. */
 SECStatus
 tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supported_versions)
@@ -4536,37 +4586,44 @@ tls13_NegotiateVersion(sslSocket *ss, co
 
         for (offset = 0; offset < versions.len; offset += 2) {
             PRUint16 supported =
                 (versions.data[offset] << 8) | versions.data[offset + 1];
             if (supported == wire) {
                 ss->version = version;
                 return SECSuccess;
             }
-            if (ss->opt.enableAltHandshaketype && !IS_DTLS(ss) &&
+            if (ss->opt.enableAltHandshaketype &&
+                !IS_DTLS(ss) &&
                 supported == alt_wire) {
+                rv = ssl3_RegisterExtensionSender(ss, &ss->xtnData,
+                                                  ssl_tls13_supported_versions_xtn,
+                                                  tls13_ServerSendSupportedVersionsXtn);
+                if (rv != SECSuccess) {
+                    return SECFailure;
+                }
+                ss->ssl3.hs.altHandshakeType = PR_TRUE;
                 ss->version = version;
-                ss->ssl3.hs.altHandshakeType = PR_TRUE;
                 return SECSuccess;
             }
         }
     }
 
     FATAL_ERROR(ss, SSL_ERROR_UNSUPPORTED_VERSION, protocol_version);
     return SECFailure;
 }
 
 SECStatus
-SSLExp_UseAltServerHelloType(PRFileDesc *fd, PRBool enable)
+SSLExp_UseAltHandshakeType(PRFileDesc *fd, PRBool enable)
 {
     sslSocket *ss;
 
     ss = ssl_FindSocket(fd);
-    if (!ss) {
-        SSL_DBG(("%d: SSL[%d]: bad socket in SSLExp_UseAltServerHelloType",
+    if (!ss || IS_DTLS(ss)) {
+        SSL_DBG(("%d: SSL[%d]: bad socket in SSLExp_UseAltHandshakeType",
                  SSL_GETPID(), fd));
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
     ss->opt.enableAltHandshaketype = enable;
 
     return SECSuccess;
--- a/security/nss/lib/ssl/tls13con.h
+++ b/security/nss/lib/ssl/tls13con.h
@@ -80,11 +80,12 @@ PRInt32 tls13_Read0RttData(sslSocket *ss
 SECStatus tls13_HandleEndOfEarlyData(sslSocket *ss);
 SECStatus tls13_HandleEarlyApplicationData(sslSocket *ss, sslBuffer *origBuf);
 PRBool tls13_ClientAllow0Rtt(const sslSocket *ss, const sslSessionID *sid);
 PRUint16 tls13_EncodeDraftVersion(SSL3ProtocolVersion version);
 PRUint16 tls13_EncodeAltDraftVersion(SSL3ProtocolVersion version);
 SECStatus tls13_NegotiateVersion(sslSocket *ss,
                                  const TLSExtension *supported_versions);
 SECStatus tls13_SendNewSessionTicket(sslSocket *ss);
-SECStatus SSLExp_UseAltServerHelloType(PRFileDesc *fd, PRBool enable);
+SECStatus SSLExp_UseAltHandshakeType(PRFileDesc *fd, PRBool enable);
+void tls13_SetSpecRecordVersion(sslSocket *ss, ssl3CipherSpec *spec);
 
 #endif /* __tls13con_h_ */
--- a/security/nss/lib/ssl/tls13exthandle.c
+++ b/security/nss/lib/ssl/tls13exthandle.c
@@ -868,32 +868,37 @@ tls13_ClientHandleTicketEarlyDataInfoXtn
 
     xtnData->max_early_data_size = PR_ntohl(utmp);
 
     return SECSuccess;
 }
 
 /*
  *     struct {
+ *       select (Handshake.msg_type) {
+ *       case client_hello:
  *          ProtocolVersion versions<2..254>;
+ *       case server_hello:
+ *          ProtocolVersion version;
+ *       };
  *     } SupportedVersions;
  */
 PRInt32
 tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append,
                                      PRUint32 maxBytes)
 {
     PRInt32 extensions_len;
     PRUint16 version;
     SECStatus rv;
 
     if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) {
         return 0;
     }
 
-    SSL_TRC(3, ("%d: TLS13[%d]: send supported_versions extension",
+    SSL_TRC(3, ("%d: TLS13[%d]: client send supported_versions extension",
                 SSL_GETPID(), ss->fd));
 
     /* Extension type, extension len fiels, vector len field,
      * length of the values. */
     extensions_len = 2 + 2 + 1 +
                      2 * (ss->vrange.max - ss->vrange.min + 1);
 
     if (ss->opt.enableAltHandshaketype && !IS_DTLS(ss)) {
@@ -936,16 +941,60 @@ tls13_ClientSendSupportedVersionsXtn(con
 
         xtnData->advertised[xtnData->numAdvertised++] =
             ssl_tls13_supported_versions_xtn;
     }
 
     return extensions_len;
 }
 
+PRInt32
+tls13_ServerSendSupportedVersionsXtn(const sslSocket *ss,
+                                     TLSExtensionData *xtnData,
+                                     PRBool append, PRUint32 maxBytes)
+{
+    SECStatus rv;
+    PRInt32 extensions_len;
+
+    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+        PORT_Assert(0); /* Can't happen. */
+        return SECSuccess;
+    }
+    if (!ss->ssl3.hs.altHandshakeType) {
+        PORT_Assert(0); /* Can't happen. */
+        return SECSuccess;
+    }
+
+    SSL_TRC(3, ("%d: TLS13[%d]: server send supported_versions extension",
+                SSL_GETPID(), ss->fd));
+
+    extensions_len = 2 + 2 + 2; /* type, len, version */
+    if (maxBytes < (PRUint32)extensions_len) {
+        PORT_Assert(0);
+        return 0;
+    }
+
+    if (append) {
+        rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_supported_versions_xtn, 2);
+        if (rv != SECSuccess)
+            return -1;
+
+        rv = ssl3_ExtAppendHandshakeNumber(ss, 2, 2);
+        if (rv != SECSuccess)
+            return -1;
+
+        rv = ssl3_ExtAppendHandshakeNumber(
+            ss, tls13_EncodeAltDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3), 2);
+        if (rv != SECSuccess) {
+            return -1;
+        }
+    }
+    return extensions_len;
+}
+
 /*
  *    struct {
  *        opaque cookie<1..2^16-1>;
  *    } Cookie;
  */
 SECStatus
 tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data)
 {
--- a/security/nss/lib/ssl/tls13exthandle.h
+++ b/security/nss/lib/ssl/tls13exthandle.h
@@ -48,16 +48,20 @@ PRInt32 tls13_ServerSendEarlyDataXtn(con
                                      PRBool append,
                                      PRUint32 maxBytes);
 SECStatus tls13_ClientHandleTicketEarlyDataInfoXtn(
     const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
     SECItem *data);
 PRInt32 tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnData,
                                              PRBool append,
                                              PRUint32 maxBytes);
+PRInt32 tls13_ServerSendSupportedVersionsXtn(const sslSocket *ss,
+                                             TLSExtensionData *xtnData,
+                                             PRBool append,
+                                             PRUint32 maxBytes);
 SECStatus tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
                                       SECItem *data);
 PRInt32 tls13_ClientSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData,
                                      PRBool append,
                                      PRUint32 maxBytes);
 PRInt32 tls13_ClientSendPskKeyExchangeModesXtn(const sslSocket *ss,
                                                TLSExtensionData *xtnData,
                                                PRBool append, PRUint32 maxBytes);
--- a/security/nss/lib/util/nssutil.h
+++ b/security/nss/lib/util/nssutil.h
@@ -14,19 +14,19 @@
 
 /*
  * NSS utilities's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
  */
-#define NSSUTIL_VERSION "3.34 Beta"
+#define NSSUTIL_VERSION "3.35 Beta"
 #define NSSUTIL_VMAJOR 3
-#define NSSUTIL_VMINOR 34
+#define NSSUTIL_VMINOR 35
 #define NSSUTIL_VPATCH 0
 #define NSSUTIL_VBUILD 0
 #define NSSUTIL_BETA PR_TRUE
 
 SEC_BEGIN_PROTOS
 
 /*
  * Returns a const string of the UTIL library version.
--- a/security/nss/lib/util/pkcs11uri.c
+++ b/security/nss/lib/util/pkcs11uri.c
@@ -237,17 +237,17 @@ fail:
 
 /* Compare two attribute names by the array index in attr_names.  Both
  * attribute names must be present in attr_names, otherwise it is a
  * programming error. */
 static int
 pk11uri_CompareByPosition(const char *a, const char *b,
                           const char **attr_names, size_t num_attr_names)
 {
-    int i, j;
+    size_t i, j;
 
     for (i = 0; i < num_attr_names; i++) {
         if (strcmp(a, attr_names[i]) == 0) {
             break;
         }
     }
     PR_ASSERT(i < num_attr_names);
 
--- a/security/nss/lib/util/secport.c
+++ b/security/nss/lib/util/secport.c
@@ -784,14 +784,14 @@ NSS_SecureMemcmp(const void *ia, const v
 /*
  * Perform a constant-time check if a memory region is all 0. The return value
  * is 0 if the memory region is all zero.
  */
 unsigned int
 NSS_SecureMemcmpZero(const void *mem, size_t n)
 {
     PRUint8 zero = 0;
-    int i;
+    size_t i;
     for (i = 0; i < n; ++i) {
         zero |= *(PRUint8 *)((uintptr_t)mem + i);
     }
     return zero;
 }
--- a/security/nss/tests/ssl_gtests/ssl_gtests.sh
+++ b/security/nss/tests/ssl_gtests/ssl_gtests.sh
@@ -16,26 +16,27 @@
 # ---------------
 #   FIXME ... known problems, search for this string
 #   NOTE .... unexpected behavior
 #
 ########################################################################
 
 # Generate input to certutil
 certscript() {
+  ca=n
   while [ $# -gt 0 ]; do
     case $1 in
       sign) echo 0 ;;
       kex) echo 2 ;;
-      ca) echo 5;echo 6 ;;
+      ca) echo 5;echo 6;ca=y ;;
     esac; shift
   done;
   echo 9
   echo n
-  echo ${ca:-n}
+  echo $ca
   echo
   echo n
 }
 
 # $1: name
 # $2: type
 # $3+: usages: sign or kex
 make_cert() {
@@ -45,19 +46,19 @@ make_cert() {
   case $type in
     dsa) type_args='-g 1024' ;;
     rsa) type_args='-g 1024' ;;
     rsa2048) type_args='-g 2048';type=rsa ;;
     rsapss) type_args='-g 1024 --pss';type=rsa ;;
     p256) type_args='-q nistp256';type=ec ;;
     p384) type_args='-q secp384r1';type=ec ;;
     p521) type_args='-q secp521r1';type=ec ;;
-    rsa_ca) type_args='-g 1024';trust='CT,CT,CT';ca=y;type=rsa ;;
+    rsa_ca) type_args='-g 1024';trust='CT,CT,CT';type=rsa ;;
     rsa_chain) type_args='-g 1024';sign='-c rsa_ca';type=rsa;;
-    rsapss_ca) type_args='-g 1024 --pss';trust='CT,CT,CT';ca=y;type=rsa ;;
+    rsapss_ca) type_args='-g 1024 --pss';trust='CT,CT,CT';type=rsa ;;
     rsapss_chain) type_args='-g 1024';sign='-c rsa_pss_ca';type=rsa;;
     rsa_ca_rsapss_chain) type_args='-g 1024 --pss-sign';sign='-c rsa_ca';type=rsa;;
     ecdh_rsa) type_args='-q nistp256';sign='-c rsa_ca';type=ec ;;
   esac
   shift 2
   counter=$(($counter + 1))
   certscript $@ | ${BINDIR}/certutil -S \
     -z ${R_NOISE_FILE} -d "${PROFILEDIR}" \