Bug 1577822 - land NSS 03039d4fad57 UPGRADE_NSS_RELEASE, r=kjacobs
authorJ.C. Jones <jc@mozilla.com>
Tue, 24 Sep 2019 17:22:25 +0000
changeset 494832 73f2bfcab947866dd1d1719dcd8de805522473ff
parent 494831 1868efc4e885f660f7cdc23c123d96b91805b52d
child 494833 81b6550038065bdcb3e823d71ac165e2f4ce84b0
push id114131
push userdluca@mozilla.com
push dateThu, 26 Sep 2019 09:47:34 +0000
treeherdermozilla-inbound@1dc1a755079a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskjacobs
bugs1577822, 1580286, 1577448, 1399095, 1267894, 1581507, 1234830, 1242894, 1242852, 1581759
milestone71.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 1577822 - land NSS 03039d4fad57 UPGRADE_NSS_RELEASE, r=kjacobs 2019-09-23 Daiki Ueno <dueno@redhat.com> * gtests/ssl_gtest/ssl_recordsize_unittest.cc, lib/ssl/ssl3con.c, tests/tlsfuzzer/config.json.in, tests/tlsfuzzer/tlsfuzzer.sh: Bug 1580286, account for IV size when checking TLS 1.2 records, r=mt Summary: This increases the limit of record expansion by 16 so that it doesn't reject maximum block padding when HMAC-SHA384 is used. To test this, tlsfuzzer is updated to the latest version (commit 80d7932ead1d8dae6e555cfd2b1c4c5beb2847df). Reviewers: mt Reviewed By: mt Bug #: 1580286 [03039d4fad57] [tip] 2019-09-20 Kai Engert <kaie@kuix.de> * tests/smime/smime.sh: Bug 1577448 - Create additional nested S/MIME test messages for Thunderbird. r=jcj [57977ceea00e] 2019-09-19 Kai Engert <kaie@kuix.de> * automation/taskcluster/docker-gcc-4.4/Dockerfile, automation/taskcluster/graph/src/try_syntax.js, automation/taskcluster/scripts/build.sh, automation/taskcluster/scripts/build_gyp.sh, automation/taskcluster/scripts/build_nspr.sh, automation/taskcluster/scripts/check_abi.sh, automation/taskcluster/scripts/gen_coverage_report.sh, automation/taskcluster/scripts/run_coverity.sh, automation/taskcluster/scripts/run_scan_build.sh, automation/taskcluster/windows/build.sh, automation/taskcluster/windows/build_gyp.sh: Bug 1399095 - Allow nss-try to be used to test NSPR changes. r=kjacobs [6e1a8a7cb469] 2019-09-16 Marcus Burghardt <mburghardt@mozilla.com> * gtests/ssl_gtest/manifest.mn, gtests/ssl_gtest/ssl_cipherorder_unittest.cc, gtests/ssl_gtest/ssl_gtest.gyp, lib/ssl/ssl3con.c, lib/ssl/sslexp.h, lib/ssl/sslsock.c: Bug 1267894 - New functions for CipherSuites Ordering and gtests. r=jcj,kjacobs,mt Created two new experimental functions which permit the caller change the default order of CipherSuites used during the handshake. [2deb38fc1d68] 2019-09-18 Christian Weisgerber <naddy@mips.inka.de> * tests/policy/policy.sh, tests/ssl/ssl.sh: Bug 1581507 - Fix unportable grep expression in test scripts r=marcusburghardt [edc1e405afa4] 2019-09-18 Franziskus Kiefer <franziskuskiefer@gmail.com> * lib/jar/jarfile.c: Bug 1234830 - [CID 1242894][CID 1242852] unused values. r=kaie,r=kjacobs [b6d3f5c95aad] 2019-09-18 Kai Engert <kaie@kuix.de> * cmd/symkeyutil/symkeyutil.c: Bug 1581759 - fix incorrect if condition in symkeyutil. r=kjacobs [306550105228] Differential Revision: https://phabricator.services.mozilla.com/D46967
security/nss/TAG-INFO
security/nss/automation/taskcluster/docker-gcc-4.4/Dockerfile
security/nss/automation/taskcluster/graph/src/try_syntax.js
security/nss/automation/taskcluster/scripts/build.sh
security/nss/automation/taskcluster/scripts/build_gyp.sh
security/nss/automation/taskcluster/scripts/build_nspr.sh
security/nss/automation/taskcluster/scripts/check_abi.sh
security/nss/automation/taskcluster/scripts/gen_coverage_report.sh
security/nss/automation/taskcluster/scripts/run_coverity.sh
security/nss/automation/taskcluster/scripts/run_scan_build.sh
security/nss/automation/taskcluster/windows/build.sh
security/nss/automation/taskcluster/windows/build_gyp.sh
security/nss/cmd/symkeyutil/symkeyutil.c
security/nss/coreconf/coreconf.dep
security/nss/gtests/ssl_gtest/manifest.mn
security/nss/gtests/ssl_gtest/ssl_cipherorder_unittest.cc
security/nss/gtests/ssl_gtest/ssl_gtest.gyp
security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc
security/nss/lib/jar/jarfile.c
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/sslexp.h
security/nss/lib/ssl/sslsock.c
security/nss/tests/policy/policy.sh
security/nss/tests/smime/smime.sh
security/nss/tests/ssl/ssl.sh
security/nss/tests/tlsfuzzer/config.json.in
security/nss/tests/tlsfuzzer/tlsfuzzer.sh
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-a3ee4f26b4c1
\ No newline at end of file
+03039d4fad57
\ No newline at end of file
--- a/security/nss/automation/taskcluster/docker-gcc-4.4/Dockerfile
+++ b/security/nss/automation/taskcluster/docker-gcc-4.4/Dockerfile
@@ -4,16 +4,17 @@ LABEL maintainer="Martin Thomson <martin
 RUN dpkg --add-architecture i386
 RUN apt-get update \
  && apt-get install -y --no-install-recommends \
     ca-certificates \
     g++-4.4 \
     gcc-4.4 \
     locales \
     make \
+    patch \
     mercurial \
     zlib1g-dev \
  && rm -rf /var/lib/apt/lists/* \
  && apt-get autoremove -y && apt-get clean -y
 
 ENV SHELL /bin/bash
 ENV USER worker
 ENV LOGNAME $USER
--- a/security/nss/automation/taskcluster/graph/src/try_syntax.js
+++ b/security/nss/automation/taskcluster/graph/src/try_syntax.js
@@ -178,11 +178,22 @@ export async function initFilter() {
     }
   }
 
   // Check for try syntax in changeset comment.
   let match = comment.match(/\btry:\s*(.*)\s*$/m);
 
   // Add try syntax filter.
   if (match) {
-    queue.filter(filter(parseOptions(match[1])));
+    let match1 = match[1];
+    queue.filter(filter(parseOptions(match1)));
+
+    if (match1.includes("--nspr-patch")) {
+      queue.map(task => {
+        if (!task.env) {
+          task.env = {};
+        }
+        task.env.ALLOW_NSPR_PATCH = "1";
+        return task;
+      });
+    }
   }
 }
--- a/security/nss/automation/taskcluster/scripts/build.sh
+++ b/security/nss/automation/taskcluster/scripts/build.sh
@@ -8,14 +8,20 @@ if [ -n "$NSS_BUILD_MODULAR" ]; then
     $(dirname "$0")/build_softoken.sh || exit $?
     $(dirname "$0")/build_nss.sh || exit $?
     exit
 fi
 
 # Clone NSPR if needed.
 hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
 
+if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+  pushd nspr
+  cat ../nss/nspr.patch | patch -p1
+  popd
+fi
+
 # Build.
 make -C nss nss_build_all
 
 # Package.
 mkdir artifacts
 tar cvfjh artifacts/dist.tar.bz2 dist
--- a/security/nss/automation/taskcluster/scripts/build_gyp.sh
+++ b/security/nss/automation/taskcluster/scripts/build_gyp.sh
@@ -1,15 +1,21 @@
 #!/usr/bin/env bash
 
 source $(dirname "$0")/tools.sh
 
 # Clone NSPR if needed.
 hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
 
+if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+  pushd nspr
+  cat ../nss/nspr.patch | patch -p1
+  popd
+fi
+
 # Build.
 nss/build.sh -g -v --enable-libpkix "$@"
 
 # Package.
 if [[ $(uname) = "Darwin" ]]; then
   mkdir -p public
   tar cvfjh public/dist.tar.bz2 dist
 else
--- a/security/nss/automation/taskcluster/scripts/build_nspr.sh
+++ b/security/nss/automation/taskcluster/scripts/build_nspr.sh
@@ -2,16 +2,22 @@
 
 set -v -e -x
 
 source $(dirname $0)/tools.sh
 
 # Clone NSPR if needed.
 hg_clone https://hg.mozilla.org/projects/nspr nspr default
 
+if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+  pushd nspr
+  cat ../nss/nspr.patch | patch -p1
+  popd
+fi
+
 # Build.
 rm -rf dist
 make -C nss build_nspr
 
 # Package.
 test -d artifacts || mkdir artifacts
 rm -rf dist-nspr
 mv dist dist-nspr
--- a/security/nss/automation/taskcluster/scripts/check_abi.sh
+++ b/security/nss/automation/taskcluster/scripts/check_abi.sh
@@ -15,16 +15,22 @@ set_env()
   if [ ! -d "nspr" ]; then
     for i in 0 2 5; do
       sleep $i
       hg clone -r "default" "https://hg.mozilla.org/projects/nspr" "${HGDIR}/nspr" && break
       rm -rf nspr
     done
   fi
 
+  if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+    pushd nspr
+    cat ../nss/nspr.patch | patch -p1
+    popd
+  fi
+
   cd nss
   ./build.sh -v -c
   cd ..
 }
 
 check_abi()
 {
   set_env
--- a/security/nss/automation/taskcluster/scripts/gen_coverage_report.sh
+++ b/security/nss/automation/taskcluster/scripts/gen_coverage_report.sh
@@ -1,12 +1,18 @@
 #!/usr/bin/env bash
 
 source $(dirname "$0")/tools.sh
 
 # Clone NSPR.
 hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
 
+if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+  pushd nspr
+  cat ../nss/nspr.patch | patch -p1
+  popd
+fi
+
 out=/home/worker/artifacts
 mkdir -p $out
 
 # Generate coverage report.
 cd nss && ./mach coverage --outdir=$out ssl_gtests
--- a/security/nss/automation/taskcluster/scripts/run_coverity.sh
+++ b/security/nss/automation/taskcluster/scripts/run_coverity.sh
@@ -1,15 +1,21 @@
 #!/usr/bin/env bash
 
 source $(dirname "$0")/tools.sh
 
 # Clone NSPR if needed.
 if [ ! -d "nspr" ]; then
     hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
+
+  if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+    pushd nspr
+    cat ../nss/nspr.patch | patch -p1
+    popd
+  fi
 fi
 
 # Build and run Coverity
 cd nss
 ./mach static-analysis
 
 # Return the exit code of the Coverity Analysis
-exit $?
\ No newline at end of file
+exit $?
--- a/security/nss/automation/taskcluster/scripts/run_scan_build.sh
+++ b/security/nss/automation/taskcluster/scripts/run_scan_build.sh
@@ -1,15 +1,21 @@
 #!/usr/bin/env bash
 
 source $(dirname "$0")/tools.sh
 
 # Clone NSPR if needed.
 if [ ! -d "nspr" ]; then
     hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
+
+    if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+      pushd nspr
+      cat ../nss/nspr.patch | patch -p1
+      popd
+    fi
 fi
 
 # Build.
 cd nss
 make nss_build_all
 
 # What we want to scan.
 # key: directory to scan
--- a/security/nss/automation/taskcluster/windows/build.sh
+++ b/security/nss/automation/taskcluster/windows/build.sh
@@ -7,13 +7,19 @@ if [[ "$USE_64" == 1 ]]; then
 else
     m=x86
 fi
 source "$(dirname "$0")/setup.sh"
 
 # Clone NSPR.
 hg_clone https://hg.mozilla.org/projects/nspr nspr default
 
+if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+  pushd nspr
+  cat ../nss/nspr.patch | patch -p1
+  popd
+fi
+
 # Build.
 make -C nss nss_build_all
 
 # Package.
 7z a public/build/dist.7z dist
--- a/security/nss/automation/taskcluster/windows/build_gyp.sh
+++ b/security/nss/automation/taskcluster/windows/build_gyp.sh
@@ -26,13 +26,19 @@ export GYP_MSVS_OVERRIDE_PATH="${VSPATH}
 export GYP_MSVS_VERSION=2015
 popd
 
 export PATH="${PATH}:${PWD}/ninja/bin:${PWD}/gyp/test-env/Scripts"
 
 # Clone NSPR.
 hg_clone https://hg.mozilla.org/projects/nspr nspr default
 
+if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+  pushd nspr
+  cat ../nss/nspr.patch | patch -p1
+  popd
+fi
+
 # Build with gyp.
 ./nss/build.sh -g -v --enable-libpkix "$@"
 
 # Package.
 7z a public/build/dist.7z dist
--- a/security/nss/cmd/symkeyutil/symkeyutil.c
+++ b/security/nss/cmd/symkeyutil/symkeyutil.c
@@ -249,17 +249,17 @@ BufToHex(SECItem *outbuf)
 int
 HexToBuf(char *inString, SECItem *outbuf)
 {
     int len = strlen(inString);
     int outlen = len + 1 / 2;
     int trueLen = 0;
 
     outbuf->data = PORT_Alloc(outlen);
-    if (outbuf->data) {
+    if (!outbuf->data) {
         return -1;
     }
 
     while (*inString) {
         int digit1, digit2;
         digit1 = GetDigit(*inString++);
         digit2 = GetDigit(*inString++);
         if ((digit1 == -1) || (digit2 == -1)) {
--- 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/gtests/ssl_gtest/manifest.mn
+++ b/security/nss/gtests/ssl_gtest/manifest.mn
@@ -12,16 +12,17 @@ CSRCS = \
       $(NULL)
 
 CPPSRCS = \
       bloomfilter_unittest.cc \
       ssl_0rtt_unittest.cc \
       ssl_agent_unittest.cc \
       ssl_auth_unittest.cc \
       ssl_cert_ext_unittest.cc \
+      ssl_cipherorder_unittest.cc \
       ssl_ciphersuite_unittest.cc \
       ssl_custext_unittest.cc \
       ssl_damage_unittest.cc \
       ssl_debug_env_unittest.cc \
       ssl_dhe_unittest.cc \
       ssl_drop_unittest.cc \
       ssl_ecdh_unittest.cc \
       ssl_ems_unittest.cc \
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/ssl_gtest/ssl_cipherorder_unittest.cc
@@ -0,0 +1,241 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ssl.h"
+#include "sslerr.h"
+#include "sslproto.h"
+
+#include <memory>
+
+#include "tls_connect.h"
+#include "tls_filter.h"
+
+namespace nss_test {
+
+class TlsCipherOrderTest : public TlsConnectTestBase {
+ protected:
+  virtual void ConfigureTLS() {
+    EnsureTlsSetup();
+    ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+  }
+
+  virtual SECStatus BuildTestLists(std::vector<uint16_t> &cs_initial_list,
+                                   std::vector<uint16_t> &cs_new_list) {
+    // This is the current CipherSuites order of enabled CipherSuites as defined
+    // in ssl3con.c
+    const PRUint16 *kCipherSuites = SSL_GetImplementedCiphers();
+
+    for (unsigned int i = 0; i < kNumImplementedCiphers; i++) {
+      PRBool pref = PR_FALSE, policy = PR_FALSE;
+      SECStatus rv;
+      rv = SSL_CipherPolicyGet(kCipherSuites[i], &policy);
+      if (rv != SECSuccess) {
+        return SECFailure;
+      }
+      rv = SSL_CipherPrefGetDefault(kCipherSuites[i], &pref);
+      if (rv != SECSuccess) {
+        return SECFailure;
+      }
+      if (pref && policy) {
+        cs_initial_list.push_back(kCipherSuites[i]);
+      }
+    }
+
+    // We will test set function with the first 15 enabled ciphers.
+    const PRUint16 kNumCiphersToSet = 15;
+    for (unsigned int i = 0; i < kNumCiphersToSet; i++) {
+      cs_new_list.push_back(cs_initial_list[i]);
+    }
+    cs_new_list[0] = cs_initial_list[1];
+    cs_new_list[1] = cs_initial_list[0];
+    return SECSuccess;
+  }
+
+ public:
+  TlsCipherOrderTest() : TlsConnectTestBase(ssl_variant_stream, 0) {}
+  const unsigned int kNumImplementedCiphers = SSL_GetNumImplementedCiphers();
+};
+
+const PRUint16 kCSUnsupported[] = {20196, 10101};
+const PRUint16 kNumCSUnsupported = PR_ARRAY_SIZE(kCSUnsupported);
+const PRUint16 kCSEmpty[] = {0};
+
+// Get the active CipherSuites odered as they were compiled
+TEST_F(TlsCipherOrderTest, CipherOrderGet) {
+  std::vector<uint16_t> initial_cs_order;
+  std::vector<uint16_t> new_cs_order;
+  SECStatus result = BuildTestLists(initial_cs_order, new_cs_order);
+  ASSERT_EQ(result, SECSuccess);
+  ConfigureTLS();
+
+  std::vector<uint16_t> current_cs_order(SSL_GetNumImplementedCiphers() + 1);
+  unsigned int current_num_active_cs = 0;
+  result = SSL_CipherSuiteOrderGet(client_->ssl_fd(), current_cs_order.data(),
+                                   &current_num_active_cs);
+  ASSERT_EQ(result, SECSuccess);
+  ASSERT_EQ(current_num_active_cs, initial_cs_order.size());
+  for (unsigned int i = 0; i < initial_cs_order.size(); i++) {
+    EXPECT_EQ(initial_cs_order[i], current_cs_order[i]);
+  }
+  // Get the chosen CipherSuite during the Handshake without any modification.
+  Connect();
+  SSLChannelInfo channel;
+  result = SSL_GetChannelInfo(client_->ssl_fd(), &channel, sizeof channel);
+  ASSERT_EQ(result, SECSuccess);
+  EXPECT_EQ(channel.cipherSuite, initial_cs_order[0]);
+}
+
+// The "server" used for gtests honor only its ciphersuites order.
+// So, we apply the new set for the server instead of client.
+// This is enough to test the effect of SSL_CipherSuiteOrderSet function.
+TEST_F(TlsCipherOrderTest, CipherOrderSet) {
+  std::vector<uint16_t> initial_cs_order;
+  std::vector<uint16_t> new_cs_order;
+  SECStatus result = BuildTestLists(initial_cs_order, new_cs_order);
+  ASSERT_EQ(result, SECSuccess);
+  ConfigureTLS();
+
+  // change the server_ ciphersuites order.
+  result = SSL_CipherSuiteOrderSet(server_->ssl_fd(), new_cs_order.data(),
+                                   new_cs_order.size());
+  ASSERT_EQ(result, SECSuccess);
+
+  // The function expect an array. We are using vector for VStudio
+  // compatibility.
+  std::vector<uint16_t> current_cs_order(SSL_GetNumImplementedCiphers() + 1);
+  unsigned int current_num_active_cs = 0;
+  result = SSL_CipherSuiteOrderGet(server_->ssl_fd(), current_cs_order.data(),
+                                   &current_num_active_cs);
+  ASSERT_EQ(result, SECSuccess);
+  ASSERT_EQ(current_num_active_cs, new_cs_order.size());
+  for (unsigned int i = 0; i < new_cs_order.size(); i++) {
+    ASSERT_EQ(new_cs_order[i], current_cs_order[i]);
+  }
+
+  Connect();
+  SSLChannelInfo channel;
+  // changes in server_ order reflect in client chosen ciphersuite.
+  result = SSL_GetChannelInfo(client_->ssl_fd(), &channel, sizeof channel);
+  ASSERT_EQ(result, SECSuccess);
+  EXPECT_EQ(channel.cipherSuite, new_cs_order[0]);
+}
+
+// Duplicate socket configuration from a model.
+TEST_F(TlsCipherOrderTest, CipherOrderCopySocket) {
+  std::vector<uint16_t> initial_cs_order;
+  std::vector<uint16_t> new_cs_order;
+  SECStatus result = BuildTestLists(initial_cs_order, new_cs_order);
+  ASSERT_EQ(result, SECSuccess);
+  ConfigureTLS();
+
+  // Use the existing sockets for this test.
+  result = SSL_CipherSuiteOrderSet(client_->ssl_fd(), new_cs_order.data(),
+                                   new_cs_order.size());
+  ASSERT_EQ(result, SECSuccess);
+
+  std::vector<uint16_t> current_cs_order(SSL_GetNumImplementedCiphers() + 1);
+  unsigned int current_num_active_cs = 0;
+  result = SSL_CipherSuiteOrderGet(server_->ssl_fd(), current_cs_order.data(),
+                                   &current_num_active_cs);
+  ASSERT_EQ(result, SECSuccess);
+  ASSERT_EQ(current_num_active_cs, initial_cs_order.size());
+  for (unsigned int i = 0; i < current_num_active_cs; i++) {
+    ASSERT_EQ(initial_cs_order[i], current_cs_order[i]);
+  }
+
+  // Import/Duplicate configurations from client_ to server_
+  PRFileDesc *rv = SSL_ImportFD(client_->ssl_fd(), server_->ssl_fd());
+  EXPECT_NE(nullptr, rv);
+
+  result = SSL_CipherSuiteOrderGet(server_->ssl_fd(), current_cs_order.data(),
+                                   &current_num_active_cs);
+  ASSERT_EQ(result, SECSuccess);
+  ASSERT_EQ(current_num_active_cs, new_cs_order.size());
+  for (unsigned int i = 0; i < new_cs_order.size(); i++) {
+    EXPECT_EQ(new_cs_order.data()[i], current_cs_order[i]);
+  }
+}
+
+// If the infomed num of elements is lower than the actual list size, only the
+// first "informed num" elements will be considered. The rest is ignored.
+TEST_F(TlsCipherOrderTest, CipherOrderSetLower) {
+  std::vector<uint16_t> initial_cs_order;
+  std::vector<uint16_t> new_cs_order;
+  SECStatus result = BuildTestLists(initial_cs_order, new_cs_order);
+  ASSERT_EQ(result, SECSuccess);
+  ConfigureTLS();
+
+  result = SSL_CipherSuiteOrderSet(client_->ssl_fd(), new_cs_order.data(),
+                                   new_cs_order.size() - 1);
+  ASSERT_EQ(result, SECSuccess);
+
+  std::vector<uint16_t> current_cs_order(SSL_GetNumImplementedCiphers() + 1);
+  unsigned int current_num_active_cs = 0;
+  result = SSL_CipherSuiteOrderGet(client_->ssl_fd(), current_cs_order.data(),
+                                   &current_num_active_cs);
+  ASSERT_EQ(result, SECSuccess);
+  ASSERT_EQ(current_num_active_cs, new_cs_order.size() - 1);
+  for (unsigned int i = 0; i < new_cs_order.size() - 1; i++) {
+    ASSERT_EQ(new_cs_order.data()[i], current_cs_order[i]);
+  }
+}
+
+// Testing Errors Controls
+TEST_F(TlsCipherOrderTest, CipherOrderSetControls) {
+  std::vector<uint16_t> initial_cs_order;
+  std::vector<uint16_t> new_cs_order;
+  SECStatus result = BuildTestLists(initial_cs_order, new_cs_order);
+  ASSERT_EQ(result, SECSuccess);
+  ConfigureTLS();
+
+  // Create a new vector with diplicated entries
+  std::vector<uint16_t> repeated_cs_order(SSL_GetNumImplementedCiphers() + 1);
+  std::copy(initial_cs_order.begin(), initial_cs_order.end(),
+            repeated_cs_order.begin());
+  repeated_cs_order[0] = repeated_cs_order[1];
+
+  // Repeated ciphersuites in the list
+  result = SSL_CipherSuiteOrderSet(client_->ssl_fd(), repeated_cs_order.data(),
+                                   initial_cs_order.size());
+  EXPECT_EQ(result, SECFailure);
+
+  // Zero size for the sent list
+  result = SSL_CipherSuiteOrderSet(client_->ssl_fd(), new_cs_order.data(), 0);
+  EXPECT_EQ(result, SECFailure);
+
+  // Wrong size, greater than actual
+  result = SSL_CipherSuiteOrderSet(client_->ssl_fd(), new_cs_order.data(),
+                                   SSL_GetNumImplementedCiphers() + 1);
+  EXPECT_EQ(result, SECFailure);
+
+  // Wrong ciphersuites, not implemented
+  result = SSL_CipherSuiteOrderSet(client_->ssl_fd(), kCSUnsupported,
+                                   kNumCSUnsupported);
+  EXPECT_EQ(result, SECFailure);
+
+  // Null list
+  result =
+      SSL_CipherSuiteOrderSet(client_->ssl_fd(), nullptr, new_cs_order.size());
+  EXPECT_EQ(result, SECFailure);
+
+  // Empty list
+  result =
+      SSL_CipherSuiteOrderSet(client_->ssl_fd(), kCSEmpty, new_cs_order.size());
+  EXPECT_EQ(result, SECFailure);
+
+  // Confirm that the controls are working, as the current ciphersuites
+  // remained untouched
+  std::vector<uint16_t> current_cs_order(SSL_GetNumImplementedCiphers() + 1);
+  unsigned int current_num_active_cs = 0;
+  result = SSL_CipherSuiteOrderGet(client_->ssl_fd(), current_cs_order.data(),
+                                   &current_num_active_cs);
+  ASSERT_EQ(result, SECSuccess);
+  ASSERT_EQ(current_num_active_cs, initial_cs_order.size());
+  for (unsigned int i = 0; i < initial_cs_order.size(); i++) {
+    ASSERT_EQ(initial_cs_order[i], current_cs_order[i]);
+  }
+}
+}  // namespace nss_test
--- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
+++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
@@ -13,16 +13,17 @@
       'sources': [
         'bloomfilter_unittest.cc',
         'libssl_internals.c',
         'selfencrypt_unittest.cc',
         'ssl_0rtt_unittest.cc',
         'ssl_agent_unittest.cc',
         'ssl_auth_unittest.cc',
         'ssl_cert_ext_unittest.cc',
+        'ssl_cipherorder_unittest.cc',
         'ssl_ciphersuite_unittest.cc',
         'ssl_custext_unittest.cc',
         'ssl_damage_unittest.cc',
         'ssl_debug_env_unittest.cc',
         'ssl_dhe_unittest.cc',
         'ssl_drop_unittest.cc',
         'ssl_ecdh_unittest.cc',
         'ssl_ems_unittest.cc',
--- a/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc
@@ -225,24 +225,25 @@ TEST_P(TlsConnectTls13, RecordSizePlaint
 
   // Consume the alert at the server.
   server_->Handshake();
   server_->CheckErrorCode(SSL_ERROR_RECORD_OVERFLOW_ALERT);
 }
 
 // Tweak the ciphertext of server records so that they greatly exceed the limit.
 // This requires a much larger expansion than for plaintext to trigger the
-// guard, which runs before decryption (current allowance is 304 octets).
+// guard, which runs before decryption (current allowance is 320 octets,
+// see MAX_EXPANSION in ssl3con.c).
 TEST_P(TlsConnectTls13, RecordSizeCiphertextExceed) {
   EnsureTlsSetup();
 
   client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
   Connect();
 
-  auto server_expand = MakeTlsFilter<TlsRecordExpander>(server_, 320);
+  auto server_expand = MakeTlsFilter<TlsRecordExpander>(server_, 336);
   server_->SendData(100);
 
   client_->ExpectReadWriteError();
   ExpectAlert(client_, kTlsAlertRecordOverflow);
   client_->ReadBytes(100);
   EXPECT_EQ(SSL_ERROR_RX_RECORD_TOO_LONG, client_->error_code());
 
   // Consume the alert at the server.
--- a/security/nss/lib/jar/jarfile.c
+++ b/security/nss/lib/jar/jarfile.c
@@ -203,23 +203,22 @@ JAR_extract(JAR *jar, char *path, char *
     }
     if (jar->fp == NULL) {
         /* file not found */
         return JAR_ERR_FNF;
     }
 
     phy = jar_get_physical(jar, path);
     if (phy) {
-        if (phy->compression != 0 && phy->compression != 8) {
-            /* unsupported compression method */
-            result = JAR_ERR_CORRUPT;
-        }
         if (phy->compression == 0) {
             result = jar_physical_extraction((PRFileDesc *)jar->fp, outpath, phy->offset, phy->length);
         } else {
+            /* compression methods other than 8 are unsupported,
+             * but for historical reasons, jar_physical_inflate will be called for
+             * unsupported compression method constants too. */
             result = jar_physical_inflate((PRFileDesc *)jar->fp, outpath,
                                           phy->offset, phy->length,
                                           (unsigned int)phy->compression);
         }
 
 #if defined(XP_UNIX) || defined(XP_BEOS)
         if (phy->mode)
             chmod(outpath, 0400 | (mode_t)phy->mode);
@@ -300,42 +299,41 @@ jar_physical_inflate(JAR_FILE fp, char *
     z_stream zs;
     JAR_FILE out;
 
     /* Raw inflate in zlib 1.1.4 needs an extra dummy byte at the end */
     if ((inbuf = (char *)PORT_ZAlloc(ICHUNK + 1)) == NULL)
         return JAR_ERR_MEMORY;
 
     if ((outbuf = (char *)PORT_ZAlloc(OCHUNK)) == NULL) {
-        PORT_Free(inbuf);
-        return JAR_ERR_MEMORY;
+        status = JAR_ERR_MEMORY;
+        goto loser;
     }
 
     PORT_Memset(&zs, 0, sizeof(zs));
     status = inflateInit2(&zs, -MAX_WBITS);
     if (status != Z_OK) {
-        PORT_Free(inbuf);
-        PORT_Free(outbuf);
-        return JAR_ERR_GENERAL;
+        status = JAR_ERR_GENERAL;
+        goto loser;
     }
 
     if ((out = JAR_FOPEN(outpath, "wb")) != NULL) {
+        int status2 = 0;
         unsigned long at = 0;
 
         JAR_FSEEK(fp, offset, (PRSeekWhence)0);
         while (at < length) {
             unsigned long chunk = (at + ICHUNK <= length) ? ICHUNK : length - at;
             unsigned long tin;
 
             if (JAR_FREAD(fp, inbuf, chunk) != chunk) {
                 /* incomplete read */
                 JAR_FCLOSE(out);
-                PORT_Free(inbuf);
-                PORT_Free(outbuf);
-                return JAR_ERR_CORRUPT;
+                status = JAR_ERR_CORRUPT;
+                break;
             }
             at += chunk;
             if (at == length) {
                 /* add an extra dummy byte at the end */
                 inbuf[chunk++] = 0xDD;
             }
             zs.next_in = (Bytef *)inbuf;
             zs.avail_in = chunk;
@@ -346,38 +344,48 @@ jar_physical_inflate(JAR_FILE fp, char *
                 unsigned long ochunk;
 
                 zs.next_out = (Bytef *)outbuf;
                 zs.avail_out = OCHUNK;
                 status = inflate(&zs, Z_NO_FLUSH);
                 if (status != Z_OK && status != Z_STREAM_END) {
                     /* error during decompression */
                     JAR_FCLOSE(out);
-                    PORT_Free(inbuf);
-                    PORT_Free(outbuf);
-                    return JAR_ERR_CORRUPT;
+                    status = JAR_ERR_CORRUPT;
+                    break;
                 }
                 ochunk = zs.total_out - prev_total;
                 if (JAR_FWRITE(out, outbuf, ochunk) < (long)ochunk) {
                     /* most likely a disk full error */
                     status = JAR_ERR_DISK;
                     break;
                 }
                 if (status == Z_STREAM_END)
                     break;
             }
+            if (status != Z_OK) {
+                break;
+            }
         }
         JAR_FCLOSE(out);
-        status = inflateEnd(&zs);
+        status2 = inflateEnd(&zs);
+        if (status == Z_OK) {
+            status = status2;
+        }
     } else {
         /* error opening output file */
         status = JAR_ERR_DISK;
     }
-    PORT_Free(inbuf);
-    PORT_Free(outbuf);
+loser:
+    if (inbuf) {
+        PORT_Free(inbuf);
+    }
+    if (outbuf) {
+        PORT_Free(outbuf);
+    }
     return status;
 }
 
 /*
  *  j a r _ i n f l a t e _ m e m o r y
  *
  *  Call zlib to inflate the given memory chunk. It is re-XP_ALLOC'd,
  *  and thus appears to operate inplace to the caller.
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -900,18 +900,19 @@ static unsigned int
 count_cipher_suites(sslSocket *ss, PRUint8 policy)
 {
     unsigned int i, count = 0;
 
     if (SSL_ALL_VERSIONS_DISABLED(&ss->vrange)) {
         return 0;
     }
     for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
-        if (ssl3_config_match(&ss->cipherSuites[i], policy, &ss->vrange, ss))
+        if (ssl3_config_match(&ss->cipherSuites[i], policy, &ss->vrange, ss)) {
             count++;
+        }
     }
     if (count == 0) {
         PORT_SetError(SSL_ERROR_SSL_DISABLED);
     }
     return count;
 }
 
 /* For TLS 1.3, when resuming, check for a ciphersuite that is both compatible
@@ -5215,16 +5216,17 @@ ssl3_SendClientHello(sslSocket *ss, sslC
     if (fallbackSCSV) {
         rv = ssl3_AppendHandshakeNumber(ss, TLS_FALLBACK_SCSV,
                                         sizeof(ssl3CipherSuite));
         if (rv != SECSuccess) {
             goto loser; /* err set by ssl3_AppendHandshake* */
         }
         actual_count++;
     }
+    /* CipherSuites are appended to Hello message here */
     for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
         ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
         if (ssl3_config_match(suite, ss->ssl3.policy, &ss->vrange, ss)) {
             actual_count++;
             if (actual_count > num_suites) {
                 /* set error card removal/insertion error */
                 PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
                 goto loser;
@@ -12651,18 +12653,19 @@ ssl3_GetCipherSpec(sslSocket *ss, SSL3Ci
     }
     SSL_TRC(10, ("%d: DTLS[%d]: Couldn't find cipherspec from epoch %d",
                  SSL_GETPID(), ss->fd, epoch));
     return NULL;
 }
 
 /* MAX_EXPANSION is the amount by which a record might plausibly be expanded
  * when protected.  It's the worst case estimate, so the sum of block cipher
- * padding (up to 256 octets) and HMAC (48 octets for SHA-384). */
-#define MAX_EXPANSION (256 + 48)
+ * padding (up to 256 octets), HMAC (48 octets for SHA-384), and IV (16
+ * octets for AES). */
+#define MAX_EXPANSION (256 + 48 + 16)
 
 /* if cText is non-null, then decipher and check the MAC of the
  * SSL record from cText->buf (typically gs->inbuf)
  * into databuf (typically gs->buf), and any previous contents of databuf
  * is lost.  Then handle databuf according to its SSL record type,
  * unless it's an application record.
  *
  * If cText is NULL, then the ciphertext has previously been deciphered and
--- a/security/nss/lib/ssl/sslexp.h
+++ b/security/nss/lib/ssl/sslexp.h
@@ -782,16 +782,55 @@ typedef PRTime(PR_CALLBACK *SSLTimeFunc)
                           const SECKEYPublicKey *_dcPub,                      \
                           SSLSignatureScheme _dcCertVerifyAlg,                \
                           PRUint32 _dcValidFor,                               \
                           PRTime _now,                                        \
                           SECItem *_out),                                     \
                          (cert, certPriv, dcPub, dcCertVerifyAlg, dcValidFor, \
                           now, out))
 
+/* New functions created to permit get/set the CipherSuites Order for the
+ * handshake (Client Hello).
+ *
+ * The *Get function puts the current set of active (enabled and policy set as
+ * PR_TRUE) cipher suites in the cipherOrder outparam. Cipher suites that 
+ * aren't active aren't included. The paramenters are:
+ *   - PRFileDesc *fd = FileDescriptor to get information.
+ *   - PRUint16 *cipherOrder = The memory allocated for cipherOrder needs to be
+ *     SSL_GetNumImplementedCiphers() * sizeof(PRUint16) or more.
+ *   - PRUint16 numCiphers = The number of active ciphersuites listed in 
+ *     *cipherOrder is written here.
+ *
+ * The *Set function permits reorder the CipherSuites list for the Handshake
+ * (Client Hello). The default ordering defined in ssl3con.c is enough in
+ * almost all cases. But, if the client needs some hardening or performance
+ * adjusts related to CipherSuites, this can be done with this function.
+ * The caller has to be aware about the risk of call this function while a
+ * handshake are being processed in this fd/socket. For example, if you disable
+ * a cipher after the handshake and this cipher was choosen for that
+ * connection, something bad will happen.
+ * The parameters are:
+ *   - PRFileDesc *fd = FileDescriptor to change.
+ *   - const PRUint16 *cipherOrder = Must receive all ciphers to be ordered, in
+ *     the desired order. They will be set in the begin of the list. Only
+ *     suites listed by SSL_ImplementedCiphers() can be included.
+ *   - PRUint16 numCiphers = Must receive the number of items in *cipherOrder. 
+ * */
+#define SSL_CipherSuiteOrderGet(fd, cipherOrder, numCiphers)         \
+    SSL_EXPERIMENTAL_API("SSL_CipherSuiteOrderGet",                  \
+                         (PRFileDesc * _fd, PRUint16 * _cipherOrder, \
+                          unsigned int *_numCiphers),                \
+                         (fd, cipherOrder, numCiphers))
+
+#define SSL_CipherSuiteOrderSet(fd, cipherOrder, numCiphers)              \
+    SSL_EXPERIMENTAL_API("SSL_CipherSuiteOrderSet",                       \
+                         (PRFileDesc * _fd, const PRUint16 *_cipherOrder, \
+                          PRUint16 _numCiphers),                          \
+                         (fd, cipherOrder, numCiphers))
+
 /* Deprecated experimental APIs */
 #define SSL_UseAltServerHelloType(fd, enable) SSL_DEPRECATED_EXPERIMENTAL_API
 #define SSL_SetupAntiReplay(a, b, c) SSL_DEPRECATED_EXPERIMENTAL_API
 #define SSL_InitAntiReplay(a, b, c) SSL_DEPRECATED_EXPERIMENTAL_API
 
 SEC_END_PROTOS
 
 #endif /* __sslexp_h_ */
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -1535,16 +1535,129 @@ SSL_CipherPrefGet(PRFileDesc *fd, PRInt3
         *enabled = PR_FALSE;
         rv = SECSuccess;
     } else {
         rv = ssl3_CipherPrefGet(ss, (ssl3CipherSuite)which, enabled);
     }
     return rv;
 }
 
+/* The client can call this function to be aware of the current
+ * CipherSuites order. */
+SECStatus
+SSLExp_CipherSuiteOrderGet(PRFileDesc *fd, PRUint16 *cipherOrder,
+                           unsigned int *numCiphers)
+{
+    if (!fd) {
+        SSL_DBG(("%d: SSL: file descriptor in CipherSuiteOrderGet is null",
+                 SSL_GETPID()));
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+    if (!cipherOrder || !numCiphers) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+    sslSocket *ss = ssl_FindSocket(fd);
+    if (!ss) {
+        SSL_DBG(("%d: SSL[%d]: bad socket in CipherSuiteOrderGet", SSL_GETPID(),
+                 fd));
+        return SECFailure; /* Error code already set. */
+    }
+
+    unsigned int enabled = 0;
+    ssl_Get1stHandshakeLock(ss);
+    ssl_GetSSL3HandshakeLock(ss);
+    for (unsigned int i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
+        const ssl3CipherSuiteCfg *suiteCfg = &ss->cipherSuites[i];
+        if (suiteCfg && suiteCfg->enabled &&
+            suiteCfg->policy != SSL_NOT_ALLOWED) {
+            cipherOrder[enabled++] = suiteCfg->cipher_suite;
+        }
+    }
+    ssl_ReleaseSSL3HandshakeLock(ss);
+    ssl_Release1stHandshakeLock(ss);
+    *numCiphers = enabled;
+    return SECSuccess;
+}
+
+/* This function permits reorder the CipherSuites List for the Handshake
+ * (Client Hello). */
+SECStatus
+SSLExp_CipherSuiteOrderSet(PRFileDesc *fd, const PRUint16 *cipherOrder,
+                           unsigned int numCiphers)
+{
+    if (!fd) {
+        SSL_DBG(("%d: SSL: file descriptor in CipherSuiteOrderGet is null",
+                 SSL_GETPID()));
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+    if (!cipherOrder || !numCiphers || numCiphers > ssl_V3_SUITES_IMPLEMENTED) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+    sslSocket *ss = ssl_FindSocket(fd);
+    if (!ss) {
+        SSL_DBG(("%d: SSL[%d]: bad socket in CipherSuiteOrderSet", SSL_GETPID(),
+                 fd));
+        return SECFailure; /* Error code already set. */
+    }
+    ssl3CipherSuiteCfg tmpSuiteCfg[ssl_V3_SUITES_IMPLEMENTED];
+    ssl_Get1stHandshakeLock(ss);
+    ssl_GetSSL3HandshakeLock(ss);
+    /* For each cipherSuite given as input, verify that it is
+     * known to NSS and only present in the list once. */
+    for (unsigned int i = 0; i < numCiphers; i++) {
+        const ssl3CipherSuiteCfg *suiteCfg =
+            ssl_LookupCipherSuiteCfg(cipherOrder[i], ss->cipherSuites);
+        if (!suiteCfg) {
+            PORT_SetError(SEC_ERROR_INVALID_ARGS);
+            ssl_ReleaseSSL3HandshakeLock(ss);
+            ssl_Release1stHandshakeLock(ss);
+            return SECFailure;
+        }
+        for (unsigned int j = i + 1; j < numCiphers; j++) {
+            /* This is a duplicate entry. */
+            if (cipherOrder[i] == cipherOrder[j]) {
+                PORT_SetError(SEC_ERROR_INVALID_ARGS);
+                ssl_ReleaseSSL3HandshakeLock(ss);
+                ssl_Release1stHandshakeLock(ss);
+                return SECFailure;
+            }
+        }
+        tmpSuiteCfg[i] = *suiteCfg;
+        tmpSuiteCfg[i].enabled = PR_TRUE;
+    }
+    /* Find all defined ciphersuites not present in the input list and append
+     * them after the preferred. This guarantees that the socket will always
+     * have a complete list of size ssl_V3_SUITES_IMPLEMENTED */
+    unsigned int cfgIdx = numCiphers;
+    for (unsigned int i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
+        PRBool received = PR_FALSE;
+        for (unsigned int j = 0; j < numCiphers; j++) {
+            if (ss->cipherSuites[i].cipher_suite ==
+                tmpSuiteCfg[j].cipher_suite) {
+                received = PR_TRUE;
+                break;
+            }
+        }
+        if (!received) {
+            tmpSuiteCfg[cfgIdx] = ss->cipherSuites[i];
+            tmpSuiteCfg[cfgIdx++].enabled = PR_FALSE;
+        }
+    }
+    PORT_Assert(cfgIdx == ssl_V3_SUITES_IMPLEMENTED);
+    /* now we can rewrite the socket with the desired order */
+    PORT_Memcpy(ss->cipherSuites, tmpSuiteCfg, sizeof(tmpSuiteCfg));
+    ssl_ReleaseSSL3HandshakeLock(ss);
+    ssl_Release1stHandshakeLock(ss);
+    return SECSuccess;
+}
+
 SECStatus
 NSS_SetDomesticPolicy(void)
 {
     SECStatus status = SECSuccess;
     const PRUint16 *cipher;
     SECStatus rv;
     PRUint32 policy;
 
@@ -4099,16 +4212,18 @@ SSL_CanBypass(CERTCertificate *cert, SEC
     }
 struct {
     const char *const name;
     void *function;
 } ssl_experimental_functions[] = {
 #ifndef SSL_DISABLE_EXPERIMENTAL_API
     EXP(AeadDecrypt),
     EXP(AeadEncrypt),
+    EXP(CipherSuiteOrderGet),
+    EXP(CipherSuiteOrderSet),
     EXP(CreateAntiReplayContext),
     EXP(DelegateCredential),
     EXP(DestroyAead),
     EXP(DestroyResumptionTokenInfo),
     EXP(EnableESNI),
     EXP(EncodeESNIKeys),
     EXP(GetCurrentEpoch),
     EXP(GetExtensionSupport),
--- a/security/nss/tests/policy/policy.sh
+++ b/security/nss/tests/policy/policy.sh
@@ -9,17 +9,17 @@
 # mozilla/security/nss/tests/policy/policy.sh
 #
 # Script to test NSS crypto policy code
 #
 ########################################################################
 
 ignore_blank_lines()
 {
-  LC_ALL=C grep -v '^[[:space:]]*\(#\|$\)' "$1"
+  LC_ALL=C egrep -v '^[[:space:]]*(#|$)' "$1"
 }
 
 policy_run_tests()
 {
   html_head "CRYPTO-POLICY"
 
   POLICY_INPUT=${QADIR}/policy/crypto-policy.txt
 
--- a/security/nss/tests/smime/smime.sh
+++ b/security/nss/tests/smime/smime.sh
@@ -14,16 +14,37 @@
 #
 # special strings
 # ---------------
 #   FIXME ... known problems, search for this string
 #   NOTE .... unexpected behavior
 #
 ########################################################################
 
+# parameter: MIME part boundary
+make_multipart()
+{
+  mp_start="Content-Type: multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha-HASHHASH; boundary=\"$1\"
+
+This is a cryptographically signed message in MIME format.
+
+--$1"
+
+  mp_middle="
+--$1
+Content-Type: application/pkcs7-signature; name=smime.p7s
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename=smime.p7s
+Content-Description: S/MIME Cryptographic Signature
+"
+
+  mp_end="--$1--
+"
+}
+
 ############################## smime_init ##############################
 # local shell function to initialize this script
 ########################################################################
 smime_init()
 {
   SCRIPTNAME=smime.sh      # sourced - $0 would point to all.sh
 
   if [ -z "${CLEANUP}" ] ; then     # if nobody else is responsible for
@@ -48,16 +69,26 @@ smime_init()
 
   SMIMEDIR=${HOSTDIR}/smime
   R_SMIMEDIR=../smime
   mkdir -p ${SMIMEDIR}
   cd ${SMIMEDIR}
   cp ${QADIR}/smime/alice.txt ${SMIMEDIR}
 
   mkdir tb
+
+  make_multipart "------------ms030903020902020502030404"
+  multipart_start="$mp_start"
+  multipart_middle="$mp_middle"
+  multipart_end="$mp_end"
+
+  make_multipart "------------ms010205070902020502030809"
+  multipart_start_b2="$mp_start"
+  multipart_middle_b2="$mp_middle"
+  multipart_end_b2="$mp_end"
 }
 
 cms_sign()
 {
   HASH_CMD="-H SHA${HASH}"
   SIG=sig.SHA${HASH}
 
   echo "$SCRIPTNAME: Signing Detached Message {$HASH} ------------------"
@@ -106,16 +137,21 @@ cms_sign()
   html_msg $? 0 "Compare Attached Signed Data and Original (ECDSA w/ ${HASH})" "."
 }
 
 header_mime_from_to_subject="MIME-Version: 1.0
 From: Alice@example.com
 To: Bob@example.com
 Subject: "
 
+header_dave_mime_from_to_subject="MIME-Version: 1.0
+From: Dave@example.com
+To: Bob@example.com
+Subject: "
+
 header_opaque_signed="Content-Type: application/pkcs7-mime; name=smime.p7m;
     smime-type=signed-data
 Content-Transfer-Encoding: base64
 Content-Disposition: attachment; filename=smime.p7m
 Content-Description: S/MIME Cryptographic Signature
 "
 
 header_enveloped="Content-Type: application/pkcs7-mime; name=smime.p7m;
@@ -125,33 +161,16 @@ Content-Disposition: attachment; filenam
 Content-Description: S/MIME Encrypted Message
 "
 
 header_clearsigned="Content-Type: text/plain; charset=utf-8; format=flowed
 Content-Transfer-Encoding: quoted-printable
 Content-Language: en-US
 "
 
-multipart_start="Content-Type: multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha-HASHHASH; boundary=\"------------ms030903020902020502030404\"
-
-This is a cryptographically signed message in MIME format.
-
---------------ms030903020902020502030404"
-
-multipart_middle="
---------------ms030903020902020502030404
-Content-Type: application/pkcs7-signature; name=smime.p7s
-Content-Transfer-Encoding: base64
-Content-Disposition: attachment; filename=smime.p7s
-Content-Description: S/MIME Cryptographic Signature
-"
-
-multipart_end="--------------ms030903020902020502030404--
-"
-
 header_plaintext="Content-Type: text/plain
 "
 
 CR=$(printf '\r')
 
 mime_init()
 {
   OUT="tb/alice.mime"
@@ -164,22 +183,25 @@ mime_init()
   cat alice.txt >>${OUT}
   sed -i"" "s/\$/${CR}/" ${OUT}
 }
 
 smime_enveloped()
 {
   ${PROFTOOL} ${BINDIR}/cmsutil -E -r bob@example.com -i tb/alice.mime -d ${P_R_ALICEDIR} -p nss -o tb/alice.mime.env
 
+  OUT="tb/alice.env"
+  echo "${header_enveloped}" >>${OUT}
+  cat "tb/alice.mime.env" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
+  echo >>${OUT}
+
   OUT="tb/alice.env.eml"
   echo -n "${header_mime_from_to_subject}" >>${OUT}
   echo "enveloped ${SIG}" >>${OUT}
-  echo "${header_enveloped}" >>${OUT}
-  cat "tb/alice.mime.env" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
-  echo >>${OUT}
+  cat "tb/alice.env" >>${OUT}
   sed -i"" "s/\$/${CR}/" ${OUT}
 }
 
 smime_signed_enveloped()
 {
   SIG=sig.SHA${HASH}
 
   ${PROFTOOL} ${BINDIR}/cmsutil -S -T -N Alice ${HASH_CMD} -i tb/alice.mime -d ${P_R_ALICEDIR} -p nss -o tb/alice.mime.d${SIG}
@@ -196,17 +218,17 @@ smime_signed_enveloped()
   OUT="tb/alice.d${SIG}.multipart.eml"
   echo -n "${header_mime_from_to_subject}" >>${OUT}
   echo "clear-signed ${SIG}" >>${OUT}
   cat "tb/alice.d${SIG}.multipart" >>${OUT}
   sed -i"" "s/\$/$CR/" ${OUT}
 
   OUT="tb/alice.d${SIG}.multipart.env.eml"
   echo -n "${header_mime_from_to_subject}" >>${OUT}
-  echo "enveloped clear-signed $SIG" >>${OUT}
+  echo "clear-signed then enveloped $SIG" >>${OUT}
   echo "$header_enveloped" >>${OUT}
   cat "tb/alice.d${SIG}.multipart.env" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
   echo >>${OUT}
   sed -i"" "s/\$/$CR/" ${OUT}
 
   ${PROFTOOL} ${BINDIR}/cmsutil -S -N Alice ${HASH_CMD} -i tb/alice.textplain -d ${P_R_ALICEDIR} -p nss -o tb/alice.textplain.${SIG}
 
   OUT="tb/alice.${SIG}.opaque"
@@ -219,17 +241,17 @@ smime_signed_enveloped()
   echo -n "${header_mime_from_to_subject}" >>${OUT}
   echo "opaque-signed $SIG" >>${OUT}
   cat "tb/alice.${SIG}.opaque" >>${OUT}
   echo >>${OUT}
   sed -i"" "s/\$/$CR/" ${OUT}
 
   OUT="tb/alice.${SIG}.opaque.env.eml"
   echo -n "${header_mime_from_to_subject}" >>${OUT}
-  echo "enveloped opaque-signed $SIG" >>${OUT}
+  echo "opaque-signed then enveloped $SIG" >>${OUT}
   echo "$header_enveloped" >>$OUT
   cat "tb/alice.${SIG}.opaque.env" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
   echo >>${OUT}
   sed -i"" "s/\$/$CR/" ${OUT}
 
   # bad messages below
 
   OUT="tb/alice.d${SIG}.multipart.bad.eml"
@@ -247,16 +269,177 @@ smime_signed_enveloped()
 
   OUT="tb/alice.d${SIG}.multipart.mismatch-econtent.eml"
   echo -n "${header_mime_from_to_subject}" >>${OUT}
   echo "BAD mismatch-econtent $SIG" >>${OUT}
   cat "tb/alice.d${SIG}.multipart.mismatch-econtent" >>${OUT}
   sed -i"" "s/\$/$CR/" ${OUT}
 }
 
+smime_plain_signed()
+{
+  SIG=sig.SHA${HASH}
+
+  ${PROFTOOL} ${BINDIR}/cmsutil -S -T -N Alice ${HASH_CMD} -i tb/alice.textplain -d ${P_R_ALICEDIR} -p nss -o tb/alice.plain.d${SIG}
+
+  OUT="tb/alice.plain.d${SIG}.multipart"
+  echo "${multipart_start}" | sed "s/HASHHASH/${HASH}/" >>${OUT}
+  cat tb/alice.textplain | sed 's/\r$//' >>${OUT}
+  echo "${multipart_middle}" >>${OUT}
+  cat tb/alice.plain.d${SIG} | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
+  echo "${multipart_end}" >>${OUT}
+
+  ${PROFTOOL} ${BINDIR}/cmsutil -S -N Alice ${HASH_CMD} -i tb/alice.textplain -d ${P_R_ALICEDIR} -p nss -o tb/alice.plain.${SIG}
+
+  OUT="tb/alice.plain.${SIG}.opaque"
+  echo "$header_opaque_signed" >>${OUT}
+  cat tb/alice.plain.${SIG} | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
+
+  # Second outer, opaque signature layer.
+
+  INPUT="tb/alice.plain.d${SIG}.multipart"
+  OUT_SIG="${INPUT}.dave.${SIG}"
+  ${PROFTOOL} ${BINDIR}/cmsutil -S -N Dave ${HASH_CMD} -i "$INPUT" -d ${P_R_DAVEDIR} -p nss -o "$OUT_SIG"
+
+  OUT_MIME="${OUT_SIG}.opaque"
+  echo "$header_opaque_signed" >>${OUT_MIME}
+  cat "$OUT_SIG" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT_MIME}
+
+  OUT_EML="${OUT_MIME}.eml"
+  echo -n "${header_dave_mime_from_to_subject}" >>${OUT_EML}
+  echo "clear-signed $SIG then opaque signed by dave" >>${OUT_EML}
+  cat "${OUT_MIME}" >>${OUT_EML}
+  echo >>${OUT_EML}
+  sed -i"" "s/\$/$CR/" ${OUT_EML}
+
+  INPUT="tb/alice.plain.${SIG}.opaque"
+  OUT_SIG="${INPUT}.dave.${SIG}"
+  ${PROFTOOL} ${BINDIR}/cmsutil -S -N Dave ${HASH_CMD} -i "$INPUT" -d ${P_R_DAVEDIR} -p nss -o "$OUT_SIG"
+
+  OUT_MIME="${OUT_SIG}.opaque"
+  echo "$header_opaque_signed" >>${OUT_MIME}
+  cat "$OUT_SIG" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT_MIME}
+
+  OUT_EML="${OUT_MIME}.eml"
+  echo -n "${header_dave_mime_from_to_subject}" >>${OUT_EML}
+  echo "opaque-signed $SIG then opaque signed by dave" >>${OUT_EML}
+  cat "${OUT_MIME}" >>${OUT_EML}
+  echo >>${OUT_EML}
+  sed -i"" "s/\$/$CR/" ${OUT_EML}
+
+  # Alternatively, second outer, multipart signature layer.
+
+  INPUT="tb/alice.plain.d${SIG}.multipart"
+  OUT_SIG="${INPUT}.dave.d${SIG}"
+  cat "$INPUT" | sed "s/\$/$CR/" > "${INPUT}.cr"
+  ${PROFTOOL} ${BINDIR}/cmsutil -S -T -N Dave ${HASH_CMD} -i "${INPUT}.cr" -d ${P_R_DAVEDIR} -p nss -o "$OUT_SIG"
+
+  OUT_MIME="${OUT_SIG}.multipart"
+  echo "${multipart_start_b2}" | sed "s/HASHHASH/${HASH}/" >>${OUT_MIME}
+  cat "${INPUT}.cr" | sed 's/\r$//' >>${OUT_MIME}
+  rm "${INPUT}.cr"
+  echo "${multipart_middle_b2}" >>${OUT_MIME}
+  echo >>${OUT_MIME}
+  cat "$OUT_SIG" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT_MIME}
+  echo "${multipart_end_b2}" >>${OUT_MIME}
+
+  OUT_EML="${OUT_MIME}.eml"
+  echo -n "${header_dave_mime_from_to_subject}" >>${OUT_EML}
+  echo "clear-signed $SIG then clear-signed signed by dave" >>${OUT_EML}
+  cat "${OUT_MIME}" >>${OUT_EML}
+  echo >>${OUT_EML}
+  sed -i"" "s/\$/$CR/" ${OUT_EML}
+
+  INPUT="tb/alice.plain.${SIG}.opaque"
+  OUT_SIG="${INPUT}.dave.d${SIG}"
+  cat "$INPUT" | sed "s/\$/$CR/" > "${INPUT}.cr"
+  ${PROFTOOL} ${BINDIR}/cmsutil -S -T -N Dave ${HASH_CMD} -i "${INPUT}.cr" -d ${P_R_DAVEDIR} -p nss -o "$OUT_SIG"
+
+  OUT_MIME="${OUT_SIG}.multipart"
+  echo "${multipart_start_b2}" | sed "s/HASHHASH/${HASH}/" >>${OUT_MIME}
+  cat "${INPUT}.cr" | sed 's/\r$//' >>${OUT_MIME}
+  rm "${INPUT}.cr"
+  echo "${multipart_middle_b2}" >>${OUT_MIME}
+  echo >>${OUT_MIME}
+  cat "$OUT_SIG" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT_MIME}
+  echo "${multipart_end_b2}" >>${OUT_MIME}
+
+  OUT_EML="${OUT_MIME}.eml"
+  echo -n "${header_dave_mime_from_to_subject}" >>${OUT_EML}
+  echo "opaque-signed $SIG then clear-signed signed by dave" >>${OUT_EML}
+  cat "${OUT_MIME}" >>${OUT_EML}
+  echo >>${OUT_EML}
+  sed -i"" "s/\$/$CR/" ${OUT_EML}
+}
+
+smime_enveloped_signed()
+{
+  SIG=sig.SHA${HASH}
+
+  ${PROFTOOL} ${BINDIR}/cmsutil -S -T -N Alice ${HASH_CMD} -i tb/alice.env -d ${P_R_ALICEDIR} -p nss -o tb/alice.env.d${SIG}
+
+  OUT="tb/alice.env.d${SIG}.multipart"
+  echo "${multipart_start}" | sed "s/HASHHASH/${HASH}/" >>${OUT}
+  cat tb/alice.env | sed 's/\r$//' >>${OUT}
+  echo "${multipart_middle}" >>${OUT}
+  cat tb/alice.env.d${SIG} | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
+  echo "${multipart_end}" >>${OUT}
+
+  OUT="tb/alice.env.d${SIG}.multipart.eml"
+  echo -n "${header_mime_from_to_subject}" >>${OUT}
+  echo "enveloped then clear-signed ${SIG}" >>${OUT}
+  cat "tb/alice.env.d${SIG}.multipart" >>${OUT}
+  sed -i"" "s/\$/$CR/" ${OUT}
+
+  ${PROFTOOL} ${BINDIR}/cmsutil -S -N Alice ${HASH_CMD} -i tb/alice.env -d ${P_R_ALICEDIR} -p nss -o tb/alice.env.${SIG}
+
+  OUT="tb/alice.env.${SIG}.opaque"
+  echo "$header_opaque_signed" >>${OUT}
+  cat tb/alice.env.${SIG} | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
+
+  OUT="tb/alice.env.${SIG}.opaque.eml"
+  echo -n "${header_mime_from_to_subject}" >>${OUT}
+  echo "enveloped then opaque-signed $SIG" >>${OUT}
+  cat "tb/alice.env.${SIG}.opaque" >>${OUT}
+  echo >>${OUT}
+  sed -i"" "s/\$/$CR/" ${OUT}
+
+  # Second outer, opaque signature layer.
+
+  INPUT="tb/alice.env.d${SIG}.multipart"
+  OUT_SIG="${INPUT}.dave.${SIG}"
+  ${PROFTOOL} ${BINDIR}/cmsutil -S -N Dave ${HASH_CMD} -i "$INPUT" -d ${P_R_DAVEDIR} -p nss -o "$OUT_SIG"
+
+  OUT_MIME="${OUT_SIG}.opaque"
+  echo "$header_opaque_signed" >>${OUT_MIME}
+  cat "$OUT_SIG" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT_MIME}
+
+  OUT_EML="${OUT_MIME}.eml"
+  echo -n "${header_dave_mime_from_to_subject}" >>${OUT_EML}
+  echo "enveloped then clear-signed $SIG then opaque signed by dave" >>${OUT_EML}
+  cat "${OUT_MIME}" >>${OUT_EML}
+  echo >>${OUT_EML}
+  sed -i"" "s/\$/$CR/" ${OUT_EML}
+
+  INPUT="tb/alice.env.${SIG}.opaque"
+  OUT_SIG="${INPUT}.dave.${SIG}"
+  ${PROFTOOL} ${BINDIR}/cmsutil -S -N Dave ${HASH_CMD} -i "$INPUT" -d ${P_R_DAVEDIR} -p nss -o "$OUT_SIG"
+
+  OUT_MIME="${OUT_SIG}.opaque"
+  echo "$header_opaque_signed" >>${OUT_MIME}
+  cat "$OUT_SIG" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT_MIME}
+
+  OUT_EML="${OUT_MIME}.eml"
+  echo -n "${header_dave_mime_from_to_subject}" >>${OUT_EML}
+  echo "enveloped then opaque-signed $SIG then opaque signed by dave" >>${OUT_EML}
+  cat "${OUT_MIME}" >>${OUT_EML}
+  echo >>${OUT_EML}
+  sed -i"" "s/\$/$CR/" ${OUT_EML}
+}
+
 smime_p7()
 {
   echo "$SCRIPTNAME: p7 util Data Tests ------------------------------"
   echo "p7env -d ${P_R_ALICEDIR} -r Alice -i alice.txt -o alice_p7.env"
   ${PROFTOOL} ${BINDIR}/p7env -d ${P_R_ALICEDIR} -r Alice -i alice.txt -o alice_p7.env
   html_msg $? 0 "Creating envelope for user Alice" "."
 
   echo "p7content -d ${P_R_ALICEDIR} -i alice_p7.env -o alice_p7.data"
@@ -285,25 +468,33 @@ smime_p7()
 smime_main()
 {
   mime_init
   smime_enveloped
 
   HASH="1"
   cms_sign
   smime_signed_enveloped
+  smime_plain_signed
+  smime_enveloped_signed
   HASH="256"
   cms_sign
   smime_signed_enveloped
+  smime_plain_signed
+  smime_enveloped_signed
   HASH="384"
   cms_sign
   smime_signed_enveloped
+  smime_plain_signed
+  smime_enveloped_signed
   HASH="512"
   cms_sign
   smime_signed_enveloped
+  smime_plain_signed
+  smime_enveloped_signed
 
   echo "$SCRIPTNAME: Enveloped Data Tests ------------------------------"
   echo "cmsutil -E -r bob@example.com -i alice.txt -d ${P_R_ALICEDIR} -p nss \\"
   echo "        -o alice.env"
   ${PROFTOOL} ${BINDIR}/cmsutil -E -r bob@example.com -i alice.txt -d ${P_R_ALICEDIR} -p nss -o alice.env
   html_msg $? 0 "Create Enveloped Data Alice" "."
 
   echo "cmsutil -D -i alice.env -d ${P_R_BOBDIR} -p nss -o alice.data1"
--- a/security/nss/tests/ssl/ssl.sh
+++ b/security/nss/tests/ssl/ssl.sh
@@ -279,17 +279,17 @@ start_selfserv()
       PID=`cat ${SERVERPID}`
   fi
 
   echo "selfserv with PID ${PID} started at `date`"
 }
 
 ignore_blank_lines()
 {
-  LC_ALL=C grep -v '^[[:space:]]*\(#\|$\)' "$1"
+  LC_ALL=C egrep -v '^[[:space:]]*(#|$)' "$1"
 }
 
 ############################## ssl_cov #################################
 # local shell function to perform SSL Cipher Coverage tests
 ########################################################################
 ssl_cov()
 {
   #verbose="-v"
--- a/security/nss/tests/tlsfuzzer/config.json.in
+++ b/security/nss/tests/tlsfuzzer/config.json.in
@@ -155,10 +155,30 @@
                     "-e", "Protocol (3, 0) in SSLv2 compatible ClientHello",
                     "-e", "Protocol (3, 1) in SSLv2 compatible ClientHello",
                     "-e", "Protocol (3, 2) in SSLv2 compatible ClientHello",
                     "-e", "Protocol (3, 3) in SSLv2 compatible ClientHello",
                     "-e", "Protocol (3, 0)"
                 ]
             }
         ]
+    },
+    {
+        "server_command": [
+            "@SELFSERV@", "-w", "nss", "-d", "@SERVERDIR@",
+            "-V", "tls1.0:", "-H", "1",
+            "-n", "rsa",
+            "-c", ":C028",
+            "-p", "@PORT@"
+        ],
+        "server_hostname": "@HOSTADDR@",
+        "server_port": @PORT@,
+        "tests" : [
+            {
+                "name" : "test-atypical-padding.py",
+                "arguments": [
+                    "-p", "@PORT@",
+                    "2^14 bytes of AppData with 256 bytes of padding (SHA384)"
+                ]
+            }
+        ]
     }
 ]
--- a/security/nss/tests/tlsfuzzer/tlsfuzzer.sh
+++ b/security/nss/tests/tlsfuzzer/tlsfuzzer.sh
@@ -39,21 +39,21 @@ tlsfuzzer_init()
   mkdir -p "${HOSTDIR}/tlsfuzzer"
   pushd "${HOSTDIR}/tlsfuzzer"
   tlsfuzzer_certs
 
   TLSFUZZER=${TLSFUZZER:=tlsfuzzer}
   if [ ! -d "$TLSFUZZER" ]; then
     # Can't use git-copy.sh here, as tlsfuzzer doesn't have any tags
     git clone -q https://github.com/tomato42/tlsfuzzer/ "$TLSFUZZER"
-    git -C "$TLSFUZZER" checkout a40ce4085052a4da9a05f9149b835a76c194a0c6
+    git -C "$TLSFUZZER" checkout 80d7932ead1d8dae6e555cfd2b1c4c5beb2847df
 
     # We could use tlslite-ng from pip, but the pip command installed
     # on TC is too old to support --pre
-    ${QADIR}/../fuzz/config/git-copy.sh https://github.com/tomato42/tlslite-ng/ v0.8.0-alpha18 tlslite-ng
+    ${QADIR}/../fuzz/config/git-copy.sh https://github.com/tomato42/tlslite-ng/ v0.8.0-alpha27 tlslite-ng
 
     pushd "$TLSFUZZER"
     ln -s ../tlslite-ng/tlslite tlslite
     popd
 
     # Install tlslite-ng dependencies
     ${QADIR}/../fuzz/config/git-copy.sh https://github.com/warner/python-ecdsa master python-ecdsa
     ${QADIR}/../fuzz/config/git-copy.sh https://github.com/benjaminp/six master six
@@ -94,17 +94,17 @@ tlsfuzzer_cleanup()
 {
   cd ${QADIR}
   . common/cleanup.sh
 }
 
 tlsfuzzer_run_tests()
 {
   pushd "${HOSTDIR}/tlsfuzzer/${TLSFUZZER}"
-  PYTHONPATH=. python tests/scripts_retention.py config.json "${BINDIR}/selfserv"
+  PYTHONPATH=. python tests/scripts_retention.py config.json "${BINDIR}/selfserv" 512
   html_msg $? 0 "tlsfuzzer" "Run successfully"
   popd
 }
 
 cd "$(dirname "$0")"
 tlsfuzzer_init
 tlsfuzzer_run_tests
 tlsfuzzer_cleanup