Bug 1305970, Upgrade Firefox 52 to NSS 3.28, landing RC0, a=jcristau
authorKai Engert <kaie@kuix.de>
Wed, 21 Dec 2016 13:07:37 +0100
changeset 353091 e6ec59a1128a587af3d45b9d529105cee4e1205d
parent 353090 81a1f25491a65bdf41584a261a3d44607af9ac95
child 353092 d6234c629f13559d45ce37261e2ada413c0097f7
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjcristau
bugs1305970
milestone52.0a2
Bug 1305970, Upgrade Firefox 52 to NSS 3.28, landing RC0, a=jcristau
security/nss/TAG-INFO
security/nss/cmd/certutil/certutil.c
security/nss/cmd/crlutil/crlutil.c
security/nss/cmd/smimetools/cmsutil.c
security/nss/coreconf/coreconf.dep
security/nss/fuzz/clone_corpus.sh
security/nss/fuzz/clone_libfuzzer.sh
security/nss/fuzz/fuzz.gyp
security/nss/fuzz/git-copy.sh
security/nss/fuzz/libFuzzer/libFuzzer.gyp
security/nss/gtests/ssl_gtest/libssl_internals.c
security/nss/gtests/ssl_gtest/libssl_internals.h
security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc
security/nss/gtests/ssl_gtest/tls_agent.cc
security/nss/gtests/ssl_gtest/tls_agent.h
security/nss/lib/certhigh/certvfy.c
security/nss/lib/libpkix/include/pkix_errorstrings.h
security/nss/lib/libpkix/pkix/top/pkix_build.c
security/nss/lib/nss/nss.h
security/nss/lib/pk11wrap/pk11pars.c
security/nss/lib/smime/cmssigdata.c
security/nss/lib/softoken/softkver.h
security/nss/lib/ssl/ssl.def
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3ext.c
security/nss/lib/ssl/ssl3gthr.c
security/nss/lib/ssl/ssl3prot.h
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/sslproto.h
security/nss/lib/ssl/sslsock.c
security/nss/lib/ssl/sslt.h
security/nss/lib/ssl/tls13con.c
security/nss/lib/ssl/tls13exthandle.c
security/nss/lib/ssl/tls13exthandle.h
security/nss/lib/util/nssutil.h
security/nss/tests/libpkix/certs/PayPalEE.cert
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-6c26f0cd19ba
+NSS_3_28_RC0
--- a/security/nss/cmd/certutil/certutil.c
+++ b/security/nss/cmd/certutil/certutil.c
@@ -44,17 +44,17 @@
 
 #define GEN_BREAK(e) \
     rv = e;          \
     break;
 
 char *progName;
 
 static CERTCertificateRequest *
-GetCertRequest(const SECItem *reqDER)
+GetCertRequest(const SECItem *reqDER, void *pwarg)
 {
     CERTCertificateRequest *certReq = NULL;
     CERTSignedData signedData;
     PLArenaPool *arena = NULL;
     SECStatus rv;
 
     do {
         arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
@@ -78,17 +78,17 @@ GetCertRequest(const SECItem *reqDER)
             break;
         }
         rv = SEC_ASN1DecodeItem(arena, certReq,
                                 SEC_ASN1_GET(CERT_CertificateRequestTemplate), &signedData.data);
         if (rv) {
             break;
         }
         rv = CERT_VerifySignedDataWithPublicKeyInfo(&signedData,
-                                                    &certReq->subjectPublicKeyInfo, NULL /* wincx */);
+                                                    &certReq->subjectPublicKeyInfo, pwarg);
     } while (0);
 
     if (rv) {
         SECU_PrintError(progName, "bad certificate request\n");
         if (arena) {
             PORT_FreeArena(arena, PR_FALSE);
         }
         certReq = NULL;
@@ -1995,17 +1995,17 @@ CreateCert(
     void *extHandle = NULL;
     CERTCertificate *subjectCert = NULL;
     CERTCertificateRequest *certReq = NULL;
     SECStatus rv = SECSuccess;
     CERTCertExtension **CRexts;
 
     do {
         /* Create a certrequest object from the input cert request der */
-        certReq = GetCertRequest(certReqDER);
+        certReq = GetCertRequest(certReqDER, pwarg);
         if (certReq == NULL) {
             GEN_BREAK(SECFailure)
         }
 
         subjectCert = MakeV1Cert(handle, certReq, issuerNickName, selfsign,
                                  serialNumber, warpmonths, validityMonths);
         if (subjectCert == NULL) {
             GEN_BREAK(SECFailure)
--- a/security/nss/cmd/crlutil/crlutil.c
+++ b/security/nss/cmd/crlutil/crlutil.c
@@ -368,17 +368,17 @@ loser:
         CERT_DestroyCertificate(cert);
     return cert;
 }
 
 static CERTSignedCrl *
 CreateModifiedCRLCopy(PLArenaPool *arena, CERTCertDBHandle *certHandle,
                       CERTCertificate **cert, char *certNickName,
                       PRFileDesc *inFile, PRInt32 decodeOptions,
-                      PRInt32 importOptions)
+                      PRInt32 importOptions, secuPWData *pwdata)
 {
     SECItem crlDER = { 0, NULL, 0 };
     CERTSignedCrl *signCrl = NULL;
     CERTSignedCrl *modCrl = NULL;
     PLArenaPool *modArena = NULL;
     SECStatus rv = SECSuccess;
 
     if (!arena || !certHandle || !certNickName) {
@@ -414,17 +414,17 @@ CreateModifiedCRLCopy(PLArenaPool *arena
             /* If caCert is a v2 certificate, make sure that it
              * can be used for crl signing purpose */
             *cert = FindSigningCert(certHandle, modCrl, NULL);
             if (!*cert) {
                 goto loser;
             }
 
             rv = CERT_VerifySignedData(&modCrl->signatureWrap, *cert,
-                                       PR_Now(), NULL);
+                                       PR_Now(), pwdata);
             if (rv != SECSuccess) {
                 SECU_PrintError(progName, "fail to verify signed data\n");
                 goto loser;
             }
         }
     } else {
         modCrl = FindCRL(certHandle, certNickName, SEC_CRL_TYPE);
         if (!modCrl) {
@@ -702,17 +702,18 @@ GenerateCRL(CERTCertDBHandle *certHandle
     arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
     if (!arena) {
         SECU_PrintError(progName, "fail to allocate memory\n");
         return SECFailure;
     }
 
     if (modifyFlag == PR_TRUE) {
         signCrl = CreateModifiedCRLCopy(arena, certHandle, &cert, certNickName,
-                                        inFile, decodeOptions, importOptions);
+                                        inFile, decodeOptions, importOptions,
+                                        pwdata);
         if (signCrl == NULL) {
             rv = SECFailure;
             goto loser;
         }
     }
 
     if (!cert) {
         cert = FindSigningCert(certHandle, signCrl, certNickName);
--- a/security/nss/cmd/smimetools/cmsutil.c
+++ b/security/nss/cmd/smimetools/cmsutil.c
@@ -468,16 +468,17 @@ signed_data(struct signOptionsStr *signO
     if (signerinfo == NULL) {
         fprintf(stderr, "ERROR: cannot create CMS signerInfo object.\n");
         goto loser;
     }
     if (cms_verbose) {
         fprintf(stderr,
                 "Created CMS message, added signed data w/ signerinfo\n");
     }
+    signerinfo->cmsg->pwfn_arg = pwcb_arg;
     /* we want the cert chain included for this one */
     if (NSS_CMSSignerInfo_IncludeCerts(signerinfo, NSSCMSCM_CertChain,
                                        signOptions->options->certUsage) !=
         SECSuccess) {
         fprintf(stderr, "ERROR: cannot find cert chain.\n");
         goto loser;
     }
     if (cms_verbose) {
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/security/nss/fuzz/clone_corpus.sh
+++ b/security/nss/fuzz/clone_corpus.sh
@@ -1,11 +1,4 @@
 #!/bin/sh
 
-cd $(dirname $0)
-
-mkdir tmp/
-git clone --no-checkout --depth 1 https://github.com/mozilla/nss-fuzzing-corpus tmp/
-(cd tmp && git reset --hard master)
-
-mkdir -p corpus
-cp -r tmp/* corpus
-rm -Rf tmp/
+d=$(dirname $0)
+exec $d/git-copy.sh https://github.com/mozilla/nss-fuzzing-corpus master $d/corpus
--- a/security/nss/fuzz/clone_libfuzzer.sh
+++ b/security/nss/fuzz/clone_libfuzzer.sh
@@ -1,11 +1,4 @@
 #!/bin/sh
 
-cd $(dirname $0)
-
-mkdir tmp/
-git clone --no-checkout --depth 1 https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer tmp/
-(cd tmp && git reset --hard 1b543d6e5073b56be214394890c9193979a3d7e1)
-
-mkdir -p libFuzzer
-cp tmp/*.cpp tmp/*.h tmp/*.def libFuzzer
-rm -Rf tmp/
+d=$(dirname $0)
+exec $d/git-copy.sh https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer 1b543d6e5073b56be214394890c9193979a3d7e1 $d/libFuzzer
--- a/security/nss/fuzz/fuzz.gyp
+++ b/security/nss/fuzz/fuzz.gyp
@@ -3,26 +3,59 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 {
   'includes': [
     '../coreconf/config.gypi',
     '../cmd/platlibs.gypi'
   ],
   'targets': [
     {
+      'target_name': 'libFuzzer',
+      'type': 'static_library',
+      'sources': [
+        'libFuzzer/FuzzerCrossOver.cpp',
+        'libFuzzer/FuzzerDriver.cpp',
+        'libFuzzer/FuzzerExtFunctionsDlsym.cpp',
+        'libFuzzer/FuzzerExtFunctionsWeak.cpp',
+        'libFuzzer/FuzzerIO.cpp',
+        'libFuzzer/FuzzerLoop.cpp',
+        'libFuzzer/FuzzerMutate.cpp',
+        'libFuzzer/FuzzerSHA1.cpp',
+        'libFuzzer/FuzzerTracePC.cpp',
+        'libFuzzer/FuzzerTraceState.cpp',
+        'libFuzzer/FuzzerUtil.cpp',
+        'libFuzzer/FuzzerUtilDarwin.cpp',
+        'libFuzzer/FuzzerUtilLinux.cpp',
+      ],
+      'cflags': [
+        '-O2',
+      ],
+      'cflags/': [
+        ['exclude', '-fsanitize='],
+        ['exclude', '-fsanitize-'],
+      ],
+      'xcode_settings': {
+        'GCC_OPTIMIZATION_LEVEL': '2', # -O2
+        'OTHER_CFLAGS/': [
+          ['exclude', '-fsanitize='],
+          ['exclude', '-fsanitize-'],
+        ],
+      },
+    },
+    {
       'target_name': 'nssfuzz',
       'type': 'executable',
       'sources': [
         'nssfuzz.cc',
         'pkcs8_target.cc',
         'quickder_targets.cc',
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
-        '<(DEPTH)/fuzz/libFuzzer/libFuzzer.gyp:libFuzzer'
+        'libFuzzer',
       ]
     }
   ],
   'target_defaults': {
     'include_dirs': [
       'libFuzzer',
     ],
   },
new file mode 100755
--- /dev/null
+++ b/security/nss/fuzz/git-copy.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+set -e
+
+if [ $# -lt 3 ]; then
+  echo "Usage: $0 <repo> <branch> <directory>" 1>&2
+  exit 2
+fi
+
+REPO=$1
+COMMIT=$2
+DIR=$3
+
+echo "Copy '$COMMIT' from '$REPO' to '$DIR'"
+if [ -f $DIR/.git-copy ]; then
+  CURRENT=$(cat $DIR/.git-copy)
+  if [ $(echo -n $COMMIT | wc -c) != "40" ]; then
+    ACTUAL=$(git ls-remote $REPO $COMMIT | cut -c 1-40 -)
+  else
+    ACTUAL=$COMMIT
+  fi
+  if [ CURRENT = ACTUAL ]; then
+    echo "Up to date."
+  fi
+fi
+
+mkdir -p $DIR
+git -C $DIR init -q
+git -C $DIR fetch -q --depth=1 $REPO $COMMIT:git-copy-tmp
+git -C $DIR reset --hard git-copy-tmp
+git -C $DIR show-ref HEAD | cut -c 1-40 - > $DIR/.git-copy
+rm -rf $DIR/.git
deleted file mode 100644
--- a/security/nss/fuzz/libFuzzer/libFuzzer.gyp
+++ /dev/null
@@ -1,43 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-{
-  'includes': [
-    '../../coreconf/config.gypi'
-  ],
-  'targets': [
-    {
-      'target_name': 'libFuzzer',
-      'type': 'static_library',
-      'sources': [
-        'FuzzerCrossOver.cpp',
-        'FuzzerDriver.cpp',
-        'FuzzerExtFunctionsDlsym.cpp',
-        'FuzzerExtFunctionsWeak.cpp',
-        'FuzzerIO.cpp',
-        'FuzzerLoop.cpp',
-        'FuzzerMutate.cpp',
-        'FuzzerSHA1.cpp',
-        'FuzzerTracePC.cpp',
-        'FuzzerTraceState.cpp',
-        'FuzzerUtil.cpp',
-        'FuzzerUtilDarwin.cpp',
-        'FuzzerUtilLinux.cpp',
-      ],
-      'cflags': [
-        '-O2',
-      ],
-      'cflags/': [
-        ['exclude', '-fsanitize='],
-        ['exclude', '-fsanitize-'],
-      ],
-      'xcode_settings': {
-        'GCC_OPTIMIZATION_LEVEL': '2', # -O2
-        'OTHER_CFLAGS/': [
-          ['exclude', '-fsanitize='],
-          ['exclude', '-fsanitize-'],
-        ],
-      },
-    }
-  ],
-}
--- a/security/nss/gtests/ssl_gtest/libssl_internals.c
+++ b/security/nss/gtests/ssl_gtest/libssl_internals.c
@@ -308,8 +308,33 @@ SECStatus SSLInt_AdvanceWriteSeqByAWindo
 }
 
 SSLKEAType SSLInt_GetKEAType(SSLNamedGroup group) {
   const sslNamedGroupDef *groupDef = ssl_LookupNamedGroup(group);
   if (!groupDef) return ssl_kea_null;
 
   return groupDef->keaType;
 }
+
+SECStatus SSLInt_EnableShortHeaders(PRFileDesc *fd) {
+  sslSocket *ss;
+
+  ss = ssl_FindSocket(fd);
+  if (!ss) {
+    return SECFailure;
+  }
+
+  ss->opt.enableShortHeaders = PR_TRUE;
+  return SECSuccess;
+}
+
+SECStatus SSLInt_UsingShortHeaders(PRFileDesc *fd, PRBool *result) {
+  sslSocket *ss;
+
+  ss = ssl_FindSocket(fd);
+  if (!ss) {
+    return SECFailure;
+  }
+
+  *result = ss->ssl3.hs.shortHeaders;
+
+  return SECSuccess;
+}
--- a/security/nss/gtests/ssl_gtest/libssl_internals.h
+++ b/security/nss/gtests/ssl_gtest/libssl_internals.h
@@ -32,10 +32,12 @@ PRBool SSLInt_DamageEarlyTrafficSecret(P
 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);
 PRBool SSLInt_SendNewSessionTicket(PRFileDesc *fd);
 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);
+SECStatus SSLInt_EnableShortHeaders(PRFileDesc *fd);
+SECStatus SSLInt_UsingShortHeaders(PRFileDesc *fd, PRBool *result);
 
 #endif  // ndef libssl_internals_h_
--- a/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc
@@ -205,16 +205,24 @@ TEST_P(TlsConnectTls13, UnknownAlert) {
 TEST_P(TlsConnectTls13, AlertWrongLevel) {
   Connect();
   SSLInt_SendAlert(server_->ssl_fd(), kTlsAlertWarning,
                    kTlsAlertUnexpectedMessage);
   client_->ExpectReadWriteError();
   client_->WaitForErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT, 2000);
 }
 
+TEST_F(TlsConnectStreamTls13, NegotiateShortHeaders) {
+  client_->SetShortHeadersEnabled();
+  server_->SetShortHeadersEnabled();
+  client_->ExpectShortHeaders();
+  server_->ExpectShortHeaders();
+  Connect();
+}
+
 INSTANTIATE_TEST_CASE_P(GenericStream, TlsConnectGeneric,
                         ::testing::Combine(TlsConnectTestBase::kTlsModesStream,
                                            TlsConnectTestBase::kTlsVAll));
 INSTANTIATE_TEST_CASE_P(
     GenericDatagram, TlsConnectGeneric,
     ::testing::Combine(TlsConnectTestBase::kTlsModesDatagram,
                        TlsConnectTestBase::kTlsV11Plus));
 
--- a/security/nss/gtests/ssl_gtest/tls_agent.cc
+++ b/security/nss/gtests/ssl_gtest/tls_agent.cc
@@ -63,17 +63,18 @@ TlsAgent::TlsAgent(const std::string& na
       auth_certificate_hook_called_(false),
       handshake_callback_called_(false),
       error_code_(0),
       send_ctr_(0),
       recv_ctr_(0),
       expect_readwrite_error_(false),
       handshake_callback_(),
       auth_certificate_callback_(),
-      sni_callback_() {
+      sni_callback_(),
+      expect_short_headers_(false) {
   memset(&info_, 0, sizeof(info_));
   memset(&csinfo_, 0, sizeof(csinfo_));
   SECStatus rv = SSL_VersionRangeGetDefault(
       mode_ == STREAM ? ssl_variant_stream : ssl_variant_datagram, &vrange_);
   EXPECT_EQ(SECSuccess, rv);
 }
 
 TlsAgent::~TlsAgent() {
@@ -360,16 +361,23 @@ void TlsAgent::SetSessionCacheEnabled(bo
 void TlsAgent::Set0RttEnabled(bool en) {
   EXPECT_TRUE(EnsureTlsSetup());
 
   SECStatus rv =
       SSL_OptionSet(ssl_fd_, SSL_ENABLE_0RTT_DATA, en ? PR_TRUE : PR_FALSE);
   EXPECT_EQ(SECSuccess, rv);
 }
 
+void TlsAgent::SetShortHeadersEnabled() {
+  EXPECT_TRUE(EnsureTlsSetup());
+
+  SECStatus rv = SSLInt_EnableShortHeaders(ssl_fd_);
+  EXPECT_EQ(SECSuccess, rv);
+}
+
 void TlsAgent::SetVersionRange(uint16_t minver, uint16_t maxver) {
   vrange_.min = minver;
   vrange_.max = maxver;
 
   if (ssl_fd_) {
     SECStatus rv = SSL_VersionRangeSet(ssl_fd_, &vrange_);
     EXPECT_EQ(SECSuccess, rv);
   }
@@ -383,16 +391,18 @@ void TlsAgent::GetVersionRange(uint16_t*
 void TlsAgent::SetExpectedVersion(uint16_t version) {
   expected_version_ = version;
 }
 
 void TlsAgent::SetServerKeyBits(uint16_t bits) { server_key_bits_ = bits; }
 
 void TlsAgent::ExpectReadWriteError() { expect_readwrite_error_ = true; }
 
+void TlsAgent::ExpectShortHeaders() { expect_short_headers_ = true; }
+
 void TlsAgent::SetSignatureSchemes(const SSLSignatureScheme* schemes,
                                    size_t count) {
   EXPECT_TRUE(EnsureTlsSetup());
   EXPECT_LE(count, SSL_SignatureMaxCount());
   EXPECT_EQ(SECSuccess,
             SSL_SignatureSchemePrefSet(ssl_fd_, schemes,
                                        static_cast<unsigned int>(count)));
   EXPECT_EQ(SECFailure, SSL_SignatureSchemePrefSet(ssl_fd_, schemes, 0))
@@ -653,16 +663,20 @@ void TlsAgent::Connected() {
     // by DTLS for retransmission.
     PRInt32 expected = ((mode_ == DGRAM) && (role_ == CLIENT)) ? 3 : 2;
     EXPECT_EQ(expected, cipherSuites);
     if (expected != cipherSuites) {
       SSLInt_PrintTls13CipherSpecs(ssl_fd_);
     }
   }
 
+  PRBool short_headers;
+  rv = SSLInt_UsingShortHeaders(ssl_fd_, &short_headers);
+  EXPECT_EQ(SECSuccess, rv);
+  EXPECT_EQ((PRBool)expect_short_headers_, short_headers);
   SetState(STATE_CONNECTED);
 }
 
 void TlsAgent::EnableExtendedMasterSecret() {
   ASSERT_TRUE(EnsureTlsSetup());
 
   SECStatus rv =
       SSL_OptionSet(ssl_fd_, SSL_ENABLE_EXTENDED_MASTER_SECRET, PR_TRUE);
--- a/security/nss/gtests/ssl_gtest/tls_agent.h
+++ b/security/nss/gtests/ssl_gtest/tls_agent.h
@@ -116,25 +116,27 @@ class TlsAgent : public PollTarget {
   void RequestClientAuth(bool requireAuth);
   bool GetClientAuthCredentials(CERTCertificate** cert,
                                 SECKEYPrivateKey** priv) const;
 
   void ConfigureSessionCache(SessionResumptionMode mode);
   void SetSessionTicketsEnabled(bool en);
   void SetSessionCacheEnabled(bool en);
   void Set0RttEnabled(bool en);
+  void SetShortHeadersEnabled();
   void SetVersionRange(uint16_t minver, uint16_t maxver);
   void GetVersionRange(uint16_t* minver, uint16_t* maxver);
   void CheckPreliminaryInfo();
   void ResetPreliminaryInfo();
   void SetExpectedVersion(uint16_t version);
   void SetServerKeyBits(uint16_t bits);
   void ExpectReadWriteError();
   void EnableFalseStart();
   void ExpectResumption();
+  void ExpectShortHeaders();
   void SetSignatureSchemes(const SSLSignatureScheme* schemes, size_t count);
   void EnableAlpn(const uint8_t* val, size_t len);
   void CheckAlpn(SSLNextProtoState expected_state,
                  const std::string& expected = "") const;
   void EnableSrtp();
   void CheckSrtp() const;
   void CheckErrorCode(int32_t expected) const;
   void WaitForErrorCode(int32_t expected, uint32_t delay) const;
@@ -356,16 +358,17 @@ class TlsAgent : public PollTarget {
   SSLVersionRange vrange_;
   PRErrorCode error_code_;
   size_t send_ctr_;
   size_t recv_ctr_;
   bool expect_readwrite_error_;
   HandshakeCallbackFunction handshake_callback_;
   AuthCertificateCallbackFunction auth_certificate_callback_;
   SniCallbackFunction sni_callback_;
+  bool expect_short_headers_;
 };
 
 inline std::ostream& operator<<(std::ostream& stream,
                                 const TlsAgent::State& state) {
   return stream << TlsAgent::state_str(state);
 }
 
 class TlsAgentTestBase : public ::testing::Test {
--- a/security/nss/lib/certhigh/certvfy.c
+++ b/security/nss/lib/certhigh/certvfy.c
@@ -393,16 +393,152 @@ cert_AddToVerifyLog(CERTVerifyLog *log, 
     }
 
 #define LOG_ERROR(log, cert, depth, arg)                       \
     if (log != NULL) {                                         \
         cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \
                             (void *)(PRWord)arg);              \
     }
 
+/* /C=CN/O=WoSign CA Limited/CN=CA \xE6\xB2\x83\xE9\x80\x9A\xE6\xA0\xB9\xE8\xAF\x81\xE4\xB9\xA6
+ * Using a consistent naming convention, this would actually be called
+ * 'CA沃通根证书DN', but since GCC 6.2.1 apparently can't handle UTF-8
+ * identifiers, this will have to do.
+ */
+static const unsigned char CAWoSignRootDN[72] = {
+    0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+    0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11,
+    0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D,
+    0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03,
+    0x0C, 0x12, 0x43, 0x41, 0x20, 0xE6, 0xB2, 0x83, 0xE9, 0x80, 0x9A, 0xE6, 0xA0,
+    0xB9, 0xE8, 0xAF, 0x81, 0xE4, 0xB9, 0xA6,
+};
+
+/* /C=CN/O=WoSign CA Limited/CN=CA WoSign ECC Root */
+static const unsigned char CAWoSignECCRootDN[72] = {
+    0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+    0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11,
+    0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D,
+    0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03,
+    0x13, 0x12, 0x43, 0x41, 0x20, 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45,
+    0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74,
+};
+
+/* /C=CN/O=WoSign CA Limited/CN=Certification Authority of WoSign */
+static const unsigned char CertificationAuthorityofWoSignDN[87] = {
+    0x30, 0x55, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+    0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11,
+    0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D,
+    0x69, 0x74, 0x65, 0x64, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03,
+    0x13, 0x21, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
+    0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20,
+    0x6F, 0x66, 0x20, 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E,
+};
+
+/* /C=CN/O=WoSign CA Limited/CN=Certification Authority of WoSign G2 */
+static const unsigned char CertificationAuthorityofWoSignG2DN[90] = {
+    0x30, 0x58, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+    0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11,
+    0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D,
+    0x69, 0x74, 0x65, 0x64, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03,
+    0x13, 0x24, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
+    0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20,
+    0x6F, 0x66, 0x20, 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, 0x32,
+};
+
+/* /C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority */
+static const unsigned char StartComCertificationAuthorityDN[127] = {
+    0x30, 0x7D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+    0x49, 0x4C, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D,
+    0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20, 0x4C, 0x74, 0x64, 0x2E,
+    0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x22, 0x53, 0x65,
+    0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6C, 0x20,
+    0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53,
+    0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55,
+    0x04, 0x03, 0x13, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20,
+    0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E,
+    0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79,
+};
+
+/* /C=IL/O=StartCom Ltd./CN=StartCom Certification Authority G2 */
+static const unsigned char StartComCertificationAuthorityG2DN[85] = {
+    0x30, 0x53, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+    0x49, 0x4C, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D,
+    0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20, 0x4C, 0x74, 0x64, 0x2E,
+    0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x23, 0x53, 0x74,
+    0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
+    0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F,
+    0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32,
+};
+
+struct DataAndLength {
+    const unsigned char *data;
+    PRUint32 len;
+};
+
+static const struct DataAndLength StartComAndWoSignDNs[] = {
+    { CAWoSignRootDN,
+      sizeof(CAWoSignRootDN) },
+    { CAWoSignECCRootDN,
+      sizeof(CAWoSignECCRootDN) },
+    { CertificationAuthorityofWoSignDN,
+      sizeof(CertificationAuthorityofWoSignDN) },
+    { CertificationAuthorityofWoSignG2DN,
+      sizeof(CertificationAuthorityofWoSignG2DN) },
+    { StartComCertificationAuthorityDN,
+      sizeof(StartComCertificationAuthorityDN) },
+    { StartComCertificationAuthorityG2DN,
+      sizeof(StartComCertificationAuthorityG2DN) },
+};
+
+static PRBool
+CertIsStartComOrWoSign(const CERTCertificate *cert)
+{
+    int i;
+    const struct DataAndLength *dn = StartComAndWoSignDNs;
+
+    for (i = 0; i < sizeof(StartComAndWoSignDNs) / sizeof(struct DataAndLength); ++i, dn++) {
+        if (cert->derSubject.len == dn->len &&
+            memcmp(cert->derSubject.data, dn->data, dn->len) == 0) {
+            return PR_TRUE;
+        }
+    }
+    return PR_FALSE;
+}
+
+SECStatus
+isIssuerCertAllowedAtCertIssuanceTime(CERTCertificate *issuerCert,
+                                      CERTCertificate *referenceCert)
+{
+    if (!issuerCert || !referenceCert) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+
+    if (CertIsStartComOrWoSign(issuerCert)) {
+        /* PRTime is microseconds since the epoch, whereas JS time is milliseconds.
+         * (new Date("2016-10-21T00:00:00Z")).getTime() * 1000
+         */
+        static const PRTime OCTOBER_21_2016 = 1477008000000000;
+
+        PRTime notBefore, notAfter;
+        SECStatus rv;
+
+        rv = CERT_GetCertTimes(referenceCert, &notBefore, &notAfter);
+        if (rv != SECSuccess)
+            return rv;
+
+        if (notBefore > OCTOBER_21_2016) {
+            return SECFailure;
+        }
+    }
+
+    return SECSuccess;
+}
+
 static SECStatus
 cert_VerifyCertChainOld(CERTCertDBHandle *handle, CERTCertificate *cert,
                         PRBool checkSig, PRBool *sigerror,
                         SECCertUsage certUsage, PRTime t, void *wincx,
                         CERTVerifyLog *log, PRBool *revoked)
 {
     SECTrustType trustType;
     CERTBasicConstraints basicConstraint;
@@ -610,16 +746,23 @@ cert_VerifyCertChainOld(CERTCertDBHandle
         rv = CERT_CompareNameSpace(issuerCert, namesList, certsList,
                                    arena, &badCert);
         if (rv != SECSuccess || badCert != NULL) {
             PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE);
             LOG_ERROR_OR_EXIT(log, badCert, count + 1, 0);
             goto loser;
         }
 
+        rv = isIssuerCertAllowedAtCertIssuanceTime(issuerCert, cert);
+        if (rv != SECSuccess) {
+            PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
+            LOG_ERROR(log, issuerCert, count + 1, 0);
+            goto loser;
+        }
+
         /* XXX - the error logging may need to go down into CRL stuff at some
          * point
          */
         /* check revoked list (issuer) */
         rv = SEC_CheckCRL(handle, subjectCert, issuerCert, t, wincx);
         if (rv == SECFailure) {
             if (revoked) {
                 *revoked = PR_TRUE;
--- a/security/nss/lib/libpkix/include/pkix_errorstrings.h
+++ b/security/nss/lib/libpkix/include/pkix_errorstrings.h
@@ -1090,9 +1090,10 @@ PKIX_ERRORENTRY(X500NAMEGETCOMMONNAMEFAI
 PKIX_ERRORENTRY(X500NAMEGETCOUNTRYNAMEFAILED,pkix_pl_X500Name_GetCountryName failed,0),
 PKIX_ERRORENTRY(X500NAMEGETORGNAMEFAILED,pkix_pl_X500Name_GetOrgName failed,0),
 PKIX_ERRORENTRY(X500NAMEGETSECNAMEFAILED,pkix_pl_X500Name_GetSECName failed,0),
 PKIX_ERRORENTRY(X500NAMEHASHCODEFAILED,PKIX_PL_X500Name_Hashcode failed,0),
 PKIX_ERRORENTRY(X500NAMEMATCHFAILED,PKIX_PL_X500Name_Match failed,0),
 PKIX_ERRORENTRY(X500NAMETOSTRINGFAILED,PKIX_PL_X500Name_ToString failed,0),
 PKIX_ERRORENTRY(ZEROLENGTHBYTEARRAYFORCRLENCODING,Zero-length ByteArray for CRL encoding,0),
 PKIX_ERRORENTRY(INVALIDOCSPHTTPMETHOD,Unsupported HTTP Method for OCSP retrieval,0),
-PKIX_ERRORENTRY(OCSPGETREQUESTTOOBIG,OCSP request too big for HTTP GET method,0)
+PKIX_ERRORENTRY(OCSPGETREQUESTTOOBIG,OCSP request too big for HTTP GET method,0),
+PKIX_ERRORENTRY(CERTISBLACKLISTEDATISSUANCETIME,Issuer Certificate is distrusted at the time the subordinate certifiate was issued,SEC_ERROR_UNTRUSTED_ISSUER)
--- a/security/nss/lib/libpkix/pkix/top/pkix_build.c
+++ b/security/nss/lib/libpkix/pkix/top/pkix_build.c
@@ -1938,16 +1938,20 @@ pkix_PrepareForwardBuilderStateForAIA(
 {
         PORT_Assert(state->useOnlyLocal == PKIX_TRUE);
         state->useOnlyLocal = PKIX_FALSE;
         state->certStoreIndex = 0;
         state->numFanout = state->buildConstants.maxFanout;
         state->status = BUILD_TRYAIA;
 }
 
+extern SECStatus
+isIssuerCertAllowedAtCertIssuanceTime(CERTCertificate *issuerCert,
+                                      CERTCertificate *referenceCert);
+
 /*
  * FUNCTION: pkix_BuildForwardDepthFirstSearch
  * DESCRIPTION:
  *
  *  This function performs a depth first search in the "forward" direction (from
  *  the target Cert to the trust anchor). A non-NULL targetCert must be stored
  *  in the ForwardBuilderState before this function is called. It is not written
  *  recursively since execution may be suspended in in any of several places
@@ -2052,31 +2056,33 @@ pkix_BuildForwardDepthFirstSearch(
         PKIX_PL_Object *subjectName = NULL;
         PKIX_ValidateResult *valResult = NULL;
         PKIX_ForwardBuilderState *childState = NULL;
         PKIX_ForwardBuilderState *parentState = NULL;
         PKIX_PL_Object *revCheckerState = NULL;
         PKIX_ComCertSelParams *certSelParams = NULL;
         PKIX_TrustAnchor *trustAnchor = NULL;
         PKIX_PL_Cert *trustedCert = NULL;
+        PKIX_PL_Cert *targetCert = NULL;
         PKIX_VerifyNode *verifyNode = NULL;
         PKIX_Error *verifyError = NULL;
         PKIX_Error *finalError = NULL;
         void *nbio = NULL;
         PKIX_UInt32 numIterations = 0;
 
         PKIX_ENTER(BUILD, "pkix_BuildForwardDepthFirstSearch");
         PKIX_NULLCHECK_THREE(pNBIOContext, state, pValResult);
 
         nbio = *pNBIOContext;
         *pNBIOContext = NULL;
         PKIX_INCREF(state->validityDate);
         validityDate = state->validityDate;
         canBeCached = state->canBeCached;
         PKIX_DECREF(*pValResult);
+        targetCert = state->buildConstants.targetCert;
 
         /*
          * We return if successful; if we fall off the end
          * of this "while" clause our search has failed.
          */
         while (outOfOptions == PKIX_FALSE) {
             /*
              * The maximum number of iterations works around a bug that
@@ -2349,16 +2355,22 @@ pkix_BuildForwardDepthFirstSearch(
                     PKIX_DECREF(state->candidateCert);
                     PKIX_CHECK(PKIX_List_GetItem
                             (state->candidateCerts,
                             state->certIndex,
                             (PKIX_PL_Object **)&(state->candidateCert),
                             plContext),
                             PKIX_LISTGETITEMFAILED);
 
+                    if (isIssuerCertAllowedAtCertIssuanceTime(
+                          state->candidateCert->nssCert, targetCert->nssCert)
+                            != SECSuccess) {
+                        PKIX_ERROR(PKIX_CERTISBLACKLISTEDATISSUANCETIME);
+                    }
+
                     if ((state->verifyNode) != NULL) {
                             PKIX_CHECK_FATAL(pkix_VerifyNode_Create
                                     (state->candidateCert,
                                     0,
                                     NULL,
                                     &verifyNode,
                                     plContext),
                                     PKIX_VERIFYNODECREATEFAILED);
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -17,22 +17,22 @@
 
 /*
  * NSS's major version, minor version, patch level, build number, and whether
  * this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define NSS_VERSION "3.28" _NSS_CUSTOMIZED " Beta"
+#define NSS_VERSION "3.28" _NSS_CUSTOMIZED
 #define NSS_VMAJOR 3
 #define NSS_VMINOR 28
 #define NSS_VPATCH 0
 #define NSS_VBUILD 0
-#define NSS_BETA PR_TRUE
+#define NSS_BETA PR_FALSE
 
 #ifndef RC_INVOKED
 
 #include "seccomon.h"
 
 typedef struct NSSInitParametersStr NSSInitParameters;
 
 /*
--- a/security/nss/lib/pk11wrap/pk11pars.c
+++ b/security/nss/lib/pk11wrap/pk11pars.c
@@ -1009,16 +1009,20 @@ static char *
 secmod_getConfigDir(const char *spec, char **certPrefix, char **keyPrefix,
                     PRBool *readOnly)
 {
     char *config = NULL;
 
     *certPrefix = NULL;
     *keyPrefix = NULL;
     *readOnly = NSSUTIL_ArgHasFlag("flags", "readOnly", spec);
+    if (NSSUTIL_ArgHasFlag("flags", "nocertdb", spec) ||
+        NSSUTIL_ArgHasFlag("flags", "nokeydb", spec)) {
+        return NULL;
+    }
 
     spec = NSSUTIL_ArgStrip(spec);
     while (*spec) {
         int next;
         NSSUTIL_HANDLE_STRING_ARG(spec, config, "configdir=", ;)
         NSSUTIL_HANDLE_STRING_ARG(spec, *certPrefix, "certPrefix=", ;)
         NSSUTIL_HANDLE_STRING_ARG(spec, *keyPrefix, "keyPrefix=", ;)
         NSSUTIL_HANDLE_FINAL_ARG(spec)
@@ -1128,16 +1132,23 @@ secmod_matchPrefix(char *prefix1, char *
  * SECMODConfigLists directly, so this function breaks them out to their
  * components. */
 static PRBool
 secmod_matchConfig(char *configDir1, char *configDir2,
                    char *certPrefix1, char *certPrefix2,
                    char *keyPrefix1, char *keyPrefix2,
                    PRBool isReadOnly1, PRBool isReadOnly2)
 {
+    /* TODO: Document the answer to the question:
+     *       "Why not allow them to match if they are both NULL?"
+     * See: https://bugzilla.mozilla.org/show_bug.cgi?id=1318633#c1
+     */
+    if ((configDir1 == NULL) || (configDir2 == NULL)) {
+        return PR_FALSE;
+    }
     if (strcmp(configDir1, configDir2) != 0) {
         return PR_FALSE;
     }
     if (!secmod_matchPrefix(certPrefix1, certPrefix2)) {
         return PR_FALSE;
     }
     if (!secmod_matchPrefix(keyPrefix1, keyPrefix2)) {
         return PR_FALSE;
@@ -1164,17 +1175,16 @@ secmod_MatchConfigList(const char *spec,
     char *certPrefix;
     char *keyPrefix;
     PRBool isReadOnly;
     PRBool ret = PR_FALSE;
     int i;
 
     config = secmod_getConfigDir(spec, &certPrefix, &keyPrefix, &isReadOnly);
     if (!config) {
-        ret = PR_TRUE;
         goto done;
     }
 
     /* NOTE: we dbm isn't multiple open safe. If we open the same database
      * twice from two different locations, then we can corrupt our database
      * (the cache will be inconsistent). Protect against this by claiming
      * for comparison only that we are always openning dbm databases read only.
      */
--- a/security/nss/lib/smime/cmssigdata.c
+++ b/security/nss/lib/smime/cmssigdata.c
@@ -701,16 +701,17 @@ NSS_CMSSignedData_VerifyCertsOnly(NSSCMS
                                   CERTCertDBHandle *certdb,
                                   SECCertUsage usage)
 {
     CERTCertificate *cert;
     SECStatus rv = SECSuccess;
     int i;
     int count;
     PRTime now;
+    void *pwarg = NULL;
 
     if (!sigd || !certdb || !sigd->rawCerts) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
     count = NSS_CMSArray_Count((void **)sigd->rawCerts);
     now = PR_Now();
@@ -719,18 +720,21 @@ NSS_CMSSignedData_VerifyCertsOnly(NSSCMS
             cert = CERT_DupCertificate(sigd->certs[i]);
         } else {
             cert = CERT_FindCertByDERCert(certdb, sigd->rawCerts[i]);
             if (!cert) {
                 rv = SECFailure;
                 break;
             }
         }
+        if (sigd->cmsg) {
+            pwarg = sigd->cmsg->pwfn_arg;
+        }
         rv |= CERT_VerifyCert(certdb, cert, PR_TRUE, usage, now,
-                              NULL, NULL);
+                              pwarg, NULL);
         CERT_DestroyCertificate(cert);
     }
 
     return rv;
 }
 
 /*
  * NSS_CMSSignedData_HasDigests - see if we have digests in place
--- a/security/nss/lib/softoken/softkver.h
+++ b/security/nss/lib/softoken/softkver.h
@@ -16,16 +16,16 @@
 
 /*
  * Softoken's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define SOFTOKEN_VERSION "3.28" SOFTOKEN_ECC_STRING " Beta"
+#define SOFTOKEN_VERSION "3.28" SOFTOKEN_ECC_STRING
 #define SOFTOKEN_VMAJOR 3
 #define SOFTOKEN_VMINOR 28
 #define SOFTOKEN_VPATCH 0
 #define SOFTOKEN_VBUILD 0
-#define SOFTOKEN_BETA PR_TRUE
+#define SOFTOKEN_BETA PR_FALSE
 
 #endif /* _SOFTKVER_H_ */
--- a/security/nss/lib/ssl/ssl.def
+++ b/security/nss/lib/ssl/ssl.def
@@ -209,20 +209,15 @@ SSL_ConfigServerCert;
 ;+NSS_3.27 {    # NSS 3.27 release
 ;+    global:
 SSL_NamedGroupConfig;
 ;+    local:
 ;+*;
 ;+};
 ;+NSS_3.28 {    # NSS 3.28 release
 ;+    global:
+SSL_ExportEarlyKeyingMaterial;
 SSL_SendAdditionalKeyShares;
 SSL_SignatureSchemePrefSet;
 SSL_SignatureSchemePrefGet;
 ;+    local:
 ;+*;
 ;+};
-;+NSS_3.29 {    # NSS 3.29 release
-;+    global:
-SSL_ExportEarlyKeyingMaterial;
-;+    local:
-;+*;
-;+};
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -2575,22 +2575,34 @@ ssl3_CompressMACEncryptRecord(ssl3Cipher
 }
 
 SECStatus
 ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec,
                   PRBool capRecordVersion, SSL3ContentType type,
                   const SSL3Opaque *pIn, PRUint32 contentLen, sslBuffer *wrBuf)
 {
     const ssl3BulkCipherDef *cipher_def = cwSpec->cipher_def;
-    PRUint16 headerLen = IS_DTLS(ss) ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH;
-    sslBuffer protBuf = { wrBuf->buf + headerLen, 0, wrBuf->space - headerLen };
+    PRUint16 headerLen;
+    sslBuffer protBuf;
     SSL3ProtocolVersion version = cwSpec->version;
     PRBool isTLS13;
+    PRUint8 *ptr = wrBuf->buf;
     SECStatus rv;
 
+    if (ss->ssl3.hs.shortHeaders) {
+        PORT_Assert(!IS_DTLS(ss));
+        PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
+        headerLen = TLS13_RECORD_HEADER_LENGTH_SHORT;
+    } else {
+        headerLen = IS_DTLS(ss) ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH;
+    }
+    protBuf.buf = wrBuf->buf + headerLen;
+    protBuf.len = 0;
+    protBuf.space = wrBuf->space - headerLen;
+
     PORT_Assert(cipher_def->max_records <= RECORD_SEQ_MAX);
     if ((cwSpec->write_seq_num & RECORD_SEQ_MAX) >= cipher_def->max_records) {
         SSL_TRC(3, ("%d: SSL[-]: write sequence number at limit 0x%0llx",
                     SSL_GETPID(), cwSpec->write_seq_num));
         PORT_SetError(SSL_ERROR_TOO_MANY_RECORDS);
         return SECFailure;
     }
 
@@ -2610,39 +2622,42 @@ ssl_ProtectRecord(sslSocket *ss, ssl3Cip
 #endif
     if (rv != SECSuccess) {
         return SECFailure; /* error was set */
     }
 
     PORT_Assert(protBuf.len <= MAX_FRAGMENT_LENGTH + (isTLS13 ? 256 : 1024));
     wrBuf->len = protBuf.len + headerLen;
 
+    if (ss->ssl3.hs.shortHeaders) {
+        PORT_Assert(!IS_DTLS(ss)); /* Decoder not yet implemented. */
+        (void)ssl_EncodeUintX(0x8000 | protBuf.len, 2, ptr);
+    } else {
 #ifndef UNSAFE_FUZZER_MODE
-    if (isTLS13 && cipher_def->calg != ssl_calg_null) {
-        wrBuf->buf[0] = content_application_data;
-    } else
+        if (isTLS13 && cipher_def->calg != ssl_calg_null) {
+            *ptr++ = content_application_data;
+        } else
 #endif
-    {
-        wrBuf->buf[0] = type;
-    }
-
-    if (IS_DTLS(ss)) {
-        version = isTLS13 ? SSL_LIBRARY_VERSION_TLS_1_1 : version;
-        version = dtls_TLSVersionToDTLSVersion(version);
-
-        (void)ssl_EncodeUintX(version, 2, &wrBuf->buf[1]);
-        (void)ssl_EncodeUintX(cwSpec->write_seq_num, 8, &wrBuf->buf[3]);
-        (void)ssl_EncodeUintX(protBuf.len, 2, &wrBuf->buf[11]);
-    } else {
-        if (capRecordVersion || isTLS13) {
-            version = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0, version);
-        }
-
-        (void)ssl_EncodeUintX(version, 2, &wrBuf->buf[1]);
-        (void)ssl_EncodeUintX(protBuf.len, 2, &wrBuf->buf[3]);
+        {
+            *ptr++ = type;
+        }
+
+        if (IS_DTLS(ss)) {
+            version = isTLS13 ? SSL_LIBRARY_VERSION_TLS_1_1 : version;
+            version = dtls_TLSVersionToDTLSVersion(version);
+
+            ptr = ssl_EncodeUintX(version, 2, ptr);
+            ptr = ssl_EncodeUintX(cwSpec->write_seq_num, 8, ptr);
+        } else {
+            if (capRecordVersion || isTLS13) {
+                version = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0, version);
+            }
+            ptr = ssl_EncodeUintX(version, 2, ptr);
+        }
+        (void)ssl_EncodeUintX(protBuf.len, 2, ptr);
     }
     ++cwSpec->write_seq_num;
 
     return SECSuccess;
 }
 
 /* Process the plain text before sending it.
  * Returns the number of bytes of plaintext that were successfully sent
--- a/security/nss/lib/ssl/ssl3ext.c
+++ b/security/nss/lib/ssl/ssl3ext.c
@@ -34,16 +34,17 @@ static const ssl3ExtensionHandler client
     { ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn },
     { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
     { ssl_signed_cert_timestamp_xtn, &ssl3_ServerHandleSignedCertTimestampXtn },
     { ssl_tls13_key_share_xtn, &tls13_ServerHandleKeyShareXtn },
     { ssl_tls13_pre_shared_key_xtn, &tls13_ServerHandlePreSharedKeyXtn },
     { ssl_tls13_early_data_xtn, &tls13_ServerHandleEarlyDataXtn },
     { ssl_tls13_psk_key_exchange_modes_xtn,
       &tls13_ServerHandlePskKeyExchangeModesXtn },
+    { ssl_tls13_short_header_xtn, &tls13_HandleShortHeaderXtn },
     { -1, NULL }
 };
 
 /* These two tables are used by the client, to handle server hello
  * extensions. */
 static const ssl3ExtensionHandler serverHelloHandlersTLS[] = {
     { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
     /* TODO: add a handler for ssl_ec_point_formats_xtn */
@@ -53,16 +54,17 @@ static const ssl3ExtensionHandler server
     { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn },
     { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn },
     { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
     { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
     { 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_tls13_short_header_xtn, &tls13_HandleShortHeaderXtn },
     { -1, NULL }
 };
 
 static const ssl3ExtensionHandler helloRetryRequestHandlers[] = {
     { ssl_tls13_key_share_xtn, tls13_ClientHandleKeyShareXtnHrr },
     { ssl_tls13_cookie_xtn, tls13_ClientHandleHrrCookie },
     { -1, NULL }
 };
@@ -110,16 +112,17 @@ static const ssl3HelloExtensionSender cl
       { ssl_signed_cert_timestamp_xtn, &ssl3_ClientSendSignedCertTimestampXtn },
       { ssl_tls13_key_share_xtn, &tls13_ClientSendKeyShareXtn },
       { 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_tls13_short_header_xtn, &tls13_SendShortHeaderXtn },
       { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
       { ssl_tls13_cookie_xtn, &tls13_ClientSendHrrCookieXtn },
       { ssl_tls13_psk_key_exchange_modes_xtn,
         &tls13_ClientSendPskKeyExchangeModesXtn },
       /* The pre_shared_key extension MUST be last. */
       { ssl_tls13_pre_shared_key_xtn, &tls13_ClientSendPreSharedKeyXtn },
       /* any extra entries will appear as { 0, NULL }    */
     };
--- a/security/nss/lib/ssl/ssl3gthr.c
+++ b/security/nss/lib/ssl/ssl3gthr.c
@@ -92,17 +92,17 @@ ssl3_GatherData(sslSocket *ss, sslGather
     int nb;
     int err;
     int rv = 1;
     PRUint8 v2HdrLength = 0;
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     if (gs->state == GS_INIT) {
         gs->state = GS_HEADER;
-        gs->remainder = 5;
+        gs->remainder = ss->ssl3.hs.shortHeaders ? 2 : 5;
         gs->offset = 0;
         gs->writeOffset = 0;
         gs->readOffset = 0;
         gs->inbuf.len = 0;
     }
 
     lbp = gs->inbuf.buf;
     for (;;) {
@@ -144,20 +144,32 @@ ssl3_GatherData(sslSocket *ss, sslGather
         }
 
         /* have received entire record header, or entire record. */
         switch (gs->state) {
             case GS_HEADER:
                 /* Check for SSLv2 handshakes. Always assume SSLv3 on clients,
                  * support SSLv2 handshakes only when ssl2gs != NULL. */
                 if (!ssl2gs || ssl3_isLikelyV3Hello(gs->hdr)) {
-                    /* Should have an SSLv3 record header in gs->hdr. Extract
+                    /* Should have a non-SSLv2 record header in gs->hdr. Extract
                      * the length of the following encrypted data, and then
-                     * read in the rest of the SSL3 record into gs->inbuf. */
-                    gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4];
+                     * read in the rest of the record into gs->inbuf. */
+                    if (ss->ssl3.hs.shortHeaders) {
+                        PRUint16 len = (gs->hdr[0] << 8) | gs->hdr[1];
+                        if (!(len & 0x8000)) {
+                            SSL_DBG(("%d: SSL3[%d]: incorrectly formatted header"));
+                            SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
+                            gs->state = GS_INIT;
+                            PORT_SetError(SSL_ERROR_BAD_MAC_READ);
+                            return SECFailure;
+                        }
+                        gs->remainder = len & ~0x8000;
+                    } else {
+                        gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4];
+                    }
                 } else {
                     /* Probably an SSLv2 record header. No need to handle any
                      * security escapes (gs->hdr[0] & 0x40) as we wouldn't get
                      * here if one was set. See ssl3_isLikelyV3Hello(). */
                     gs->remainder = ((gs->hdr[0] & 0x7f) << 8) | gs->hdr[1];
                     ssl2gs->isV2 = PR_TRUE;
                     v2HdrLength = 2;
 
@@ -453,18 +465,23 @@ ssl3_GatherCompleteHandshake(sslSocket *
                     return rv;
                 }
             } else {
                 /* decipher it, and handle it if it's a handshake.
                  * If it's application data, ss->gs.buf will not be empty upon return.
                  * If it's a change cipher spec, alert, or handshake message,
                  * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess.
                  */
-                cText.type = (SSL3ContentType)ss->gs.hdr[0];
-                cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
+                if (ss->ssl3.hs.shortHeaders) {
+                    cText.type = content_application_data;
+                    cText.version = SSL_LIBRARY_VERSION_TLS_1_0;
+                } else {
+                    cText.type = (SSL3ContentType)ss->gs.hdr[0];
+                    cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
+                }
 
                 if (IS_DTLS(ss)) {
                     sslSequenceNumber seq_num;
 
                     cText.version = dtls_DTLSVersionToTLSVersion(cText.version);
                     /* DTLS sequence number */
                     PORT_Memcpy(&seq_num, &ss->gs.hdr[3], sizeof(seq_num));
                     cText.seq_num = PR_ntohll(seq_num);
--- a/security/nss/lib/ssl/ssl3prot.h
+++ b/security/nss/lib/ssl/ssl3prot.h
@@ -27,16 +27,17 @@ typedef PRUint16 ssl3CipherSuite;
 #define MAX_COMPRESSION_METHODS 10
 #define MAX_MAC_LENGTH 64
 #define MAX_PADDING_LENGTH 64
 #define MAX_KEY_LENGTH 64
 #define EXPORT_KEY_LENGTH 5
 #define SSL3_RANDOM_LENGTH 32
 
 #define SSL3_RECORD_HEADER_LENGTH 5
+#define TLS13_RECORD_HEADER_LENGTH_SHORT 2
 
 /* SSL3_RECORD_HEADER_LENGTH + epoch/sequence_number */
 #define DTLS_RECORD_HEADER_LENGTH 13
 
 #define MAX_FRAGMENT_LENGTH 16384
 
 typedef enum {
     content_change_cipher_spec = 20,
--- a/security/nss/lib/ssl/sslimpl.h
+++ b/security/nss/lib/ssl/sslimpl.h
@@ -288,16 +288,17 @@ typedef struct sslOptionsStr {
     unsigned int enableALPN : 1;
     unsigned int reuseServerECDHEKey : 1;
     unsigned int enableFallbackSCSV : 1;
     unsigned int enableServerDhe : 1;
     unsigned int enableExtendedMS : 1;
     unsigned int enableSignedCertTimestamps : 1;
     unsigned int requireDHENamedGroups : 1;
     unsigned int enable0RttData : 1;
+    unsigned int enableShortHeaders : 1;
 } sslOptions;
 
 typedef enum { sslHandshakingUndetermined = 0,
                sslHandshakingAsClient,
                sslHandshakingAsServer
 } sslHandshakingType;
 
 #define SSL_LOCK_RANK_SPEC 255
@@ -866,16 +867,17 @@ typedef struct SSL3HandshakeStateStr {
     sslZeroRttIgnore zeroRttIgnore; /* Are we ignoring 0-RTT? */
     ssl3CipherSuite zeroRttSuite;   /* The cipher suite we used for 0-RTT. */
     PRCList bufferedEarlyData;      /* Buffered TLS 1.3 early data
                                      * on server.*/
     PRBool helloRetry;              /* True if HelloRetryRequest has been sent
                                      * or received. */
     ssl3KEADef kea_def_mutable;     /* Used to hold the writable kea_def
                                      * we use for TLS 1.3 */
+    PRBool shortHeaders;            /* Assigned if we are doing short headers. */
 } SSL3HandshakeState;
 
 /*
 ** This is the "ssl3" struct, as in "ss->ssl3".
 ** note:
 ** usually,   crSpec == cwSpec and prSpec == pwSpec.
 ** Sometimes, crSpec == pwSpec and prSpec == cwSpec.
 ** But there are never more than 2 actual specs.
--- a/security/nss/lib/ssl/sslproto.h
+++ b/security/nss/lib/ssl/sslproto.h
@@ -204,16 +204,26 @@
 #define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9
 #define TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256     0xCCAA
 
 /* Special TLS 1.3 cipher suites that really just specify AEAD */
 #define TLS_AES_128_GCM_SHA256                0x1301
 #define TLS_AES_256_GCM_SHA384                0x1302
 #define TLS_CHACHA20_POLY1305_SHA256          0x1303
 
+/* PSK cipher suites. NSS doesn't actually support these, but we
+ * exposed them when TLS 1.3 used them so we need to keep them
+ * in the API. */
+#define TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256   0xCCAC
+#define TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256     0xCCAD
+#define TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256   0xD001
+#define TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384   0xD002
+#define TLS_DHE_PSK_WITH_AES_128_GCM_SHA256     0x00AA /* RFC 5487 */
+#define TLS_DHE_PSK_WITH_AES_256_GCM_SHA384     0x00AB /* RFC 5487 */
+
 /* DTLS-SRTP cipher suites from RFC 5764 */
 /* If you modify this, also modify MAX_DTLS_SRTP_CIPHER_SUITES in sslimpl.h */
 #define SRTP_AES128_CM_HMAC_SHA1_80             0x0001
 #define SRTP_AES128_CM_HMAC_SHA1_32             0x0002
 #define SRTP_NULL_HMAC_SHA1_80                  0x0005
 #define SRTP_NULL_HMAC_SHA1_32                  0x0006
 
 /* DO NOT USE. (deprecated, will be removed) */
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -73,17 +73,22 @@ static sslOptions ssl_defaults = {
     PR_FALSE,              /* enableNPN          */
     PR_TRUE,               /* enableALPN         */
     PR_TRUE,               /* reuseServerECDHEKey */
     PR_FALSE,              /* enableFallbackSCSV */
     PR_TRUE,               /* enableServerDhe */
     PR_FALSE,              /* enableExtendedMS    */
     PR_FALSE,              /* enableSignedCertTimestamps */
     PR_FALSE,              /* requireDHENamedGroups */
-    PR_FALSE               /* enable0RttData */
+    PR_FALSE,              /* enable0RttData */
+#ifdef NSS_ENABLE_TLS13_SHORT_HEADERS
+    PR_TRUE /* enableShortHeaders */
+#else
+    PR_FALSE /* enableShortHeaders */
+#endif
 };
 
 /*
  * default range of enabled SSL/TLS protocols
  */
 static SSLVersionRange versions_defaults_stream = {
     SSL_LIBRARY_VERSION_TLS_1_0,
     SSL_LIBRARY_VERSION_TLS_1_2
--- a/security/nss/lib/ssl/sslt.h
+++ b/security/nss/lib/ssl/sslt.h
@@ -383,27 +383,28 @@ typedef enum {
     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_tls13_psk_key_exchange_modes_xtn = 45,
     ssl_tls13_ticket_early_data_info_xtn = 46,
     ssl_next_proto_nego_xtn = 13172,
-    ssl_renegotiation_info_xtn = 0xff01
+    ssl_renegotiation_info_xtn = 0xff01,
+    ssl_tls13_short_header_xtn = 0xff03
 } SSLExtensionType;
 
 /* This is the old name for the supported_groups extensions. */
 #define ssl_elliptic_curves_xtn ssl_supported_groups_xtn
 
 /* 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 18
+#define SSL_MAX_EXTENSIONS 19
 
 /* 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
@@ -1442,16 +1442,17 @@ tls13_HandleClientHelloPart2(sslSocket *
                                 kHkdfLabelEarlyTrafficSecret,
                                 NULL, /* Current running hash. */
                                 &ss->ssl3.hs.clientEarlyTrafficSecret);
         if (rv != SECSuccess) {
             FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
             return SECFailure;
         }
     }
+
     ssl_GetXmitBufLock(ss);
     rv = tls13_SendServerHelloSequence(ss);
     ssl_ReleaseXmitBufLock(ss);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, PORT_GetError(), handshake_failure);
         return SECFailure;
     }
 
@@ -1852,16 +1853,19 @@ tls13_SendEncryptedServerSequence(sslSoc
 
     rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake,
                              CipherSpecWrite, PR_FALSE);
     if (rv != SECSuccess) {
         LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
 
+    ss->ssl3.hs.shortHeaders = ssl3_ExtensionNegotiated(
+        ss, ssl_tls13_short_header_xtn);
+
     if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) {
         rv = ssl3_RegisterExtensionSender(ss, &ss->xtnData, ssl_tls13_early_data_xtn,
                                           tls13_ServerSendEarlyDataXtn);
         if (rv != SECSuccess) {
             return SECFailure; /* Error code set already. */
         }
     }
 
@@ -2058,16 +2062,19 @@ tls13_HandleServerHelloPart2(sslSocket *
     if (rv != SECSuccess) {
         return SECFailure;
     }
     rv = tls13_ComputeHandshakeSecrets(ss);
     if (rv != SECSuccess) {
         return SECFailure; /* error code is set. */
     }
 
+    ss->ssl3.hs.shortHeaders = ssl3_ExtensionNegotiated(
+        ss, ssl_tls13_short_header_xtn);
+
     rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake,
                              CipherSpecRead, PR_FALSE);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SSL_ERROR_INIT_CIPHER_SUITE_FAILURE, internal_error);
         return SECFailure;
     }
     TLS13_SET_HS_STATE(ss, wait_encrypted_extensions);
 
@@ -3990,17 +3997,18 @@ static const struct {
     { 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, ExtensionSendCertificate },
     { ssl_cert_status_xtn, ExtensionSendCertificate },
     { ssl_tls13_ticket_early_data_info_xtn, ExtensionNewSessionTicket },
-    { ssl_tls13_cookie_xtn, ExtensionSendHrr }
+    { ssl_tls13_cookie_xtn, ExtensionSendHrr },
+    { ssl_tls13_short_header_xtn, ExtensionSendClear }
 };
 
 PRBool
 tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message)
 {
     unsigned int i;
 
     PORT_Assert((message == client_hello) ||
@@ -4262,16 +4270,17 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss
 {
     SECStatus rv;
 
     /* Don't do anything if there is no early_data xtn, which means we're
      * not doing early data. */
     if (!ssl3_ClientExtensionAdvertised(ss, ssl_tls13_early_data_xtn)) {
         return SECSuccess;
     }
+
     ss->ssl3.hs.zeroRttState = ssl_0rtt_sent;
     ss->ssl3.hs.zeroRttSuite = ss->ssl3.hs.cipher_suite;
 
     SSL_TRC(3, ("%d: TLS13[%d]: in 0-RTT mode", SSL_GETPID(), ss->fd));
 
     /* Set the ALPN data as if it was negotiated. We check in the ServerHello
      * handler that the server negotiates the same value. */
     if (ss->sec.ci.sid->u.ssl3.alpnSelection.len) {
--- a/security/nss/lib/ssl/tls13exthandle.c
+++ b/security/nss/lib/ssl/tls13exthandle.c
@@ -1064,8 +1064,106 @@ tls13_ServerHandlePskKeyExchangeModesXtn
         return SECFailure;
     }
 
     /* Keep track of negotiated extensions. */
     xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
 
     return SECSuccess;
 }
+
+PRInt32
+tls13_SendShortHeaderXtn(const sslSocket *ss,
+                         TLSExtensionData *xtnData,
+                         PRBool append, PRUint32 maxBytes)
+{
+    PRUint32 extension_len = 2 + 2; /* Type + length (0). */
+
+    if (!ss->opt.enableShortHeaders) {
+        return 0;
+    }
+
+    /* Presently this is incompatible with 0-RTT. We will fix if
+     * it becomes more than an experiment. */
+    if (ss->opt.enable0RttData) {
+        return 0;
+    }
+
+    if (IS_DTLS(ss)) {
+        return 0;
+    }
+
+    SSL_TRC(3, ("%d: TLS13[%d]: send short_header extension",
+                SSL_GETPID(), ss->fd));
+
+    if (maxBytes < extension_len) {
+        PORT_Assert(0);
+        return 0;
+    }
+
+    if (append) {
+        SECStatus rv;
+
+        rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_short_header_xtn, 2);
+        if (rv != SECSuccess)
+            return -1;
+
+        rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2);
+        if (rv != SECSuccess)
+            return -1;
+
+        xtnData->advertised[xtnData->numAdvertised++] =
+            ssl_tls13_short_header_xtn;
+    }
+
+    return extension_len;
+}
+
+SECStatus
+tls13_HandleShortHeaderXtn(
+    const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
+    SECItem *data)
+{
+    SSL_TRC(3, ("%d: TLS13[%d]: handle early_data extension",
+                SSL_GETPID(), ss->fd));
+
+    /* If we are doing < TLS 1.3, then ignore this. */
+    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+        return SECSuccess;
+    }
+
+    /* Presently this is incompatible with 0-RTT. We will fix if
+     * it becomes more than an experiment. */
+    if (ss->opt.enable0RttData) {
+        return SECSuccess;
+    }
+
+    if (IS_DTLS(ss)) {
+        PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION);
+        return SECFailure;
+    }
+
+    if (data->len) {
+        PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
+        return SECFailure;
+    }
+
+    if (!ss->opt.enableShortHeaders) {
+        /* Ignore. */
+        return SECSuccess;
+    }
+
+    /* Keep track of negotiated extensions. */
+    xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
+
+    if (ss->sec.isServer) {
+        SECStatus rv;
+
+        rv = ssl3_RegisterExtensionSender(ss, xtnData,
+                                          ssl_tls13_short_header_xtn,
+                                          tls13_SendShortHeaderXtn);
+        if (rv != SECSuccess) {
+            return SECFailure;
+        }
+    }
+
+    return SECSuccess;
+}
--- a/security/nss/lib/ssl/tls13exthandle.h
+++ b/security/nss/lib/ssl/tls13exthandle.h
@@ -59,10 +59,16 @@ PRInt32 tls13_ClientSendHrrCookieXtn(con
                                      PRBool append,
                                      PRUint32 maxBytes);
 PRInt32 tls13_ClientSendPskKeyExchangeModesXtn(const sslSocket *ss,
                                                TLSExtensionData *xtnData,
                                                PRBool append, PRUint32 maxBytes);
 SECStatus tls13_ServerHandlePskKeyExchangeModesXtn(const sslSocket *ss,
                                                    TLSExtensionData *xtnData,
                                                    PRUint16 ex_type, SECItem *data);
+PRInt32 tls13_SendShortHeaderXtn(const sslSocket *ss,
+                                 TLSExtensionData *xtnData,
+                                 PRBool append, PRUint32 maxBytes);
+SECStatus tls13_HandleShortHeaderXtn(
+    const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
+    SECItem *data);
 
 #endif
--- a/security/nss/lib/util/nssutil.h
+++ b/security/nss/lib/util/nssutil.h
@@ -14,22 +14,22 @@
 
 /*
  * NSS utilities's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
  */
-#define NSSUTIL_VERSION "3.28 Beta"
+#define NSSUTIL_VERSION "3.28"
 #define NSSUTIL_VMAJOR 3
 #define NSSUTIL_VMINOR 28
 #define NSSUTIL_VPATCH 0
 #define NSSUTIL_VBUILD 0
-#define NSSUTIL_BETA PR_TRUE
+#define NSSUTIL_BETA PR_FALSE
 
 SEC_BEGIN_PROTOS
 
 /*
  * Returns a const string of the UTIL library version.
  */
 extern const char *NSSUTIL_GetVersion(void);
 
index a826a1da252f02cf2d1612d88b5e85356cce7810..d71fbb5016b2ac180a61303d2aa2732910aa7a4b
GIT binary patch
literal 1376
zc$_n6VvR9qVsTl(%*4pVB*1j*!`#KcY~J;Vq_QlrJ*IEK%f_kI=F#?@mywa1mBFCE
zklTQhjX9KsO_(V(*ih6!7{uWc=5fhP&vZ^LDpByvOE#1=5C;i!3k#H&m+PefrILYC
zddc~@hWZA&ASq^HHMovo4@V;fkIeK81;^sz(xSw?<Wz;=)S|M~A_Zqh137VCLo-7|
z0}}%<hyrpgfLudEBQV#X7S%<<27(|ChcK6OVoqjSeo<a#qM@JxKS+>Wm?JnbPr)m{
zI2Fm|0g06Xi8(qThwB+i8Aw1}E(j4;2q?-=DNQcP%+G@v%`D7SkXTuem;>^UK@+1A
zau_kPGB7tW@-qO%xtN+585vI16-T)q%WMh?<+)!TxxHFWc=5KLH20f)pNl<q{B!ZE
z%kN^Erkro#vEW$L#HP&~4?f{43;&%_`oZd2$uXO4M@udgUhBUyOY4q!?+)hVtN+9u
zxm}x1S1h$Ka4<aCVD`>n`e)^|mcydQT;$6Se7fADUiMHmy5cXl;DVdUMOSWi%BBWB
zD)eTlEE37hTbd;r<;nl&@V7d@hsV8h{X|)KZhhfC>!`>6e9y956=yu3mb7kRT(v)Q
zf1G$uq(r;w-O9FE?s}iX85q-JUM1gl%)By7;jfP=TU79W<BIT(RT;7zDWdmV>IFT*
zoc<|ixp9f5m7UyJ*B&gF$6x-Fae<)CLndZM2FArrjE{jKa^FB67=W_MED{D{4I+UV
z|0k?xVlTBhb2Bw1X_3&5$RcY4S&#xg7BLo)&l6NqpPH*aWeQJyqy1HD&LsxL6$YXp
zX+ah~1D+=2NZ<nr^D{F3XJKJxVqE|+MU_R&K!lA$n~jl`m7SRp&SEks1xd@Z<Qe1`
zm@F__V9=(QQBqQ1rLUh{lw*vNT=k1H5{+~-5_OBg=}|Y`R1c^IQ<n)bx_m&^DzLa3
zI2)L=aVE5RFt+{8VPrJWGSGlIj)_rB24re6&{*`WqwgFLY{0?Bmfpw%%&7*A%`i=j
zj4b5_r3NZ6z5!#K1k`Ey$;AaIh8Xz5RWY?W!aR@&k}gKI4VFDYxf7H*;dv91HJu%S
zekw8G0r^Q76!J_43}}S~GbsHl?%p&zyXNcsWp4js+um<0pEaGwsXLB0_T!b?uibte
z5Yb7n>YS_B=VI$JuYba--TS{qi#$;mQOcZa^Ox64<DmDG=e{E6zMRnzl4P8(7N4^#
zVNYGw?o(4sr#$+4sv~nt*t}_9f1a^lwbP{O?1p`Z)!U0hJZ9YZp?_5JVOkJJ6z~7L
zf;a2tKCv%*70~H3wO9CZ*7Jq-;gekS_BtH=6E^Qi`AnwUk8kwX+gUGbWBVOpHnUsC
z=ayn<W7Z^9S(BF&4mkDqcD;0;rq?&&)$G)>D?Pq1legQK{M~KSsVDEdzZfLBn!dex
il#jFb`lZ<WY;$k**RxM@{h%k;WAQU%y=m8(m#qL5@YweN