Bug 1305970 - land NSS 0x6b3812492e71, r=me
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Wed, 05 Oct 2016 17:52:14 +0200
changeset 316612 4297f858ea5dbecb26625e12d1092824aa78402f
parent 316611 77d637164bfdbf3ab7c30fe01f0bafae36c792c9
child 316613 871153c1b8b26da037fba183a558cbec584dfc09
push id82486
push userfranziskuskiefer@gmail.com
push dateWed, 05 Oct 2016 16:03:23 +0000
treeherdermozilla-inbound@4297f858ea5d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1305970
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1305970 - land NSS 0x6b3812492e71, r=me
security/nss/TAG-INFO
security/nss/cmd/derdump/derdump.c
security/nss/coreconf/coreconf.dep
security/nss/coreconf/sanitizers.mk
security/nss/external_tests/ssl_gtest/databuffer.h
security/nss/external_tests/ssl_gtest/libssl_internals.c
security/nss/external_tests/ssl_gtest/libssl_internals.h
security/nss/external_tests/ssl_gtest/ssl_0rtt_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_damage_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_ecdh_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_extension_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_hrr_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_loopback_unittest.cc
security/nss/external_tests/ssl_gtest/tls_connect.cc
security/nss/external_tests/ssl_gtest/tls_connect.h
security/nss/external_tests/ssl_gtest/tls_filter.cc
security/nss/external_tests/util_gtest/util_utf8_unittest.cc
security/nss/lib/softoken/legacydb/keydb.c
security/nss/lib/softoken/legacydb/pcertdb.c
security/nss/lib/softoken/pkcs11c.c
security/nss/lib/ssl/dtlscon.c
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3ext.c
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/sslt.h
security/nss/lib/ssl/tls13con.c
security/nss/lib/ssl/tls13con.h
security/nss/lib/util/secasn1e.c
security/nss/lib/util/utf8.c
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-e7553afc7665
+6b3812492e71
--- a/security/nss/cmd/derdump/derdump.c
+++ b/security/nss/cmd/derdump/derdump.c
@@ -29,47 +29,48 @@ Usage(char *progName)
 }
 
 int
 main(int argc, char **argv)
 {
     char *progName;
     FILE *outFile;
     PRFileDesc *inFile;
-    SECItem der;
+    SECItem der = { siBuffer, NULL, 0 };
     SECStatus rv;
     PRInt16 xp_error;
     PRBool raw = PR_FALSE;
     PLOptState *optstate;
     PLOptStatus status;
+    int retval = -1;
 
     progName = strrchr(argv[0], '/');
     progName = progName ? progName + 1 : argv[0];
 
     /* Parse command line arguments */
     inFile = 0;
     outFile = 0;
     optstate = PL_CreateOptState(argc, argv, "i:o:r");
     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
         switch (optstate->option) {
             case 'i':
                 inFile = PR_Open(optstate->value, PR_RDONLY, 0);
                 if (!inFile) {
                     fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
                             progName, optstate->value);
-                    return -1;
+                    goto cleanup;
                 }
                 break;
 
             case 'o':
                 outFile = fopen(optstate->value, "w");
                 if (!outFile) {
                     fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
                             progName, optstate->value);
-                    return -1;
+                    goto cleanup;
                 }
                 break;
 
             case 'r':
                 raw = PR_TRUE;
                 break;
 
             default:
@@ -80,30 +81,48 @@ main(int argc, char **argv)
     if (status == PL_OPT_BAD)
         Usage(progName);
 
     if (!inFile)
         inFile = PR_STDIN;
     if (!outFile)
         outFile = stdout;
 
-    rv = NSS_NoDB_Init(NULL); /* XXX */
+    rv = NSS_NoDB_Init(NULL);
     if (rv != SECSuccess) {
         SECU_PrintPRandOSError(progName);
-        return -1;
+        goto cleanup;
     }
 
     rv = SECU_ReadDERFromFile(&der, inFile, PR_FALSE, PR_FALSE);
     if (rv == SECSuccess) {
         rv = DER_PrettyPrint(outFile, &der, raw);
-        if (rv == SECSuccess)
-            return 0;
+        if (rv == SECSuccess) {
+            retval = 0;
+            goto cleanup;
+        }
     }
 
     xp_error = PORT_GetError();
     if (xp_error) {
         SECU_PrintError(progName, "error %d", xp_error);
     }
     if (errno) {
         SECU_PrintSystemError(progName, "errno=%d", errno);
     }
-    return 1;
+    retval = 1;
+
+cleanup:
+    retval |= NSS_Shutdown();
+    if (inFile) {
+        PR_Close(inFile);
+    }
+    if (outFile) {
+        fflush(outFile);
+        fclose(outFile);
+    }
+    PL_DestroyOptState(optstate);
+    if (der.data) {
+        PORT_Free(der.data);
+    }
+
+    return retval;
 }
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,8 +5,9 @@
 
 /*
  * 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/coreconf/sanitizers.mk
+++ b/security/nss/coreconf/sanitizers.mk
@@ -1,13 +1,19 @@
 # Address Sanitizer support; include this in OS-specific .mk files
 # *after* defining the variables that are appended to here.
 
 ifeq ($(USE_ASAN), 1)
-SANITIZER_FLAGS_COMMON = -fsanitize=address $(EXTRA_SANITIZER_FLAGS)
+SANITIZER_FLAGS_COMMON = -fsanitize=address
+
+ifeq ($(USE_UBSAN), 1)
+SANITIZER_FLAGS_COMMON += -fsanitize=undefined -fno-sanitize-recover=undefined
+endif
+
+SANITIZER_FLAGS_COMMON += $(EXTRA_SANITIZER_FLAGS)
 SANITIZER_CFLAGS = $(SANITIZER_FLAGS_COMMON)
 SANITIZER_LDFLAGS = $(SANITIZER_FLAGS_COMMON)
 OS_CFLAGS += $(SANITIZER_CFLAGS)
 LDFLAGS += $(SANITIZER_LDFLAGS)
 
 # ASan needs frame pointers to save stack traces for allocation/free sites.
 # (Warning: some platforms, like ARM Linux in Thumb mode, don't have useful
 # frame pointers even with this option.)
--- a/security/nss/external_tests/ssl_gtest/databuffer.h
+++ b/security/nss/external_tests/ssl_gtest/databuffer.h
@@ -59,29 +59,34 @@ class DataBuffer {
       data_ = nullptr;
       len_ = 0;
     }
   }
 
   // Write will do a new allocation and expand the size of the buffer if needed.
   // Returns the offset of the end of the write.
   size_t Write(size_t index, const uint8_t* val, size_t count) {
+    assert(val);
     if (index + count > len_) {
       size_t newlen = index + count;
       uint8_t* tmp = new uint8_t[newlen];  // Always > 0.
-      memcpy(static_cast<void*>(tmp), static_cast<const void*>(data_), len_);
+      if (data_) {
+        memcpy(static_cast<void*>(tmp), static_cast<const void*>(data_), len_);
+      }
       if (index > len_) {
         memset(static_cast<void*>(tmp + len_), 0, index - len_);
       }
       delete[] data_;
       data_ = tmp;
       len_ = newlen;
     }
-    memcpy(static_cast<void*>(data_ + index), static_cast<const void*>(val),
-           count);
+    if (data_) {
+      memcpy(static_cast<void*>(data_ + index), static_cast<const void*>(val),
+             count);
+    }
     return index + count;
   }
 
   size_t Write(size_t index, const DataBuffer& buf) {
     return Write(index, buf.data(), buf.len());
   }
 
   // Write an integer, also performing host-to-network order conversion.
@@ -111,16 +116,17 @@ class DataBuffer {
   // Starting at |index|, remove |remove| bytes and replace them with the
   // contents of |buf|.
   void Splice(const DataBuffer& buf, size_t index, size_t remove = 0) {
     Splice(buf.data(), buf.len(), index, remove);
   }
 
   void Splice(const uint8_t* ins, size_t ins_len, size_t index,
               size_t remove = 0) {
+    assert(ins);
     uint8_t* old_value = data_;
     size_t old_len = len_;
 
     // The amount of stuff remaining from the tail of the old.
     size_t tail_len = old_len - std::min(old_len, index + remove);
     // The new length: the head of the old, the new, and the tail of the old.
     len_ = index + ins_len + tail_len;
     data_ = new uint8_t[len_ ? len_ : 1];
--- a/security/nss/external_tests/ssl_gtest/libssl_internals.c
+++ b/security/nss/external_tests/ssl_gtest/libssl_internals.c
@@ -142,18 +142,19 @@ PRBool SSLInt_CheckSecretsDestroyed(PRFi
   sslSocket *ss = ssl_FindSocket(fd);
   if (!ss) {
     return PR_FALSE;
   }
 
   CHECK_SECRET(currentSecret);
   CHECK_SECRET(resumptionPsk);
   CHECK_SECRET(dheSecret);
-  CHECK_SECRET(earlyTrafficSecret);
-  CHECK_SECRET(hsTrafficSecret);
+  CHECK_SECRET(clientEarlyTrafficSecret);
+  CHECK_SECRET(clientHsTrafficSecret);
+  CHECK_SECRET(serverHsTrafficSecret);
 
   return PR_TRUE;
 }
 
 PRBool sslint_DamageTrafficSecret(PRFileDesc *fd, size_t offset) {
   unsigned char data[32] = {0};
   PK11SymKey **keyPtr;
   PK11SlotInfo *slot = PK11_GetInternalSlot();
@@ -175,24 +176,29 @@ PRBool sslint_DamageTrafficSecret(PRFile
   PK11_FreeSlot(slot);
   if (!*keyPtr) {
     return PR_FALSE;
   }
 
   return PR_TRUE;
 }
 
-PRBool SSLInt_DamageHsTrafficSecret(PRFileDesc *fd) {
+PRBool SSLInt_DamageClientHsTrafficSecret(PRFileDesc *fd) {
   return sslint_DamageTrafficSecret(
-      fd, offsetof(SSL3HandshakeState, hsTrafficSecret));
+      fd, offsetof(SSL3HandshakeState, clientHsTrafficSecret));
+}
+
+PRBool SSLInt_DamageServerHsTrafficSecret(PRFileDesc *fd) {
+  return sslint_DamageTrafficSecret(
+      fd, offsetof(SSL3HandshakeState, serverHsTrafficSecret));
 }
 
 PRBool SSLInt_DamageEarlyTrafficSecret(PRFileDesc *fd) {
   return sslint_DamageTrafficSecret(
-      fd, offsetof(SSL3HandshakeState, earlyTrafficSecret));
+      fd, offsetof(SSL3HandshakeState, clientEarlyTrafficSecret));
 }
 
 SECStatus SSLInt_Set0RttAlpn(PRFileDesc *fd, PRUint8 *data, unsigned int len) {
   sslSocket *ss = ssl_FindSocket(fd);
   if (!ss) {
     return SECFailure;
   }
 
--- a/security/nss/external_tests/ssl_gtest/libssl_internals.h
+++ b/security/nss/external_tests/ssl_gtest/libssl_internals.h
@@ -23,17 +23,18 @@ SECStatus SSLInt_UpdateSSLv2ClientRandom
                                          size_t msg_len);
 
 PRBool SSLInt_ExtensionNegotiated(PRFileDesc *fd, PRUint16 ext);
 void SSLInt_ClearSessionTicketKey();
 PRInt32 SSLInt_CountTls13CipherSpecs(PRFileDesc *fd);
 void SSLInt_ForceTimerExpiry(PRFileDesc *fd);
 SECStatus SSLInt_SetMTU(PRFileDesc *fd, PRUint16 mtu);
 PRBool SSLInt_CheckSecretsDestroyed(PRFileDesc *fd);
-PRBool SSLInt_DamageHsTrafficSecret(PRFileDesc *fd);
+PRBool SSLInt_DamageClientHsTrafficSecret(PRFileDesc *fd);
+PRBool SSLInt_DamageServerHsTrafficSecret(PRFileDesc *fd);
 PRBool SSLInt_DamageEarlyTrafficSecret(PRFileDesc *fd);
 SECStatus SSLInt_Set0RttAlpn(PRFileDesc *fd, PRUint8 *data, unsigned int len);
 PRBool SSLInt_HasCertWithAuthType(PRFileDesc *fd, SSLAuthType authType);
 PRBool SSLInt_SendAlert(PRFileDesc *fd, uint8_t level, uint8_t type);
 SECStatus SSLInt_AdvanceWriteSeqNum(PRFileDesc *fd, PRUint64 to);
 SECStatus SSLInt_AdvanceReadSeqNum(PRFileDesc *fd, PRUint64 to);
 SECStatus SSLInt_AdvanceWriteSeqByAWindow(PRFileDesc *fd, PRInt32 extra);
 SSLKEAType SSLInt_GetKEAType(SSLNamedGroup group);
--- a/security/nss/external_tests/ssl_gtest/ssl_0rtt_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_0rtt_unittest.cc
@@ -22,41 +22,61 @@ extern "C" {
 
 namespace nss_test {
 
 TEST_P(TlsConnectTls13, ZeroRtt) {
   SetupForZeroRtt();
   client_->Set0RttEnabled(true);
   server_->Set0RttEnabled(true);
   ExpectResumption(RESUME_TICKET);
-  ZeroRttSendReceive(true);
+  ZeroRttSendReceive(true, true);
   Handshake();
   ExpectEarlyDataAccepted(true);
   CheckConnected();
   SendReceive();
 }
 
 TEST_P(TlsConnectTls13, ZeroRttServerRejectByOption) {
   SetupForZeroRtt();
   client_->Set0RttEnabled(true);
   ExpectResumption(RESUME_TICKET);
-  ZeroRttSendReceive(false);
+  ZeroRttSendReceive(true, false);
+  Handshake();
+  CheckConnected();
+  SendReceive();
+}
+
+// Test that we don't try to send 0-RTT data when the server sent
+// us a ticket without the 0-RTT flags.
+TEST_P(TlsConnectTls13, ZeroRttOptionsSetLate) {
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  Connect();
+  SendReceive();  // Need to read so that we absorb the session ticket.
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+  Reset();
+  server_->StartConnect();
+  client_->StartConnect();
+  // Now turn on 0-RTT but too late for the ticket.
+  client_->Set0RttEnabled(true);
+  server_->Set0RttEnabled(true);
+  ExpectResumption(RESUME_TICKET);
+  ZeroRttSendReceive(false, false);
   Handshake();
   CheckConnected();
   SendReceive();
 }
 
 TEST_P(TlsConnectTls13, ZeroRttServerForgetTicket) {
   SetupForZeroRtt();
   client_->Set0RttEnabled(true);
   server_->Set0RttEnabled(true);
   ClearServerCache();
   ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
   ExpectResumption(RESUME_NONE);
-  ZeroRttSendReceive(false);
+  ZeroRttSendReceive(true, false);
   Handshake();
   CheckConnected();
   SendReceive();
 }
 
 TEST_P(TlsConnectTls13, ZeroRttServerOnly) {
   ExpectResumption(RESUME_NONE);
   server_->Set0RttEnabled(true);
@@ -82,17 +102,17 @@ TEST_P(TlsConnectTls13, ZeroRttServerOnl
 TEST_P(TlsConnectTls13, TestTls13ZeroRttAlpn) {
   EnableAlpn();
   SetupForZeroRtt();
   EnableAlpn();
   client_->Set0RttEnabled(true);
   server_->Set0RttEnabled(true);
   ExpectResumption(RESUME_TICKET);
   ExpectEarlyDataAccepted(true);
-  ZeroRttSendReceive(true, [this]() {
+  ZeroRttSendReceive(true, true, [this]() {
     client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "a");
     return true;
   });
   Handshake();
   CheckConnected();
   SendReceive();
   CheckAlpn("a");
 }
@@ -104,17 +124,17 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRtt
   SetupForZeroRtt();
   static const uint8_t client_alpn[] = {0x01, 0x61, 0x01, 0x62};  // "a", "b"
   static const uint8_t server_alpn[] = {0x01, 0x62};              // "b"
   client_->EnableAlpn(client_alpn, sizeof(client_alpn));
   server_->EnableAlpn(server_alpn, sizeof(server_alpn));
   client_->Set0RttEnabled(true);
   server_->Set0RttEnabled(true);
   ExpectResumption(RESUME_TICKET);
-  ZeroRttSendReceive(false, [this]() {
+  ZeroRttSendReceive(true, false, [this]() {
     client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "a");
     return true;
   });
   Handshake();
   CheckConnected();
   SendReceive();
   CheckAlpn("b");
 }
@@ -125,17 +145,17 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRtt
 // should then fail the connection.
 TEST_P(TlsConnectTls13, TestTls13ZeroRttNoAlpnServer) {
   EnableAlpn();
   SetupForZeroRtt();
   client_->Set0RttEnabled(true);
   server_->Set0RttEnabled(true);
   EnableAlpn();
   ExpectResumption(RESUME_TICKET);
-  ZeroRttSendReceive(true, [this]() {
+  ZeroRttSendReceive(true, true, [this]() {
     PRUint8 b[] = {'b'};
     client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "a");
     EXPECT_EQ(SECSuccess, SSLInt_Set0RttAlpn(client_->ssl_fd(), b, sizeof(b)));
     client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "b");
     return true;
   });
   Handshake();
   client_->CheckErrorCode(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
@@ -145,17 +165,17 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRtt
 // Set up with no ALPN and then set the client so it thinks it has ALPN.
 // The server responds without the extension and the client returns an
 // error.
 TEST_P(TlsConnectTls13, TestTls13ZeroRttNoAlpnClient) {
   SetupForZeroRtt();
   client_->Set0RttEnabled(true);
   server_->Set0RttEnabled(true);
   ExpectResumption(RESUME_TICKET);
-  ZeroRttSendReceive(true, [this]() {
+  ZeroRttSendReceive(true, true, [this]() {
     PRUint8 b[] = {'b'};
     EXPECT_EQ(SECSuccess, SSLInt_Set0RttAlpn(client_->ssl_fd(), b, 1));
     client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "b");
     return true;
   });
   Handshake();
   client_->CheckErrorCode(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
   server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
@@ -165,17 +185,17 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRtt
 TEST_P(TlsConnectTls13, TestTls13ZeroRttAlpnChangeBoth) {
   EnableAlpn();
   SetupForZeroRtt();
   static const uint8_t alpn[] = {0x01, 0x62};  // "b"
   EnableAlpn(alpn, sizeof(alpn));
   client_->Set0RttEnabled(true);
   server_->Set0RttEnabled(true);
   ExpectResumption(RESUME_TICKET);
-  ZeroRttSendReceive(false, [this]() {
+  ZeroRttSendReceive(true, false, [this]() {
     client_->CheckAlpn(SSL_NEXT_PROTO_NO_SUPPORT);
     return false;
   });
   Handshake();
   CheckConnected();
   SendReceive();
   CheckAlpn("b");
 }
--- a/security/nss/external_tests/ssl_gtest/ssl_damage_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_damage_unittest.cc
@@ -29,17 +29,17 @@ TEST_F(TlsConnectTest, DamageSecretHandl
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->StartConnect();
   client_->StartConnect();
   client_->Handshake();
   server_->Handshake();
   std::cerr << "Damaging HS secret\n";
-  SSLInt_DamageHsTrafficSecret(server_->ssl_fd());
+  SSLInt_DamageClientHsTrafficSecret(server_->ssl_fd());
   client_->Handshake();
   server_->Handshake();
   // The client thinks it has connected.
   EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state());
   server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
   client_->Handshake();
   client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
 }
@@ -47,15 +47,15 @@ TEST_F(TlsConnectTest, DamageSecretHandl
 TEST_F(TlsConnectTest, DamageSecretHandleServerFinished) {
   client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->SetPacketFilter(new AfterRecordN(
       server_, client_,
       0,  // ServerHello.
-      [this]() { SSLInt_DamageHsTrafficSecret(client_->ssl_fd()); }));
+      [this]() { SSLInt_DamageServerHsTrafficSecret(client_->ssl_fd()); }));
   ConnectExpectFail();
   client_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
   server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
 }
 
 }  // namespace nspr_test
--- a/security/nss/external_tests/ssl_gtest/ssl_ecdh_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_ecdh_unittest.cc
@@ -255,16 +255,33 @@ TEST_P(TlsConnectGeneric, P256andCurve25
   client_->ConfigNamedGroups(client_groups);
   server_->ConfigNamedGroups(server_groups);
 
   Connect();
 
   CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign, 255);
 }
 
+TEST_P(TlsConnectGeneric, P256ClientAndCurve25519Server) {
+  EnsureTlsSetup();
+  client_->DisableAllCiphers();
+  client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
+
+  // the client sends a P256 key share while the server prefers 25519.
+  const std::vector<SSLNamedGroup> server_groups = {ssl_grp_ec_curve25519};
+  const std::vector<SSLNamedGroup> client_groups = {ssl_grp_ec_secp256r1};
+
+  client_->ConfigNamedGroups(client_groups);
+  server_->ConfigNamedGroups(server_groups);
+
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
+  server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
+}
+
 // Replace the point in the client key exchange message with an empty one
 class ECCClientKEXFilter : public TlsHandshakeFilter {
  public:
   ECCClientKEXFilter() {}
 
  protected:
   virtual PacketFilter::Action FilterHandshake(const HandshakeHeader &header,
                                                const DataBuffer &input,
--- a/security/nss/external_tests/ssl_gtest/ssl_extension_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_extension_unittest.cc
@@ -84,28 +84,32 @@ class TlsExtensionInjector : public TlsH
       offset = parser.consumed();
     } else {
       return KEEP;
     }
 
     *output = input;
 
     // Increase the size of the extensions.
-    uint16_t* len_addr = reinterpret_cast<uint16_t*>(output->data() + offset);
-    *len_addr = htons(ntohs(*len_addr) + data_.len() + 4);
+    uint16_t ext_len;
+    memcpy(&ext_len, output->data() + offset, sizeof(ext_len));
+    ext_len = htons(ntohs(ext_len) + data_.len() + 4);
+    memcpy(output->data() + offset, &ext_len, sizeof(ext_len));
 
     // Insert the extension type and length.
     DataBuffer type_length;
     type_length.Allocate(4);
     type_length.Write(0, extension_, 2);
     type_length.Write(2, data_.len(), 2);
     output->Splice(type_length, offset + 2);
 
     // Insert the payload.
-    output->Splice(data_, offset + 6);
+    if (data_.len() > 0) {
+      output->Splice(data_, offset + 6);
+    }
 
     return CHANGE;
   }
 
  private:
   const uint16_t extension_;
   const DataBuffer data_;
 };
@@ -178,16 +182,25 @@ class TlsExtensionTest12
 
 class TlsExtensionTest13 : public TlsExtensionTestBase,
                            public ::testing::WithParamInterface<std::string> {
  public:
   TlsExtensionTest13()
       : TlsExtensionTestBase(TlsConnectTestBase::ToMode(GetParam()),
                              SSL_LIBRARY_VERSION_TLS_1_3) {}
 
+  void ConnectWithBogusVersionList(const uint8_t* buf, size_t len) {
+    DataBuffer versions_buf(buf, len);
+    client_->SetPacketFilter(new TlsExtensionReplacer(
+        ssl_tls13_supported_versions_xtn, versions_buf));
+    ConnectExpectFail();
+    client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+    server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+  }
+
   void ConnectWithReplacementVersionList(uint16_t version) {
     DataBuffer versions_buf;
 
     size_t index = versions_buf.Write(0, 2, 1);
     versions_buf.Write(index, version, 2);
     client_->SetPacketFilter(new TlsExtensionReplacer(
         ssl_tls13_supported_versions_xtn, versions_buf));
     ConnectExpectFail();
@@ -509,16 +522,55 @@ TEST_P(TlsExtensionTest13, EmptyClientKe
 TEST_F(TlsExtensionTest13Stream, DropServerKeyShare) {
   EnsureTlsSetup();
   server_->SetPacketFilter(new TlsExtensionDropper(ssl_tls13_key_share_xtn));
   ConnectExpectFail();
   EXPECT_EQ(SSL_ERROR_MISSING_KEY_SHARE, client_->error_code());
   EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
 }
 
+TEST_F(TlsExtensionTest13Stream, WrongServerKeyShare) {
+  const uint16_t wrong_group = ssl_grp_ec_secp384r1;
+
+  static const uint8_t key_share[] = {
+      wrong_group >> 8,
+      wrong_group & 0xff,  // Group we didn't offer.
+      0x00,
+      0x02,  // length = 2
+      0x01,
+      0x02};
+  DataBuffer buf(key_share, sizeof(key_share));
+  EnsureTlsSetup();
+  server_->SetPacketFilter(
+      new TlsExtensionReplacer(ssl_tls13_key_share_xtn, buf));
+  ConnectExpectFail();
+  EXPECT_EQ(SSL_ERROR_RX_MALFORMED_KEY_SHARE, client_->error_code());
+  EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
+}
+
+// TODO(ekr@rtfm.com): This is the wrong error code. See bug 1307269.
+TEST_F(TlsExtensionTest13Stream, UnknownServerKeyShare) {
+  const uint16_t wrong_group = 0xffff;
+
+  static const uint8_t key_share[] = {
+      wrong_group >> 8,
+      wrong_group & 0xff,  // Group we didn't offer.
+      0x00,
+      0x02,  // length = 2
+      0x01,
+      0x02};
+  DataBuffer buf(key_share, sizeof(key_share));
+  EnsureTlsSetup();
+  server_->SetPacketFilter(
+      new TlsExtensionReplacer(ssl_tls13_key_share_xtn, buf));
+  ConnectExpectFail();
+  EXPECT_EQ(SSL_ERROR_MISSING_KEY_SHARE, client_->error_code());
+  EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
+}
+
 TEST_F(TlsExtensionTest13Stream, DropServerSignatureAlgorithms) {
   EnsureTlsSetup();
   server_->SetPacketFilter(
       new TlsExtensionDropper(ssl_signature_algorithms_xtn));
   ConnectExpectFail();
   EXPECT_EQ(SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION,
             client_->error_code());
   EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
@@ -719,16 +771,26 @@ TEST_P(TlsExtensionTest13, RemoveTls13Fr
   client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
   server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
 #else
   client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
   server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
 #endif
 }
 
+TEST_P(TlsExtensionTest13, EmptyVersionList) {
+  static const uint8_t ext[] = {0x00, 0x00};
+  ConnectWithBogusVersionList(ext, sizeof(ext));
+}
+
+TEST_P(TlsExtensionTest13, OddVersionList) {
+  static const uint8_t ext[] = {0x00, 0x01, 0x00};
+  ConnectWithBogusVersionList(ext, sizeof(ext));
+}
+
 INSTANTIATE_TEST_CASE_P(ExtensionStream, TlsExtensionTestGeneric,
                         ::testing::Combine(TlsConnectTestBase::kTlsModesStream,
                                            TlsConnectTestBase::kTlsVAll));
 INSTANTIATE_TEST_CASE_P(ExtensionDatagram, TlsExtensionTestGeneric,
                         ::testing::Combine(TlsConnectTestBase::kTlsModesAll,
                                            TlsConnectTestBase::kTlsV11Plus));
 INSTANTIATE_TEST_CASE_P(ExtensionDatagramOnly, TlsExtensionTestDtls,
                         TlsConnectTestBase::kTlsV11Plus);
--- a/security/nss/external_tests/ssl_gtest/ssl_hrr_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_hrr_unittest.cc
@@ -178,65 +178,103 @@ TEST_F(TlsConnectTest, Select12AfterHell
   server_->StartConnect();
   Handshake();
   EXPECT_EQ(SSL_ERROR_ILLEGAL_PARAMETER_ALERT, server_->error_code());
   EXPECT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
 }
 
 class HelloRetryRequestAgentTest : public TlsAgentTestClient {
  protected:
-  void MakeHelloRetryRequestRecord(SSLNamedGroup group, DataBuffer* hrr_record,
-                                   uint32_t seq_num = 0) const {
-    const uint8_t canned_hrr[] = {
-        SSL_LIBRARY_VERSION_TLS_1_3 >> 8,
-        SSL_LIBRARY_VERSION_TLS_1_3 & 0xff,
-        0,
-        0,  // The cipher suite is ignored.
-        static_cast<uint8_t>(group >> 8),
-        static_cast<uint8_t>(group),
-        0,
-        0  // no extensions
-    };
+  void SetUp() override {
+    TlsAgentTestClient::SetUp();
+    EnsureInit();
+    agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3,
+                            SSL_LIBRARY_VERSION_TLS_1_3);
+    agent_->StartConnect();
+  }
+
+  void MakeCannedHrr(const uint8_t* body, size_t len, DataBuffer* hrr_record,
+                     uint32_t seq_num = 0) const {
+    DataBuffer hrr_data;
+    hrr_data.Allocate(len + 4);
+    size_t i = 0;
+    i = hrr_data.Write(i, static_cast<uint32_t>(SSL_LIBRARY_VERSION_TLS_1_3),
+                       2);
+    i = hrr_data.Write(i, static_cast<uint32_t>(len), 2);
+    if (len) {
+      hrr_data.Write(i, body, len);
+    }
     DataBuffer hrr;
-    MakeHandshakeMessage(kTlsHandshakeHelloRetryRequest, canned_hrr,
-                         sizeof(canned_hrr), &hrr, seq_num);
+    MakeHandshakeMessage(kTlsHandshakeHelloRetryRequest, hrr_data.data(),
+                         hrr_data.len(), &hrr, seq_num);
     MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, hrr.data(),
                hrr.len(), hrr_record, seq_num);
   }
+
+  void MakeGroupHrr(SSLNamedGroup group, DataBuffer* hrr_record,
+                    uint32_t seq_num = 0) const {
+    const uint8_t group_hrr[] = {
+        static_cast<uint8_t>(ssl_tls13_key_share_xtn >> 8),
+        static_cast<uint8_t>(ssl_tls13_key_share_xtn),
+        0,
+        2,  // length of key share extension
+        static_cast<uint8_t>(group >> 8),
+        static_cast<uint8_t>(group)};
+    MakeCannedHrr(group_hrr, sizeof(group_hrr), hrr_record, seq_num);
+  }
 };
 
 // Send two HelloRetryRequest messages in response to the ClientHello.  The are
 // constructed to appear legitimate by asking for a new share in each, so that
 // the client has to count to work out that the server is being unreasonable.
 TEST_P(HelloRetryRequestAgentTest, SendSecondHelloRetryRequest) {
-  EnsureInit();
-  agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3,
-                          SSL_LIBRARY_VERSION_TLS_1_3);
-  agent_->StartConnect();
-
-  DataBuffer hrr_record;
-  MakeHelloRetryRequestRecord(ssl_grp_ec_secp384r1, &hrr_record, 0);
-  ProcessMessage(hrr_record, TlsAgent::STATE_CONNECTING);
-  MakeHelloRetryRequestRecord(ssl_grp_ec_secp521r1, &hrr_record, 1);
-  ProcessMessage(hrr_record, TlsAgent::STATE_ERROR,
+  DataBuffer hrr;
+  MakeGroupHrr(ssl_grp_ec_secp384r1, &hrr, 0);
+  ProcessMessage(hrr, TlsAgent::STATE_CONNECTING);
+  MakeGroupHrr(ssl_grp_ec_secp521r1, &hrr, 1);
+  ProcessMessage(hrr, TlsAgent::STATE_ERROR,
                  SSL_ERROR_RX_UNEXPECTED_HELLO_RETRY_REQUEST);
 }
 
 // Here the client receives a HelloRetryRequest with a group that they already
 // provided a share for.
 TEST_P(HelloRetryRequestAgentTest, HandleBogusHelloRetryRequest) {
-  EnsureInit();
-  agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3,
-                          SSL_LIBRARY_VERSION_TLS_1_3);
-  agent_->StartConnect();
+  DataBuffer hrr;
+  MakeGroupHrr(ssl_grp_ec_secp256r1, &hrr);
+  ProcessMessage(hrr, TlsAgent::STATE_ERROR,
+                 SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST);
+}
+
+TEST_P(HelloRetryRequestAgentTest, HandleNoopHelloRetryRequest) {
+  DataBuffer hrr;
+  MakeCannedHrr(nullptr, 0U, &hrr);
+  ProcessMessage(hrr, TlsAgent::STATE_ERROR,
+                 SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST);
+}
 
-  DataBuffer hrr_record;
-  MakeHelloRetryRequestRecord(ssl_grp_ec_secp256r1, &hrr_record);
-  ProcessMessage(hrr_record, TlsAgent::STATE_ERROR,
-                 SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST);
+TEST_P(HelloRetryRequestAgentTest, HandleHelloRetryRequestCookie) {
+  const uint8_t canned_cookie_hrr[] = {
+      static_cast<uint8_t>(ssl_tls13_cookie_xtn >> 8),
+      static_cast<uint8_t>(ssl_tls13_cookie_xtn),
+      0,
+      5,  // length of cookie extension
+      0,
+      3,  // cookie value length
+      0xc0,
+      0x0c,
+      0x13};
+  DataBuffer hrr;
+  MakeCannedHrr(canned_cookie_hrr, sizeof(canned_cookie_hrr), &hrr);
+  TlsExtensionCapture* capture = new TlsExtensionCapture(ssl_tls13_cookie_xtn);
+  agent_->SetPacketFilter(capture);
+  ProcessMessage(hrr, TlsAgent::STATE_CONNECTING);
+  const size_t cookie_pos = 2 + 2;  // cookie_xtn, extension len
+  DataBuffer cookie(canned_cookie_hrr + cookie_pos,
+                    sizeof(canned_cookie_hrr) - cookie_pos);
+  EXPECT_EQ(cookie, capture->extension());
 }
 
 INSTANTIATE_TEST_CASE_P(HelloRetryRequestAgentTests, HelloRetryRequestAgentTest,
                         TlsConnectTestBase::kTlsModesAll);
 #ifndef NSS_DISABLE_TLS_1_3
 INSTANTIATE_TEST_CASE_P(HelloRetryRequestKeyExchangeTests, TlsKeyExchange13,
                         ::testing::Combine(TlsConnectTestBase::kTlsModesAll,
                                            TlsConnectTestBase::kTlsV13));
--- a/security/nss/external_tests/ssl_gtest/ssl_loopback_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_loopback_unittest.cc
@@ -34,16 +34,30 @@ TEST_P(TlsConnectGeneric, Connect) {
 
 TEST_P(TlsConnectGeneric, ConnectEcdsa) {
   SetExpectedVersion(std::get<1>(GetParam()));
   Reset(TlsAgent::kServerEcdsa256);
   Connect();
   CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa);
 }
 
+TEST_P(TlsConnectGenericPre13, CipherSuiteMismatch) {
+  EnsureTlsSetup();
+  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
+    client_->EnableSingleCipher(TLS_AES_128_GCM_SHA256);
+    server_->EnableSingleCipher(TLS_AES_256_GCM_SHA384);
+  } else {
+    client_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
+    server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);
+  }
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
+  server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
+}
+
 TEST_P(TlsConnectGenericPre13, ConnectFalseStart) {
   client_->EnableFalseStart();
   Connect();
   SendReceive();
 }
 
 TEST_P(TlsConnectGeneric, ConnectAlpn) {
   EnableAlpn();
--- a/security/nss/external_tests/ssl_gtest/tls_connect.cc
+++ b/security/nss/external_tests/ssl_gtest/tls_connect.cc
@@ -481,27 +481,32 @@ void TlsConnectTestBase::SetupForResume(
   Connect();
   SendReceive();  // Need to read so that we absorb the session ticket.
   CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
 
   Reset();
 }
 
 void TlsConnectTestBase::ZeroRttSendReceive(
-    bool expect_readable, std::function<bool()> post_clienthello_check) {
+    bool expect_writable, bool expect_readable,
+    std::function<bool()> post_clienthello_check) {
   const char* k0RttData = "ABCDEF";
   const PRInt32 k0RttDataLen = static_cast<PRInt32>(strlen(k0RttData));
 
   client_->Handshake();  // Send ClientHello.
   if (post_clienthello_check) {
     if (!post_clienthello_check()) return;
   }
   PRInt32 rv =
       PR_Write(client_->ssl_fd(), k0RttData, k0RttDataLen);  // 0-RTT write.
-  EXPECT_EQ(k0RttDataLen, rv);
+  if (expect_writable) {
+    EXPECT_EQ(k0RttDataLen, rv);
+  } else {
+    EXPECT_EQ(SECFailure, rv);
+  }
   server_->Handshake();  // Consume ClientHello, EE, Finished.
 
   std::vector<uint8_t> buf(k0RttDataLen);
   rv = PR_Read(server_->ssl_fd(), buf.data(), k0RttDataLen);  // 0-RTT read
   if (expect_readable) {
     std::cerr << "0-RTT read " << rv << " bytes\n";
     EXPECT_EQ(k0RttDataLen, rv);
   } else {
--- a/security/nss/external_tests/ssl_gtest/tls_connect.h
+++ b/security/nss/external_tests/ssl_gtest/tls_connect.h
@@ -94,17 +94,17 @@ class TlsConnectTestBase : public ::test
   void EnsureModelSockets();
   void CheckAlpn(const std::string& val);
   void EnableSrtp();
   void CheckSrtp() const;
   void SendReceive();
   void SetupForZeroRtt();
   void SetupForResume();
   void ZeroRttSendReceive(
-      bool expect_readable,
+      bool expect_writable, bool expect_readable,
       std::function<bool()> post_clienthello_check = nullptr);
   void Receive(size_t amount);
   void ExpectExtendedMasterSecret(bool expected);
   void ExpectEarlyDataAccepted(bool expected);
 
  protected:
   Mode mode_;
   TlsAgent* client_;
--- a/security/nss/external_tests/ssl_gtest/tls_filter.cc
+++ b/security/nss/external_tests/ssl_gtest/tls_filter.cc
@@ -400,17 +400,19 @@ PacketFilter::Action TlsExtensionFilter:
       std::cerr << "extension old: " << extension << std::endl;
       std::cerr << "extension new: " << filtered << std::endl;
       source = &filtered;
     }
 
     // Write out extension.
     offset = output->Write(offset, extension_type, 2);
     offset = output->Write(offset, source->len(), 2);
-    offset = output->Write(offset, *source);
+    if (source->len() > 0) {
+      offset = output->Write(offset, *source);
+    }
   }
   output->Truncate(offset);
 
   if (changed) {
     size_t newlen = output->len() - length_offset - 2;
     EXPECT_GT(0x10000U, newlen);
     if (newlen >= 0x10000) {
       return KEEP;  // bad: size increased too much
--- a/security/nss/external_tests/util_gtest/util_utf8_unittest.cc
+++ b/security/nss/external_tests/util_gtest/util_utf8_unittest.cc
@@ -942,19 +942,26 @@ const char *const kUtf8BadCases[] = {
     "\xED\xBF\xBF",
     "\xED\xA0\x80\xE0\xBF\xBF",
 };
 
 // Invalid UTF-16 sequences (0-terminated)
 
 const Utf16BadCase kUtf16BadCases[] = {
     // Leading surrogate not followed by trailing surrogate:
-    {{0xD800, 0, 0}},      {{0xD800, 0x41, 0}},   {{0xD800, 0xfe, 0}},
-    {{0xD800, 0x3bb, 0}},  {{0xD800, 0xD800, 0}}, {{0xD800, 0xFEFF, 0}},
+    {{0xD800, 0, 0}},
+    {{0xD800, 0x41, 0}},
+    {{0xD800, 0xfe, 0}},
+    {{0xD800, 0x3bb, 0}},
+    {{0xD800, 0xD800, 0}},
+    {{0xD800, 0xFEFF, 0}},
     {{0xD800, 0xFFFD, 0}},
+    // Trailing surrogate, not preceded by a leading one.
+    {{0xDC00, 0, 0}},
+    {{0xDE6D, 0xD834, 0}},
 };
 
 // Parameterized test instantiations:
 
 INSTANTIATE_TEST_CASE_P(Ucs4TestCases, Ucs4Test,
                         ::testing::ValuesIn(kUcs4Cases));
 
 INSTANTIATE_TEST_CASE_P(Iso88591TestCases, Ucs2Test,
--- a/security/nss/lib/softoken/legacydb/keydb.c
+++ b/security/nss/lib/softoken/legacydb/keydb.c
@@ -125,17 +125,19 @@ encode_dbkey(NSSLOWKEYDBKey *dbkey, unsi
     PORT_Assert(dbkey->salt.len < 256);
     buf[1] = dbkey->salt.len;
 
     /* set length of nickname */
     PORT_Assert(nnlen < 256);
     buf[2] = nnlen;
 
     /* copy salt */
-    PORT_Memcpy(&buf[3], dbkey->salt.data, dbkey->salt.len);
+    if (dbkey->salt.len > 0) {
+        PORT_Memcpy(&buf[3], dbkey->salt.data, dbkey->salt.len);
+    }
 
     /* copy nickname */
     PORT_Memcpy(&buf[3 + dbkey->salt.len], nn, nnlen);
 
     /* copy encrypted key */
     PORT_Memcpy(&buf[3 + dbkey->salt.len + nnlen], dbkey->derPK.data,
                 dbkey->derPK.len);
 
--- a/security/nss/lib/softoken/legacydb/pcertdb.c
+++ b/security/nss/lib/softoken/legacydb/pcertdb.c
@@ -2185,18 +2185,20 @@ EncodeDBSubjectEntry(certDBEntrySubject 
         tmpbuf += 2;
     }
 
     for (i = 0; i < ncerts; i++) {
         PORT_Memcpy(tmpbuf, certKeys[i].data, certKeys[i].len);
         tmpbuf += certKeys[i].len;
     }
     for (i = 0; i < ncerts; i++) {
-        PORT_Memcpy(tmpbuf, keyIDs[i].data, keyIDs[i].len);
-        tmpbuf += keyIDs[i].len;
+        if (keyIDs[i].len) {
+            PORT_Memcpy(tmpbuf, keyIDs[i].data, keyIDs[i].len);
+            tmpbuf += keyIDs[i].len;
+        }
     }
 
     if (entry->emailAddrs) {
         tmpbuf[0] = (PRUint8)(entry->nemailAddrs >> 8);
         tmpbuf[1] = (PRUint8)(entry->nemailAddrs);
         tmpbuf += 2;
         for (i = 0; i < entry->nemailAddrs; i++) {
             int nameLen = PORT_Strlen(entry->emailAddrs[i]) + 1;
--- a/security/nss/lib/softoken/pkcs11c.c
+++ b/security/nss/lib/softoken/pkcs11c.c
@@ -687,27 +687,32 @@ sftk_ChaCha20Poly1305_CreateContext(cons
     if (ChaCha20Poly1305_InitContext(&ctx->freeblCtx, key, keyLen,
                                      params->ulTagLen) != SECSuccess) {
         PORT_Free(ctx);
         return NULL;
     }
 
     PORT_Memcpy(ctx->nonce, params->pNonce, sizeof(ctx->nonce));
 
+    /* AAD data and length must both be null, or both non-null. */
+    PORT_Assert((params->pAAD == NULL) == (params->ulAADLen == 0));
+
     if (params->ulAADLen > sizeof(ctx->ad)) {
         /* Need to allocate an overflow buffer for the additional data. */
         ctx->adOverflow = (unsigned char *)PORT_Alloc(params->ulAADLen);
         if (!ctx->adOverflow) {
             PORT_Free(ctx);
             return NULL;
         }
         PORT_Memcpy(ctx->adOverflow, params->pAAD, params->ulAADLen);
     } else {
         ctx->adOverflow = NULL;
-        PORT_Memcpy(ctx->ad, params->pAAD, params->ulAADLen);
+        if (params->pAAD) {
+            PORT_Memcpy(ctx->ad, params->pAAD, params->ulAADLen);
+        }
     }
     ctx->adLen = params->ulAADLen;
 
     return ctx;
 }
 
 static void
 sftk_ChaCha20Poly1305_DestroyContext(SFTKChaCha20Poly1305Info *ctx,
--- a/security/nss/lib/ssl/dtlscon.c
+++ b/security/nss/lib/ssl/dtlscon.c
@@ -995,17 +995,16 @@ dtls_SetMTU(sslSocket *ss, PRUint16 adve
  * Caller must hold Handshake and RecvBuf locks.
  */
 SECStatus
 dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 {
     int errCode = SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
     SECStatus rv;
     PRInt32 temp;
-    SECItem cookie = { siBuffer, NULL, 0 };
     SSL3AlertDescription desc = illegal_parameter;
 
     SSL_TRC(3, ("%d: SSL3[%d]: handle hello_verify_request handshake",
                 SSL_GETPID(), ss->fd));
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     if (ss->ssl3.hs.ws != wait_server_hello) {
@@ -1020,29 +1019,28 @@ dtls_HandleHelloVerifyRequest(sslSocket 
         goto loser; /* alert has been sent */
     }
 
     if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE &&
         temp != SSL_LIBRARY_VERSION_DTLS_1_2_WIRE) {
         goto alert_loser;
     }
 
-    /* The cookie */
-    rv = ssl3_ConsumeHandshakeVariable(ss, &cookie, 1, &b, &length);
+    /* Read the cookie.
+     * IMPORTANT: The value of ss->ssl3.hs.cookie is only valid while the
+     * HelloVerifyRequest message remains valid. */
+    rv = ssl3_ConsumeHandshakeVariable(ss, &ss->ssl3.hs.cookie, 1, &b, &length);
     if (rv != SECSuccess) {
         goto loser; /* alert has been sent */
     }
-    if (cookie.len > DTLS_COOKIE_BYTES) {
+    if (ss->ssl3.hs.cookie.len > DTLS_COOKIE_BYTES) {
         desc = decode_error;
         goto alert_loser; /* malformed. */
     }
 
-    PORT_Memcpy(ss->ssl3.hs.cookie, cookie.data, cookie.len);
-    ss->ssl3.hs.cookieLen = cookie.len;
-
     ssl_GetXmitBufLock(ss); /*******************************/
 
     /* Now re-send the client hello */
     rv = ssl3_SendClientHello(ss, client_hello_retransmit);
 
     ssl_ReleaseXmitBufLock(ss); /*******************************/
 
     if (rv == SECSuccess)
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -5152,17 +5152,17 @@ ssl3_SendClientHello(sslSocket *ss, sslC
 
     length = sizeof(SSL3ProtocolVersion) + SSL3_RANDOM_LENGTH +
              1 + (sid->version >= SSL_LIBRARY_VERSION_TLS_1_3
                       ? 0
                       : sid->u.ssl3.sessionIDLength) +
              2 + num_suites * sizeof(ssl3CipherSuite) +
              1 + numCompressionMethods + total_exten_len;
     if (IS_DTLS(ss)) {
-        length += 1 + ss->ssl3.hs.cookieLen;
+        length += 1 + ss->ssl3.hs.cookie.len;
     }
 
     /* A padding extension may be included to ensure that the record containing
      * the ClientHello doesn't have a length between 256 and 511 bytes
      * (inclusive). Initial, ClientHello records with such lengths trigger bugs
      * in F5 devices.
      *
      * This is not done for DTLS, for renegotiation, or when there are no
@@ -5232,17 +5232,17 @@ ssl3_SendClientHello(sslSocket *ss, sslC
         if (sid->u.ssl3.lock) {
             PR_RWLock_Unlock(sid->u.ssl3.lock);
         }
         return rv; /* err set by ssl3_AppendHandshake* */
     }
 
     if (IS_DTLS(ss)) {
         rv = ssl3_AppendHandshakeVariable(
-            ss, ss->ssl3.hs.cookie, ss->ssl3.hs.cookieLen, 1);
+            ss, ss->ssl3.hs.cookie.data, ss->ssl3.hs.cookie.len, 1);
         if (rv != SECSuccess) {
             if (sid->u.ssl3.lock) {
                 PR_RWLock_Unlock(sid->u.ssl3.lock);
             }
             return rv; /* err set by ssl3_AppendHandshake* */
         }
     }
 
@@ -6891,17 +6891,19 @@ ssl3_HandleServerHelloPart2(sslSocket *s
     /* get a new sid */
     ss->sec.ci.sid = sid = ssl3_NewSessionID(ss, PR_FALSE);
     if (sid == NULL) {
         goto alert_loser; /* memory error is set. */
     }
 
     sid->version = ss->version;
     sid->u.ssl3.sessionIDLength = sidBytes->len;
-    PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes->data, sidBytes->len);
+    if (sidBytes->len > 0) {
+        PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes->data, sidBytes->len);
+    }
 
     sid->u.ssl3.keys.extendedMasterSecretUsed =
         ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn);
 
     /* Copy Signed Certificate Timestamps, if any. */
     if (ss->xtnData.signedCertTimestamps.data) {
         rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.signedCertTimestamps,
                               &ss->xtnData.signedCertTimestamps);
@@ -8248,18 +8250,18 @@ ssl3_HandleClientHello(sslSocket *ss, SS
             goto loser; /* malformed */
         }
     }
 
     versionExtension = ssl3_FindExtension(ss, ssl_tls13_supported_versions_xtn);
     if (versionExtension) {
         rv = tls13_NegotiateVersion(ss, versionExtension);
         if (rv != SECSuccess) {
-            desc = protocol_version;
-            errCode = SSL_ERROR_UNSUPPORTED_VERSION;
+            errCode = PORT_GetError();
+            desc = (errCode == SSL_ERROR_UNSUPPORTED_VERSION) ? protocol_version : illegal_parameter;
             goto alert_loser;
         }
     } else {
         /* The PR_MIN here ensures that we never negotiate 1.3 if the
          * peer didn't offer "supported_versions". */
         rv = ssl3_NegotiateVersion(ss,
                                    PR_MIN(version,
                                           SSL_LIBRARY_VERSION_TLS_1_2),
@@ -12719,18 +12721,21 @@ ssl3_InitState(sslSocket *ss)
     }
 
     ss->ssl3.hs.clientHelloHash = NULL;
     PR_INIT_CLIST(&ss->ssl3.hs.remoteKeyShares);
     ss->ssl3.hs.currentSecret = NULL;
     ss->ssl3.hs.resumptionPsk = NULL;
     ss->ssl3.hs.resumptionContext = nullItem;
     ss->ssl3.hs.dheSecret = NULL;
-    ss->ssl3.hs.trafficSecret = NULL;
-    ss->ssl3.hs.hsTrafficSecret = NULL;
+    ss->ssl3.hs.clientEarlyTrafficSecret = NULL;
+    ss->ssl3.hs.clientHsTrafficSecret = NULL;
+    ss->ssl3.hs.serverHsTrafficSecret = NULL;
+    ss->ssl3.hs.clientTrafficSecret = NULL;
+    ss->ssl3.hs.serverTrafficSecret = NULL;
     ss->ssl3.hs.certificateRequest = NULL;
     PR_INIT_CLIST(&ss->ssl3.hs.cipherSpecs);
 
     PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space);
     ss->ssl3.hs.messages.buf = NULL;
     ss->ssl3.hs.messages.space = 0;
 
     ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
@@ -13055,22 +13060,26 @@ ssl3_DestroySSL3Info(sslSocket *ss)
     if (ss->ssl3.hs.currentSecret)
         PK11_FreeSymKey(ss->ssl3.hs.currentSecret);
     if (ss->ssl3.hs.resumptionPsk)
         PK11_FreeSymKey(ss->ssl3.hs.resumptionPsk);
     if (ss->ssl3.hs.dheSecret)
         PK11_FreeSymKey(ss->ssl3.hs.dheSecret);
     if (ss->ssl3.hs.resumptionContext.data)
         SECITEM_FreeItem(&ss->ssl3.hs.resumptionContext, PR_FALSE);
-    if (ss->ssl3.hs.earlyTrafficSecret)
-        PK11_FreeSymKey(ss->ssl3.hs.earlyTrafficSecret);
-    if (ss->ssl3.hs.hsTrafficSecret)
-        PK11_FreeSymKey(ss->ssl3.hs.hsTrafficSecret);
-    if (ss->ssl3.hs.trafficSecret)
-        PK11_FreeSymKey(ss->ssl3.hs.trafficSecret);
+    if (ss->ssl3.hs.clientEarlyTrafficSecret)
+        PK11_FreeSymKey(ss->ssl3.hs.clientEarlyTrafficSecret);
+    if (ss->ssl3.hs.clientHsTrafficSecret)
+        PK11_FreeSymKey(ss->ssl3.hs.clientHsTrafficSecret);
+    if (ss->ssl3.hs.serverHsTrafficSecret)
+        PK11_FreeSymKey(ss->ssl3.hs.serverHsTrafficSecret);
+    if (ss->ssl3.hs.clientTrafficSecret)
+        PK11_FreeSymKey(ss->ssl3.hs.clientTrafficSecret);
+    if (ss->ssl3.hs.serverTrafficSecret)
+        PK11_FreeSymKey(ss->ssl3.hs.serverTrafficSecret);
 
     ss->ssl3.hs.zeroRttState = ssl_0rtt_none;
     /* Destroy TLS 1.3 buffered early data. */
     tls13_DestroyEarlyData(&ss->ssl3.hs.bufferedEarlyData);
 
     ss->ssl3.initialized = PR_FALSE;
 
     SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
--- a/security/nss/lib/ssl/ssl3ext.c
+++ b/security/nss/lib/ssl/ssl3ext.c
@@ -91,16 +91,19 @@ static PRInt32 ssl3_SendExtendedMasterSe
 static SECStatus ssl3_HandleExtendedMasterSecretXtn(sslSocket *ss,
                                                     PRUint16 ex_type,
                                                     SECItem *data);
 static PRInt32 tls13_ClientSendKeyShareXtn(sslSocket *ss, PRBool append,
                                            PRUint32 maxBytes);
 static SECStatus tls13_ClientHandleKeyShareXtn(sslSocket *ss,
                                                PRUint16 ex_type,
                                                SECItem *data);
+static SECStatus tls13_ClientHandleKeyShareXtnHrr(sslSocket *ss,
+                                                  PRUint16 ex_type,
+                                                  SECItem *data);
 static SECStatus tls13_ServerHandleKeyShareXtn(sslSocket *ss,
                                                PRUint16 ex_type,
                                                SECItem *data);
 static PRInt32 tls13_ClientSendPreSharedKeyXtn(sslSocket *ss, PRBool append,
                                                PRUint32 maxBytes);
 static SECStatus tls13_ServerHandlePreSharedKeyXtn(sslSocket *ss,
                                                    PRUint16 ex_type,
                                                    SECItem *data);
@@ -117,16 +120,21 @@ static SECStatus tls13_ClientHandleEarly
 static SECStatus tls13_ClientHandleTicketEarlyDataInfoXtn(
     sslSocket *ss, PRUint16 ex_type,
     SECItem *data);
 static SECStatus tls13_ClientHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type,
                                               SECItem *data);
 static PRInt32 tls13_ClientSendSupportedVersionsXtn(sslSocket *ss,
                                                     PRBool append,
                                                     PRUint32 maxBytes);
+static SECStatus tls13_ClientHandleHrrCookie(sslSocket *ss, PRUint16 ex_type,
+                                             SECItem *data);
+static PRInt32 tls13_ClientSendHrrCookieXtn(sslSocket *ss,
+                                            PRBool append,
+                                            PRUint32 maxBytes);
 
 /*
  * Write bytes.  Using this function means the SECItem structure
  * cannot be freed.  The caller is expected to call this function
  * on a shallow copy of the structure.
  */
 static SECStatus
 ssl3_AppendToItem(SECItem *item, const unsigned char *buf, PRUint32 bytes)
@@ -282,16 +290,22 @@ static const ssl3ExtensionHandler server
     { ssl_signed_cert_timestamp_xtn, &ssl3_ClientHandleSignedCertTimestampXtn },
     { ssl_tls13_key_share_xtn, &tls13_ClientHandleKeyShareXtn },
     { ssl_tls13_pre_shared_key_xtn, &tls13_ClientHandlePreSharedKeyXtn },
     { ssl_tls13_early_data_xtn, &tls13_ClientHandleEarlyDataXtn },
     { ssl_signature_algorithms_xtn, &tls13_ClientHandleSigAlgsXtn },
     { -1, NULL }
 };
 
+static const ssl3ExtensionHandler helloRetryRequestHandlers[] = {
+    { ssl_tls13_key_share_xtn, tls13_ClientHandleKeyShareXtnHrr },
+    { ssl_tls13_cookie_xtn, tls13_ClientHandleHrrCookie },
+    { -1, NULL }
+};
+
 static const ssl3ExtensionHandler serverHelloHandlersSSL3[] = {
     { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
     { -1, NULL }
 };
 
 static const ssl3ExtensionHandler newSessionTicketHandlers[] = {
     { ssl_tls13_ticket_early_data_info_xtn,
       &tls13_ClientHandleTicketEarlyDataInfoXtn },
@@ -324,17 +338,18 @@ static const ssl3HelloExtensionSender cl
       { ssl_tls13_key_share_xtn, &tls13_ClientSendKeyShareXtn },
       { ssl_tls13_pre_shared_key_xtn, &tls13_ClientSendPreSharedKeyXtn },
       { ssl_tls13_early_data_xtn, &tls13_ClientSendEarlyDataXtn },
       /* Some servers (e.g. WebSphere Application Server 7.0 and Tomcat) will
        * time out or terminate the connection if the last extension in the
        * client hello is empty. They are not intolerant of TLS 1.2, so list
        * signature_algorithms at the end. See bug 1243641. */
       { ssl_tls13_supported_versions_xtn, &tls13_ClientSendSupportedVersionsXtn },
-      { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
+      { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
+      { ssl_tls13_cookie_xtn, &tls13_ClientSendHrrCookieXtn }
       /* any extra entries will appear as { 0, NULL }    */
     };
 
 static const ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] = {
     { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }
     /* any extra entries will appear as { 0, NULL }    */
 };
 
@@ -2160,16 +2175,20 @@ ssl3_HandleParsedExtensions(sslSocket *s
     switch (handshakeMessage) {
         case client_hello:
             handlers = clientHelloHandlers;
             break;
         case new_session_ticket:
             PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
             handlers = newSessionTicketHandlers;
             break;
+        case hello_retry_request:
+            PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
+            handlers = helloRetryRequestHandlers;
+            break;
         case encrypted_extensions:
             PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
         /* fall through */
         case server_hello:
             if (ss->version > SSL_LIBRARY_VERSION_3_0) {
                 handlers = serverHelloHandlersTLS;
             } else {
                 handlers = serverHelloHandlersSSL3;
@@ -2186,17 +2205,18 @@ ssl3_HandleParsedExtensions(sslSocket *s
          cursor = PR_NEXT_LINK(cursor)) {
         TLSExtension *extension = (TLSExtension *)cursor;
         const ssl3ExtensionHandler *handler;
 
         /* Check whether the server sent an extension which was not advertised
          * in the ClientHello */
         if (!ss->sec.isServer &&
             !ssl3_ClientExtensionAdvertised(ss, extension->type) &&
-            (handshakeMessage != new_session_ticket)) {
+            (handshakeMessage != new_session_ticket) &&
+            (extension->type != ssl_tls13_cookie_xtn)) {
             (void)SSL3_SendAlert(ss, alert_fatal, unsupported_extension);
             PORT_SetError(SSL_ERROR_RX_UNEXPECTED_EXTENSION);
             return SECFailure;
         }
 
         /* Check that this is a legal extension in TLS 1.3 */
         if (isTLS13 && !tls13_ExtensionAllowed(extension->type, handshakeMessage)) {
             if (handshakeMessage == client_hello) {
@@ -3165,16 +3185,59 @@ tls13_ClientHandleKeyShareXtn(sslSocket 
     if (data->len) {
         PORT_SetError(SSL_ERROR_RX_MALFORMED_KEY_SHARE);
         return SECFailure;
     }
 
     return SECSuccess;
 }
 
+static SECStatus
+tls13_ClientHandleKeyShareXtnHrr(sslSocket *ss, PRUint16 ex_type, SECItem *data)
+{
+    SECStatus rv;
+    PRInt32 tmp;
+    const sslNamedGroupDef *group;
+
+    PORT_Assert(!ss->sec.isServer);
+    PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
+
+    SSL_TRC(3, ("%d: SSL3[%d]: handle key_share extension in HRR",
+                SSL_GETPID(), ss->fd));
+
+    tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
+    if (tmp < 0) {
+        return SECFailure; /* error code already set */
+    }
+    if (data->len) {
+        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
+        PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST);
+        return SECFailure;
+    }
+
+    group = ssl_LookupNamedGroup((SSLNamedGroup)tmp);
+    /* If the group is not enabled, or we already have a share for the
+     * requested group, abort. */
+    if (!ssl_NamedGroupEnabled(ss, group) ||
+        ssl_LookupEphemeralKeyPair(ss, group)) {
+        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
+        PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST);
+        return SECFailure;
+    }
+
+    rv = tls13_CreateKeyShare(ss, group);
+    if (rv != SECSuccess) {
+        (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
+        PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
+        return SECFailure;
+    }
+
+    return SECSuccess;
+}
+
 /* Handle an incoming KeyShare extension at the server and copy to
  * |ss->ssl3.hs.remoteKeyShares| for future use. The key
  * share is processed in tls13_HandleClientKeyShare(). */
 static SECStatus
 tls13_ServerHandleKeyShareXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
 {
     SECStatus rv;
     PRInt32 length;
@@ -3755,17 +3818,17 @@ tls13_ClientSendSupportedVersionsXtn(ssl
     SSL_TRC(3, ("%d: TLS13[%d]: send supported_versions extension",
                 SSL_GETPID(), ss->fd));
 
     /* Extension type, extension len fiels, vector len field,
      * length of the values. */
     extensions_len = 2 + 2 + 1 +
                      2 * (ss->vrange.max - ss->vrange.min + 1);
 
-    if (maxBytes < extensions_len) {
+    if (maxBytes < (PRUint32)extensions_len) {
         PORT_Assert(0);
         return 0;
     }
 
     if (append) {
         rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_supported_versions_xtn, 2);
         if (rv != SECSuccess)
             return -1;
@@ -3784,16 +3847,84 @@ tls13_ClientSendSupportedVersionsXtn(ssl
             if (rv != SECSuccess)
                 return -1;
         }
     }
 
     return extensions_len;
 }
 
+/*
+ *    struct {
+ *        opaque cookie<1..2^16-1>;
+ *    } Cookie;
+ */
+SECStatus
+tls13_ClientHandleHrrCookie(sslSocket *ss, PRUint16 ex_type, SECItem *data)
+{
+    SECStatus rv;
+
+    SSL_TRC(3, ("%d: TLS13[%d]: handle cookie extension",
+                SSL_GETPID(), ss->fd));
+
+    PORT_Assert(ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3);
+
+    /* IMPORTANT: this is only valid while the HelloRetryRequest is still valid. */
+    rv = ssl3_ConsumeHandshakeVariable(ss, &ss->ssl3.hs.cookie, 2,
+                                       &data->data, &data->len);
+    if (rv != SECSuccess) {
+        PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST);
+        return SECFailure;
+    }
+    if (!ss->ssl3.hs.cookie.len || data->len) {
+        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
+        PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST);
+        return SECFailure;
+    }
+
+    return SECSuccess;
+}
+
+PRInt32
+tls13_ClientSendHrrCookieXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
+{
+    PRInt32 extension_len;
+
+    if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3 ||
+        !ss->ssl3.hs.cookie.len) {
+        return 0;
+    }
+
+    SSL_TRC(3, ("%d: TLS13[%d]: send cookie extension", SSL_GETPID(), ss->fd));
+
+    /* Extension type, length, cookie length, cookie value. */
+    extension_len = 2 + 2 + 2 + ss->ssl3.hs.cookie.len;
+
+    if (maxBytes < (PRUint32)extension_len) {
+        PORT_Assert(0);
+        return 0;
+    }
+
+    if (append) {
+        SECStatus rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_cookie_xtn, 2);
+        if (rv != SECSuccess)
+            return -1;
+
+        rv = ssl3_AppendHandshakeNumber(ss, extension_len - 4, 2);
+        if (rv != SECSuccess)
+            return -1;
+
+        rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.hs.cookie.data,
+                                          ss->ssl3.hs.cookie.len, 2);
+        if (rv != SECSuccess)
+            return -1;
+    }
+    return extension_len;
+}
+
 void
 ssl3_DestroyRemoteExtensions(PRCList *list)
 {
     PRCList *cur_p;
 
     while (!PR_CLIST_IS_EMPTY(list)) {
         cur_p = PR_LIST_TAIL(list);
         PR_REMOVE_LINK(cur_p);
--- a/security/nss/lib/ssl/sslimpl.h
+++ b/security/nss/lib/ssl/sslimpl.h
@@ -932,40 +932,40 @@ typedef struct SSL3HandshakeStateStr {
     PRUint16 maxMessageSent;       /* The largest message we sent */
     PRUint16 recvMessageSeq;       /* The receiving message sequence
                                     * number */
     sslBuffer recvdFragments;      /* The fragments we have received in
                                     * a bitmask */
     PRInt32 recvdHighWater;        /* The high water mark for fragments
                                     * received. -1 means no reassembly
                                     * in progress. */
-    unsigned char cookie[32];      /* The cookie */
-    unsigned char cookieLen;       /* The length of the cookie */
+    SECItem cookie;                /* The Hello(Retry|Verify)Request cookie. */
     PRIntervalTime rtTimerStarted; /* When the timer was started */
     DTLSTimerCb rtTimerCb;         /* The function to call on expiry */
     PRUint32 rtTimeoutMs;          /* The length of the current timeout
                                     * used for backoff (in ms) */
     PRUint32 rtRetries;            /* The retry counter */
     SECItem srvVirtName;           /* for server: name that was negotiated
                           * with a client. For client - is
                           * always set to NULL.*/
 
     /* This group of values is used for TLS 1.3 and above */
-    PK11Context *clientHelloHash;   /* The client hello hash state, used
+    PK11Context *clientHelloHash;         /* The client hello hash state, used
                                         * by the server for 0-RTT. */
-    PRCList remoteKeyShares;        /* The other side's public keys */
-    PK11SymKey *currentSecret;      /* The secret down the "left hand side"
+    PRCList remoteKeyShares;              /* The other side's public keys */
+    PK11SymKey *currentSecret;            /* The secret down the "left hand side"
                                         * of the TLS 1.3 key schedule. */
-    PK11SymKey *resumptionPsk;      /* The resumption PSK. */
-    SECItem resumptionContext;      /* The resumption context. */
-    PK11SymKey *dheSecret;          /* The (EC)DHE shared secret. */
-    PK11SymKey *earlyTrafficSecret; /* The secret we use for 0-RTT. */
-    PK11SymKey *hsTrafficSecret;    /* The handshake traffic secret. */
-    PK11SymKey *trafficSecret;      /* The source key to use to generate
-                                        * traffic keys */
+    PK11SymKey *resumptionPsk;            /* The resumption PSK. */
+    SECItem resumptionContext;            /* The resumption context. */
+    PK11SymKey *dheSecret;                /* The (EC)DHE shared secret. */
+    PK11SymKey *clientEarlyTrafficSecret; /* The secret we use for 0-RTT. */
+    PK11SymKey *clientHsTrafficSecret;    /* The source keys for handshake */
+    PK11SymKey *serverHsTrafficSecret;    /* traffic keys. */
+    PK11SymKey *clientTrafficSecret;      /* The source keys for application */
+    PK11SymKey *serverTrafficSecret;      /* traffic keys */
     /* The certificate request from the server. */
     TLS13CertificateRequest *certificateRequest;
     PRCList cipherSpecs;            /* The cipher specs in the sequence they
                                         * will be applied. */
     ssl3CipherSpec *nullSpec;       /* In case 0-RTT is rejected. */
     sslZeroRttState zeroRttState;   /* Are we doing a 0-RTT handshake? */
     sslZeroRttIgnore zeroRttIgnore; /* Are we ignoring 0-RTT? */
     PRCList bufferedEarlyData;      /* Buffered TLS 1.3 early data
--- a/security/nss/lib/ssl/sslt.h
+++ b/security/nss/lib/ssl/sslt.h
@@ -309,29 +309,33 @@ typedef enum {
     ssl_signed_cert_timestamp_xtn = 18,
     ssl_padding_xtn = 21,
     ssl_extended_master_secret_xtn = 23,
     ssl_session_ticket_xtn = 35,
     ssl_tls13_key_share_xtn = 40,
     ssl_tls13_pre_shared_key_xtn = 41,
     ssl_tls13_early_data_xtn = 42,
     ssl_tls13_supported_versions_xtn = 43,
+    ssl_tls13_cookie_xtn = 44,
     ssl_next_proto_nego_xtn = 13172,
     ssl_renegotiation_info_xtn = 0xff01
 } SSLExtensionType;
 
 typedef enum {
     ssl_tls13_ticket_early_data_info_xtn = 1
 } TLS13TicketExtensionType;
 
 /* This is the old name for the supported_groups extensions. */
 #define ssl_elliptic_curves_xtn ssl_supported_groups_xtn
 
-#define SSL_MAX_EXTENSIONS 16 /* doesn't include ssl_padding_xtn or \
-                               * TLS 1.3 NewSessionTicket extensions. */
+/* SSL_MAX_EXTENSIONS doesn't include ssl_padding_xtn.  It includes the maximum
+ * number of extensions that are supported for any single message type.  That
+ * is, a ClientHello; ServerHello and TLS 1.3 NewSessionTicket and
+ * HelloRetryRequest extensions are smaller. */
+#define SSL_MAX_EXTENSIONS 17
 
 /* Deprecated */
 typedef enum {
     ssl_dhe_group_none = 0,
     ssl_ff_dhe_2048_group = 1,
     ssl_ff_dhe_3072_group = 2,
     ssl_ff_dhe_4096_group = 3,
     ssl_ff_dhe_6144_group = 4,
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -64,17 +64,19 @@ static SECStatus tls13_HandleCertificate
 static SECStatus tls13_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b,
                                                 PRUint32 length);
 static SECStatus
 tls13_SendCertificateVerify(sslSocket *ss, SECKEYPrivateKey *privKey);
 static SECStatus tls13_HandleCertificateVerify(
     sslSocket *ss, SSL3Opaque *b, PRUint32 length,
     TLS13CombinedHash *hashes);
 static SECStatus
-tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key, const char *label,
+tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key,
+                   const char *prefix,
+                   const char *suffix,
                    const TLS13CombinedHash *hashes,
                    PK11SymKey **dest);
 static void tls13_SetNullCipherSpec(sslSocket *ss, ssl3CipherSpec **specp);
 static SECStatus tls13_SendEndOfEarlyData(sslSocket *ss);
 static SECStatus tls13_SendFinished(sslSocket *ss, PK11SymKey *baseKey);
 static SECStatus tls13_VerifyFinished(sslSocket *ss, PK11SymKey *secret,
                                       SSL3Opaque *b, PRUint32 length,
                                       const TLS13CombinedHash *hashes);
@@ -100,35 +102,37 @@ static SECStatus tls13_ComputeApplicatio
 static SECStatus tls13_ComputeFinalSecrets(sslSocket *ss);
 static SECStatus tls13_ComputeFinished(
     sslSocket *ss, PK11SymKey *baseKey, const TLS13CombinedHash *hashes,
     PRBool sending, PRUint8 *output, unsigned int *outputLen,
     unsigned int maxOutputLen);
 static SECStatus tls13_SendClientSecondRound(sslSocket *ss);
 static SECStatus tls13_FinishHandshake(sslSocket *ss);
 
+const char kHkdfLabelClient[] = "client";
+const char kHkdfLabelServer[] = "server";
 const char kHkdfLabelEarlyTrafficSecret[] = "early traffic secret";
 const char kHkdfLabelHandshakeTrafficSecret[] = "handshake traffic secret";
 const char kHkdfLabelApplicationTrafficSecret[] = "application traffic secret";
-const char kHkdfLabelClientFinishedSecret[] = "client finished";
-const char kHkdfLabelServerFinishedSecret[] = "server finished";
+const char kHkdfLabelFinishedSecret[] = "finished";
 const char kHkdfLabelResumptionMasterSecret[] = "resumption master secret";
 const char kHkdfLabelResumptionPsk[] = "resumption psk";
 const char kHkdfLabelResumptionContext[] = "resumption context";
 const char kHkdfLabelExporterMasterSecret[] = "exporter master secret";
 const char kHkdfPhaseEarlyHandshakeDataKeys[] = "early handshake key expansion";
 const char kHkdfPhaseEarlyApplicationDataKeys[] = "early application data key expansion";
 const char kHkdfPhaseHandshakeKeys[] = "handshake key expansion";
 const char kHkdfPhaseApplicationDataKeys[] = "application data key expansion";
-const char kHkdfPurposeClientWriteKey[] = "client write key";
-const char kHkdfPurposeServerWriteKey[] = "server write key";
-const char kHkdfPurposeClientWriteIv[] = "client write iv";
-const char kHkdfPurposeServerWriteIv[] = "server write iv";
-const char kClientFinishedLabel[] = "client finished";
-const char kServerFinishedLabel[] = "server finished";
+const char kHkdfPurposeKey[] = "key";
+const char kHkdfPurposeIv[] = "iv";
+
+#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);
 
@@ -688,55 +692,62 @@ loser:
     }
     return SECFailure;
 }
 
 /* Key Derivation Functions.
  *
  * Below is the key schedule from [draft-ietf-tls-tls13].
  *
- * The relevant functions from this file are indicated by tls13_Foo().
+ * * The relevant functions from this file are indicated by tls13_Foo().
+ *                 0
+ *                 |
+ *                 v
+ *   PSK ->  HKDF-Extract
+ *                 |
+ *                 v
+ *           Early Secret ---> Derive-Secret(., "client early traffic secret",
+ *                 |                         ClientHello)
+ *                 |                         = client_early_traffic_secret
+ *                 v
+ * (EC)DHE -> HKDF-Extract
+ *                 |
+ *                 v
+ *         Handshake Secret
+ *                 |
+ *                 +---------> Derive-Secret(., "client handshake traffic secret",
+ *                 |                         ClientHello...ServerHello)
+ *                 |                         = client_handshake_traffic_secret
+ *                 |
+ *                 +---------> Derive-Secret(., "server handshake traffic secret",
+ *                 |                         ClientHello...ServerHello)
+ *                 |                         = server_handshake_traffic_secret
+ *                 |
+ *                 v
+ *      0 -> HKDF-Extract
+ *                 |
+ *                 v
+ *            Master Secret
+ *                 |
+ *                 +---------> Derive-Secret(., "client application traffic secret",
+ *                 |                         ClientHello...Server Finished)
+ *                 |                         = client_traffic_secret_0
+ *                 |
+ *                 +---------> Derive-Secret(., "server application traffic secret",
+ *                 |                         ClientHello...Server Finished)
+ *                 |                         = server_traffic_secret_0
+ *                 |
+ *                 +---------> Derive-Secret(., "exporter master secret",
+ *                 |                         ClientHello...Client Finished)
+ *                 |                         = exporter_secret
+ *                 |
+ *                 +---------> Derive-Secret(., "resumption master secret",
+ *                                           ClientHello...Client Finished)
+ *                                           = resumption_secret
  *
- *                  0
- *                  |
- *                  v
- *    PSK ->  HKDF-Extract      tls13_ComputeEarlySecrets()
- *                  |
- *                  v
- *            Early Secret  --> Derive-Secret(., "early traffic secret",
- *                  |                         ClientHello)
- *                  |                         = early_traffic_secret
- *                  v
- * (EC)DHE -> HKDF-Extract      tls13_ComputeHandshakeSecrets()
- *                  |
- *                  v
- *               Handshake
- *                Secret -----> Derive-Secret(., "handshake traffic secret",
- *                  |                         ClientHello + ServerHello)
- *                  |                         = handshake_traffic_secret
- *                  v
- *       0 -> HKDF-Extract      tls13_ComputeApplicationSecret
- *                  |
- *                  v
- *             Master Secret
- *                  |
- *                  +---------> Derive-Secret(., "application traffic secret",
- *                  |                         ClientHello...Server Finished)
- *                  |                         = traffic_secret_0
- *                  |
- *                  |
- *                  |           tls13_ComputeFinalSecrets()
- *                  |
- *                  +---------> Derive-Secret(., "exporter master secret",
- *                  |                         ClientHello...Client Finished)
- *                  |                         = exporter_secret
- *                  |
- *                  +---------> Derive-Secret(., "resumption master secret",
- *                                            ClientHello...Client Finished)
- *                                            = resumption_secret
  */
 
 static SECStatus
 tls13_ComputeEarlySecrets(sslSocket *ss, PRBool setup0Rtt)
 {
     SECStatus rv = SECSuccess;
     PK11Context *ctx;
     PRUint8 hash[HASH_LENGTH_MAX];
@@ -794,19 +805,20 @@ tls13_ComputeEarlySecrets(sslSocket *ss,
                           tls13_GetHashSize(ss)) == NULL) {
         return SECFailure;
     }
     PORT_Memcpy(ss->ssl3.hs.resumptionContext.data, hash, len);
 
     if (setup0Rtt) {
         /* Derive the early secret. */
         rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
+                                kHkdfLabelClient,
                                 kHkdfLabelEarlyTrafficSecret,
                                 NULL,
-                                &ss->ssl3.hs.earlyTrafficSecret);
+                                &ss->ssl3.hs.clientEarlyTrafficSecret);
         if (rv != SECSuccess)
             return SECFailure;
     }
 
     return SECSuccess;
 }
 
 static SECStatus
@@ -824,20 +836,29 @@ tls13_ComputeHandshakeSecrets(sslSocket 
         LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
         return rv;
     }
     PK11_FreeSymKey(ss->ssl3.hs.dheSecret);
     ss->ssl3.hs.dheSecret = NULL;
     PK11_FreeSymKey(ss->ssl3.hs.currentSecret);
     ss->ssl3.hs.currentSecret = newSecret;
 
-    /* Now compute |hsTrafficSecret| */
+    /* Now compute |*HsTrafficSecret| */
     rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
+                            kHkdfLabelClient,
                             kHkdfLabelHandshakeTrafficSecret, NULL,
-                            &ss->ssl3.hs.hsTrafficSecret);
+                            &ss->ssl3.hs.clientHsTrafficSecret);
+    if (rv != SECSuccess) {
+        LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
+        return rv;
+    }
+    rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
+                            kHkdfLabelServer,
+                            kHkdfLabelHandshakeTrafficSecret, NULL,
+                            &ss->ssl3.hs.serverHsTrafficSecret);
     if (rv != SECSuccess) {
         LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
         return rv;
     }
 
     /* Crank HKDF forward to make master secret, which we
      * stuff in current secret. */
     rv = tls13_HkdfExtract(ss->ssl3.hs.currentSecret,
@@ -856,19 +877,28 @@ tls13_ComputeHandshakeSecrets(sslSocket 
 }
 
 static SECStatus
 tls13_ComputeApplicationSecrets(sslSocket *ss)
 {
     SECStatus rv;
 
     rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
+                            kHkdfLabelClient,
                             kHkdfLabelApplicationTrafficSecret,
                             NULL,
-                            &ss->ssl3.hs.trafficSecret);
+                            &ss->ssl3.hs.clientTrafficSecret);
+    if (rv != SECSuccess) {
+        return SECFailure;
+    }
+    rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
+                            kHkdfLabelServer,
+                            kHkdfLabelApplicationTrafficSecret,
+                            NULL,
+                            &ss->ssl3.hs.serverTrafficSecret);
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
     return SECSuccess;
 }
 
 static SECStatus
@@ -876,17 +906,17 @@ tls13_ComputeFinalSecrets(sslSocket *ss)
 {
     SECStatus rv;
     PK11SymKey *resumptionMasterSecret = NULL;
 
     PORT_Assert(!ss->ssl3.crSpec->master_secret);
     PORT_Assert(!ss->ssl3.cwSpec->master_secret);
 
     rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
-                            kHkdfLabelResumptionMasterSecret,
+                            NULL, kHkdfLabelResumptionMasterSecret,
                             NULL, &resumptionMasterSecret);
     PK11_FreeSymKey(ss->ssl3.hs.currentSecret);
     ss->ssl3.hs.currentSecret = NULL;
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
     /* This is pretty gross. TLS 1.3 uses a number of master secrets:
@@ -1370,45 +1400,52 @@ tls13_SendHelloRetryRequest(sslSocket *s
     if (ss->ssl3.hs.helloRetry) {
         FATAL_ERROR(ss, SSL_ERROR_BAD_2ND_CLIENT_HELLO, illegal_parameter);
         return SECFailure;
     }
 
     ssl_GetXmitBufLock(ss);
     rv = ssl3_AppendHandshakeHeader(ss, hello_retry_request,
                                     2 +     /* version */
-                                        2 + /* cipher suite */
-                                        2 + /* group */
-                                        2 /* (empty) extensions */);
+                                        2 + /* extension length */
+                                        2 + /* group extension id */
+                                        2 + /* group extension length */
+                                        2 /* group */);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
         goto loser;
     }
 
     rv = ssl3_AppendHandshakeNumber(
         ss, tls13_EncodeDraftVersion(ss->version), 2);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
         goto loser;
     }
 
-    rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.cipher_suite, 2);
+    /* Length of extensions. */
+    rv = ssl3_AppendHandshakeNumber(ss, 2 + 2 + 2, 2);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
         goto loser;
     }
 
-    rv = ssl3_AppendHandshakeNumber(ss, selectedGroup->name, 2);
+    /* Key share extension - currently the only reason we send this. */
+    rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_key_share_xtn, 2);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
         goto loser;
     }
-
-    /* Send an empty extensions block. */
-    rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
+    /* Key share extension length. */
+    rv = ssl3_AppendHandshakeNumber(ss, 2, 2);
+    if (rv != SECSuccess) {
+        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+        goto loser;
+    }
+    rv = ssl3_AppendHandshakeNumber(ss, selectedGroup->name, 2);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
         goto loser;
     }
 
     rv = ssl3_FlushHandshake(ss, 0);
     if (rv != SECSuccess) {
         goto loser; /* error code set by ssl3_FlushHandshake */
@@ -1573,17 +1610,16 @@ tls13_SendCertificateRequest(sslSocket *
 }
 
 static SECStatus
 tls13_HandleHelloRetryRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 {
     SECStatus rv;
     PRInt32 tmp;
     PRUint32 version;
-    const sslNamedGroupDef *group;
 
     SSL_TRC(3, ("%d: TLS13[%d]: handle hello retry request",
                 SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     /* Client */
@@ -1614,55 +1650,34 @@ tls13_HandleHelloRetryRequest(sslSocket 
     }
     version = tls13_DecodeDraftVersion((PRUint16)tmp);
     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;
     }
 
-    /* Ignore the cipher suite, it's going to be removed soon anyway. */
-    tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
-    if (tmp < 0) {
-        return SECFailure; /* error code already set */
-    }
-
-    tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
-    if (tmp < 0) {
-        return SECFailure; /* error code already set */
-    }
-    group = ssl_LookupNamedGroup((SSLNamedGroup)tmp);
-    if (!ssl_NamedGroupEnabled(ss, group)) {
-        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST,
-                    illegal_parameter);
-        return SECFailure;
-    }
-
     tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
     if (tmp < 0) {
         return SECFailure; /* error code already set */
     }
-    /* Ignore the extensions. */
-    if (tmp != length) {
+    /* Extensions must be non-empty and use the remainder of the message.
+     * This means that a HelloRetryRequest cannot be a no-op: we must have an
+     * extension, it must be one that we understand and recognize as being valid
+     * for HelloRetryRequest, and all the extensions we permit cause us to
+     * modify our ClientHello in some way. */
+    if (!tmp || tmp != length) {
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST,
                     decode_error);
         return SECFailure;
     }
 
-    /* If there is already a share for the requested group, abort. */
-    if (ssl_LookupEphemeralKeyPair(ss, group)) {
-        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST,
-                    illegal_parameter);
-        return SECFailure;
-    }
-
-    rv = tls13_CreateKeyShare(ss, group);
+    rv = ssl3_HandleExtensions(ss, &b, &length, hello_retry_request);
     if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SEC_ERROR_KEYGEN_FAIL, internal_error);
-        return SECFailure;
+        return SECFailure; /* Error code set below */
     }
 
     ss->ssl3.hs.helloRetry = PR_TRUE;
 
     ssl_GetXmitBufLock(ss);
     rv = ssl3_SendClientHello(ss, client_hello_retry);
     ssl_ReleaseXmitBufLock(ss);
     if (rv != SECSuccess) {
@@ -1808,17 +1823,17 @@ tls13_SendEncryptedServerSequence(sslSoc
 
         svrPrivKey = ss->sec.serverCert->serverKeyPair->privKey;
         rv = tls13_SendCertificateVerify(ss, svrPrivKey);
         if (rv != SECSuccess) {
             return SECFailure; /* err code is set. */
         }
     }
 
-    rv = tls13_SendFinished(ss, ss->ssl3.hs.hsTrafficSecret);
+    rv = tls13_SendFinished(ss, ss->ssl3.hs.serverHsTrafficSecret);
     if (rv != SECSuccess) {
         return SECFailure; /* error code is set. */
     }
 
     return SECSuccess;
 }
 
 /* Called from:  ssl3_HandleClientHello */
@@ -2243,22 +2258,39 @@ loser:
 }
 
 /*
  *    Derive-Secret(Secret, Label, Messages) =
  *       HKDF-Expand-Label(Secret, Label,
  *                         Hash(Messages) + Hash(resumption_context), L))
  */
 static SECStatus
-tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key, const char *label,
+tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key,
+                   const char *prefix,
+                   const char *suffix,
                    const TLS13CombinedHash *hashes,
                    PK11SymKey **dest)
 {
     SECStatus rv;
     TLS13CombinedHash hashesTmp;
+    char buf[100];
+    const char *label;
+
+    if (prefix) {
+        if ((strlen(prefix) + strlen(suffix) + 2) > sizeof(buf)) {
+            PORT_Assert(0);
+            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+            return SECFailure;
+        }
+        (void)PR_snprintf(buf, sizeof(buf), "%s %s",
+                          prefix, suffix);
+        label = buf;
+    } else {
+        label = suffix;
+    }
 
     SSL_TRC(3, ("%d: TLS13[%d]: deriving secret '%s'",
                 SSL_GETPID(), ss->fd, label));
     if (!hashes) {
         rv = tls13_ComputeHandshakeHashes(ss, &hashesTmp);
         if (rv != SECSuccess) {
             PORT_Assert(0); /* Should never fail */
             ssl_MapLowLevelError(SEC_ERROR_LIBRARY_FAILURE);
@@ -2289,96 +2321,96 @@ tls13_DeriveTrafficKeys(sslSocket *ss, s
     size_t keySize = spec->cipher_def->key_size;
     size_t ivSize = spec->cipher_def->iv_size +
                     spec->cipher_def->explicit_nonce_size; /* This isn't always going to
                                                               * work, but it does for
                                                               * AES-GCM */
     CK_MECHANISM_TYPE bulkAlgorithm = ssl3_Alg2Mech(spec->cipher_def->calg);
     PK11SymKey **prkp = NULL;
     PK11SymKey *prk = NULL;
+    PRBool clientKey;
+    ssl3KeyMaterial *target;
     const char *phase;
     char label[256]; /* Arbitrary buffer large enough to hold the label */
     SECStatus rv;
 
+    if (ss->sec.isServer ^ (direction == CipherSpecWrite)) {
+        clientKey = PR_TRUE;
+        target = &spec->client;
+    } else {
+        clientKey = PR_FALSE;
+        target = &spec->server;
+    }
+
 #define FORMAT_LABEL(phase_, purpose_)                                              \
     do {                                                                            \
         PRUint32 n = PR_snprintf(label, sizeof(label), "%s, %s", phase_, purpose_); \
         /* Check for getting close. */                                              \
         if ((n + 1) >= sizeof(label)) {                                             \
             LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);                               \
             PORT_Assert(0);                                                         \
             goto loser;                                                             \
         }                                                                           \
     } while (0)
-#define EXPAND_TRAFFIC_KEY(purpose_, target_)                               \
-    do {                                                                    \
-        FORMAT_LABEL(phase, purpose_);                                      \
-        rv = tls13_HkdfExpandLabel(prk, tls13_GetHash(ss),                  \
-                                   NULL, 0,                                 \
-                                   label, strlen(label),                    \
-                                   bulkAlgorithm, keySize, &spec->target_); \
-        if (rv != SECSuccess) {                                             \
-            LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);                       \
-            PORT_Assert(0);                                                 \
-            goto loser;                                                     \
-        }                                                                   \
-    } while (0)
-
-#define EXPAND_TRAFFIC_IV(purpose_, target_)                  \
-    do {                                                      \
-        FORMAT_LABEL(phase, purpose_);                        \
-        rv = tls13_HkdfExpandLabelRaw(prk, tls13_GetHash(ss), \
-                                      NULL, 0,                \
-                                      label, strlen(label),   \
-                                      spec->target_, ivSize); \
-        if (rv != SECSuccess) {                               \
-            LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);         \
-            PORT_Assert(0);                                   \
-            goto loser;                                       \
-        }                                                     \
-    } while (0)
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     switch (type) {
         case TrafficKeyEarlyHandshake:
+            PORT_Assert(clientKey);
             phase = kHkdfPhaseEarlyHandshakeDataKeys;
-            prkp = &ss->ssl3.hs.earlyTrafficSecret;
+            prkp = &ss->ssl3.hs.clientEarlyTrafficSecret;
             break;
         case TrafficKeyEarlyApplicationData:
+            PORT_Assert(clientKey);
             phase = kHkdfPhaseEarlyApplicationDataKeys;
-            prkp = &ss->ssl3.hs.earlyTrafficSecret;
+            prkp = &ss->ssl3.hs.clientEarlyTrafficSecret;
             break;
         case TrafficKeyHandshake:
             phase = kHkdfPhaseHandshakeKeys;
-            prkp = &ss->ssl3.hs.hsTrafficSecret;
+            prkp = clientKey ? &ss->ssl3.hs.clientHsTrafficSecret : &ss->ssl3.hs.serverHsTrafficSecret;
             break;
         case TrafficKeyApplicationData:
             phase = kHkdfPhaseApplicationDataKeys;
-            prkp = &ss->ssl3.hs.trafficSecret;
+            prkp = clientKey ? &ss->ssl3.hs.clientTrafficSecret : &ss->ssl3.hs.serverTrafficSecret;
             break;
         default:
             LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
             PORT_Assert(0);
             return SECFailure;
     }
     PORT_Assert(prkp != NULL);
     prk = *prkp;
 
     SSL_TRC(3, ("%d: TLS13[%d]: deriving traffic keys phase='%s'",
                 SSL_GETPID(), ss->fd, phase));
     PORT_Assert(phase);
     spec->phase = phase;
 
-    if ((direction == CipherSpecWrite) ^ (ss->sec.isServer)) {
-        EXPAND_TRAFFIC_KEY(kHkdfPurposeClientWriteKey, client.write_key);
-        EXPAND_TRAFFIC_IV(kHkdfPurposeClientWriteIv, client.write_iv);
-    } else {
-        EXPAND_TRAFFIC_KEY(kHkdfPurposeServerWriteKey, server.write_key);
-        EXPAND_TRAFFIC_IV(kHkdfPurposeServerWriteIv, server.write_iv);
+    FORMAT_LABEL(phase, kHkdfPurposeKey);
+    rv = tls13_HkdfExpandLabel(prk, tls13_GetHash(ss),
+                               NULL, 0,
+                               label, strlen(label),
+                               bulkAlgorithm, keySize,
+                               &target->write_key);
+    if (rv != SECSuccess) {
+        LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
+        PORT_Assert(0);
+        goto loser;
+    }
+
+    FORMAT_LABEL(phase, kHkdfPurposeIv);
+    rv = tls13_HkdfExpandLabelRaw(prk, tls13_GetHash(ss),
+                                  NULL, 0,
+                                  label, strlen(label),
+                                  target->write_iv, ivSize);
+    if (rv != SECSuccess) {
+        LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
+        PORT_Assert(0);
+        goto loser;
     }
 
     if (deleteSecret) {
         PK11_FreeSymKey(prk);
         *prkp = NULL;
     }
     return SECSuccess;
 
@@ -3030,17 +3062,17 @@ tls13_ComputeFinished(sslSocket *ss, PK1
                       PRBool sending, PRUint8 *output, unsigned int *outputLen,
                       unsigned int maxOutputLen)
 {
     SECStatus rv;
     PK11Context *hmacCtx = NULL;
     CK_MECHANISM_TYPE macAlg = tls13_GetHmacMechanism(ss);
     SECItem param = { siBuffer, NULL, 0 };
     unsigned int outputLenUint;
-    const char *label = (ss->sec.isServer ^ sending) ? kHkdfLabelClientFinishedSecret : kHkdfLabelServerFinishedSecret;
+    const char *label = kHkdfLabelFinishedSecret;
     PK11SymKey *secret = NULL;
 
     PORT_Assert(baseKey);
     PRINT_BUF(50, (NULL, "Handshake hash", hashes->hash, hashes->len));
 
     /* Now derive the appropriate finished secret from the base secret. */
     rv = tls13_HkdfExpandLabel(baseKey,
                                tls13_GetHash(ss),
@@ -3181,17 +3213,17 @@ tls13_ClientHandleFinished(sslSocket *ss
                 SSL_GETPID(), ss->fd));
 
     rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_FINISHED,
                               wait_finished);
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
-    rv = tls13_VerifyFinished(ss, ss->ssl3.hs.hsTrafficSecret,
+    rv = tls13_VerifyFinished(ss, ss->ssl3.hs.serverHsTrafficSecret,
                               b, length, hashes);
     if (rv != SECSuccess)
         return SECFailure;
 
     return tls13_SendClientSecondRound(ss);
 }
 
 static SECStatus
@@ -3209,19 +3241,19 @@ tls13_ServerHandleFinished(sslSocket *ss
 
     rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_FINISHED, wait_finished,
                               wait_0rtt_finished);
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
     if (TLS13_IN_HS_STATE(ss, wait_finished)) {
-        secret = ss->ssl3.hs.hsTrafficSecret;
+        secret = ss->ssl3.hs.clientHsTrafficSecret;
     } else {
-        secret = ss->ssl3.hs.earlyTrafficSecret;
+        secret = ss->ssl3.hs.clientEarlyTrafficSecret;
     }
 
     rv = tls13_VerifyFinished(ss, secret, b, length, hashes);
     if (rv != SECSuccess)
         return SECFailure;
 
     if (TLS13_IN_HS_STATE(ss, wait_0rtt_finished)) {
         /* Reset the hashes. */
@@ -3282,18 +3314,20 @@ tls13_FinishHandshake(sslSocket *ss)
     rv = tls13_ComputeFinalSecrets(ss);
     if (rv != SECSuccess)
         return SECFailure;
 
     /* The first handshake is now completed. */
     ss->handshake = NULL;
 
     /* Don't need this. */
-    PK11_FreeSymKey(ss->ssl3.hs.hsTrafficSecret);
-    ss->ssl3.hs.hsTrafficSecret = NULL;
+    PK11_FreeSymKey(ss->ssl3.hs.clientHsTrafficSecret);
+    ss->ssl3.hs.clientHsTrafficSecret = NULL;
+    PK11_FreeSymKey(ss->ssl3.hs.serverHsTrafficSecret);
+    ss->ssl3.hs.serverHsTrafficSecret = NULL;
 
     TLS13_SET_HS_STATE(ss, idle_handshake);
 
     ssl_FinishHandshake(ss);
 
     return SECSuccess;
 }
 
@@ -3384,17 +3418,17 @@ tls13_SendClientSecondRound(sslSocket *s
         rv = tls13_SendCertificateVerify(ss, ss->ssl3.clientPrivateKey);
         SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
         ss->ssl3.clientPrivateKey = NULL;
         if (rv != SECSuccess) {
             goto loser; /* err is set. */
         }
     }
 
-    rv = tls13_SendFinished(ss, ss->ssl3.hs.hsTrafficSecret);
+    rv = tls13_SendFinished(ss, ss->ssl3.hs.clientHsTrafficSecret);
     if (rv != SECSuccess) {
         goto loser; /* err code was set. */
     }
     rv = ssl3_FlushHandshake(ss, IS_DTLS(ss) ? ssl_SEND_FLAG_NO_RETRANSMIT : 0);
     if (rv != SECSuccess) {
         goto loser;
     }
 
@@ -3664,16 +3698,18 @@ tls13_HandleNewSessionTicket(sslSocket *
 
     return SECSuccess;
 }
 
 typedef enum {
     ExtensionNotUsed,
     ExtensionClientOnly,
     ExtensionSendClear,
+    ExtensionSendClearOrHrr,
+    ExtensionSendHrr,
     ExtensionSendEncrypted,
     ExtensionNewSessionTicket
 } Tls13ExtensionStatus;
 
 static const struct {
     PRUint16 ex_value;
     Tls13ExtensionStatus status;
 } KnownExtensions[] = {
@@ -3681,33 +3717,35 @@ static const struct {
     { ssl_supported_groups_xtn, ExtensionSendEncrypted },
     { ssl_ec_point_formats_xtn, ExtensionNotUsed },
     { ssl_signature_algorithms_xtn, ExtensionSendClear },
     { ssl_use_srtp_xtn, ExtensionSendEncrypted },
     { ssl_app_layer_protocol_xtn, ExtensionSendEncrypted },
     { ssl_padding_xtn, ExtensionNotUsed },
     { ssl_extended_master_secret_xtn, ExtensionNotUsed },
     { ssl_session_ticket_xtn, ExtensionClientOnly },
-    { ssl_tls13_key_share_xtn, ExtensionSendClear },
+    { ssl_tls13_key_share_xtn, ExtensionSendClearOrHrr },
     { 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, ExtensionSendEncrypted },
     { ssl_cert_status_xtn, ExtensionSendEncrypted },
-    { ssl_tls13_ticket_early_data_info_xtn, ExtensionNewSessionTicket }
+    { ssl_tls13_ticket_early_data_info_xtn, ExtensionNewSessionTicket },
+    { ssl_tls13_cookie_xtn, ExtensionSendHrr }
 };
 
 PRBool
 tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message)
 {
     unsigned int i;
 
     PORT_Assert((message == client_hello) ||
                 (message == server_hello) ||
+                (message == hello_retry_request) ||
                 (message == encrypted_extensions) ||
                 (message == new_session_ticket));
 
     for (i = 0; i < PR_ARRAY_SIZE(KnownExtensions); i++) {
         if (KnownExtensions[i].ex_value == extension)
             break;
     }
     if (i == PR_ARRAY_SIZE(KnownExtensions)) {
@@ -3719,16 +3757,23 @@ tls13_ExtensionAllowed(PRUint16 extensio
     switch (KnownExtensions[i].status) {
         case ExtensionNotUsed:
             return PR_FALSE;
         case ExtensionClientOnly:
             return message == client_hello;
         case ExtensionSendClear:
             return message == client_hello ||
                    message == server_hello;
+        case ExtensionSendClearOrHrr:
+            return message == client_hello ||
+                   message == server_hello ||
+                   message == hello_retry_request;
+        case ExtensionSendHrr:
+            return message == client_hello ||
+                   message == hello_retry_request;
         case ExtensionSendEncrypted:
             return message == client_hello ||
                    message == encrypted_extensions;
         case ExtensionNewSessionTicket:
             return message == new_session_ticket;
     }
 
     PORT_Assert(0);
@@ -4013,17 +4058,17 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss
 
     rv = tls13_SetCipherSpec(ss, TrafficKeyEarlyHandshake,
                              CipherSpecWrite, PR_FALSE);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
         return SECFailure;
     }
 
-    rv = tls13_SendFinished(ss, ss->ssl3.hs.earlyTrafficSecret);
+    rv = tls13_SendFinished(ss, ss->ssl3.hs.clientEarlyTrafficSecret);
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
     /* Restore the handshake hashes to where they were before we
      * sent Finished. */
     ss->ssl3.hs.messages.len = bufferLen;
 
--- a/security/nss/lib/ssl/tls13con.h
+++ b/security/nss/lib/ssl/tls13con.h
@@ -47,16 +47,17 @@ SECStatus tls13_HandleClientHelloPart2(s
                                        const SECItem *suites,
                                        sslSessionID *sid);
 SECStatus tls13_HandleServerHelloPart2(sslSocket *ss);
 SECStatus tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
                                                 PRUint32 length,
                                                 SSL3Hashes *hashesPtr);
 void tls13_DestroyKeyShareEntry(TLS13KeyShareEntry *entry);
 void tls13_DestroyKeyShares(PRCList *list);
+SECStatus tls13_CreateKeyShare(sslSocket *ss, const sslNamedGroupDef *groupDef);
 void tls13_DestroyEarlyData(PRCList *list);
 void tls13_CipherSpecAddRef(ssl3CipherSpec *spec);
 void tls13_CipherSpecRelease(ssl3CipherSpec *spec);
 void tls13_DestroyCipherSpecs(PRCList *list);
 PRBool tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message);
 SECStatus tls13_ProtectRecord(sslSocket *ss,
                               ssl3CipherSpec *cwSpec,
                               SSL3ContentType type,
--- a/security/nss/lib/util/secasn1e.c
+++ b/security/nss/lib/util/secasn1e.c
@@ -1415,18 +1415,20 @@ static void
 sec_asn1e_encode_item_store(void *arg, const char *buf, unsigned long len,
                             int depth, SEC_ASN1EncodingPart data_kind)
 {
     SECItem *dest;
 
     dest = (SECItem *)arg;
     PORT_Assert(dest != NULL);
 
-    PORT_Memcpy(dest->data + dest->len, buf, len);
-    dest->len += len;
+    if (len > 0) {
+        PORT_Memcpy(dest->data + dest->len, buf, len);
+        dest->len += len;
+    }
 }
 
 /*
  * Allocate an entire SECItem, or just the data part of it, to hold
  * "len" bytes of stuff.  Allocate from the given pool, if specified,
  * otherwise just do a vanilla PORT_Alloc.
  *
  * XXX This seems like a reasonable general-purpose function (for SECITEM_)?
--- a/security/nss/lib/util/utf8.c
+++ b/security/nss/lib/util/utf8.c
@@ -317,25 +317,28 @@ sec_port_ucs2_utf8_conversion_function(
             return PR_FALSE;
         }
 
         for (i = 0; i < inBufLen; i += 2) {
             if ((inBuf[i + H_0] == 0x00) && ((inBuf[i + H_1] & 0x80) == 0x00))
                 len += 1;
             else if (inBuf[i + H_0] < 0x08)
                 len += 2;
-            else if (((inBuf[i + 0 + H_0] & 0xFC) == 0xD8)) {
+            else if (((inBuf[i + H_0] & 0xFC) == 0xD8)) {
                 if (((inBufLen - i) > 2) && ((inBuf[i + 2 + H_0] & 0xFC) == 0xDC)) {
                     i += 2;
                     len += 4;
                 } else {
                     return PR_FALSE;
                 }
-            } else
+            } else if ((inBuf[i + H_0] & 0xFC) == 0xDC) {
+                return PR_FALSE;
+            } else {
                 len += 3;
+            }
         }
 
         if (len > maxOutBufLen) {
             *outBufLen = len;
             return PR_FALSE;
         }
 
         len = 0;