Update NSS draft
authorEKR <ekr@rtfm.com>
Thu, 22 Sep 2016 16:01:08 -0700
changeset 416740 894576375b5f043f6f6643c1279e45fbc18169b3
parent 416562 f0e6cc6360213ba21fd98c887b55fce5c680df68
child 416741 f06ac226ecdace5fb08ea924691f8dba1fa81bcf
push id30242
push userekr@mozilla.com
push dateFri, 23 Sep 2016 00:57:39 +0000
milestone52.0a1
Update NSS MozReview-Commit-ID: HQnqWmGClov
security/nss/TAG-INFO
security/nss/automation/buildbot-slave/build.sh
security/nss/automation/taskcluster/docker/setup.sh
security/nss/automation/taskcluster/graph/src/extend.js
security/nss/automation/taskcluster/graph/src/try_syntax.js
security/nss/cmd/bltest/blapitest.c
security/nss/cmd/certutil/certutil.c
security/nss/cmd/certutil/keystuff.c
security/nss/cmd/ecperf/ecperf.c
security/nss/cmd/ecperf/manifest.mn
security/nss/cmd/ectest/ectest.c
security/nss/cmd/ectest/testvecs.h
security/nss/cmd/fipstest/fipstest.c
security/nss/cmd/listsuites/listsuites.c
security/nss/cmd/selfserv/selfserv.c
security/nss/cmd/signtool/javascript.c
security/nss/cmd/ssltap/ssltap.c
security/nss/cmd/strsclnt/strsclnt.c
security/nss/cmd/tstclnt/tstclnt.c
security/nss/cmd/vfyserv/vfyutil.c
security/nss/coreconf/Darwin.mk
security/nss/coreconf/Linux.mk
security/nss/coreconf/coreconf.dep
security/nss/external_tests/nss_bogo_shim/config.json
security/nss/external_tests/nss_bogo_shim/nss_bogo_shim.cc
security/nss/external_tests/pk11_gtest/manifest.mn
security/nss/external_tests/ssl_gtest/libssl_internals.c
security/nss/external_tests/ssl_gtest/libssl_internals.h
security/nss/external_tests/ssl_gtest/ssl_agent_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_ciphersuite_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_dhe_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_drop_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_ecdh_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_ems_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_extension_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_hrr_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_resumption_unittest.cc
security/nss/external_tests/ssl_gtest/tls_agent.cc
security/nss/external_tests/ssl_gtest/tls_agent.h
security/nss/external_tests/ssl_gtest/tls_connect.cc
security/nss/external_tests/ssl_gtest/tls_connect.h
security/nss/external_tests/ssl_gtest/tls_parser.h
security/nss/lib/ckfw/builtins/certdata.txt
security/nss/lib/ckfw/builtins/config.mk
security/nss/lib/cryptohi/keyi.h
security/nss/lib/cryptohi/keythi.h
security/nss/lib/cryptohi/manifest.mn
security/nss/lib/cryptohi/seckey.c
security/nss/lib/freebl/Makefile
security/nss/lib/freebl/blapit.h
security/nss/lib/freebl/ec.c
security/nss/lib/freebl/ec.h
security/nss/lib/freebl/ecdecode.c
security/nss/lib/freebl/ecl/ecl-curve.h
security/nss/lib/freebl/ecl/ecl-exp.h
security/nss/lib/freebl/ecl/ecl-priv.h
security/nss/lib/freebl/ecl/ecl.h
security/nss/lib/freebl/ecl/tests/ecp_test.c
security/nss/lib/freebl/manifest.mn
security/nss/lib/nss/nss.h
security/nss/lib/pk11wrap/pk11akey.c
security/nss/lib/pk11wrap/pk11skey.c
security/nss/lib/softoken/pkcs11.c
security/nss/lib/softoken/pkcs11c.c
security/nss/lib/softoken/softkver.h
security/nss/lib/sqlite/Makefile
security/nss/lib/ssl/derive.c
security/nss/lib/ssl/dtlscon.c
security/nss/lib/ssl/manifest.mn
security/nss/lib/ssl/ssl.h
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3ecc.c
security/nss/lib/ssl/ssl3ext.c
security/nss/lib/ssl/ssl3prot.h
security/nss/lib/ssl/sslcert.c
security/nss/lib/ssl/sslcert.h
security/nss/lib/ssl/sslcon.c
security/nss/lib/ssl/sslenum.c
security/nss/lib/ssl/sslerr.h
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/sslinfo.c
security/nss/lib/ssl/sslproto.h
security/nss/lib/ssl/sslsecur.c
security/nss/lib/ssl/sslsnce.c
security/nss/lib/ssl/sslsock.c
security/nss/lib/ssl/sslt.h
security/nss/lib/ssl/tls13con.c
security/nss/lib/ssl/tls13con.h
security/nss/lib/util/manifest.mn
security/nss/lib/util/nssutil.h
security/nss/lib/util/pkcs11t.h
security/nss/lib/util/secoid.c
security/nss/lib/util/secoidt.h
security/nss/tests/all.sh
security/nss/tests/common/init.sh
security/nss/tests/ec/ecperf.sh
security/nss/tests/ec/ectest.sh
security/nss/tests/iopr/server_scr/cipher.list
security/nss/tests/ssl/ssl.sh
security/nss/tests/ssl/sslcov.txt
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-NSS_3_27_BRANCH
+0cd63b117eb4
--- a/security/nss/automation/buildbot-slave/build.sh
+++ b/security/nss/automation/buildbot-slave/build.sh
@@ -289,23 +289,16 @@ prepare()
     mkdir -p ${OUTPUTDIR}
 
     # Remove temporary test files from previous jobs, that weren't cleaned up
     # by move_results(), e.g. caused by unexpected interruptions.
     rm -rf ${HGDIR}/tests_results/
 
     cd ${HGDIR}/nss
 
-    if [ -z "${NSS_DISABLE_ECC}" -a -n "${NSS_ECC_MORE_THAN_SUITE_B}" ]; then
-        ECF="lib/freebl/ecl/ecl-curve.h"
-	print_log "hg revert -r NSS_3_11_1_RTM ${ECF}"
-        hg revert -r NSS_3_11_1_RTM security/nss/${ECF}
-        cp -f security/nss/${ECF} ${ECF}
-    fi
-
     if [ -n "${FEWER_STRESS_ITERATIONS}" ]; then
         sed -i 's/-c_1000_/-c_500_/g' tests/ssl/sslstress.txt
     fi
 
     return 0
 }
 
 move_results()
--- a/security/nss/automation/taskcluster/docker/setup.sh
+++ b/security/nss/automation/taskcluster/docker/setup.sh
@@ -10,16 +10,17 @@ apt-get -y update && apt-get -y upgrade
 apt-get install -y --no-install-recommends apt-utils
 
 apt_packages=()
 apt_packages+=('build-essential')
 apt_packages+=('ca-certificates')
 apt_packages+=('curl')
 apt_packages+=('npm')
 apt_packages+=('git')
+apt_packages+=('golang-1.6')
 apt_packages+=('ninja-build')
 apt_packages+=('pkg-config')
 apt_packages+=('zlib1g-dev')
 
 # 32-bit builds
 apt_packages+=('lib32z1-dev')
 apt_packages+=('gcc-multilib')
 apt_packages+=('g++-multilib')
--- a/security/nss/automation/taskcluster/graph/src/extend.js
+++ b/security/nss/automation/taskcluster/graph/src/extend.js
@@ -23,21 +23,38 @@ queue.filter(task => {
 
     // Remove extra builds w/o libpkix for non-linux64-debug.
     if (task.symbol == "noLibpkix" &&
         (task.platform != "linux64" || task.collection != "debug")) {
       return false;
     }
   }
 
+  if (task.tests == "bogo") {
+    // No BoGo tests on Windows.
+    if (task.platform == "windows2012-64") {
+      return false;
+    }
+
+    // No BoGo tests on ARM.
+    if (task.collection == "arm-debug") {
+      return false;
+    }
+  }
+
   return true;
 });
 
 queue.map(task => {
   if (task.collection == "asan") {
+    // Disable LSan on BoGo runs, for now.
+    if (task.tests == "bogo") {
+      task.env.ASAN_OPTIONS = "detect_leaks=0";
+    }
+
     // CRMF and FIPS tests still leak, unfortunately.
     if (task.tests == "crmf" || task.tests == "fips") {
       task.env.ASAN_OPTIONS = "detect_leaks=0";
     }
 
     // SSL(standard) runs on ASan take some time.
     if (task.tests == "ssl" && task.cycle == "standard") {
       task.maxRunTime = 7200;
@@ -276,17 +293,20 @@ async function scheduleWindows(name, bas
 /*****************************************************************************/
 
 function scheduleTests(task_build, task_cert, test_base) {
   test_base = merge({kind: "test"}, test_base);
 
   // Schedule tests that do NOT need certificates.
   let no_cert_base = merge(test_base, {parent: task_build});
   queue.scheduleTask(merge(no_cert_base, {
-    name: "Gtests", symbol: "Gtest", tests: "ssl_gtests gtests"
+    name: "Gtests", symbol: "Gtest", tests: "ssl_gtests gtests", cycle: "standard"
+  }));
+  queue.scheduleTask(merge(no_cert_base, {
+    name: "Bogo tests", symbol: "Bogo", tests: "bogo", cycle: "standard"
   }));
   queue.scheduleTask(merge(no_cert_base, {
     name: "Chains tests", symbol: "Chains", tests: "chains"
   }));
   queue.scheduleTask(merge(no_cert_base, {
     name: "Cipher tests", symbol: "Cipher", tests: "cipher"
   }));
   queue.scheduleTask(merge(no_cert_base, {
@@ -360,17 +380,17 @@ async function scheduleTools() {
     name: "scan-build-3.9",
     env: {
       USE_64: "1",
       GCC_VERSION: "clang",
       GXX_VERSION: "clang++"
     },
     artifacts: {
       public: {
-        expires: 24,
+        expires: 24 * 7,
         type: "directory",
         path: "/home/worker/artifacts"
       }
     },
     command: [
       "/bin/bash",
       "-c",
       "bin/checkout.sh && nss/automation/taskcluster/scripts/run_scan_build.sh"
--- a/security/nss/automation/taskcluster/graph/src/try_syntax.js
+++ b/security/nss/automation/taskcluster/graph/src/try_syntax.js
@@ -26,19 +26,23 @@ function parseOptions(opts) {
   let platforms = intersect(opts.platform.split(/\s*,\s*/), allPlatforms);
 
   // If the given value is nonsense or "none" default to all platforms.
   if (platforms.length == 0 && opts.platform != "none") {
     platforms = allPlatforms;
   }
 
   // Parse unit tests.
-  let allUnitTests = ["crmf", "chains", "cipher", "db", "ec", "fips", "gtest",
-                      "lowhash", "merge", "sdr", "smime", "tools", "ssl"];
-  let unittests = intersect(opts.unittests.split(/\s*,\s*/), allUnitTests);
+  let aliases = {"gtests": "gtest"};
+  let allUnitTests = ["bogo", "crmf", "chains", "cipher", "db", "ec", "fips",
+                      "gtest", "lowhash", "merge", "sdr", "smime", "tools",
+                      "ssl"];
+  let unittests = intersect(opts.unittests.split(/\s*,\s*/).map(t => {
+    return aliases[t] || t;
+  }), allUnitTests);
 
   // If the given value is "all" run all tests.
   // If it's nonsense then don't run any tests.
   if (opts.unittests == "all") {
     unittests = allUnitTests;
   } else if (unittests.length == 0) {
     unittests = [];
   }
--- a/security/nss/cmd/bltest/blapitest.c
+++ b/security/nss/cmd/bltest/blapitest.c
@@ -154,17 +154,17 @@ Usage()
     PRINTUSAGE("", "", "  nistp521, prime192v1, prime192v2, prime192v3,");
     PRINTUSAGE("", "", "  prime239v1, prime239v2, prime239v3, c2pnb163v1,");
     PRINTUSAGE("", "", "  c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1,");
     PRINTUSAGE("", "", "  c2tnb191v2, c2tnb191v3, c2onb191v4, c2onb191v5,");
     PRINTUSAGE("", "", "  c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3,");
     PRINTUSAGE("", "", "  c2onb239v4, c2onb239v5, c2pnb272w1, c2pnb304w1,");
     PRINTUSAGE("", "", "  c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1,");
     PRINTUSAGE("", "", "  secp112r2, secp128r1, secp128r2, sect113r1, sect113r2,");
-    PRINTUSAGE("", "", "  sect131r1, sect131r2");
+    PRINTUSAGE("", "", "  sect131r1, sect131r2, curve25519");
 #endif
     PRINTUSAGE("", "-p", "do performance test");
     PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads");
     PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)");
     fprintf(stderr, "\n");
     PRINTUSAGE(progName, "-V -m mode", "Verify a signed buffer");
     PRINTUSAGE("", "", "[-i plaintext] [-s signature] [-k key]");
     PRINTUSAGE("", "", "[-p repetitions | -5 time_interval] [-4 th_num]");
@@ -491,16 +491,17 @@ static CurveNameTagPair nameTagPair[] =
       { "secp112r2", SEC_OID_SECG_EC_SECP112R2 },
       { "secp128r1", SEC_OID_SECG_EC_SECP128R1 },
       { "secp128r2", SEC_OID_SECG_EC_SECP128R2 },
 
       { "sect113r1", SEC_OID_SECG_EC_SECT113R1 },
       { "sect113r2", SEC_OID_SECG_EC_SECT113R2 },
       { "sect131r1", SEC_OID_SECG_EC_SECT131R1 },
       { "sect131r2", SEC_OID_SECG_EC_SECT131R2 },
+      { "curve25519", SEC_OID_CURVE25519 },
     };
 
 static SECItem *
 getECParams(const char *curve)
 {
     SECItem *ecparams;
     SECOidData *oidData = NULL;
     SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
@@ -1882,16 +1883,17 @@ bltest_ecdsa_init(bltestCipherInfo *ciph
         pubkey->ecParams.base.len = key->ecParams.base.len;
         pubkey->ecParams.base.data = key->ecParams.base.data;
         pubkey->ecParams.order.len = key->ecParams.order.len;
         pubkey->ecParams.order.data = key->ecParams.order.data;
         pubkey->ecParams.cofactor = key->ecParams.cofactor;
         pubkey->ecParams.DEREncoding.len = key->ecParams.DEREncoding.len;
         pubkey->ecParams.DEREncoding.data = key->ecParams.DEREncoding.data;
         pubkey->ecParams.name = key->ecParams.name;
+        pubkey->ecParams.pointSize = key->ecParams.pointSize;
         pubkey->publicValue.len = key->publicValue.len;
         pubkey->publicValue.data = key->publicValue.data;
         asymk->pubKey = pubkey;
         cipherInfo->cipher.pubkeyCipher = ecdsa_verifyDigest;
     }
     return SECSuccess;
 }
 #endif
--- a/security/nss/cmd/certutil/certutil.c
+++ b/security/nss/cmd/certutil/certutil.c
@@ -426,20 +426,25 @@ DumpChain(CERTCertDBHandle *handle, char
     CERT_DestroyCertificate(the_cert);
     if (!chain) {
         SECU_PrintError(progName, "Could not obtain chain for: %s\n", name);
         return SECFailure;
     }
     for (i = chain->len - 1; i >= 0; i--) {
         CERTCertificate *c;
         c = CERT_FindCertByDERCert(handle, &chain->certs[i]);
-        for (j = i; j < chain->len - 1; j++)
+        for (j = i; j < chain->len - 1; j++) {
             printf("  ");
-        printf("\"%s\" [%s]\n\n", c->nickname, c->subjectName);
-        CERT_DestroyCertificate(c);
+        }
+        if (c) {
+            printf("\"%s\" [%s]\n\n", c->nickname, c->subjectName);
+            CERT_DestroyCertificate(c);
+        } else {
+            printf("(null)\n\n");
+        }
     }
     CERT_DestroyCertificateList(chain);
     return SECSuccess;
 }
 
 static SECStatus
 outputCertOrExtension(CERTCertificate *the_cert, PRBool raw, PRBool ascii,
                       SECItem *extensionOID, PRFileDesc *outfile)
@@ -1252,17 +1257,17 @@ luG(enum usage_level ul, const char *com
         "   -f password-file");
     FPS "%-20s Specify the noise file to be used\n",
         "   -z noisefile");
     FPS "%-20s read PQG value from pqgfile (dsa only)\n",
         "   -q pqgfile");
 #ifndef NSS_DISABLE_ECC
     FPS "%-20s Elliptic curve name (ec only)\n",
         "   -q curve-name");
-    FPS "%-20s One of nistp256, nistp384, nistp521\n", "");
+    FPS "%-20s One of nistp256, nistp384, nistp521, curve25519\n", "");
 #ifdef NSS_ECC_MORE_THAN_SUITE_B
     FPS "%-20s sect163k1, nistk163, sect163r1, sect163r2,\n", "");
     FPS "%-20s nistb163, sect193r1, sect193r2, sect233k1, nistk233,\n", "");
     FPS "%-20s sect233r1, nistb233, sect239k1, sect283k1, nistk283,\n", "");
     FPS "%-20s sect283r1, nistb283, sect409k1, nistk409, sect409r1,\n", "");
     FPS "%-20s nistb409, sect571k1, nistk571, sect571r1, nistb571,\n", "");
     FPS "%-20s secp160k1, secp160r1, secp160r2, secp192k1, secp192r1,\n", "");
     FPS "%-20s nistp192, secp224k1, secp224r1, nistp224, secp256k1,\n", "");
--- a/security/nss/cmd/certutil/keystuff.c
+++ b/security/nss/cmd/certutil/keystuff.c
@@ -471,16 +471,17 @@ static CurveNameTagPair nameTagPair[] =
       { "secp112r2", SEC_OID_SECG_EC_SECP112R2 },
       { "secp128r1", SEC_OID_SECG_EC_SECP128R1 },
       { "secp128r2", SEC_OID_SECG_EC_SECP128R2 },
 
       { "sect113r1", SEC_OID_SECG_EC_SECT113R1 },
       { "sect113r2", SEC_OID_SECG_EC_SECT113R2 },
       { "sect131r1", SEC_OID_SECG_EC_SECT131R1 },
       { "sect131r2", SEC_OID_SECG_EC_SECT131R2 },
+      { "curve25519", SEC_OID_CURVE25519 },
     };
 
 static SECKEYECParams *
 getECParams(const char *curve)
 {
     SECKEYECParams *ecparams;
     SECOidData *oidData = NULL;
     SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
--- a/security/nss/cmd/ecperf/ecperf.c
+++ b/security/nss/cmd/ecperf/ecperf.c
@@ -4,16 +4,17 @@
 
 #include "blapi.h"
 #include "ec.h"
 #include "ecl-curve.h"
 #include "prprf.h"
 #include "basicutil.h"
 #include "pkcs11.h"
 #include "nspr.h"
+#include "certt.h" /* TODO: remove when old curves are removed */
 #include <stdio.h>
 
 #define __PASTE(x, y) x##y
 
 /*
  * Get the NSS specific PKCS #11 function names.
  */
 #undef CK_PKCS11_FUNCTION_INFO
@@ -81,17 +82,18 @@ static SECOidTag ecCurve_oid_map[] = {
     SEC_OID_SECG_EC_SECT131R2,
     SEC_OID_SECG_EC_SECT163R1,
     SEC_OID_SECG_EC_SECT193R1,
     SEC_OID_SECG_EC_SECT193R2,
     SEC_OID_SECG_EC_SECT239K1,
     SEC_OID_UNKNOWN, /* ECCurve_WTLS_1 */
     SEC_OID_UNKNOWN, /* ECCurve_WTLS_8 */
     SEC_OID_UNKNOWN, /* ECCurve_WTLS_9 */
-    SEC_OID_UNKNOWN  /* ECCurve_pastLastCurve */
+    SEC_OID_CURVE25519,
+    SEC_OID_UNKNOWN /* ECCurve_pastLastCurve */
 };
 
 typedef SECStatus (*op_func)(void *, void *, void *);
 typedef SECStatus (*pk11_op_func)(CK_SESSION_HANDLE, void *, void *, void *);
 
 typedef SECItem SECKEYECParams;
 
 typedef struct ThreadDataStr {
@@ -253,30 +255,47 @@ M_TimeOperation(void (*threadFunc)(void 
     }
     PORT_Free(threadIDs);
     PORT_Free(threadData);
 
     return SECSuccess;
 }
 
 /* Test curve using specific field arithmetic. */
-#define ECTEST_NAMED_GFP(name_c, name_v)                               \
-    if (usefreebl) {                                                   \
-        printf("Testing %s using freebl implementation...\n", name_c); \
-        rv = ectest_curve_freebl(name_v, iterations, numThreads);      \
-        if (rv != SECSuccess)                                          \
-            goto cleanup;                                              \
-        printf("... okay.\n");                                         \
-    }                                                                  \
-    if (usepkcs11) {                                                   \
-        printf("Testing %s using pkcs11 implementation...\n", name_c); \
-        rv = ectest_curve_pkcs11(name_v, iterations, numThreads);      \
-        if (rv != SECSuccess)                                          \
-            goto cleanup;                                              \
-        printf("... okay.\n");                                         \
+#define ECTEST_NAMED_GFP(name_c, name_v)                                        \
+    if (usefreebl) {                                                            \
+        printf("Testing %s using freebl implementation...\n", name_c);          \
+        rv = ectest_curve_freebl(name_v, iterations, numThreads, ec_field_GFp); \
+        if (rv != SECSuccess)                                                   \
+            goto cleanup;                                                       \
+        printf("... okay.\n");                                                  \
+    }                                                                           \
+    if (usepkcs11) {                                                            \
+        printf("Testing %s using pkcs11 implementation...\n", name_c);          \
+        rv = ectest_curve_pkcs11(name_v, iterations, numThreads);               \
+        if (rv != SECSuccess)                                                   \
+            goto cleanup;                                                       \
+        printf("... okay.\n");                                                  \
+    }
+
+/* Test curve using specific field arithmetic. */
+#define ECTEST_NAMED_CUSTOM(name_c, name_v)                                       \
+    if (usefreebl) {                                                              \
+        printf("Testing %s using freebl implementation...\n", name_c);            \
+        rv = ectest_curve_freebl(name_v, iterations, numThreads, ec_field_plain); \
+        if (rv != SECSuccess)                                                     \
+            goto cleanup;                                                         \
+        printf("... okay.\n");                                                    \
+    }                                                                             \
+    if (usepkcs11) {                                                              \
+        printf("Testing %s using pkcs11 implementation...\n", name_c);            \
+        rv = ectest_curve_pkcs11(name_v, iterations, numThreads);                 \
+        if (rv != SECSuccess)                                                     \
+            goto cleanup;                                                         \
+        printf("... okay.\n");                                                    \
     }
 
 /*
  * Initializes a SECItem from a hexadecimal string
  *
  * Warning: This function ignores leading 00's, so any leading 00's
  * in the hexadecimal string must be optional.
  */
@@ -505,39 +524,44 @@ ectest_curve_pkcs11(ECCurveName curve, i
     ecdh_params.pPublicData = template.pValue;
 
     mech.mechanism = CKM_ECDH1_DERIVE;
     mech.pParameter = (void *)&ecdh_params;
     mech.ulParameterLen = sizeof(ecdh_params);
 
     lock = PR_NewLock();
 
-    rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Derive, "ECDH_Derive",
-                         &ecPriv, &mech, NULL, iterations, numThreads,
-                         lock, session, 0, &deriveRate);
-    if (rv != SECSuccess) {
-        goto cleanup;
-    }
-    rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Sign, "ECDSA_Sign",
-                         (void *)&ecPriv, &sig, &digest, iterations, numThreads,
-                         lock, session, 1, &signRate);
-    if (rv != SECSuccess) {
-        goto cleanup;
+    if (ecCurve_map[curve]->usage & KU_KEY_AGREEMENT) {
+        rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Derive, "ECDH_Derive",
+                             &ecPriv, &mech, NULL, iterations, numThreads,
+                             lock, session, 0, &deriveRate);
+        if (rv != SECSuccess) {
+            goto cleanup;
+        }
     }
-    printf("        ECDHE max rate = %.2f\n", (deriveRate + signRate) / 4.0);
-    /* get a signature */
-    rv = PKCS11_Sign(session, &ecPriv, &sig, &digest);
-    if (rv != SECSuccess) {
-        goto cleanup;
-    }
-    rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Verify, "ECDSA_Verify",
-                         (void *)&ecPub, &sig, &digest, iterations, numThreads,
-                         lock, session, 0, NULL);
-    if (rv != SECSuccess) {
-        goto cleanup;
+
+    if (ecCurve_map[curve]->usage & KU_DIGITAL_SIGNATURE) {
+        rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Sign, "ECDSA_Sign",
+                             (void *)&ecPriv, &sig, &digest, iterations, numThreads,
+                             lock, session, 1, &signRate);
+        if (rv != SECSuccess) {
+            goto cleanup;
+        }
+        printf("        ECDHE max rate = %.2f\n", (deriveRate + signRate) / 4.0);
+        /* get a signature */
+        rv = PKCS11_Sign(session, &ecPriv, &sig, &digest);
+        if (rv != SECSuccess) {
+            goto cleanup;
+        }
+        rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Verify, "ECDSA_Verify",
+                             (void *)&ecPub, &sig, &digest, iterations, numThreads,
+                             lock, session, 0, NULL);
+        if (rv != SECSuccess) {
+            goto cleanup;
+        }
     }
 
 cleanup:
     if (lock) {
         PR_DestroyLock(lock);
     }
     return rv;
 }
@@ -557,17 +581,18 @@ ECDH_DeriveWrap(ECPrivateKey *priv, ECPu
     SECITEM_FreeItem(&secret, PR_FALSE);
     return rv;
 }
 
 /* Performs basic tests of elliptic curve cryptography over prime fields.
  * If tests fail, then it prints an error message, aborts, and returns an
  * error code. Otherwise, returns 0. */
 SECStatus
-ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads)
+ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads,
+                    ECFieldType fieldType)
 {
     ECParams ecParams = { 0 };
     ECPrivateKey *ecPriv = NULL;
     ECPublicKey ecPub;
     SECItem sig;
     SECItem digest;
     unsigned char sigData[256];
     unsigned char digestData[20];
@@ -589,19 +614,20 @@ ectest_curve_freebl(ECCurveName curve, i
     ecParams.name = curve;
     ecParams.type = ec_params_named;
     ecParams.curveOID.data = NULL;
     ecParams.curveOID.len = 0;
     ecParams.curve.seed.data = NULL;
     ecParams.curve.seed.len = 0;
     ecParams.DEREncoding.data = NULL;
     ecParams.DEREncoding.len = 0;
+    ecParams.pointSize = ecCurve_map[curve]->pointSize;
 
     ecParams.fieldID.size = ecCurve_map[curve]->size;
-    ecParams.fieldID.type = ec_field_GFp;
+    ecParams.fieldID.type = fieldType;
     hexString2SECItem(arena, &ecParams.fieldID.u.prime, ecCurve_map[curve]->irr);
     hexString2SECItem(arena, &ecParams.curve.a, ecCurve_map[curve]->curvea);
     hexString2SECItem(arena, &ecParams.curve.b, ecCurve_map[curve]->curveb);
     genenc[0] = '0';
     genenc[1] = '4';
     genenc[2] = '\0';
     strcat(genenc, ecCurve_map[curve]->genx);
     strcat(genenc, ecCurve_map[curve]->geny);
@@ -617,34 +643,39 @@ ectest_curve_freebl(ECCurveName curve, i
 
     rv = EC_NewKey(&ecParams, &ecPriv);
     if (rv != SECSuccess) {
         return SECFailure;
     }
     ecPub.ecParams = ecParams;
     ecPub.publicValue = ecPriv->publicValue;
 
-    rv = M_TimeOperation(genericThread, (op_func)ECDH_DeriveWrap, "ECDH_Derive",
-                         ecPriv, &ecPub, NULL, iterations, numThreads, 0, 0, 0, &deriveRate);
-    if (rv != SECSuccess) {
-        goto cleanup;
+    if (ecCurve_map[curve]->usage & KU_KEY_AGREEMENT) {
+        rv = M_TimeOperation(genericThread, (op_func)ECDH_DeriveWrap, "ECDH_Derive",
+                             ecPriv, &ecPub, NULL, iterations, numThreads, 0, 0, 0, &deriveRate);
+        if (rv != SECSuccess) {
+            goto cleanup;
+        }
     }
-    rv = M_TimeOperation(genericThread, (op_func)ECDSA_SignDigest, "ECDSA_Sign",
-                         ecPriv, &sig, &digest, iterations, numThreads, 0, 0, 1, &signRate);
-    if (rv != SECSuccess)
-        goto cleanup;
-    printf("        ECDHE max rate = %.2f\n", (deriveRate + signRate) / 4.0);
-    rv = ECDSA_SignDigest(ecPriv, &sig, &digest);
-    if (rv != SECSuccess) {
-        goto cleanup;
-    }
-    rv = M_TimeOperation(genericThread, (op_func)ECDSA_VerifyDigest, "ECDSA_Verify",
-                         &ecPub, &sig, &digest, iterations, numThreads, 0, 0, 0, NULL);
-    if (rv != SECSuccess) {
-        goto cleanup;
+
+    if (ecCurve_map[curve]->usage & KU_DIGITAL_SIGNATURE) {
+        rv = M_TimeOperation(genericThread, (op_func)ECDSA_SignDigest, "ECDSA_Sign",
+                             ecPriv, &sig, &digest, iterations, numThreads, 0, 0, 1, &signRate);
+        if (rv != SECSuccess)
+            goto cleanup;
+        printf("        ECDHE max rate = %.2f\n", (deriveRate + signRate) / 4.0);
+        rv = ECDSA_SignDigest(ecPriv, &sig, &digest);
+        if (rv != SECSuccess) {
+            goto cleanup;
+        }
+        rv = M_TimeOperation(genericThread, (op_func)ECDSA_VerifyDigest, "ECDSA_Verify",
+                             &ecPub, &sig, &digest, iterations, numThreads, 0, 0, 0, NULL);
+        if (rv != SECSuccess) {
+            goto cleanup;
+        }
     }
 
 cleanup:
     PORT_FreeArena(arena, PR_FALSE);
     PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE);
     return rv;
 }
 
@@ -738,16 +769,17 @@ main(int argv, char **argc)
 #ifdef NSS_ECC_MORE_THAN_SUITE_B
         ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
         ECTEST_NAMED_GFP("NIST-P192", ECCurve_NIST_P192);
         ECTEST_NAMED_GFP("NIST-P224", ECCurve_NIST_P224);
 #endif
         ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
         ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
         ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
+        ECTEST_NAMED_CUSTOM("Curve25519", ECCurve25519);
     }
 #ifdef NSS_ECC_MORE_THAN_SUITE_B
     if (ansi) {
         ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v1", ECCurve_X9_62_PRIME_192V1);
         ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v2", ECCurve_X9_62_PRIME_192V2);
         ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v3", ECCurve_X9_62_PRIME_192V3);
         ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v1", ECCurve_X9_62_PRIME_239V1);
         ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v2", ECCurve_X9_62_PRIME_239V2);
--- a/security/nss/cmd/ecperf/manifest.mn
+++ b/security/nss/cmd/ecperf/manifest.mn
@@ -6,19 +6,13 @@
 DEPTH = ../..
 CORE_DEPTH = ../..
 
 # MODULE public and private header directories are implicitly REQUIRED.
 MODULE = nss
 
 INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
 
-# This next line is used by .mk files
-# and gets translated into $LINCS in manifest.mnw
-REQUIRES = dbm seccmd
-
-# DIRS =
-
 CSRCS = ecperf.c
 
 PROGRAM = ecperf
 
 USE_STATIC_LIBS = 1
--- a/security/nss/cmd/ectest/ectest.c
+++ b/security/nss/cmd/ectest/ectest.c
@@ -1,31 +1,40 @@
 /* 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 "blapi.h"
 #include "ec.h"
 #include "ecl-curve.h"
-#include "prprf.h"
-#include "basicutil.h"
-#include "secder.h"
+#include "nss.h"
+#include "secutil.h"
 #include "secitem.h"
 #include "nspr.h"
+#include "pk11pub.h"
 #include <stdio.h>
 
 typedef struct {
     ECCurveName curve;
+    int iterations;
     char *privhex;
     char *our_pubhex;
     char *their_pubhex;
     char *common_key;
     char *name;
+    ECFieldType fieldType;
 } ECDH_KAT;
 
+typedef struct {
+    ECCurveName curve;
+    char *point;
+    char *name;
+    ECFieldType fieldType;
+} ECDH_BAD;
+
 #include "testvecs.h"
 
 /*
  * Initializes a SECItem from a hexadecimal string
  *
  */
 static SECItem *
 hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
@@ -64,123 +73,362 @@ hexString2SECItem(PLArenaPool *arena, SE
             byteval = 0;
         }
         i++;
     }
 
     return item;
 }
 
+void
+printBuf(const SECItem *item)
+{
+    int i;
+    if (!item || !item->len) {
+        printf("(null)\n");
+        return;
+    }
+
+    for (i = 0; i < item->len; i++) {
+        printf("%02x", item->data[i]);
+    }
+    printf("\n");
+}
+
+/* Initialise test with basic curve populate with only the necessary things */
+SECStatus
+init_params(ECParams *ecParams, ECCurveName curve, PLArenaPool **arena,
+            ECFieldType type)
+{
+    if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) {
+        return SECFailure;
+    }
+    *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+    if (!*arena) {
+        return SECFailure;
+    }
+    ecParams->name = curve;
+    ecParams->type = ec_params_named;
+    ecParams->curveOID.data = NULL;
+    ecParams->curveOID.len = 0;
+    ecParams->curve.seed.data = NULL;
+    ecParams->curve.seed.len = 0;
+    ecParams->DEREncoding.data = NULL;
+    ecParams->DEREncoding.len = 0;
+    ecParams->arena = *arena;
+    ecParams->fieldID.size = ecCurve_map[curve]->size;
+    ecParams->fieldID.type = type;
+    ecParams->cofactor = ecCurve_map[curve]->cofactor;
+    ecParams->pointSize = ecCurve_map[curve]->pointSize;
+
+    return SECSuccess;
+}
+
 SECStatus
 ectest_ecdh_kat(ECDH_KAT *kat)
 {
     ECCurveName curve = kat->curve;
     ECParams ecParams = { 0 };
     ECPrivateKey *ecPriv = NULL;
     SECItem theirKey = { siBuffer, NULL, 0 };
     SECStatus rv = SECFailure;
-    PLArenaPool *arena;
+    PLArenaPool *arena = NULL;
     SECItem seed = { siBuffer, NULL, 0 };
     SECItem answer = { siBuffer, NULL, 0 };
     SECItem answer2 = { siBuffer, NULL, 0 };
     SECItem derived = { siBuffer, NULL, 0 };
     char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
-    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if (!arena) {
-        return SECFailure;
-    }
+    int i;
 
-    if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) {
-        PORT_FreeArena(arena, PR_FALSE);
-        return SECFailure;
+    rv = init_params(&ecParams, curve, &arena, kat->fieldType);
+    if (rv != SECSuccess) {
+        return rv;
     }
 
-    ecParams.name = curve;
-    ecParams.type = ec_params_named;
-    ecParams.curveOID.data = NULL;
-    ecParams.curveOID.len = 0;
-    ecParams.curve.seed.data = NULL;
-    ecParams.curve.seed.len = 0;
-    ecParams.DEREncoding.data = NULL;
-    ecParams.DEREncoding.len = 0;
-
-    ecParams.fieldID.size = ecCurve_map[curve]->size;
-    ecParams.fieldID.type = ec_field_GFp;
     hexString2SECItem(arena, &ecParams.fieldID.u.prime, ecCurve_map[curve]->irr);
     hexString2SECItem(arena, &ecParams.curve.a, ecCurve_map[curve]->curvea);
     hexString2SECItem(arena, &ecParams.curve.b, ecCurve_map[curve]->curveb);
     genenc[0] = '0';
     genenc[1] = '4';
     genenc[2] = '\0';
+    PORT_Assert(PR_ARRAY_SIZE(genenc) >= PORT_Strlen(ecCurve_map[curve]->genx));
+    PORT_Assert(PR_ARRAY_SIZE(genenc) >= PORT_Strlen(ecCurve_map[curve]->geny));
     strcat(genenc, ecCurve_map[curve]->genx);
     strcat(genenc, ecCurve_map[curve]->geny);
     hexString2SECItem(arena, &ecParams.base, genenc);
     hexString2SECItem(arena, &ecParams.order, ecCurve_map[curve]->order);
-    ecParams.cofactor = ecCurve_map[curve]->cofactor;
 
-    hexString2SECItem(arena, &answer, kat->our_pubhex);
+    if (kat->our_pubhex) {
+        hexString2SECItem(arena, &answer, kat->our_pubhex);
+    }
     hexString2SECItem(arena, &seed, kat->privhex);
     rv = EC_NewKeyFromSeed(&ecParams, &ecPriv, seed.data, seed.len);
     if (rv != SECSuccess) {
         rv = SECFailure;
         goto cleanup;
     }
-    if (SECITEM_CompareItem(&answer, &ecPriv->publicValue) != SECEqual) {
-        rv = SECFailure;
-        goto cleanup;
+    if (kat->our_pubhex) {
+        if (SECITEM_CompareItem(&answer, &ecPriv->publicValue) != SECEqual) {
+            rv = SECFailure;
+            goto cleanup;
+        }
     }
 
     hexString2SECItem(arena, &theirKey, kat->their_pubhex);
     hexString2SECItem(arena, &answer2, kat->common_key);
-    rv = ECDH_Derive(&theirKey, &ecParams, &ecPriv->privateValue, PR_TRUE, &derived);
+
+    rv = EC_ValidatePublicKey(&ecParams, &theirKey);
     if (rv != SECSuccess) {
+        printf("EC_ValidatePublicKey failed\n");
+        goto cleanup;
+    }
+
+    for (i = 0; i < kat->iterations; ++i) {
+        rv = ECDH_Derive(&theirKey, &ecParams, &ecPriv->privateValue, PR_TRUE, &derived);
+        if (rv != SECSuccess) {
+            rv = SECFailure;
+            goto cleanup;
+        }
+        rv = SECITEM_CopyItem(ecParams.arena, &theirKey, &ecPriv->privateValue);
+        if (rv != SECSuccess) {
+            goto cleanup;
+        }
+        rv = SECITEM_CopyItem(ecParams.arena, &ecPriv->privateValue, &derived);
+        if (rv != SECSuccess) {
+            goto cleanup;
+        }
+        SECITEM_FreeItem(&derived, PR_FALSE);
+    }
+
+    if (SECITEM_CompareItem(&answer2, &ecPriv->privateValue) != SECEqual) {
+        printf("expected: ");
+        printBuf(&answer2);
+        printf("derived:  ");
+        printBuf(&ecPriv->privateValue);
         rv = SECFailure;
         goto cleanup;
     }
 
-    if (SECITEM_CompareItem(&answer2, &derived) != SECEqual) {
-        rv = SECFailure;
+cleanup:
+    PORT_FreeArena(arena, PR_FALSE);
+    if (ecPriv) {
+        PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE);
+    }
+    if (derived.data) {
+        SECITEM_FreeItem(&derived, PR_FALSE);
+    }
+    return rv;
+}
+
+void
+PrintKey(PK11SymKey *symKey)
+{
+    char *name = PK11_GetSymKeyNickname(symKey);
+    int len = PK11_GetKeyLength(symKey);
+    int strength = PK11_GetKeyStrength(symKey, NULL);
+    SECItem *value = NULL;
+    CK_KEY_TYPE type = PK11_GetSymKeyType(symKey);
+    (void)PK11_ExtractKeyValue(symKey);
+
+    value = PK11_GetKeyData(symKey);
+    printf("%s %3d   %4d   %s  ", name ? name : "no-name", len, strength,
+           type == CKK_GENERIC_SECRET ? "generic" : "ERROR! UNKNOWN KEY TYPE");
+    printBuf(value);
+
+    PORT_Free(name);
+}
+
+SECStatus
+ectest_curve_pkcs11(SECOidTag oid)
+{
+    SECKEYECParams pk_11_ecParams = { siBuffer, NULL, 0 };
+    SECKEYPublicKey *pubKey = NULL;
+    SECKEYPrivateKey *privKey = NULL;
+    SECOidData *oidData = NULL;
+    CK_MECHANISM_TYPE target = CKM_TLS12_MASTER_KEY_DERIVE_DH;
+    PK11SymKey *symKey = NULL;
+    SECStatus rv = SECFailure;
+
+    oidData = SECOID_FindOIDByTag(oid);
+    if (oidData == NULL) {
+        printf(" >>> SECOID_FindOIDByTag failed.\n");
+        goto cleanup;
+    }
+    PORT_Assert(oidData->oid.len < 256);
+    SECITEM_AllocItem(NULL, &pk_11_ecParams, (2 + oidData->oid.len));
+    pk_11_ecParams.data[0] = SEC_ASN1_OBJECT_ID; /* we have to prepend 0x06 */
+    pk_11_ecParams.data[1] = oidData->oid.len;
+    memcpy(pk_11_ecParams.data + 2, oidData->oid.data, oidData->oid.len);
+
+    privKey = SECKEY_CreateECPrivateKey(&pk_11_ecParams, &pubKey, NULL);
+    if (!privKey || !pubKey) {
+        printf(" >>> SECKEY_CreateECPrivateKey failed.\n");
         goto cleanup;
     }
+
+    symKey = PK11_PubDeriveWithKDF(privKey, pubKey, PR_FALSE, NULL, NULL,
+                                   CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
+                                   CKD_NULL, NULL, NULL);
+    if (!symKey) {
+        printf(" >>> PK11_PubDeriveWithKDF failed.\n");
+        goto cleanup;
+    }
+    PrintKey(symKey);
+    rv = SECSuccess;
+
 cleanup:
+    if (privKey) {
+        SECKEY_DestroyPrivateKey(privKey);
+    }
+    if (pubKey) {
+        SECKEY_DestroyPublicKey(pubKey);
+    }
+    if (symKey) {
+        PK11_FreeSymKey(symKey);
+    }
+    SECITEM_FreeItem(&pk_11_ecParams, PR_FALSE);
+
+    return rv;
+}
+
+SECStatus
+ectest_validate_point(ECDH_BAD *bad)
+{
+    ECParams ecParams = { 0 };
+    SECItem point = { siBuffer, NULL, 0 };
+    SECStatus rv = SECFailure;
+    PLArenaPool *arena = NULL;
+
+    rv = init_params(&ecParams, bad->curve, &arena, bad->fieldType);
+    if (rv != SECSuccess) {
+        return rv;
+    }
+
+    hexString2SECItem(arena, &point, bad->point);
+    rv = EC_ValidatePublicKey(&ecParams, &point);
+
     PORT_FreeArena(arena, PR_FALSE);
-    PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE);
-    SECITEM_FreeItem(&derived, PR_FALSE);
     return rv;
 }
 
+void
+printUsage(char *prog)
+{
+    printf("Usage: %s [-fp] [-nd]\n"
+           "\t-f: usefreebl\n"
+           "\t-p: usepkcs11\n"
+           "\t-n: NIST curves\n"
+           "\t-d: non-NIST curves\n"
+           "You have to specify at least f or p and n or d.\n"
+           "By default no tests are executed.\n",
+           prog);
+}
+
 /* Performs tests of elliptic curve cryptography over prime fields If
  * tests fail, then it prints an error message, aborts, and returns an
  * error code. Otherwise, returns 0. */
 int
 main(int argv, char **argc)
 {
     SECStatus rv = SECSuccess;
     int numkats = 0;
     int i = 0;
+    int usepkcs11 = 0;
+    int usefreebl = 0;
+    int nist = 0;
+    int nonnist = 0;
+    SECOidTag nistOids[3] = { SEC_OID_SECG_EC_SECP256R1,
+                              SEC_OID_SECG_EC_SECP384R1,
+                              SEC_OID_SECG_EC_SECP521R1 };
 
-    rv = SECOID_Init();
+    for (i = 1; i < argv; i++) {
+        if (PL_strcasecmp(argc[i], "-p") == 0) {
+            usepkcs11 = 1;
+        } else if (PL_strcasecmp(argc[i], "-f") == 0) {
+            usefreebl = 1;
+        } else if (PL_strcasecmp(argc[i], "-n") == 0) {
+            nist = 1;
+        } else if (PL_strcasecmp(argc[i], "-d") == 0) {
+            nonnist = 1;
+        } else {
+            printUsage(argc[0]);
+            return 1;
+        }
+    }
+    if (!(usepkcs11 || usefreebl) || !(nist || nonnist)) {
+        printUsage(argc[0]);
+        return 1;
+    }
+
+    rv = NSS_NoDB_Init(NULL);
     if (rv != SECSuccess) {
-        SECU_PrintError("Error:", "SECOID_Init");
+        SECU_PrintError("Error:", "NSS_NoDB_Init");
         goto cleanup;
     }
 
-    while (ecdh_testvecs[numkats].curve != ECCurve_pastLastCurve) {
-        numkats++;
+    /* Test P256, P384, P521 */
+    if (usefreebl) {
+        if (nist) {
+            while (ecdh_testvecs[numkats].curve != ECCurve_pastLastCurve) {
+                numkats++;
+            }
+            printf("1..%d\n", numkats);
+            for (i = 0; ecdh_testvecs[i].curve != ECCurve_pastLastCurve; i++) {
+                if (ectest_ecdh_kat(&ecdh_testvecs[i]) != SECSuccess) {
+                    printf("not okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
+                    rv = SECFailure;
+                } else {
+                    printf("okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
+                }
+            }
+        }
+
+        /* Test KAT for non-NIST curves */
+        if (nonnist) {
+            for (i = 0; nonnist_testvecs[i].curve != ECCurve_pastLastCurve; i++) {
+                if (ectest_ecdh_kat(&nonnist_testvecs[i]) != SECSuccess) {
+                    printf("not okay %d - %s\n", i + 1, nonnist_testvecs[i].name);
+                    rv = SECFailure;
+                } else {
+                    printf("okay %d - %s\n", i + 1, nonnist_testvecs[i].name);
+                }
+            }
+            for (i = 0; nonnist_testvecs_bad_values[i].curve != ECCurve_pastLastCurve; i++) {
+                if (ectest_validate_point(&nonnist_testvecs_bad_values[i]) == SECSuccess) {
+                    printf("not okay %d - %s\n", i + 1, nonnist_testvecs_bad_values[i].name);
+                    rv = SECFailure;
+                } else {
+                    printf("okay %d - %s\n", i + 1, nonnist_testvecs_bad_values[i].name);
+                }
+            }
+        }
     }
-    printf("1..%d\n", numkats);
-    for (i = 0; ecdh_testvecs[i].curve != ECCurve_pastLastCurve; i++) {
-        rv = ectest_ecdh_kat(&ecdh_testvecs[i]);
-        if (rv != SECSuccess) {
-            printf("not okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
-        } else {
-            printf("okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
+
+    /* Test PK11 for non-NIST curves */
+    if (usepkcs11) {
+        if (nonnist) {
+            if (ectest_curve_pkcs11(SEC_OID_CURVE25519) != SECSuccess) {
+                printf("not okay (OID %d) - PK11 test\n", SEC_OID_CURVE25519);
+                rv = SECFailure;
+            } else {
+                printf("okay (OID %d) - PK11 test\n", SEC_OID_CURVE25519);
+            }
+        }
+        if (nist) {
+            for (i = 0; i < 3; ++i) {
+                if (ectest_curve_pkcs11(nistOids[i]) != SECSuccess) {
+                    printf("not okay (OID %d) - PK11 test\n", nistOids[i]);
+                    rv = SECFailure;
+                } else {
+                    printf("okay (OID %d) - PK11 test\n", nistOids[i]);
+                }
+            }
         }
     }
 
 cleanup:
-    rv |= SECOID_Shutdown();
+    rv |= NSS_Shutdown();
 
     if (rv != SECSuccess) {
         printf("Error: exiting with error value\n");
     }
     return rv;
 }
--- a/security/nss/cmd/ectest/testvecs.h
+++ b/security/nss/cmd/ectest/testvecs.h
@@ -1,728 +1,818 @@
 static ECDH_KAT ecdh_testvecs[] = {
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534",
       "04ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b23028af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141",
       "04700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac",
       "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b",
-      "curve: P256 vector: 0" },
+      "curve: P256 vector: 0", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5",
       "04119f2f047902782ab0c9e27a54aff5eb9b964829ca99c06b02ddba95b0a3f6d08f52b726664cac366fc98ac7a012b2682cbd962e5acb544671d41b9445704d1d",
       "04809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7aeb29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3",
       "057d636096cb80b67a8c038c890e887d1adfa4195e9b3ce241c8a778c59cda67",
-      "curve: P256 vector: 1" },
+      "curve: P256 vector: 1", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "1accfaf1b97712b85a6f54b148985a1bdc4c9bec0bd258cad4b3d603f49f32c8",
       "04d9f2b79c172845bfdb560bbb01447ca5ecc0470a09513b6126902c6b4f8d1051f815ef5ec32128d3487834764678702e64e164ff7315185e23aff5facd96d7bc",
       "04a2339c12d4a03c33546de533268b4ad667debf458b464d77443636440ee7fec3ef48a3ab26e20220bcda2c1851076839dae88eae962869a497bf73cb66faf536",
       "2d457b78b4614132477618a5b077965ec90730a8c81a1c75d6d4ec68005d67ec",
-      "curve: P256 vector: 2" },
+      "curve: P256 vector: 2", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "207c43a79bfee03db6f4b944f53d2fb76cc49ef1c9c4d34d51b6c65c4db6932d",
       "0424277c33f450462dcb3d4801d57b9ced05188f16c28eda873258048cd1607e0dc4789753e2b1f63b32ff014ec42cd6a69fac81dfe6d0d6fd4af372ae27c46f88",
       "04df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4",
       "96441259534b80f6aee3d287a6bb17b5094dd4277d9e294f8fe73e48bf2a0024",
-      "curve: P256 vector: 3" },
+      "curve: P256 vector: 3", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "59137e38152350b195c9718d39673d519838055ad908dd4757152fd8255c09bf",
       "04a8c5fdce8b62c5ada598f141adb3b26cf254c280b2857a63d2ad783a73115f6b806e1aafec4af80a0d786b3de45375b517a7e5b51ffb2c356537c9e6ef227d4a",
       "0441192d2813e79561e6a1d6f53c8bc1a433a199c835e141b05a74a97b0faeb9221af98cc45e98a7e041b01cf35f462b7562281351c8ebf3ffa02e33a0722a1328",
       "19d44c8d63e8e8dd12c22a87b8cd4ece27acdde04dbf47f7f27537a6999a8e62",
-      "curve: P256 vector: 4" },
+      "curve: P256 vector: 4", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "f5f8e0174610a661277979b58ce5c90fee6c9b3bb346a90a7196255e40b132ef",
       "047b861dcd2844a5a8363f6b8ef8d493640f55879217189d80326aad9480dfc149c4675b45eeb306405f6c33c38bc69eb2bdec9b75ad5af4706aab84543b9cc63a",
       "0433e82092a0f1fb38f5649d5867fba28b503172b7035574bf8e5b7100a3052792f2cf6b601e0a05945e335550bf648d782f46186c772c0f20d3cd0d6b8ca14b2f",
       "664e45d5bba4ac931cd65d52017e4be9b19a515f669bea4703542a2c525cd3d3",
-      "curve: P256 vector: 5" },
+      "curve: P256 vector: 5", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "3b589af7db03459c23068b64f63f28d3c3c6bc25b5bf76ac05f35482888b5190",
       "049fb38e2d58ea1baf7622e96720101cae3cde4ba6c1e9fa26d9b1de0899102863d5561b900406edf50802dd7d73e89395f8aed72fba0e1d1b61fe1d22302260f0",
       "046a9e0c3f916e4e315c91147be571686d90464e8bf981d34a90b6353bca6eeba740f9bead39c2f2bcc2602f75b8a73ec7bdffcbcead159d0174c6c4d3c5357f05",
       "ca342daa50dc09d61be7c196c85e60a80c5cb04931746820be548cdde055679d",
-      "curve: P256 vector: 6" },
+      "curve: P256 vector: 6", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "d8bf929a20ea7436b2461b541a11c80e61d826c0a4c9d322b31dd54e7f58b9c8",
       "0420f07631e4a6512a89ad487c4e9d63039e579cb0d7a556cb9e661cd59c1e7fa46de91846b3eee8a5ec09c2ab1f41e21bd83620ccdd1bdce3ab7ea6e02dd274f5",
       "04a9c0acade55c2a73ead1a86fb0a9713223c82475791cd0e210b046412ce224bbf6de0afa20e93e078467c053d241903edad734c6b403ba758c2b5ff04c9d4229",
       "35aa9b52536a461bfde4e85fc756be928c7de97923f0416c7a3ac8f88b3d4489",
-      "curve: P256 vector: 7" },
+      "curve: P256 vector: 7", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "0f9883ba0ef32ee75ded0d8bda39a5146a29f1f2507b3bd458dbea0b2bb05b4d",
       "04abb61b423be5d6c26e21c605832c9142dc1dfe5a5fff28726737936e6fbf516d733d2513ef58beab202090586fac91bf0fee31e80ab33473ab23a2d89e58fad6",
       "0494e94f16a98255fff2b9ac0c9598aac35487b3232d3231bd93b7db7df36f9eb9d8049a43579cfa90b8093a94416cbefbf93386f15b3f6e190b6e3455fedfe69a",
       "605c16178a9bc875dcbff54d63fe00df699c03e8a888e9e94dfbab90b25f39b4",
-      "curve: P256 vector: 8" },
+      "curve: P256 vector: 8", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "2beedb04b05c6988f6a67500bb813faf2cae0d580c9253b6339e4a3337bb6c08",
       "043d63e429cb5fa895a9247129bf4e48e89f35d7b11de8158efeb3e106a2a873950cae9e477ef41e7c8c1064379bb7b554ddcbcae79f9814281f1e50f0403c61f3",
       "04e099bf2a4d557460b5544430bbf6da11004d127cb5d67f64ab07c94fcdf5274fd9c50dbe70d714edb5e221f4e020610eeb6270517e688ca64fb0e98c7ef8c1c5",
       "f96e40a1b72840854bb62bc13c40cc2795e373d4e715980b261476835a092e0b",
-      "curve: P256 vector: 9" },
+      "curve: P256 vector: 9", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "77c15dcf44610e41696bab758943eff1409333e4d5a11bbe72c8f6c395e9f848",
       "04ad5d13c3db508ddcd38457e5991434a251bed49cf5ddcb59cdee73865f138c9f62cec1e70588aa4fdfc7b9a09daa678081c04e1208b9d662b8a2214bf8e81a21",
       "04f75a5fe56bda34f3c1396296626ef012dc07e4825838778a645c8248cff0165833bbdf1b1772d8059df568b061f3f1122f28a8d819167c97be448e3dc3fb0c3c",
       "8388fa79c4babdca02a8e8a34f9e43554976e420a4ad273c81b26e4228e9d3a3",
-      "curve: P256 vector: 10" },
+      "curve: P256 vector: 10", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "42a83b985011d12303db1a800f2610f74aa71cdf19c67d54ce6c9ed951e9093e",
       "04ab48caa61ea35f13f8ed07ffa6a13e8db224dfecfae1a7df8b1bb6ebaf0cb97d1274530ca2c385a3218bddfbcbf0b4024c9badd5243bff834ebff24a8618dccb",
       "042db4540d50230756158abf61d9835712b6486c74312183ccefcaef2797b7674d62f57f314e3f3495dc4e099012f5e0ba71770f9660a1eada54104cdfde77243e",
       "72877cea33ccc4715038d4bcbdfe0e43f42a9e2c0c3b017fc2370f4b9acbda4a",
-      "curve: P256 vector: 11" },
+      "curve: P256 vector: 11", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "ceed35507b5c93ead5989119b9ba342cfe38e6e638ba6eea343a55475de2800b",
       "049a8cd9bd72e71752df91440f77c547509a84df98114e7de4f26cdb39234a625dd07cfc84c8e144fab2839f5189bb1d7c88631d579bbc58012ed9a2327da52f62",
       "04cd94fc9497e8990750309e9a8534fd114b0a6e54da89c4796101897041d14ecbc3def4b5fe04faee0a11932229fff563637bfdee0e79c6deeaf449f85401c5c4",
       "e4e7408d85ff0e0e9c838003f28cdbd5247cdce31f32f62494b70e5f1bc36307",
-      "curve: P256 vector: 12" },
+      "curve: P256 vector: 12", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "43e0e9d95af4dc36483cdd1968d2b7eeb8611fcce77f3a4e7d059ae43e509604",
       "04f989cf8ee956a82e7ebd9881cdbfb2fd946189b08db53559bc8cfdd48071eb145eff28f1a18a616b04b7d337868679f6dd84f9a7b3d7b6f8af276c19611a541d",
       "0415b9e467af4d290c417402e040426fe4cf236bae72baa392ed89780dfccdb471cdf4e9170fb904302b8fd93a820ba8cc7ed4efd3a6f2d6b05b80b2ff2aee4e77",
       "ed56bcf695b734142c24ecb1fc1bb64d08f175eb243a31f37b3d9bb4407f3b96",
-      "curve: P256 vector: 13" },
+      "curve: P256 vector: 13", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "b2f3600df3368ef8a0bb85ab22f41fc0e5f4fdd54be8167a5c3cd4b08db04903",
       "0469c627625b36a429c398b45c38677cb35d8beb1cf78a571e40e99fe4eac1cd4e81690112b0a88f20f7136b28d7d47e5fbc2ada3c8edd87589bc19ec9590637bd",
       "0449c503ba6c4fa605182e186b5e81113f075bc11dcfd51c932fb21e951eee2fa18af706ff0922d87b3f0c5e4e31d8b259aeb260a9269643ed520a13bb25da5924",
       "bc5c7055089fc9d6c89f83c1ea1ada879d9934b2ea28fcf4e4a7e984b28ad2cf",
-      "curve: P256 vector: 14" },
+      "curve: P256 vector: 14", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "4002534307f8b62a9bf67ff641ddc60fef593b17c3341239e95bdb3e579bfdc8",
       "045fe964671315a18aa68a2a6e3dd1fde7e23b8ce7181471cfac43c99e1ae80262d5827be282e62c84de531b963884ba832db5d6b2c3a256f0e604fe7e6b8a7f72",
       "0419b38de39fdd2f70f7091631a4f75d1993740ba9429162c2a45312401636b29c09aed7232b28e060941741b6828bcdfa2bc49cc844f3773611504f82a390a5ae",
       "9a4e8e657f6b0e097f47954a63c75d74fcba71a30d83651e3e5a91aa7ccd8343",
-      "curve: P256 vector: 15" },
+      "curve: P256 vector: 15", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "4dfa12defc60319021b681b3ff84a10a511958c850939ed45635934ba4979147",
       "04c9b2b8496f1440bd4a2d1e52752fd372835b364885e154a7dac49295f281ec7cfbe6b926a8a4de26ccc83b802b1212400754be25d9f3eeaf008b09870ae76321",
       "042c91c61f33adfe9311c942fdbff6ba47020feff416b7bb63cec13faf9b0999546cab31b06419e5221fca014fb84ec870622a1b12bab5ae43682aa7ea73ea08d0",
       "3ca1fc7ad858fb1a6aba232542f3e2a749ffc7203a2374a3f3d3267f1fc97b78",
-      "curve: P256 vector: 16" },
+      "curve: P256 vector: 16", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "1331f6d874a4ed3bc4a2c6e9c74331d3039796314beee3b7152fcdba5556304e",
       "0459e1e101521046ad9cf1d082e9d2ec7dd22530cce064991f1e55c5bcf5fcb591482f4f673176c8fdaa0bb6e59b15a3e47454e3a04297d3863c9338d98add1f37",
       "04a28a2edf58025668f724aaf83a50956b7ac1cfbbff79b08c3bf87dfd2828d767dfa7bfffd4c766b86abeaf5c99b6e50cb9ccc9d9d00b7ffc7804b0491b67bc03",
       "1aaabe7ee6e4a6fa732291202433a237df1b49bc53866bfbe00db96a0f58224f",
-      "curve: P256 vector: 17" },
+      "curve: P256 vector: 17", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "dd5e9f70ae740073ca0204df60763fb6036c45709bf4a7bb4e671412fad65da3",
       "0430b9db2e2e977bcdc98cb87dd736cbd8e78552121925cf16e1933657c2fb23146a45028800b81291bce5c2e1fed7ded650620ebbe6050c6f3a7f0dfb4673ab5c",
       "04a2ef857a081f9d6eb206a81c4cf78a802bdf598ae380c8886ecd85fdc1ed7644563c4c20419f07bc17d0539fade1855e34839515b892c0f5d26561f97fa04d1a",
       "430e6a4fba4449d700d2733e557f66a3bf3d50517c1271b1ddae1161b7ac798c",
-      "curve: P256 vector: 18" },
+      "curve: P256 vector: 18", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "5ae026cfc060d55600717e55b8a12e116d1d0df34af831979057607c2d9c2f76",
       "0446c9ebd1a4a3c8c0b6d572b5dcfba12467603208a9cb5d2acfbb733c40cf639146c913a27d044185d38b467ace011e04d4d9bbbb8cb9ae25fa92aaf15a595e86",
       "04ccd8a2d86bc92f2e01bce4d6922cf7fe1626aed044685e95e2eebd464505f01fe9ddd583a9635a667777d5b8a8f31b0f79eba12c75023410b54b8567dddc0f38",
       "1ce9e6740529499f98d1f1d71329147a33df1d05e4765b539b11cf615d6974d3",
-      "curve: P256 vector: 19" },
+      "curve: P256 vector: 19", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "b601ac425d5dbf9e1735c5e2d5bdb79ca98b3d5be4a2cfd6f2273f150e064d9d",
       "047c9e950841d26c8dde8994398b8f5d475a022bc63de7773fcf8d552e01f1ba0acc42b9885c9b3bee0f8d8c57d3a8f6355016c019c4062fa22cff2f209b5cc2e1",
       "04c188ffc8947f7301fb7b53e36746097c2134bf9cc981ba74b4e9c4361f595e4ebf7d2f2056e72421ef393f0c0f2b0e00130e3cac4abbcc00286168e85ec55051",
       "4690e3743c07d643f1bc183636ab2a9cb936a60a802113c49bb1b3f2d0661660",
-      "curve: P256 vector: 20" },
+      "curve: P256 vector: 20", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "fefb1dda1845312b5fce6b81b2be205af2f3a274f5a212f66c0d9fc33d7ae535",
       "0438b54db85500cb20c61056edd3d88b6a9dc26780a047f213a6e1b900f76596eb6387e4e5781571e4eb8ae62991a33b5dc33301c5bc7e125d53794a39160d8fd0",
       "04317e1020ff53fccef18bf47bb7f2dd7707fb7b7a7578e04f35b3beed222a0eb609420ce5a19d77c6fe1ee587e6a49fbaf8f280e8df033d75403302e5a27db2ae",
       "30c2261bd0004e61feda2c16aa5e21ffa8d7e7f7dbf6ec379a43b48e4b36aeb0",
-      "curve: P256 vector: 21" },
+      "curve: P256 vector: 21", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "334ae0c4693d23935a7e8e043ebbde21e168a7cba3fa507c9be41d7681e049ce",
       "043f2bf1589abf3047bf3e54ac9a95379bff95f8f55405f64eca36a7eebe8ffca75212a94e66c5ae9a8991872f66a72723d80ec5b2e925745c456f5371943b3a06",
       "0445fb02b2ceb9d7c79d9c2fa93e9c7967c2fa4df5789f9640b24264b1e524fcb15c6e8ecf1f7d3023893b7b1ca1e4d178972ee2a230757ddc564ffe37f5c5a321",
       "2adae4a138a239dcd93c243a3803c3e4cf96e37fe14e6a9b717be9599959b11c",
-      "curve: P256 vector: 22" },
+      "curve: P256 vector: 22", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "2c4bde40214fcc3bfc47d4cf434b629acbe9157f8fd0282540331de7942cf09d",
       "0429c0807f10cbc42fb45c9989da50681eead716daa7b9e91fd32e062f5eb92ca0ff1d6d1955d7376b2da24fe1163a271659136341bc2eb1195fc706dc62e7f34d",
       "04a19ef7bff98ada781842fbfc51a47aff39b5935a1c7d9625c8d323d511c92de6e9c184df75c955e02e02e400ffe45f78f339e1afe6d056fb3245f4700ce606ef",
       "2e277ec30f5ea07d6ce513149b9479b96e07f4b6913b1b5c11305c1444a1bc0b",
-      "curve: P256 vector: 23" },
+      "curve: P256 vector: 23", ec_field_GFp },
 
-    { ECCurve_NIST_P256,
+    { ECCurve_NIST_P256, 1,
       "85a268f9d7772f990c36b42b0a331adc92b5941de0b862d5d89a347cbf8faab0",
       "049cf4b98581ca1779453cc816ff28b4100af56cf1bf2e5bc312d83b6b1b21d3337a5504fcac5231a0d12d658218284868229c844a04a3450d6c7381abe080bf3b",
       "04356c5a444c049a52fee0adeb7e5d82ae5aa83030bfff31bbf8ce2096cf161c4b57d128de8b2a57a094d1a001e572173f96e8866ae352bf29cddaf92fc85b2f92",
       "1e51373bd2c6044c129c436e742a55be2a668a85ae08441b6756445df5493857",
-      "curve: P256 vector: 24" },
+      "curve: P256 vector: 24", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "3cc3122a68f0d95027ad38c067916ba0eb8c38894d22e1b15618b6818a661774ad463b205da88cf699ab4d43c9cf98a1",
       "049803807f2f6d2fd966cdd0290bd410c0190352fbec7ff6247de1302df86f25d34fe4a97bef60cff548355c015dbb3e5"
       "fba26ca69ec2f5b5d9dad20cc9da711383a9dbe34ea3fa5a2af75b46502629ad54dd8b7d73a8abb06a3a3be47d650cc99",
       "04a7c76b970c3b5fe8b05d2838ae04ab47697b9eaf52e764592efda27fe7513272734466b400091adbf2d68c58e0c5006"
       "6ac68f19f2e1cb879aed43a9969b91a0839c4c38a49749b661efedf243451915ed0905a32b060992b468c64766fc8437a",
       "5f9d29dc5e31a163060356213669c8ce132e22f57c9a04f40ba7fcead493b457e5621e766c40a2e3d4d6a04b25e533f1",
-      "curve: P384 vector: 0" },
+      "curve: P384 vector: 0", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "92860c21bde06165f8e900c687f8ef0a05d14f290b3f07d8b3a8cc6404366e5d5119cd6d03fb12dc58e89f13df9cd783",
       "04ea4018f5a307c379180bf6a62fd2ceceebeeb7d4df063a66fb838aa35243419791f7e2c9d4803c9319aa0eb03c416b"
       "6668835a91484f05ef028284df6436fb88ffebabcdd69ab0133e6735a1bcfb37203d10d340a8328a7b68770ca75878a1a6",
       "0430f43fcf2b6b00de53f624f1543090681839717d53c7c955d1d69efaf0349b7363acb447240101cbb3af6641ce4b88e0"
       "25e46c0c54f0162a77efcc27b6ea792002ae2ba82714299c860857a68153ab62e525ec0530d81b5aa15897981e858757",
       "a23742a2c267d7425fda94b93f93bbcc24791ac51cd8fd501a238d40812f4cbfc59aac9520d758cf789c76300c69d2ff",
-      "curve: P384 vector: 1" },
+      "curve: P384 vector: 1", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "12cf6a223a72352543830f3f18530d5cb37f26880a0b294482c8a8ef8afad09aa78b7dc2f2789a78c66af5d1cc553853",
       "04fcfcea085e8cf74d0dced1620ba8423694f903a219bbf901b0b59d6ac81baad316a242ba32bde85cb248119b852fab6"
       "6972e3c68c7ab402c5836f2a16ed451a33120a7750a6039f3ff15388ee622b7065f7122bf6d51aefbc29b37b03404581b",
       "041aefbfa2c6c8c855a1a216774550b79a24cda37607bb1f7cc906650ee4b3816d68f6a9c75da6e4242cebfb6652f65180"
       "419d28b723ebadb7658fcebb9ad9b7adea674f1da3dc6b6397b55da0f61a3eddacb4acdb14441cb214b04a0844c02fa3",
       "3d2e640f350805eed1ff43b40a72b2abed0a518bcebe8f2d15b111b6773223da3c3489121db173d414b5bd5ad7153435",
-      "curve: P384 vector: 2" },
+      "curve: P384 vector: 2", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "8dd48063a3a058c334b5cc7a4ce07d02e5ee6d8f1f3c51a1600962cbab462690ae3cd974fb39e40b0e843daa0fd32de1",
       "04e38c9846248123c3421861ea4d32669a7b5c3c08376ad28104399494c84ff5efa3894adb2c6cbe8c3c913ef2eec5bd3"
       "c9fa84024a1028796df84021f7b6c9d02f0f4bd1a612a03cbf75a0beea43fef8ae84b48c60172aadf09c1ad016d0bf3ce",
       "048bc089326ec55b9cf59b34f0eb754d93596ca290fcb3444c83d4de3a5607037ec397683f8cef07eab2fe357eae36c44"
       "9d9d16ce8ac85b3f1e94568521aae534e67139e310ec72693526aa2e927b5b322c95a1a033c229cb6770c957cd3148dd7",
       "6a42cfc392aba0bfd3d17b7ccf062b91fc09bbf3417612d02a90bdde62ae40c54bb2e56e167d6b70db670097eb8db854",
-      "curve: P384 vector: 3" },
+      "curve: P384 vector: 3", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "84ece6cc3429309bd5b23e959793ed2b111ec5cb43b6c18085fcaea9efa0685d98a6262ee0d330ee250bc8a67d0e733f",
       "043222063a2997b302ee60ee1961108ff4c7acf1c0ef1d5fb0d164b84bce71c431705cb9aea9a45f5d73806655a058bee"
       "3e61fa9e7fbe7cd43abf99596a3d3a039e99fa9dc93b0bdd9cad81966d17eeaf557068afa7c78466bb5b22032d1100fa6",
       "04eb952e2d9ac0c20c6cc48fb225c2ad154f53c8750b003fd3b4ed8ed1dc0defac61bcdde02a2bcfee7067d75d342ed2b"
       "0f1828205baece82d1b267d0d7ff2f9c9e15b69a72df47058a97f3891005d1fb38858f5603de840e591dfa4f6e7d489e1",
       "ce7ba454d4412729a32bb833a2d1fd2ae612d4667c3a900e069214818613447df8c611de66da200db7c375cf913e4405",
-      "curve: P384 vector: 4" },
+      "curve: P384 vector: 4", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "68fce2121dc3a1e37b10f1dde309f9e2e18fac47cd1770951451c3484cdb77cb136d00e731260597cc2859601c01a25b",
       "04868be0e694841830e424d913d8e7d86b84ee1021d82b0ecf523f09fe89a76c0c95c49f2dfbcf829c1e39709d55efbb"
       "3b9195eb183675b40fd92f51f37713317e4a9b4f715c8ab22e0773b1bc71d3a219f05b8116074658ee86b52e36f3897116",
       "04441d029e244eb7168d647d4df50db5f4e4974ab3fdaf022aff058b3695d0b8c814cc88da6285dc6df1ac55c55388500"
       "3e8025ac23a41d4b1ea2aa46c50c6e479946b59b6d76497cd9249977e0bfe4a6262622f13d42a3c43d66bdbb30403c345",
       "ba69f0acdf3e1ca95caaac4ecaf475bbe51b54777efce01ca381f45370e486fe87f9f419b150c61e329a286d1aa265ec",
-      "curve: P384 vector: 5" },
+      "curve: P384 vector: 5", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "b1764c54897e7aae6de9e7751f2f37de849291f88f0f91093155b858d1cc32a3a87980f706b86cc83f927bdfdbeae0bd",
       "04c371222feaa6770c6f3ea3e0dac9740def4fcf821378b7f91ff937c21e0470f70f3a31d5c6b2912195f10926942b48ae"
       "047d6b4d765123563f81116bc665b7b8cc6207830d805fd84da7cb805a65baa7c12fd592d1b5b5e3e65d9672a9ef7662",
       "043d4e6bf08a73404accc1629873468e4269e82d90d832e58ad72142639b5a056ad8d35c66c60e8149fac0c797bceb7c2"
       "f9b0308dc7f0e6d29f8c277acbc65a21e5adb83d11e6873bc0a07fda0997f482504602f59e10bc5cb476b83d0a4f75e71",
       "1a6688ee1d6e59865d8e3ada37781d36bb0c2717eef92e61964d3927cb765c2965ea80f7f63e58c322ba0397faeaf62b",
-      "curve: P384 vector: 6" },
+      "curve: P384 vector: 6", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "f0f7a96e70d98fd5a30ad6406cf56eb5b72a510e9f192f50e1f84524dbf3d2439f7287bb36f5aa912a79deaab4adea82",
       "0499c8c41cb1ab5e0854a346e4b08a537c1706a61553387c8d94943ab15196d40dbaa55b8210a77a5d00915f2c4ea69e"
       "ab5531065bdcf17bfb3cb55a02e41a57c7f694c383ad289f900fbd656c2233a93c92e933e7a26f54cbb56f0ad875c51bb0",
       "04f5f6bef1d110da03be0017eac760cc34b24d092f736f237bc7054b3865312a813bcb62d297fb10a4f7abf54708fe2d3d"
       "06fdf8d7dc032f4e10010bf19cbf6159321252ff415fb91920d438f24e67e60c2eb0463204679fa356af44cea9c9ebf5",
       "d06a568bf2336b90cbac325161be7695eacb2295f599500d787f072612aca313ee5d874f807ddef6c1f023fe2b6e7cd0",
-      "curve: P384 vector: 7" },
+      "curve: P384 vector: 7", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "9efb87ddc61d43c482ba66e1b143aef678fbd0d1bebc2000941fabe677fe5b706bf78fce36d100b17cc787ead74bbca2",
       "044c34efee8f0c95565d2065d1bbac2a2dd25ae964320eb6bccedc5f3a9b42a881a1afca1bb6b880584fa27b01c193cd9"
       "2d8fb01dbf7cd0a3868c26b951f393c3c56c2858cee901f7793ff5d271925d13a41f8e52409f4eba1990f33acb0bac669",
       "047cdec77e0737ea37c67b89b7137fe38818010f4464438ee4d1d35a0c488cad3fde2f37d00885d36d3b795b9f93d23a6"
       "728c42ee8d6027c56cf979ba4c229fdb01d234944f8ac433650112c3cf0f02844e888a3569dfef7828a8a884589aa055e",
       "bb3b1eda9c6560d82ff5bee403339f1e80342338a991344853b56b24f109a4d94b92f654f0425edd4c205903d7586104",
-      "curve: P384 vector: 8" },
+      "curve: P384 vector: 8", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "d787a57fde22ec656a0a525cf3c738b30d73af61e743ea90893ecb2d7b622add2f94ee25c2171467afb093f3f84d0018",
       "04171546923b87b2cbbad664f01ce932bf09d6a6118168678446bfa9f0938608cb4667a98f4ec8ac1462285c2508f7486"
       "2fa41cb4db68ae71f1f8a3e8939dc52c2dec61a83c983beb2a02baf29ec49278088882ed0cf56c74b5c173b552ccf63cf",
       "048eeea3a319c8df99fbc29cb55f243a720d95509515ee5cc587a5c5ae22fbbd009e626db3e911def0b99a4f7ae304b1b"
       "a73877dc94db9adddc0d9a4b24e8976c22d73c844370e1ee857f8d1b129a3bd5f63f40caf3bd0533e38a5f5777074ff9e",
       "1e97b60add7cb35c7403dd884c0a75795b7683fff8b49f9d8672a8206bfdcf0a106b8768f983258c74167422e44e4d14",
-      "curve: P384 vector: 9" },
+      "curve: P384 vector: 9", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "83d70f7b164d9f4c227c767046b20eb34dfc778f5387e32e834b1e6daec20edb8ca5bb4192093f543b68e6aeb7ce788b",
       "0457cd770f3bbcbe0c78c770eab0b169bc45e139f86378ffae1c2b16966727c2f2eb724572b8f3eb228d130db4ff862c"
       "637ec5c8813b685558d83e924f14bc719f6eb7ae0cbb2c474227c5bda88637a4f26c64817929af999592da6f787490332f",
       "04a721f6a2d4527411834b13d4d3a33c29beb83ab7682465c6cbaf6624aca6ea58c30eb0f29dd842886695400d7254f20f"
       "14ba6e26355109ad35129366d5e3a640ae798505a7fa55a96a36b5dad33de00474f6670f522214dd7952140ab0a7eb68",
       "1023478840e54775bfc69293a3cf97f5bc914726455c66538eb5623e218feef7df4befa23e09d77145ad577db32b41f9",
-      "curve: P384 vector: 10" },
+      "curve: P384 vector: 10", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "8f558e05818b88ed383d5fca962e53413db1a0e4637eda194f761944cbea114ab9d5da175a7d57882550b0e432f395a9",
       "049a2f57f4867ce753d72b0d95195df6f96c1fae934f602efd7b6a54582f556cfa539d89005ca2edac08ad9b72dd1f60b"
       "ad9b94ee82da9cc601f346044998ba387aee56404dc6ecc8ab2b590443319d0b2b6176f9d0eac2d44678ed561607d09a9",
       "04d882a8505c2d5cb9b8851fc676677bb0087681ad53faceba1738286b45827561e7da37b880276c656cfc38b32ade847"
       "e34b314bdc134575654573cffaf40445da2e6aaf987f7e913cd4c3091523058984a25d8f21da8326192456c6a0fa5f60c",
       "6ad6b9dc8a6cf0d3691c501cbb967867f6e4bbb764b60dbff8fcff3ed42dbba39d63cf325b4b4078858495ddee75f954",
-      "curve: P384 vector: 11" },
+      "curve: P384 vector: 11", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "0f5dee0affa7bbf239d5dff32987ebb7cf84fcceed643e1d3c62d0b3352aec23b6e5ac7fa4105c8cb26126ad2d1892cb",
       "0423346bdfbc9d7c7c736e02bdf607671ff6082fdd27334a8bc75f3b23681ebe614d0597dd614fae58677c835a9f0b273"
       "b82ba36290d2f94db41479eb45ab4eaf67928a2315138d59eecc9b5285dfddd6714f77557216ea44cc6fc119d8243efaf",
       "04815c9d773dbf5fb6a1b86799966247f4006a23c92e68c55e9eaa998b17d8832dd4d84d927d831d4f68dac67c6488219f"
       "e79269948b2611484560fd490feec887cb55ef99a4b524880fa7499d6a07283aae2afa33feab97deca40bc606c4d8764",
       "cc9e063566d46b357b3fcae21827377331e5e290a36e60cd7c39102b828ae0b918dc5a02216b07fe6f1958d834e42437",
-      "curve: P384 vector: 12" },
+      "curve: P384 vector: 12", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "037b633b5b8ba857c0fc85656868232e2febf59578718391b81da8541a00bfe53c30ae04151847f27499f8d7abad8cf4",
       "048878ac8a947f7d5cb2b47aad24fbb8210d86126585399a2871f84aa9c5fde3074ae540c6bf82275ca822d0feb862bc7"
       "4632f5cd2f900c2711c32f8930728eb647d31edd8d650f9654e7d33e5ed1b475489d08daa30d8cbcba6bfc3b60d9b5a37",
       "041c0eeda7a2be000c5bdcda0478aed4db733d2a9e341224379123ad847030f29e3b168fa18e89a3c0fba2a6ce1c28fc3"
       "bec8c1c83c118c4dbea94271869f2d868eb65e8b44e21e6f14b0f4d9b38c068daefa27114255b9a41d084cc4a1ad85456",
       "deff7f03bd09865baf945e73edff6d5122c03fb561db87dec8662e09bed4340b28a9efe118337bb7d3d4f7f568635ff9",
-      "curve: P384 vector: 13" },
+      "curve: P384 vector: 13", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "e3d07106bedcc096e7d91630ffd3094df2c7859db8d7edbb2e37b4ac47f429a637d06a67d2fba33838764ef203464991",
       "04e74a1a2b85f1cbf8dbbdf050cf1aff8acb02fda2fb6591f9d3cfe4e79d0ae938a9c1483e7b75f8db24505d65065cdb1"
       "81773ee591822f7abaa856a1a60bc0a5203548dbd1cb5025466eff8481bd07614eaa04a16c3db76905913e972a5b6b59d",
       "04c95c185e256bf997f30b311548ae7f768a38dee43eeeef43083f3077be70e2bf39ac1d4daf360c514c8c6be623443d1"
       "a3e63a663eaf75d8a765ab2b9a35513d7933fa5e26420a5244550ec6c3b6f033b96db2aca3d6ac6aab052ce929595aea5",
       "c8b1038f735ad3bb3e4637c3e47eab487637911a6b7950a4e461948329d3923b969e5db663675623611a457fcda35a71",
-      "curve: P384 vector: 14" },
+      "curve: P384 vector: 14", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "f3f9b0c65a49a506632c8a45b10f66b5316f9eeb06fae218f2da62333f99905117b141c760e8974efc4af10570635791",
       "04a4ad77aa7d86e5361118a6b921710c820721210712f4c347985fdee58aa4effa1e28be80a17b120b139f96300f89b4"
       "9b1ddf22e07e03f1560d8f45a480094560dba9fae7f9531130c1b57ebb95982496524f31d3797793396fa823f22bdb4328",
       "043497238a7e6ad166df2dac039aa4dac8d17aa925e7c7631eb3b56e3aaa1c545fcd54d2e5985807910fb202b1fc191d2a"
       "a49e5c487dcc7aa40a8f234c979446040d9174e3ad357d404d7765183195aed3f913641b90c81a306ebf0d8913861316",
       "d337eaa32b9f716b8747b005b97a553c59dab0c51df41a2d49039cdae705aa75c7b9e7bc0b6a0e8c578c902bc4fff23e",
-      "curve: P384 vector: 15" },
+      "curve: P384 vector: 15", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "59fce7fad7de28bac0230690c95710c720e528f9a4e54d3a6a8cd5fc5c5f21637031ce1c5b4e3d39647d8dcb9b794664",
       "049c43bf971edf09402876ee742095381f78b1bd3aa39b5132af75dbfe7e98bd78bde10fe2e903c2b6379e1deee175a1b"
       "0a6c58ecea5a477bb01bd543b339f1cc49f1371a2cda4d46eb4e53e250597942351a99665a122ffea9bde0636c375daf2",
       "0490a34737d45b1aa65f74e0bd0659bc118f8e4b774b761944ffa6573c6df4f41dec0d11b697abd934d390871d4b453240"
       "9b590719bb3307c149a7817be355d684893a307764b512eeffe07cb699edb5a6ffbf8d6032e6c79d5e93e94212c2aa4e",
       "32d292b695a4488e42a7b7922e1ae537d76a3d21a0b2e36875f60e9f6d3e8779c2afb3a413b9dd79ae18e70b47d337c1",
-      "curve: P384 vector: 16" },
+      "curve: P384 vector: 16", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "3e49fbf950a424c5d80228dc4bc35e9f6c6c0c1d04440998da0a609a877575dbe437d6a5cedaa2ddd2a1a17fd112aded",
       "045a949594228b1a3d6f599eb3db0d06070fbc551c657b58234ba164ce3fe415fa5f3eb823c08dc29b8c341219c77b6b3"
       "d2baad447c8c290cfed25edd9031c41d0b76921457327f42db31122b81f337bbf0b1039ec830ce9061a3761953c75e4a8",
       "04dda546acfc8f903d11e2e3920669636d44b2068aeb66ff07aa266f0030e1535b0ed0203cb8a460ac990f1394faf22f1"
       "d15bbb2597913035faadf413476f4c70f7279769a40c986f470c427b4ee4962abdf8173bbad81874772925fd32f0b159f",
       "1220e7e6cad7b25df98e5bbdcc6c0b65ca6c2a50c5ff6c41dca71e475646fd489615979ca92fb4389aeadefde79a24f1",
-      "curve: P384 vector: 17" },
+      "curve: P384 vector: 17", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "50ccc1f7076e92f4638e85f2db98e0b483e6e2204c92bdd440a6deea04e37a07c6e72791c190ad4e4e86e01efba84269",
       "04756c07df0ce32c839dac9fb4733c9c28b70113a676a7057c38d223f22a3a9095a8d564653af528e04c7e1824be4a651"
       "217c2ce6962cbd2a2e066297b39d57dd9bb4680f0191d390f70b4e461419b2972ce68ad46127fdda6c39195774ea86df3",
       "04788be2336c52f4454d63ee944b1e49bfb619a08371048e6da92e584eae70bde1f171c4df378bd1f3c0ab03048a237802"
       "4673ebd8db604eaf41711748bab2968a23ca4476ce144e728247f08af752929157b5830f1e26067466bdfa8b65145a33",
       "793bb9cd22a93cf468faf804a38d12b78cb12189ec679ddd2e9aa21fa9a5a0b049ab16a23574fe04c1c3c02343b91beb",
-      "curve: P384 vector: 18" },
+      "curve: P384 vector: 18", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "06f132b71f74d87bf99857e1e4350a594e5fe35533b888552ceccbc0d8923c902e36141d7691e28631b8bc9bafe5e064",
       "042a3cc6b8ff5cde926e7e3a189a1bd029c9b586351af8838f4f201cb8f4b70ef3b0da06d352c80fc26baf8f42b784459"
       "ebf9985960176da6d23c7452a2954ffcbbcb24249b43019a2a023e0b3dabd461f19ad3e775c364f3f11ad49f3099400d3",
       "04d09bb822eb99e38060954747c82bb3278cf96bbf36fece3400f4c873838a40c135eb3babb9293bd1001bf3ecdee7bf2"
       "6d416db6e1b87bbb7427788a3b6c7a7ab2c165b1e366f9608df512037584f213a648d47f16ac326e19aae972f63fd76c9",
       "012d191cf7404a523678c6fc075de8285b243720a903047708bb33e501e0dbee5bcc40d7c3ef6c6da39ea24d830da1e8",
-      "curve: P384 vector: 19" },
+      "curve: P384 vector: 19", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "12048ebb4331ec19a1e23f1a2c773b664ccfe90a28bfb846fc12f81dff44b7443c77647164bf1e9e67fd2c07a6766241",
       "04bc18836bc7a9fdf54b5352f37d7528ab8fa8ec544a8c6180511cbfdd49cce377c39e34c031b5240dc9980503ed2f26"
       "2c8086cbe338191080f0b7a16c7afc4c7b0326f9ac66f58552ef4bb9d24de3429ed5d3277ed58fcf48f2b5f61326bec6c6",
       "0413741262ede5861dad71063dfd204b91ea1d3b7c631df68eb949969527d79a1dc59295ef7d2bca6743e8cd77b04d1"
       "b580baaeadc7e19d74a8a04451a135f1be1b02fe299f9dc00bfdf201e83d995c6950bcc1cb89d6f7b30bf54656b9a4da586",
       "ad0fd3ddffe8884b9263f3c15fe1f07f2a5a22ffdc7e967085eea45f0cd959f20f18f522763e28bcc925e496a52dda98",
-      "curve: P384 vector: 20" },
+      "curve: P384 vector: 20", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "34d61a699ca576169fcdc0cc7e44e4e1221db0fe63d16850c8104029f7d48449714b9884328cae189978754ab460b486",
       "04867f81104ccd6b163a7902b670ef406042cb0cce7dcdc63d1dfc91b2c40e3cdf7595834bf9eceb79849f1636fc8462f"
       "c9d4bde8e875ec49697d258d1d59465f8431c6f5531e1c59e9f9ebe3cf164a8d9ce10a12f1979283a959bad244dd83863",
       "049e22cbc18657f516a864b37b783348b66f1aa9626cd631f4fa1bd32ad88cf11db52057c660860d39d11fbf024fabd44"
       "46b0d53c79681c28116df71e9cee74fd56c8b7f04b39f1198cc72284e98be9562e35926fb4f48a9fbecafe729309e8b6f",
       "dc4ca392dc15e20185f2c6a8ea5ec31dfc96f56153a47394b3072b13d0015f5d4ae13beb3bed54d65848f9b8383e6c95",
-      "curve: P384 vector: 21" },
+      "curve: P384 vector: 21", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "dc60fa8736d702135ff16aab992bb88eac397f5972456c72ec447374d0d8ce61153831bfc86ad5a6eb5b60bfb96a862c",
       "04b69beede85d0f829fec1b893ccb9c3e052ff692e13b974537bc5b0f9feaf7b22e84f03231629b24866bdb4b8cf9089"
       "1466f85e2bfcaba2843285b0e14ebc07ef7dafff8b424416fee647b59897b619f20eed95a632e6a4206bf7da429c04c560",
       "042db5da5f940eaa884f4db5ec2139b0469f38e4e6fbbcc52df15c0f7cf7fcb1808c749764b6be85d2fdc5b16f58ad5d"
       "c022e8b02dcf33e1b5a083849545f84ad5e43f77cb71546dbbac0d11bdb2ee202e9d3872e8d028c08990746c5e1dde9989",
       "d765b208112d2b9ed5ad10c4046e2e3b0dbf57c469329519e239ac28b25c7d852bf757d5de0ee271cadd021d86cfd347",
-      "curve: P384 vector: 22" },
+      "curve: P384 vector: 22", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "6fa6a1c704730987aa634b0516a826aba8c6d6411d3a4c89772d7a62610256a2e2f289f5c3440b0ec1e70fa339e251ce",
       "0453de1fc1328e8de14aecab29ad8a40d6b13768f86f7d298433d20fec791f86f8bc73f358098b256a298bb488de257bf"
       "4ac28944fd27f17b82946c04c66c41f0053d3692f275da55cd8739a95bd8cd3af2f96e4de959ea8344d8945375905858b",
       "04329647baa354224eb4414829c5368c82d7893b39804e08cbb2180f459befc4b347a389a70c91a23bd9d30c83be5295d"
       "3cc8f61923fad2aa8e505d6cfa126b9fabd5af9dce290b75660ef06d1caa73681d06089c33bc4246b3aa30dbcd2435b12",
       "d3778850aeb58804fbe9dfe6f38b9fa8e20c2ca4e0dec335aafceca0333e3f2490b53c0c1a14a831ba37c4b9d74be0f2",
-      "curve: P384 vector: 23" },
+      "curve: P384 vector: 23", ec_field_GFp },
 
-    { ECCurve_NIST_P384,
+    { ECCurve_NIST_P384, 1,
       "74ad8386c1cb2ca0fcdeb31e0869bb3f48c036afe2ef110ca302bc8b910f621c9fcc54cec32bb89ec7caa84c7b8e54a8",
       "0427a3e83cfb9d5122e73129d801615857da7cc089cccc9c54ab3032a19e0a0a9f677346e37f08a0b3ed8da6e5dd69106"
       "38d60e44aa5e0fd30c918456796af37f0e41957901645e5c596c6d989f5859b03a0bd7d1f4e77936fff3c74d204e5388e",
       "0429d8a36d22200a75b7aea1bb47cdfcb1b7fd66de967041434728ab5d533a060df732130600fe6f75852a871fb2938e3"
       "9e19b53db528395de897a45108967715eb8cb55c3fcbf23379372c0873a058d57544b102ecce722b2ccabb1a603774fd5",
       "81e1e71575bb4505498de097350186430a6242fa6c57b85a5f984a23371123d2d1424eefbf804258392bc723e4ef1e35",
-      "curve: P384 vector: 24" },
+      "curve: P384 vector: 24", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "017eecc07ab4b329068fba65e56a1f8890aa935e57134ae0ffcce802735151f4eac6564f6ee9974c5e6887a1fefee5743"
       "ae2241bfeb95d5ce31ddcb6f9edb4d6fc47",
       "0400602f9d0cf9e526b29e22381c203c48a886c2b0673033366314f1ffbcba240ba42f4ef38a76174635f91e6b4ed3427"
       "5eb01c8467d05ca80315bf1a7bbd945f550a501b7c85f26f5d4b2d7355cf6b02117659943762b6d1db5ab4f1dbc44ce7b2"
       "946eb6c7de342962893fd387d1b73d7a8672d1f236961170b7eb3579953ee5cdc88cd2d",
       "0400685a48e86c79f0f0875f7bc18d25eb5fc8c0b07e5da4f4370f3a9490340854334b1e1b87fa395464c60626124a4e70"
       "d0f785601d37c09870ebf176666877a2046d01ba52c56fc8776d9e8f5db4f0cc27636d0b741bbe05400697942e80b739884"
       "a83bde99e0f6716939e632bc8986fa18dccd443a348b6c3e522497955a4f3c302f676",
       "005fc70477c3e63bc3954bd0df3ea0d1f41ee21746ed95fc5e1fdf90930d5e136672d72cc770742d1711c3c3a4c334a0ad9"
       "759436a4d3c5bf6e74b9578fac148c831",
-      "curve: P521 vector: 0" },
+      "curve: P521 vector: 0", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "00816f19c1fb10ef94d4a1d81c156ec3d1de08b66761f03f06ee4bb9dcebbbfe1eaa1ed49a6a990838d8ed318c14d74cc"
       "872f95d05d07ad50f621ceb620cd905cfb8",
       "0400d45615ed5d37fde699610a62cd43ba76bedd8f85ed31005fe00d6450fbbd101291abd96d4945a8b57bc73b3fe9f46"
       "71105309ec9b6879d0551d930dac8ba45d25501425332844e592b440c0027972ad1526431c06732df19cd46a242172d4d"
       "d67c2c8c99dfc22e49949a56cf90c6473635ce82f25b33682fb19bc33bd910ed8ce3a7fa",
       "0401df277c152108349bc34d539ee0cf06b24f5d3500677b4445453ccc21409453aafb8a72a0be9ebe54d12270aa51b3a"
       "b7f316aa5e74a951c5e53f74cd95fc29aee7a013d52f33a9f3c14384d1587fa8abe7aed74bc33749ad9c570b471776422c"
       "7d4505d9b0a96b3bfac041e4c6a6990ae7f700e5b4a6640229112deafa0cd8bb0d089b0",
       "000b3920ac830ade812c8f96805da2236e002acbbf13596a9ab254d44d0e91b6255ebf1229f366fb5a05c5884ef46032c2"
       "6d42189273ca4efa4c3db6bd12a6853759",
-      "curve: P521 vector: 1" },
+      "curve: P521 vector: 1", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "012f2e0c6d9e9d117ceb9723bced02eb3d4eebf5feeaf8ee0113ccd8057b13ddd416e0b74280c2d0ba8ed291c443bc1b14"
       "1caf8afb3a71f97f57c225c03e1e4d42b0",
       "0400717fcb3d4a40d103871ede044dc803db508aaa4ae74b70b9fb8d8dfd84bfecfad17871879698c292d2fd5e17b4f9343"
       "636c531a4fac68a35a93665546b9a87867900f3d96a8637036993ab5d244500fff9d2772112826f6436603d3eb234a44d5c"
       "4e5c577234679c4f9df725ee5b9118f23d8a58d0cc01096daf70e8dfec0128bdc2e8",
       "040092db3142564d27a5f0006f819908fba1b85038a5bc2509906a497daac67fd7aee0fc2daba4e4334eeaef0e0019204b4"
       "71cd88024f82115d8149cc0cf4f7ce1a4d5016bad0623f517b158d9881841d2571efbad63f85cbe2e581960c5d670601a67"
       "60272675a548996217e4ab2b8ebce31d71fca63fcc3c08e91c1d8edd91cf6fe845f8",
       "006b380a6e95679277cfee4e8353bf96ef2a1ebdd060749f2f046fe571053740bbcc9a0b55790bc9ab56c3208aa05ddf746"
       "a10a3ad694daae00d980d944aabc6a08f",
-      "curve: P521 vector: 2" },
+      "curve: P521 vector: 2", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "00e548a79d8b05f923b9825d11b656f222e8cb98b0f89de1d317184dc5a698f7c71161ee7dc11cd31f4f4f8ae3a981e1a3e7"
       "8bdebb97d7c204b9261b4ef92e0918e0",
       "04000ce800217ed243dd10a79ad73df578aa8a3f9194af528cd1094bbfee27a3b5481ad5862c8876c0c3f91294c0ab3aa806"
       "d9020cbaa2ed72b7fecdc5a09a6dad6f3201543c9ab45b12469232918e21d5a351f9a4b9cbf9efb2afcc402fa9b31650bec2d6"
       "41a05c440d35331c0893d11fb13151335988b303341301a73dc5f61d574e67d9",
       "0400fdd40d9e9d974027cb3bae682162eac1328ad61bc4353c45bf5afe76bf607d2894c8cce23695d920f2464fda4773d4693b"
       "e4b3773584691bdb0329b7f4c86cc2990034ceac6a3fef1c3e1c494bfe8d872b183832219a7e14da414d4e3474573671ec19b03"
       "3be831b915435905925b44947c592959945b4eb7c951c3b9c8cf52530ba23",
       "00fbbcd0b8d05331fef6086f22a6cce4d35724ab7a2f49dd8458d0bfd57a0b8b70f246c17c4468c076874b0dff7a0336823b19e"
       "98bf1cec05e4beffb0591f97713c6",
-      "curve: P521 vector: 3" },
+      "curve: P521 vector: 3", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "01c8aae94bb10b8ca4f7be577b4fb32bb2381032c4942c24fc2d753e7cc5e47b483389d9f3b956d20ee9001b1eef9f23545f72"
       "c5602140046839e963313c3decc864",
       "040106a14e2ee8ff970aa8ab0c79b97a33bba2958e070b75b94736b77bbe3f777324fa52872771aa88a63a9e8490c3378df4dc"
       "760cd14d62be700779dd1a4377943656002366ce3941e0b284b1aa81215d0d3b9778fce23c8cd1e4ed6fa0abf62156c91d4b3eb"
       "55999c3471bed275e9e60e5aa9d690d310bfb15c9c5bbd6f5e9eb39682b74",
       "040098d99dee0816550e84dbfced7e88137fddcf581a725a455021115fe49f8dc3cf233cd9ea0e6f039dc7919da973cdceaca20"
       "5da39e0bd98c8062536c47f258f44b500cd225c8797371be0c4297d2b457740100c774141d8f214c23b61aa2b6cd4806b9b70722"
       "aa4965fb622f42b7391e27e5ec21c5679c5b06b59127372997d421adc1e",
       "0145cfa38f25943516c96a5fd4bfebb2f645d10520117aa51971eff442808a23b4e23c187e639ff928c3725fbd1c0c2ad0d4aeb2"
       "07bc1a6fb6cb6d467888dc044b3c",
-      "curve: P521 vector: 4" },
+      "curve: P521 vector: 4", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "009b0af137c9696c75b7e6df7b73156bb2d45f482e5a4217324f478b10ceb76af09724cf86afa316e7f89918d31d54824a5c33"
       "107a483c15c15b96edc661340b1c0e",
       "0400748cdbb875d35f4bccb62abe20e82d32e4c14dc2feb5b87da2d0ccb11c9b6d4b7737b6c46f0dfb4d896e2db92fcf53cdbb"
       "ae2a404c0babd564ad7adeac6273efa301984acab8d8f173323de0bb60274b228871609373bb22a17287e9dec7495873abc09a"
       "8915b54c8455c8e02f654f602e23a2bbd7a9ebb74f3009bd65ecc650814cc0",
       "04007ae115adaaf041691ab6b7fb8c921f99d8ed32d283d67084e80b9ad9c40c56cd98389fb0a849d9ecf7268c297b6f934061"
       "19f40e32b5773ed25a28a9a85c4a758801a28e004e37eeaefe1f4dbb71f1878696141af3a10a9691c4ed93487214643b761fa4b"
       "0fbeeb247cf6d3fba7a60697536ad03f49b80a9d1cb079673654977c5fa94",
       "005c5721e96c273319fd60ecc46b5962f698e974b429f28fe6962f4ac656be2eb8674c4aafc037eab48ece612953b1e8d86101"
       "6b6ad0c79805784c67f73ada96f351",
-      "curve: P521 vector: 5" },
+      "curve: P521 vector: 5", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "01e48faacee6dec83ffcde944cf6bdf4ce4bae72747888ebafee455b1e91584971efb49127976a52f4142952f7c207ec0265f2b"
       "718cf3ead96ea4f62c752e4f7acd3",
       "04010eb1b4d9172bcc23f4f20cc9560fc54928c3f34ea61c00391dc766c76ed9fa608449377d1e4fadd1236025417330b4b91086"
       "704ace3e4e6484c606e2a943478c860149413864069825ee1d0828da9f4a97713005e9bd1adbc3b38c5b946900721a960fe96ad2c"
       "1b3a44fe3de9156136d44cb17cbc2415729bb782e16bfe2deb3069e43",
       "04012588115e6f7f7bdcfdf57f03b169b479758baafdaf569d04135987b2ce6164c02a57685eb5276b5dae6295d3fe90620f38b55"
       "35c6d2260c173e61eb888ca92020301542c169cf97c2596fe2ddd848a222e367c5f7e6267ebc1bcd9ab5dcf49158f1a48e4af29a89"
       "7b7e6a82091c2db874d8e7abf0f58064691344154f396dbaed188b6",
       "01736d9717429b4f412e903febe2f9e0fffd81355d6ce2c06ff3f66a3be15ceec6e65e308347593f00d7f33591da4043c30763d72"
       "749f72cdceebe825e4b34ecd570",
-      "curve: P521 vector: 6" },
+      "curve: P521 vector: 6", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "00c29aa223ea8d64b4a1eda27f39d3bc98ea0148dd98c1cbe595f8fd2bfbde119c9e017a50f5d1fc121c08c1cef31b75885955"
       "6eb3e0e042d8dd6aaac57a05ca61e3",
       "04001511c848ef60d5419a98d10204db0fe58224124370061bcfa4e9249d50618c56bf3722471b259f38263bb7b280d23caf2a"
       "1ee8737f9371cdb2732cdc958369930c01d461681ae6d8c49b4c5f4d6016143fb1bd7491573e3ed0e6c48b82e821644f87f82f0"
       "e5f08fd16f1f98fa17586200ab02ed8c627b35c3f27617ec5fd92f456203f",
       "040169491d55bd09049fdf4c2a53a660480fee4c03a0538675d1cd09b5bba78dac48543ef118a1173b3fbf8b20e39ce0e6b8"
       "90a163c50f9645b3d21d1cbb3b60a6fff40083494b2eba76910fed33c761804515011fab50e3b377abd8a8a045d886d2238d2"
       "c268ac1b6ec88bd71b7ba78e2c33c152e4bf7da5d565e4acbecf5e92c7ad662bb",
       "018f2ae9476c771726a77780208dedfefa205488996b18fecc50bfd4c132753f5766b2cd744afa9918606de2e016effc63622"
       "e9029e76dc6e3f0c69f7aeced565c2c",
-      "curve: P521 vector: 7" },
+      "curve: P521 vector: 7", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "0028692be2bf5c4b48939846fb3d5bce74654bb2646e15f8389e23708a1afadf561511ea0d9957d0b53453819d60fba8f65a1"
       "8f7b29df021b1bb01cd163293acc3cc",
       "0401cfdc10c799f5c79cb6930a65fba351748e07567993e5e410ef4cacc4cd8a25784991eb4674e41050f930c7190ac812b92"
       "45f48a7973b658daf408822fe5b85f6680180d9ddfc9af77b9c4a6f02a834db15e535e0b3845b2cce30388301b51cecbe32763"
       "07ef439b5c9e6a72dc2d94d879bc395052dbb4a5787d06efb280210fb8be037",
       "04008415f5bbd0eee387d6c09d0ef8acaf29c66db45d6ba101860ae45d3c60e1e0e3f7247a4626a60fdd404965c3566c79f644"
       "9e856ce0bf94619f97da8da24bd2cfb600fdd7c59c58c361bc50a7a5d0d36f723b17c4f2ad2b03c24d42dc50f74a8c465a0afc"
       "4683f10fab84652dfe9e928c2626b5456453e1573ff60be1507467d431fbb2",
       "0105a346988b92ed8c7a25ce4d79d21bc86cfcc7f99c6cd19dbb4a39f48ab943b79e4f0647348da0b80bd864b85c6b8d92536"
       "d6aa544dc7537a00c858f8b66319e25",
-      "curve: P521 vector: 8" },
+      "curve: P521 vector: 8", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "01194d1ee613f5366cbc44b504d21a0cf6715e209cd358f2dd5f3e71cc0d67d0e964168c42a084ebda746f9863a86bacffc81"
       "9f1edf1b8c727ccfb3047240a57c435",
       "04016bd15c8a58d366f7f2b2f298cc87b7485e9ee70d11d12448b8377c0a82c7626f67aff7f97be7a3546bf417eeeddf75a93"
       "c130191c84108042ea2fca17fd3f80d1401560502d04b74fce1743aab477a9d1eac93e5226981fdb97a7478ce4ce566ff72439"
       "31284fad850b0c2bcae0ddd2d97790160c1a2e77c3ed6c95ecc44b89e2637fc",
       "0401c721eea805a5cba29f34ba5758775be0cf6160e6c08723f5ab17bf96a1ff2bd9427961a4f34b07fc0b14ca4b2bf6845de"
       "bd5a869f124ebfa7aa72fe565050b7f1800b6e89eb0e1dcf181236f7c548fd1a8c16b258b52c1a9bfd3fe8f22841b26763265"
       "f074c4ccf2d634ae97b701956f67a11006c52d97197d92f585f5748bc2672eeb",
       "004531b3d2c6cd12f21604c8610e6723dbf4daf80b5a459d6ba5814397d1c1f7a21d7c114be964e27376aaebe3a7bc3d6af7"
       "a7f8c7befb611afe487ff032921f750f",
-      "curve: P521 vector: 9" },
+      "curve: P521 vector: 9", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "01fd90e3e416e98aa3f2b6afa7f3bf368e451ad9ca5bd54b5b14aee2ed6723dde5181f5085b68169b09fbec721372ccf6b"
       "284713f9a6356b8d560a8ff78ca3737c88",
       "0401ebea1b10d3e3b971b7efb69fc878de11c7f472e4e4d384c31b8d6288d8071517acade9b39796c7af5163bcf71aeda7"
       "77533f382c6cf0a4d9bbb938c85f44b78037016b0e3e19c2996b2cbd1ff64730e7ca90edca1984f9b2951333535e5748baa"
       "34a99f61ff4d5f812079e0f01e87789f34efdad8098015ee74a4f846dd190d16dc6e1",
       "0401c35823e440a9363ab98d9fc7a7bc0c0532dc7977a79165599bf1a9cc64c00fb387b42cca365286e8430360bfad3643"
       "bc31354eda50dc936c329ecdb60905c40fcb00d9e7f433531e44df4f6d514201cbaabb06badd6783e01111726d815531d23"
       "3c5cdb722893ffbb2027259d594de77438809738120c6f783934f926c3fb69b40c409",
       "0100c8935969077bae0ba89ef0df8161d975ec5870ac811ae7e65ca5394efba4f0633d41bf79ea5e5b9496bbd7aae000b05"
       "94baa82ef8f244e6984ae87ae1ed124b7",
-      "curve: P521 vector: 10" },
+      "curve: P521 vector: 10", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "009012ecfdadc85ced630afea534cdc8e9d1ab8be5f3753dcf5f2b09b40eda66fc6858549bc36e6f8df55998cfa9a0703a"
       "ecf6c42799c245011064f530c09db98369",
       "0400234e32be0a907131d2d128a6477e0caceb86f02479745e0fe245cb332de631c078871160482eeef584e274df7fa412c"
       "ea3e1e91f71ecba8781d9205d48386341ad01cf86455b09b1c005cffba8d76289a3759628c874beea462f51f30bd581e380"
       "3134307dedbb771b3334ee15be2e242cd79c3407d2f58935456c6941dd9b6d155a46",
       "0400093057fb862f2ad2e82e581baeb3324e7b32946f2ba845a9beeed87d6995f54918ec6619b9931955d5a89d4d74adf10"
       "46bb362192f2ef6bd3e3d2d04dd1f87054a00aa3fb2448335f694e3cda4ae0cc71b1b2f2a206fa802d7262f19983c44674f"
       "e15327acaac1fa40424c395a6556cb8167312527fae5865ecffc14bbdc17da78cdcf",
       "017f36af19303841d13a389d95ec0b801c7f9a679a823146c75c17bc44256e9ad422a4f8b31f14647b2c7d317b933f7c294"
       "6c4b8abd1d56d620fab1b5ff1a3adc71f",
-      "curve: P521 vector: 11" },
+      "curve: P521 vector: 11", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "01b5ff847f8eff20b88cfad42c06e58c3742f2f8f1fdfd64b539ba48c25926926bd5e332b45649c0b184f77255e9d58fe8"
       "afa1a6d968e2cb1d4637777120c765c128",
       "0401de3dc9263bc8c4969dc684be0eec54befd9a9f3dba194d8658a789341bf0d78d84da6735227cafaf093519516911975"
       "73c8c360a11e5285712b8bbdf5ac91b977c00812de58cd095ec2e5a9b247eb3ed41d8bef6aeace194a7a05b65aa5d289fbc9"
       "b1770ec84bb6be0c2c64cc37c1d54a7f5d71377a9adbe20f26f6f2b544a821ea831",
       "040083192ed0b1cb31f75817794937f66ad91cf74552cd510cedb9fd641310422af5d09f221cad249ee814d16dd7ac84ded"
       "9eacdc28340fcfc9c0c06abe30a2fc28cd8002212ed868c9ba0fb2c91e2c39ba93996a3e4ebf45f2852d0928c48930e875c"
       "c7b428d0e7f3f4d503e5d60c68cb49b13c2480cd486bed9200caddaddfe4ff8e3562",
       "00062f9fc29ae1a68b2ee0dcf956cbd38c88ae5f645eaa546b00ebe87a7260bf724be20d34b9d02076655c933d056b21e30"
       "4c24ddb1dedf1dd76de611fc4a2340336",
-      "curve: P521 vector: 12" },
+      "curve: P521 vector: 12", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "011a6347d4e801c91923488354cc533e7e35fddf81ff0fb7f56bb0726e0c29ee5dcdc5f394ba54cf57269048aab6e055895c"
       "8da24b8b0639a742314390cc04190ed6",
       "0400fe30267f33ba5cdefc25cbb3c9320dad9ccb1d7d376644620ca4fadee5626a3cede25ad254624def727a7048f7145f761"
       "62aa98042f9b123b2076f8e8cf59b3fdf001145dc6631953b6e2945e94301d6cbb098fe4b04f7ee9b09411df104dc82d7d79e"
       "c46a01ed0f2d3e7db6eb680694bdeb107c1078aec6cabd9ebee3d342fe7e54df",
       "0401a89b636a93e5d2ba6c2292bf23033a84f06a3ac1220ea71e806afbe097a804cc67e9baa514cfb6c12c9194be30212bf7a"
       "ae7fdf6d376c212f0554e656463ffab7e0182efcaf70fc412d336602e014da47256a0b606f2addcce8053bf817ac8656bb4e4"
       "2f14c8cbf2a68f488ab35dcdf64056271dee1f606a440ba4bd4e5a11b8b8e54f",
       "0128ab09bfec5406799e610f772ba17e892249fa8e0e7b18a04b9197034b250b48294f1867fb9641518f92766066a07a8b917"
       "b0e76879e1011e51ccbd9f540c54d4f",
-      "curve: P521 vector: 13" },
+      "curve: P521 vector: 13", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "0022b6d2a22d71dfaa811d2d9f9f31fbed27f2e1f3d239538ddf3e4cc8c39a330266db25b7bc0a9704f17bde7f3592bf5f1f2d"
       "4b56013aacc3d8d1bc02f00d3146cc",
       "0400ba38cfbf9fd2518a3f61d43549e7a6a6d28b2be57ffd3e0faceb636b34ed17e044a9f249dae8fc132e937e2d9349cd2ed7"
       "7bb1049ceb692a2ec5b17ad61502a64c001ec91d3058573fa6c0564a02a1a010160c313bc7c73510dc983e5461682b5be00dbc"
       "e7e2c682ad73f29ca822cdc111f68fabe33a7b384a648342c3cdb9f050bcdb",
       "04017200b3f16a68cbaed2bf78ba8cddfb6cffac262bba00fbc25f9dc72a07ce59372904899f364c44cb264c097b647d4412be"
       "e3e519892d534d9129f8a28f7500fee700baba8d672a4f4a3b63de48b96f56e18df5d68f7d70d5109833f43770d6732e06b39ad"
       "60d93e5b43db8789f1ec0aba47286a39ea584235acea757dbf13d53b58364",
       "0101e462e9d9159968f6440e956f11dcf2227ae4aea81667122b6af9239a291eb5d6cf5a4087f358525fcacfa46bb2db01a75a"
       "f1ba519b2d31da33eda87a9d565748",
-      "curve: P521 vector: 14" },
+      "curve: P521 vector: 14", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "005bacfff268acf6553c3c583b464ea36a1d35e2b257a5d49eb3419d5a095087c2fb4d15cf5bf5af816d0f3ff7586490ccd3ddc1"
       "a98b39ce63749c6288ce0dbdac7d",
       "040036e488da7581472a9d8e628c58d6ad727311b7e6a3f6ae33a8544f34b09280249020be7196916fafd90e2ec54b66b5468d23"
       "61b99b56fa00d7ac37abb8c6f16653011edb9fb8adb6a43f4f5f5fdc1421c9fe04fc8ba46c9b66334e3af927c8befb4307104f299"
       "acec4e30f812d9345c9720d19869dbfffd4ca3e7d2713eb5fc3f42615",
       "04004efd5dbd2f979e3831ce98f82355d6ca14a5757842875882990ab85ab9b7352dd6b9b2f4ea9a1e95c3880d65d1f3602f9ca6"
       "53dc346fac858658d75626f4d4fb080061cf15dbdaa7f31589c98400373da284506d70c89f074ed262a9e28140796b7236c2eef99"
       "016085e71552ff488c72b7339fefb7915c38459cb20ab85aec4e45052",
       "0141d6a4b719ab67eaf04a92c0a41e2dda78f4354fb90bdc35202cc7699b9b04d49616f82255debf7bbec045ae58f982a66905fc"
       "fae69d689785e38c868eb4a27e7b",
-      "curve: P521 vector: 15" },
+      "curve: P521 vector: 15", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "008e2c93c5423876223a637cad367c8589da69a2d0fc68612f31923ae50219df2452e7cc92615b67f17b57ffd2f52b19154bb40"
       "d7715336420fde2e89fee244f59dc",
       "0400fa3b35118d6c422570f724a26f90b2833b19239174cea081c53133f64db60d6940ea1261299c04c1f4587cdb0c4c39616"
       "479c1bb0c146799a118032dcf98f899c00069f040229006151fa32b51f679c8816f7c17506b403809dc77cd58a2aec430d94d"
       "13b6c916de99f355aa45fcfbc6853d686c71be496a067d24bfaea4818fc51f75",
       "040129891de0cf3cf82e8c2cf1bf90bb296fe00ab08ca45bb7892e0e227a504fdd05d2381a4448b68adff9c4153c87eacb783"
       "30d8bd52515f9f9a0b58e85f446bb4e10009edd679696d3d1d0ef327f200383253f6413683d9e4fcc87bb35f112c2f110098d"
       "15e5701d7ceee416291ff5fed85e687f727388b9afe26a4f6feed560b218e6bb",
       "00345e26e0abb1aac12b75f3a9cf41efe1c336396dffa4a067a4c2cfeb878c68b2b045faa4e5b4e6fa4678f5b603c351903b1"
       "4bf9a6a70c439257199a640890b61d1",
-      "curve: P521 vector: 16" },
+      "curve: P521 vector: 16", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "0004d49d39d40d8111bf16d28c5936554326b197353eebbcf47545393bc8d3aaf98f14f5be7074bfb38e6cc97b989754074da"
       "ddb3045f4e4ce745669fdb3ec0d5fa8",
       "04012ec226d050ce07c79b3df4d0f0891f9f7adf462e8c98dbc1a2a14f5e53a3f5ad894433587cc429a8be9ea1d84fa33b180"
       "3690dae04da7218d30026157fc995cf52004837dfbf3426f57b5c793269130abb9a38f618532211931154db4eeb9aede88e57"
       "290f842ea0f2ea9a5f74c6203a3920fe4e305f6118f676b154e1d75b9cb5eb88",
       "0401a3c20240e59f5b7a3e17c275d2314ba1741210ad58b71036f8c83cc1f6b0f409dfdd9113e94b67ec39c3291426c23ffc"
       "c447054670d2908ff8fe67dc2306034c5c01d2825bfd3af8b1e13205780c137fe938f84fde40188e61ea02cead81badfdb425"
       "c29f7d7fb0324debadc10bbb93de68f62c35069268283f5265865db57a79f7bf7",
       "006fe9de6fb8e672e7fd150fdc5e617fabb0d43906354ccfd224757c7276f7a1010091b17ed072074f8d10a5ec971eb35a5c"
       "b7076603b7bc38d432cbc059f80f9488",
-      "curve: P521 vector: 17" },
+      "curve: P521 vector: 17", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "011a5d1cc79cd2bf73ea106f0e60a5ace220813b53e27b739864334a07c03367efda7a4619fa6eef3a9746492283b3c445610"
       "a023a9cc49bf4591140384fca5c8bb5",
       "0400eb07c7332eedb7d3036059d35f7d2288d4377d5f42337ad3964079fb120ccd4c8bd384b585621055217023acd9a94fcb3"
       "b965bfb394675e788ade41a1de73e620c00491a835de2e6e7deb7e090f4a11f2c460c0b1f3d5e94ee8d751014dc720784fd3b"
       "54500c86ebaef18429f09e8e876d5d1538968a030d7715dde99f0d8f06e29d59",
       "04007e2d138f2832e345ae8ff65957e40e5ec7163f016bdf6d24a2243daa631d878a4a16783990c722382130f9e51f0c1bd6"
       "ff5ac96780e48b68f5dec95f42e6144bb500b0de5c896791f52886b0f09913e26e78dd0b69798fc4df6d95e3ca708ecbcbcce1c1895f"
       "5561bbabaae372e9e67e6e1a3be60e19b470cdf673ec1fc393d3426e20",
       "01e4e759ecedce1013baf73e6fcc0b92451d03bdd50489b78871c333114990c9ba6a9b2fc7b1a2d9a1794c1b60d9279af6f"
       "146f0bbfb0683140403bfa4ccdb524a29",
-      "curve: P521 vector: 18" },
+      "curve: P521 vector: 18", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "010c908caf1be74c616b625fc8c1f514446a6aec83b5937141d6afbb0a8c7666a7746fa1f7a6664a2123e8cdf6cd8bf836c5"
       "6d3c0ebdcc980e43a186f938f3a78ae7",
       "040031890f4c7abec3f723362285d77d2636f876817db3bbc88b01e773597b969ff6f013ea470c854ab4a7739004eb8cbea6"
       "9b82ddf36acadd406871798ecb2ac3aa7f00d8b429ae3250266b9643c0c765a60dc10155bc2531cf8627296f4978b6640a9e"
       "600e19d0037d58503fa80799546a814d7478a550aa90e5ebeb052527faaeae5d08",
       "0400118c36022209b1af8ebad1a12b566fc48744576e1199fe80de1cdf851cdf03e5b9091a8f7e079e83b7f827259b691d0"
       "c22ee29d6bdf73ec7bbfd746f2cd97a357d00da5ff4904548a342e2e7ba6a1f4ee5f840411a96cf63e6fe622f22c13e614e"
       "0a847c11a1ab3f1d12cc850c32e095614ca8f7e2721477b486e9ff40372977c3f65c",
       "0163c9191d651039a5fe985a0eea1eba018a40ab1937fcd2b61220820ee8f2302e9799f6edfc3f5174f369d672d377ea895"
       "4a8d0c8b851e81a56fda95212a6578f0e",
-      "curve: P521 vector: 19" },
+      "curve: P521 vector: 19", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "01b37d6b7288de671360425d3e5ac1ccb21815079d8d73431e9b74a6f0e7ae004a357575b11ad66642ce8b775593eba9d98"
       "bf25c75ef0b4d3a2098bbc641f59a2b77",
       "0400189a5ee34de7e35aefeaeef9220c18071b4c29a4c3bd9d954458bd3e82a7a34da34cff5579b8101c065b1f2f527cf45"
       "81501e28ef5671873e65267733d003520af01eb4bc50a7b4d4599d7e3fa773ddb9eb252c9b3422872e544bdf75c7bf60f51"
       "66ddc11eb08fa7c30822dabaee373ab468eb2d922e484e2a527fff2ebb804b7d9a37",
       "0401780edff1ca1c03cfbe593edc6c049bcb2860294a92c355489d9afb2e702075ade1c953895a456230a0cde905de4a3f"
       "38573dbfcccd67ad6e7e93f0b5581e926a5d00a5481962c9162962e7f0ebdec936935d0eaa813e8226d40d7f6119bfd940"
       "602380c86721e61db1830f51e139f210000bcec0d8edd39e54d73a9a129f95cd5fa979",
       "015d613e267a36342e0d125cdad643d80d97ed0600afb9e6b9545c9e64a98cc6da7c5aaa3a8da0bdd9dd3b97e9788218a8"
       "0abafc106ef065c8f1c4e1119ef58d298b",
-      "curve: P521 vector: 20" },
+      "curve: P521 vector: 20", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "00f2661ac762f60c5fff23be5d969ccd4ec6f98e4e72618d12bdcdb9b4102162333788c0bae59f91cdfc172c7a1681ee44d9"
       "6ab2135a6e5f3415ebbcd55165b1afb0",
       "0400a8e25a6902d687b4787cdc94c364ac7cecc5c495483ed363dc0aa95ee2bd739c4c4d46b17006c728b076350d7d7e54c"
       "6822f52f47162a25109aaaba690cab696ec0168d2f08fe19e4dc9ee7a195b03c9f7fe6676f9f520b6270557504e72ca4394"
       "a2c6918625e15ac0c51b8f95cd560123653fb8e8ee6db961e2c4c62cc54e92e2a2a9",
       "04016dacffa183e5303083a334f765de724ec5ec9402026d4797884a9828a0d321a8cfac74ab737fe20a7d6befcfc73b6a3"
       "5c1c7b01d373e31abc192d48a4241a35803011e5327cac22d305e7156e559176e19bee7e4f2f59e86f1a9d0b6603b6a7df"
       "1069bde6387feb71587b8ffce5b266e1bae86de29378a34e5c74b6724c4d40a719923",
       "014d6082a3b5ced1ab8ca265a8106f302146c4acb8c30bb14a4c991e3c82a9731288bdb91e0e85bda313912d06384fc44"
       "f2153fb13506fa9cf43c9aab5750988c943",
-      "curve: P521 vector: 21" },
+      "curve: P521 vector: 21", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "00f430ca1261f09681a9282e9e970a9234227b1d5e58d558c3cc6eff44d1bdf53de16ad5ee2b18b92d62fc79586116b0e"
       "fc15f79340fb7eaf5ce6c44341dcf8dde27",
       "04006c1d9b5eca87de1fb871a0a32f807c725adccde9b3967453a71347d608f0c030cd09e338cdecbf4a02015bc8a6e8"
       "d3e2595fe773ffc2fc4e4a55d0b1a2cc00323b01141b2109e7f4981c952aa818a2b9f6f5c41feccdb7a7a45b9b4b6729"
       "37771b008cae5f934dfe3fed10d383ab1f38769c92ce88d9be5414817ecb073a31ab368ccb",
       "0400a091421d3703e3b341e9f1e7d58f8cf7bdbd1798d001967b801d1cec27e605c580b2387c1cb464f55ce7ac803341"
       "02ab03cfb86d88af76c9f4129c01bedd3bbfc4008c9c577a8e6fc446815e9d40baa66025f15dae285f19eb668ee60ae9"
       "c98e7ecdbf2b2a68e22928059f67db188007161d3ecf397e0883f0c4eb7eaf7827a62205cc",
       "0020c00747cb8d492fd497e0fec54644bf027d418ab686381f109712a99cabe328b9743d2225836f9ad66e5d7fed1de2"
       "47e0da92f60d5b31f9e47672e57f710598f4",
-      "curve: P521 vector: 22" },
+      "curve: P521 vector: 22", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "005dc33aeda03c2eb233014ee468dff753b72f73b00991043ea353828ae69d4cd0fadeda7bb278b535d7c57406ff2e6e"
       "473a5a4ff98e90f90d6dadd25100e8d85666",
       "0400c825ba307373cec8dd2498eef82e21fd9862168dbfeb83593980ca9f82875333899fe94f137daf1c4189eb502937"
       "c3a367ea7951ed8b0f3377fcdf2922021d46a5016b8a2540d5e65493888bc337249e67c0a68774f3e8d81e3b4574a012"
       "5165f0bd58b8af9de74b35832539f95c3cd9f1b759408560aa6851ae3ac7555347b0d3b13b",
       "04004f38816681771289ce0cb83a5e29a1ab06fc91f786994b23708ff08a08a0f675b809ae99e9f9967eb1a49f196057"
       "d69e50d6dedb4dd2d9a81c02bdcc8f7f518460009efb244c8b91087de1eed766500f0e81530752d469256ef79f6b965d"
       "8a2232a0c2dbc4e8e1d09214bab38485be6e357c4200d073b52f04e4a16fc6f5247187aecb",
       "00c2bfafcd7fbd3e2fd1c750fdea61e70bd4787a7e68468c574ee99ebc47eedef064e8944a73bcb7913dbab5d93dca6"
       "60d216c553622362794f7a2acc71022bdb16f",
-      "curve: P521 vector: 23" },
+      "curve: P521 vector: 23", ec_field_GFp },
 
-    { ECCurve_NIST_P521,
+    { ECCurve_NIST_P521, 1,
       "00df14b1f1432a7b0fb053965fd8643afee26b2451ecb6a8a53a655d5fbe16e4c64ce8647225eb11e7fdcb23627471"
       "dffc5c2523bd2ae89957cba3a57a23933e5a78",
       "04004e8583bbbb2ecd93f0714c332dff5ab3bc6396e62f3c560229664329baa5138c3bb1c36428abd4e23d17fcb7"
       "a2cfcc224b2e734c8941f6f121722d7b6b9415457601cf0874f204b0363f020864672fadbf87c8811eb147758b254b"
       "74b14fae742159f0f671a018212bbf25b8519e126d4cad778cfff50d288fd39ceb0cac635b175ec0",
       "0401a32099b02c0bd85371f60b0dd20890e6c7af048c8179890fda308b359dbbc2b7a832bb8c6526c4af99a7ea3f0"
       "b3cb96ae1eb7684132795c478ad6f962e4a6f446d017627357b39e9d7632a1370b3e93c1afb5c851b910eb4ead0c9"
       "d387df67cde85003e0e427552f1cd09059aad0262e235cce5fba8cedc4fdc1463da76dcd4b6d1a46",
       "01aaf24e5d47e4080c18c55ea35581cd8da30f1a079565045d2008d51b12d0abb4411cda7a0785b15d149ed301a36"
       "97062f42da237aa7f07e0af3fd00eb1800d9c41",
-      "curve: P521 vector: 24" },
+      "curve: P521 vector: 24", ec_field_GFp },
+
+    { ECCurve_pastLastCurve, 0, NULL, NULL, NULL, NULL, NULL, 0 }
+};
 
-    { ECCurve_pastLastCurve, NULL, NULL, NULL, NULL, NULL }
+static ECDH_KAT nonnist_testvecs[] = {
+    { ECCurve25519, 1,
+      "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
+      NULL,
+      "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c",
+      "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552",
+      "curve: 25519 vector: 0", ec_field_plain },
+    { ECCurve25519, 1,
+      "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d",
+      NULL,
+      "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493",
+      "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957",
+      "curve: 25519 vector: 1", ec_field_plain },
+    { ECCurve25519, 1,
+      "0900000000000000000000000000000000000000000000000000000000000000",
+      NULL,
+      "0900000000000000000000000000000000000000000000000000000000000000",
+      "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079",
+      "curve: 25519 vector: 2", ec_field_plain },
+    { ECCurve25519, 1000,
+      "0900000000000000000000000000000000000000000000000000000000000000",
+      NULL,
+      "0900000000000000000000000000000000000000000000000000000000000000",
+      "684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51",
+      "curve: 25519 vector: 1000 iterations", ec_field_plain },
+#ifdef NSS_ENABLE_EXPENSIVE_TESTS
+    /* This test is disabled by default because it takes a very long time
+       * to run. */
+    { ECCurve25519, 1000000,
+      "0900000000000000000000000000000000000000000000000000000000000000",
+      NULL,
+      "0900000000000000000000000000000000000000000000000000000000000000",
+      "7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424",
+      "curve: 25519 vector: 1000000 iterations", ec_field_plain },
+#endif
+    { ECCurve25519, 1,
+      "174a56a75017c029e0861044d3c57c291823cf477ae6e21065cc121578bfa893",
+      NULL,
+      "7bd8396462a5788951caf3d3a28cb0904e4d081e62e6ac2d9da7152eb1310f30",
+      "28c09f6be3666a6ab3bf8f5b03eec14e95505e32726ae887053ce6a2061a9656",
+      "curve: 25519 custom vector 1", ec_field_plain },
+    { ECCurve25519, 1,
+      "577a2a7fcdacd4ccf7d7f81ba93ec83ae4bda32bec00ff7d59c294b69404f688",
+      NULL,
+      "a43b5491cbd9273abf694115f383fabe3bdc5f2baa30d2e00e43b6937a75cc5d",
+      "4aed703c32552576ca0b30a3fab53242e1eea29ddec993219d3c2b3c3e59b735",
+      "curve: 25519 custom vector 1", ec_field_plain },
+
+    { ECCurve_pastLastCurve, 0, NULL, NULL, NULL, NULL, NULL, 0 }
 };
+
+static ECDH_BAD nonnist_testvecs_bad_values[] = {
+    { ECCurve25519, "00", "curve: 25519 vector: 0 bad point", ec_field_plain },
+    { ECCurve25519,
+      "0100000000000000000000000000000000000000000000000000000000000000",
+      "curve: 25519 vector: 1 bad point", ec_field_plain },
+    { ECCurve25519,
+      "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b8",
+      "curve: 25519 vector: 2 bad point", ec_field_plain },
+    { ECCurve25519,
+      "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157",
+      "curve: 25519 vector: 3 bad point", ec_field_plain },
+    { ECCurve25519,
+      "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+      "curve: 25519 vector: 4 bad point", ec_field_plain },
+    { ECCurve25519,
+      "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+      "curve: 25519 vector: 5 bad point", ec_field_plain },
+    { ECCurve25519,
+      "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+      "curve: 25519 vector: 6 bad point", ec_field_plain },
+    { ECCurve25519,
+      "cdeb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880",
+      "curve: 25519 vector: 7 bad point", ec_field_plain },
+    { ECCurve25519,
+      "4c9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7",
+      "curve: 25519 vector: 8 bad point", ec_field_plain },
+    { ECCurve25519,
+      "d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+      "curve: 25519 vector: 9 bad point", ec_field_plain },
+    { ECCurve25519,
+      "daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+      "curve: 25519 vector: 10 bad point", ec_field_plain },
+    { ECCurve25519,
+      "dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+      "curve: 25519 vector: 11 bad point", ec_field_plain },
+
+    { ECCurve_pastLastCurve, 0, NULL, 0 }
+};
--- a/security/nss/cmd/fipstest/fipstest.c
+++ b/security/nss/cmd/fipstest/fipstest.c
@@ -2518,17 +2518,17 @@ ecdsa_pkv_test(char *reqfn)
                 goto loser;
             }
             SECITEM_FreeItem(encodedparams, PR_TRUE);
             len = (ecparams->fieldID.size + 7) >> 3;
             if (pubkey.data != NULL) {
                 PORT_Free(pubkey.data);
                 pubkey.data = NULL;
             }
-            SECITEM_AllocItem(NULL, &pubkey, 2 * len + 1);
+            SECITEM_AllocItem(NULL, &pubkey, ecparams->pointSize);
             if (pubkey.data == NULL) {
                 goto loser;
             }
             pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
             fputs(buf, ecdsaresp);
             continue;
         }
         /* Qx = ... */
--- a/security/nss/cmd/listsuites/listsuites.c
+++ b/security/nss/cmd/listsuites/listsuites.c
@@ -45,19 +45,18 @@ main(int argc, char **argv)
             ++errCount;
             fprintf(stderr,
                     "SSL_GetCipherSuiteInfo didn't like value 0x%04x (i = %d): %s\n",
                     suite, i, PORT_ErrorToString(err));
             continue;
         }
         fprintf(stdout,
                 "%s:\n" /* up to 37 spaces  */
-                "  0x%04hx %-5s %-5s %-8s %3hd %-6s %-8s %-4s %-8s %-11s\n",
+                "  0x%04hx %-5s %-5s %-8s %3hd %-6s %-8s %-4s Domestic %-11s\n",
                 info.cipherSuiteName, info.cipherSuite,
                 info.keaTypeName, info.authAlgorithmName, info.symCipherName,
                 info.effectiveKeyBits, info.macAlgorithmName,
                 enabled ? "Enabled" : "Disabled",
                 info.isFIPS ? "FIPS" : "",
-                info.isExportable ? "Export" : "Domestic",
                 info.nonStandard ? "nonStandard" : "");
     }
     return errCount;
 }
--- a/security/nss/cmd/selfserv/selfserv.c
+++ b/security/nss/cmd/selfserv/selfserv.c
@@ -90,42 +90,42 @@ static enum ocspStaplingModeEnum {
     osm_ocsp       /* retrieve ocsp status from external ocsp server,
               use empty status if server is unavailable */
 } ocspStaplingMode = osm_disabled;
 typedef enum ocspStaplingModeEnum ocspStaplingModeType;
 static char *ocspStaplingCA = NULL;
 static SECItemArray *certStatus[kt_kea_size] = { NULL };
 
 const int ssl3CipherSuites[] = {
-    -1,                                  /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
-    -1,                                  /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA    * b */
-    TLS_RSA_WITH_RC4_128_MD5,            /* c */
-    TLS_RSA_WITH_3DES_EDE_CBC_SHA,       /* d */
-    TLS_RSA_WITH_DES_CBC_SHA,            /* e */
-    TLS_RSA_EXPORT_WITH_RC4_40_MD5,      /* f */
-    TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,  /* g */
-    -1,                                  /* SSL_FORTEZZA_DMS_WITH_NULL_SHA,  * h */
-    TLS_RSA_WITH_NULL_MD5,               /* i */
-    SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,  /* j */
-    SSL_RSA_FIPS_WITH_DES_CBC_SHA,       /* k */
-    TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
-    TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,  /* m */
-    TLS_RSA_WITH_RC4_128_SHA,            /* n */
-    TLS_DHE_DSS_WITH_RC4_128_SHA,        /* o */
-    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,   /* p */
-    TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,   /* q */
-    TLS_DHE_RSA_WITH_DES_CBC_SHA,        /* r */
-    TLS_DHE_DSS_WITH_DES_CBC_SHA,        /* s */
-    TLS_DHE_DSS_WITH_AES_128_CBC_SHA,    /* t */
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,    /* u */
-    TLS_RSA_WITH_AES_128_CBC_SHA,        /* v */
-    TLS_DHE_DSS_WITH_AES_256_CBC_SHA,    /* w */
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,    /* x */
-    TLS_RSA_WITH_AES_256_CBC_SHA,        /* y */
-    TLS_RSA_WITH_NULL_SHA,               /* z */
+    -1,                                /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
+    -1,                                /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA     * b */
+    TLS_RSA_WITH_RC4_128_MD5,          /* c */
+    TLS_RSA_WITH_3DES_EDE_CBC_SHA,     /* d */
+    TLS_RSA_WITH_DES_CBC_SHA,          /* e */
+    -1,                                /* TLS_RSA_EXPORT_WITH_RC4_40_MD5        * f */
+    -1,                                /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5    * g */
+    -1,                                /* SSL_FORTEZZA_DMS_WITH_NULL_SHA        * h */
+    TLS_RSA_WITH_NULL_MD5,             /* i */
+    -1,                                /* SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA    * j */
+    -1,                                /* SSL_RSA_FIPS_WITH_DES_CBC_SHA         * k */
+    -1,                                /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA   * l */
+    -1,                                /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA    * m */
+    TLS_RSA_WITH_RC4_128_SHA,          /* n */
+    TLS_DHE_DSS_WITH_RC4_128_SHA,      /* o */
+    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
+    TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
+    TLS_DHE_RSA_WITH_DES_CBC_SHA,      /* r */
+    TLS_DHE_DSS_WITH_DES_CBC_SHA,      /* s */
+    TLS_DHE_DSS_WITH_AES_128_CBC_SHA,  /* t */
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,  /* u */
+    TLS_RSA_WITH_AES_128_CBC_SHA,      /* v */
+    TLS_DHE_DSS_WITH_AES_256_CBC_SHA,  /* w */
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,  /* x */
+    TLS_RSA_WITH_AES_256_CBC_SHA,      /* y */
+    TLS_RSA_WITH_NULL_SHA,             /* z */
     0
 };
 
 /* data and structures for shutdown */
 static int stopping;
 
 static PRBool noDelay;
 static int requestCert;
@@ -176,31 +176,29 @@ PrintParameterUsage()
     fputs(
         "-V [min]:[max] restricts the set of enabled SSL/TLS protocol versions.\n"
         "   All versions are enabled by default.\n"
         "   Possible values for min/max: ssl3 tls1.0 tls1.1 tls1.2\n"
         "   Example: \"-V ssl3:\" enables SSL 3 and newer.\n"
         "-B bypasses the PKCS11 layer for SSL encryption and MACing\n"
         "-q checks for bypassability\n"
         "-D means disable Nagle delays in TCP\n"
-        "-E means disable export ciphersuites and SSL step down key gen\n"
         "-R means disable detection of rollback from TLS to SSL3\n"
         "-a configure server for SNI.\n"
         "-k expected name negotiated on server sockets\n"
         "-b means try binding to the port and exit\n"
         "-m means test the model-socket feature of SSL_ImportFD.\n"
         "-r flag is interepreted as follows:\n"
         "    1 -r  means request, not require, cert on initial handshake.\n"
         "    2 -r's mean request  and require, cert on initial handshake.\n"
         "    3 -r's mean request, not require, cert on second handshake.\n"
         "    4 -r's mean request  and require, cert on second handshake.\n"
         "-s means disable SSL socket locking for performance\n"
         "-u means enable Session Ticket extension for TLS.\n"
         "-v means verbose output\n"
-        "-x means use export policy.\n"
         "-z means enable compression.\n"
         "-L seconds means log statistics every 'seconds' seconds (default=30).\n"
         "-M maxProcs tells how many processes to run in a multi-process server\n"
         "-N means do NOT use the server session cache.  Incompatible with -M.\n"
         "-t threads -- specify the number of threads to use for connections.\n"
         "-i pid_file file to write the process id of selfserve\n"
         "-l means use local threads instead of global threads\n"
         "-g numblocks means test throughput by sending total numblocks chunks\n"
@@ -308,58 +306,16 @@ disableAllSSLCiphers(void)
         if (rv != SECSuccess) {
             printf("SSL_CipherPrefSetDefault rejected suite 0x%04x (i = %d)\n",
                    suite, i);
             errWarn("SSL_CipherPrefSetDefault");
         }
     }
 }
 
-/* disable all the export SSL cipher suites */
-SECStatus
-disableExportSSLCiphers(void)
-{
-    const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
-    int i = SSL_NumImplementedCiphers;
-    SECStatus rv = SECSuccess;
-    SSLCipherSuiteInfo info;
-
-    while (--i >= 0) {
-        PRUint16 suite = cipherSuites[i];
-        SECStatus status;
-        status = SSL_GetCipherSuiteInfo(suite, &info, sizeof info);
-        if (status != SECSuccess) {
-            printf("SSL_GetCipherSuiteInfo rejected suite 0x%04x (i = %d)\n",
-                   suite, i);
-            errWarn("SSL_GetCipherSuiteInfo");
-            rv = SECFailure;
-            continue;
-        }
-        if (info.cipherSuite != suite) {
-            printf(
-                "SSL_GetCipherSuiteInfo returned wrong suite! Wanted 0x%04x, Got 0x%04x\n",
-                suite, i);
-            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-            rv = SECFailure;
-            continue;
-        }
-        /* should check here that info.length >= offsetof isExportable */
-        if (info.isExportable) {
-            status = SSL_CipherPolicySet(suite, SSL_NOT_ALLOWED);
-            if (status != SECSuccess) {
-                printf("SSL_CipherPolicySet rejected suite 0x%04x (i = %d)\n",
-                       suite, i);
-                errWarn("SSL_CipherPolicySet");
-                rv = SECFailure;
-            }
-        }
-    }
-    return rv;
-}
-
 static SECStatus
 mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
                      PRBool isServer)
 {
     SECStatus rv;
     CERTCertificate *peerCert;
 
     peerCert = SSL_PeerCertificate(fd);
@@ -834,17 +790,16 @@ logger(void *arg)
 ** End   thread management routines.
 **************************************************************************/
 
 PRBool useModelSocket = PR_FALSE;
 static SSLVersionRange enabledVersions;
 PRBool disableRollBack = PR_FALSE;
 PRBool NoReuse = PR_FALSE;
 PRBool hasSidCache = PR_FALSE;
-PRBool disableStepDown = PR_FALSE;
 PRBool bypassPKCS11 = PR_FALSE;
 PRBool disableLocking = PR_FALSE;
 PRBool testbypass = PR_FALSE;
 PRBool enableSessionTickets = PR_FALSE;
 PRBool enableCompression = PR_FALSE;
 PRBool failedToNegotiateName = PR_FALSE;
 PRBool enableExtendedMasterSecret = PR_FALSE;
 PRBool zeroRTT = PR_FALSE;
@@ -1900,22 +1855,16 @@ server_main(
     if (rv != SECSuccess) {
         errExit("error setting SSL/TLS version range ");
     }
 
     rv = SSL_OptionSet(model_sock, SSL_ROLLBACK_DETECTION, !disableRollBack);
     if (rv != SECSuccess) {
         errExit("error enabling RollBack detection ");
     }
-    if (disableStepDown) {
-        rv = SSL_OptionSet(model_sock, SSL_NO_STEP_DOWN, PR_TRUE);
-        if (rv != SECSuccess) {
-            errExit("error disabling SSL StepDown ");
-        }
-    }
     if (bypassPKCS11) {
         rv = SSL_OptionSet(model_sock, SSL_BYPASS_PKCS11, PR_TRUE);
         if (rv != SECSuccess) {
             errExit("error enabling PKCS11 bypass ");
         }
     }
     if (disableLocking) {
         rv = SSL_OptionSet(model_sock, SSL_NO_LOCKS, PR_TRUE);
@@ -2247,17 +2196,16 @@ main(int argc, char **argv)
     CERTCertificate *cert[kt_kea_size] = { NULL };
     SECKEYPrivateKey *privKey[kt_kea_size] = { NULL };
     int optionsFound = 0;
     int maxProcs = 1;
     unsigned short port = 0;
     SECStatus rv;
     PRStatus prStatus;
     PRBool bindOnly = PR_FALSE;
-    PRBool useExportPolicy = PR_FALSE;
     PRBool useLocalThreads = PR_FALSE;
     PLOptState *optstate;
     PLOptStatus status;
     PRThread *loggerThread = NULL;
     PRBool debugCache = PR_FALSE; /* bug 90518 */
     char emptyString[] = { "" };
     char *certPrefix = emptyString;
     PRUint32 protos = 0;
@@ -2272,19 +2220,20 @@ main(int argc, char **argv)
     progName = strrchr(tmp, '\\');
     progName = progName ? progName + 1 : tmp;
 
     PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
     SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions);
 
     /* please keep this list of options in ASCII collating sequence.
     ** numbers, then capital letters, then lower case, alphabetical.
-    */
+    ** XXX: 'E' and 'x' were used in the past, please leave some
+    **      time before resuing those. */
     optstate = PL_CreateOptState(argc, argv,
-                                 "2:A:BC:DEGH:L:M:NP:QRS:T:U:V:W:YZa:bc:d:e:f:g:hi:jk:lmn:op:qrst:uvw:xyz");
+                                 "2:A:BC:DGH:L:M:NP:QRS:T:U:V:W:YZa:bc:d:e:f:g:hi:jk:lmn:op:qrst:uvw:yz");
     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
         ++optionsFound;
         switch (optstate->option) {
             case '2':
                 fileName = optstate->value;
                 break;
 
             case 'A':
@@ -2298,19 +2247,16 @@ main(int argc, char **argv)
             case 'C':
                 if (optstate->value)
                     NumSidCacheEntries = PORT_Atoi(optstate->value);
                 break;
 
             case 'D':
                 noDelay = PR_TRUE;
                 break;
-            case 'E':
-                disableStepDown = PR_TRUE;
-                break;
             case 'H':
                 configureDHE = (PORT_Atoi(optstate->value) != 0);
                 break;
 
             case 'G':
                 enableExtendedMasterSecret = PR_TRUE;
                 break;
 
@@ -2485,20 +2431,16 @@ main(int argc, char **argv)
                 verbose++;
                 break;
 
             case 'w':
                 pwdata.source = PW_PLAINTEXT;
                 pwdata.data = passwd = PORT_Strdup(optstate->value);
                 break;
 
-            case 'x':
-                useExportPolicy = PR_TRUE;
-                break;
-
             case 'y':
                 debugCache = PR_TRUE;
                 break;
 
             case 'z':
                 enableCompression = PR_TRUE;
                 break;
 
@@ -2660,34 +2602,16 @@ main(int argc, char **argv)
 
     /* Call the NSS initialization routines */
     rv = NSS_Initialize(dir, certPrefix, certPrefix, SECMOD_DB, NSS_INIT_READONLY);
     if (rv != SECSuccess) {
         fputs("NSS_Init failed.\n", stderr);
         exit(8);
     }
 
-    /* set the policy bits true for all the cipher suites. */
-    if (useExportPolicy) {
-        NSS_SetExportPolicy();
-        if (disableStepDown) {
-            fputs("selfserv: -x and -E options may not be used together\n",
-                  stderr);
-            exit(98);
-        }
-    } else {
-        NSS_SetDomesticPolicy();
-        if (disableStepDown) {
-            rv = disableExportSSLCiphers();
-            if (rv != SECSuccess) {
-                errExit("error disabling export ciphersuites ");
-            }
-        }
-    }
-
     /* all SSL3 cipher suites are enabled by default. */
     if (cipherString) {
         char *cstringSaved = cipherString;
         int ndx;
 
         /* disable all the ciphers, then enable the ones we want. */
         disableAllSSLCiphers();
 
@@ -2846,16 +2770,19 @@ main(int argc, char **argv)
 #endif /* NSS_DISABLE_ECC */
 
     if (testbypass)
         goto cleanup;
 
     if (configureWeakDHE > 0) {
         fprintf(stderr, "selfserv: Creating dynamic weak DH parameters\n");
         rv = SSL_EnableWeakDHEPrimeGroup(NULL, PR_TRUE);
+        if (rv != SECSuccess) {
+            goto cleanup;
+        }
         fprintf(stderr, "selfserv: Done creating dynamic weak DH parameters\n");
     }
 
     /* allocate the array of thread slots, and launch the worker threads. */
     rv = launch_threads(&jobLoop, 0, 0, requestCert, useLocalThreads);
 
     if (rv == SECSuccess && logStats) {
         loggerThread = PR_CreateThread(PR_SYSTEM_THREAD,
--- a/security/nss/cmd/signtool/javascript.c
+++ b/security/nss/cmd/signtool/javascript.c
@@ -1703,16 +1703,19 @@ make_dirs(char *path, int file_perms)
 
     if (!path) {
         return 0;
     }
 
     Path = PL_strdup(path);
     start = strpbrk(Path, "/\\");
     if (!start) {
+        if (Path) {
+            PR_Free(Path);
+        }
         return 0;
     }
     start++; /* start right after first slash */
 
     /* Each time through the loop add one more directory. */
     while ((sep = strpbrk(start, "/\\"))) {
         *sep = '\0';
 
--- a/security/nss/cmd/ssltap/ssltap.c
+++ b/security/nss/cmd/ssltap/ssltap.c
@@ -1866,16 +1866,20 @@ print_ssl(DataBufferList *s, int length,
         PR_Write(PR_STDOUT, buffer, length);
         return;
     }
 
     check_integrity(s);
 
     db = PR_NEW(struct _DataBuffer);
 
+    if (!db) {
+        return;
+    }
+
     db->buffer = (unsigned char *)PORT_Alloc(length);
     db->length = length;
     db->offset = 0;
     memcpy(db->buffer, buffer, length);
     db->next = NULL;
 
     /* now, add it to the stream */
 
--- a/security/nss/cmd/strsclnt/strsclnt.c
+++ b/security/nss/cmd/strsclnt/strsclnt.c
@@ -42,42 +42,42 @@
 
 #define RD_BUF_SIZE (60 * 1024)
 
 /* Include these cipher suite arrays to re-use tstclnt's
  * cipher selection code.
  */
 
 int ssl3CipherSuites[] = {
-    -1,                                  /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
-    -1,                                  /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA     * b */
-    TLS_RSA_WITH_RC4_128_MD5,            /* c */
-    TLS_RSA_WITH_3DES_EDE_CBC_SHA,       /* d */
-    TLS_RSA_WITH_DES_CBC_SHA,            /* e */
-    TLS_RSA_EXPORT_WITH_RC4_40_MD5,      /* f */
-    TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,  /* g */
-    -1,                                  /* SSL_FORTEZZA_DMS_WITH_NULL_SHA        * h */
-    TLS_RSA_WITH_NULL_MD5,               /* i */
-    SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,  /* j */
-    SSL_RSA_FIPS_WITH_DES_CBC_SHA,       /* k */
-    TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
-    TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,  /* m */
-    TLS_RSA_WITH_RC4_128_SHA,            /* n */
-    TLS_DHE_DSS_WITH_RC4_128_SHA,        /* o */
-    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,   /* p */
-    TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,   /* q */
-    TLS_DHE_RSA_WITH_DES_CBC_SHA,        /* r */
-    TLS_DHE_DSS_WITH_DES_CBC_SHA,        /* s */
-    TLS_DHE_DSS_WITH_AES_128_CBC_SHA,    /* t */
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,    /* u */
-    TLS_RSA_WITH_AES_128_CBC_SHA,        /* v */
-    TLS_DHE_DSS_WITH_AES_256_CBC_SHA,    /* w */
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,    /* x */
-    TLS_RSA_WITH_AES_256_CBC_SHA,        /* y */
-    TLS_RSA_WITH_NULL_SHA,               /* z */
+    -1,                                /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
+    -1,                                /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA     * b */
+    TLS_RSA_WITH_RC4_128_MD5,          /* c */
+    TLS_RSA_WITH_3DES_EDE_CBC_SHA,     /* d */
+    TLS_RSA_WITH_DES_CBC_SHA,          /* e */
+    -1,                                /* TLS_RSA_EXPORT_WITH_RC4_40_MD5        * f */
+    -1,                                /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5    * g */
+    -1,                                /* SSL_FORTEZZA_DMS_WITH_NULL_SHA        * h */
+    TLS_RSA_WITH_NULL_MD5,             /* i */
+    -1,                                /* SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA    * j */
+    -1,                                /* SSL_RSA_FIPS_WITH_DES_CBC_SHA         * k */
+    -1,                                /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA   * l */
+    -1,                                /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA    * m */
+    TLS_RSA_WITH_RC4_128_SHA,          /* n */
+    TLS_DHE_DSS_WITH_RC4_128_SHA,      /* o */
+    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
+    TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
+    TLS_DHE_RSA_WITH_DES_CBC_SHA,      /* r */
+    TLS_DHE_DSS_WITH_DES_CBC_SHA,      /* s */
+    TLS_DHE_DSS_WITH_AES_128_CBC_SHA,  /* t */
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,  /* u */
+    TLS_RSA_WITH_AES_128_CBC_SHA,      /* v */
+    TLS_DHE_DSS_WITH_AES_256_CBC_SHA,  /* w */
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,  /* x */
+    TLS_RSA_WITH_AES_256_CBC_SHA,      /* y */
+    TLS_RSA_WITH_NULL_SHA,             /* z */
     0
 };
 
 #define NO_FULLHS_PERCENTAGE -1
 
 /* This global string is so that client main can see
  * which ciphers to use.
  */
--- a/security/nss/cmd/tstclnt/tstclnt.c
+++ b/security/nss/cmd/tstclnt/tstclnt.c
@@ -56,42 +56,42 @@
 #define EXIT_CODE_SIDECHANNELTEST_GOOD 0
 #define EXIT_CODE_SIDECHANNELTEST_BADCERT 1
 #define EXIT_CODE_SIDECHANNELTEST_NODATA 2
 #define EXIT_CODE_SIDECHANNELTEST_REVOKED 3
 
 PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT;
 
 int ssl3CipherSuites[] = {
-    -1,                                  /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
-    -1,                                  /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA,   * b */
-    TLS_RSA_WITH_RC4_128_MD5,            /* c */
-    TLS_RSA_WITH_3DES_EDE_CBC_SHA,       /* d */
-    TLS_RSA_WITH_DES_CBC_SHA,            /* e */
-    TLS_RSA_EXPORT_WITH_RC4_40_MD5,      /* f */
-    TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,  /* g */
-    -1,                                  /* SSL_FORTEZZA_DMS_WITH_NULL_SHA,      * h */
-    TLS_RSA_WITH_NULL_MD5,               /* i */
-    SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,  /* j */
-    SSL_RSA_FIPS_WITH_DES_CBC_SHA,       /* k */
-    TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
-    TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,  /* m */
-    TLS_RSA_WITH_RC4_128_SHA,            /* n */
-    TLS_DHE_DSS_WITH_RC4_128_SHA,        /* o */
-    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,   /* p */
-    TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,   /* q */
-    TLS_DHE_RSA_WITH_DES_CBC_SHA,        /* r */
-    TLS_DHE_DSS_WITH_DES_CBC_SHA,        /* s */
-    TLS_DHE_DSS_WITH_AES_128_CBC_SHA,    /* t */
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,    /* u */
-    TLS_RSA_WITH_AES_128_CBC_SHA,        /* v */
-    TLS_DHE_DSS_WITH_AES_256_CBC_SHA,    /* w */
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,    /* x */
-    TLS_RSA_WITH_AES_256_CBC_SHA,        /* y */
-    TLS_RSA_WITH_NULL_SHA,               /* z */
+    -1,                                /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
+    -1,                                /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA     * b */
+    TLS_RSA_WITH_RC4_128_MD5,          /* c */
+    TLS_RSA_WITH_3DES_EDE_CBC_SHA,     /* d */
+    TLS_RSA_WITH_DES_CBC_SHA,          /* e */
+    -1,                                /* TLS_RSA_EXPORT_WITH_RC4_40_MD5        * f */
+    -1,                                /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5    * g */
+    -1,                                /* SSL_FORTEZZA_DMS_WITH_NULL_SHA        * h */
+    TLS_RSA_WITH_NULL_MD5,             /* i */
+    -1,                                /* SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA    * j */
+    -1,                                /* SSL_RSA_FIPS_WITH_DES_CBC_SHA         * k */
+    -1,                                /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA   * l */
+    -1,                                /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA    * m */
+    TLS_RSA_WITH_RC4_128_SHA,          /* n */
+    TLS_DHE_DSS_WITH_RC4_128_SHA,      /* o */
+    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
+    TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
+    TLS_DHE_RSA_WITH_DES_CBC_SHA,      /* r */
+    TLS_DHE_DSS_WITH_DES_CBC_SHA,      /* s */
+    TLS_DHE_DSS_WITH_AES_128_CBC_SHA,  /* t */
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,  /* u */
+    TLS_RSA_WITH_AES_128_CBC_SHA,      /* v */
+    TLS_DHE_DSS_WITH_AES_256_CBC_SHA,  /* w */
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,  /* x */
+    TLS_RSA_WITH_AES_256_CBC_SHA,      /* y */
+    TLS_RSA_WITH_NULL_SHA,             /* z */
     0
 };
 
 unsigned long __cmp_umuls;
 PRBool verbose;
 int dumpServerChain = 0;
 int renegotiationsToDo = 0;
 int renegotiationsDone = 0;
@@ -223,17 +223,16 @@ PrintParameterUsage(void)
             "-V [min]:[max]", "", "", "");
     fprintf(stderr, "%-20s Send TLS_FALLBACK_SCSV\n", "-K");
     fprintf(stderr, "%-20s Prints only payload data. Skips HTTP header.\n", "-S");
     fprintf(stderr, "%-20s Client speaks first. \n", "-f");
     fprintf(stderr, "%-20s Use synchronous certificate validation\n", "-O");
     fprintf(stderr, "%-20s Override bad server cert. Make it OK.\n", "-o");
     fprintf(stderr, "%-20s Disable SSL socket locking.\n", "-s");
     fprintf(stderr, "%-20s Verbose progress reporting.\n", "-v");
-    fprintf(stderr, "%-20s Use export policy.\n", "-x");
     fprintf(stderr, "%-20s Ping the server and then exit.\n", "-q");
     fprintf(stderr, "%-20s Timeout for server ping (default: no timeout).\n", "-t seconds");
     fprintf(stderr, "%-20s Renegotiate N times (resuming session if N>1).\n", "-r N");
     fprintf(stderr, "%-20s Enable the session ticket extension.\n", "-u");
     fprintf(stderr, "%-20s Enable compression.\n", "-z");
     fprintf(stderr, "%-20s Enable false start.\n", "-g");
     fprintf(stderr, "%-20s Enable the cert_status extension (OCSP stapling).\n", "-T");
     fprintf(stderr, "%-20s Enable the signed_certificate_timestamp extension.\n", "-U");
@@ -273,23 +272,17 @@ PrintCipherUsage(const char *progName)
 {
     PrintUsageHeader(progName);
     fprintf(stderr, "%-20s Letter(s) chosen from the following list\n",
             "-c ciphers");
     fprintf(stderr,
             "c    SSL3 RSA WITH RC4 128 MD5\n"
             "d    SSL3 RSA WITH 3DES EDE CBC SHA\n"
             "e    SSL3 RSA WITH DES CBC SHA\n"
-            "f    SSL3 RSA EXPORT WITH RC4 40 MD5\n"
-            "g    SSL3 RSA EXPORT WITH RC2 CBC 40 MD5\n"
             "i    SSL3 RSA WITH NULL MD5\n"
-            "j    SSL3 RSA FIPS WITH 3DES EDE CBC SHA\n"
-            "k    SSL3 RSA FIPS WITH DES CBC SHA\n"
-            "l    SSL3 RSA EXPORT WITH DES CBC SHA\t(new)\n"
-            "m    SSL3 RSA EXPORT WITH RC4 56 SHA\t(new)\n"
             "n    SSL3 RSA WITH RC4 128 SHA\n"
             "o    SSL3 DHE DSS WITH RC4 128 SHA\n"
             "p    SSL3 DHE RSA WITH 3DES EDE CBC SHA\n"
             "q    SSL3 DHE DSS WITH 3DES EDE CBC SHA\n"
             "r    SSL3 DHE RSA WITH DES CBC SHA\n"
             "s    SSL3 DHE DSS WITH DES CBC SHA\n"
             "t    SSL3 DHE DSS WITH AES 128 CBC SHA\n"
             "u    SSL3 DHE RSA WITH AES 128 CBC SHA\n"
@@ -906,17 +899,16 @@ main(int argc, char **argv)
     SECStatus rv;
     PRStatus status;
     PRInt32 filesReady;
     int npds;
     int override = 0;
     SSLVersionRange enabledVersions;
     int bypassPKCS11 = 0;
     int disableLocking = 0;
-    int useExportPolicy = 0;
     int enableSessionTickets = 0;
     int enableCompression = 0;
     int enableFalseStart = 0;
     int enableCertStatus = 0;
     int enableSignedCertTimestamps = 0;
     int forceFallbackSCSV = 0;
     int enableExtendedMasterSecret = 0;
     PRBool requireDHNamedGroups = 0;
@@ -963,17 +955,17 @@ main(int argc, char **argv)
         if (sec > 0) {
             maxInterval = PR_SecondsToInterval(sec);
         }
     }
 
     SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions);
 
     optstate = PL_CreateOptState(argc, argv,
-                                 "46BCDFGHKM:OR:STUV:W:Ya:bc:d:fgh:m:n:op:qr:st:uvw:xz");
+                                 "46BCDFGHKM:OR:STUV:W:Ya:bc:d:fgh:m:n:op:qr:st:uvw:z");
     while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
         switch (optstate->option) {
             case '?':
             default:
                 Usage(progName);
                 break;
 
             case '4':
@@ -1154,20 +1146,16 @@ main(int argc, char **argv)
                 pwdata.data = PORT_Strdup(optstate->value);
                 break;
 
             case 'W':
                 pwdata.source = PW_FROMFILE;
                 pwdata.data = PORT_Strdup(optstate->value);
                 break;
 
-            case 'x':
-                useExportPolicy = 1;
-                break;
-
             case 'z':
                 enableCompression = 1;
                 break;
         }
     }
 
     PL_DestroyOptState(optstate);
 
@@ -1311,22 +1299,16 @@ main(int argc, char **argv)
 
     if (loadDefaultRootCAs) {
         SECMOD_AddNewModule("Builtins",
                             DLL_PREFIX "nssckbi." DLL_SUFFIX, 0, 0);
     } else if (rootModule) {
         SECMOD_AddNewModule("Builtins", rootModule, 0, 0);
     }
 
-    /* set the policy bits true for all the cipher suites. */
-    if (useExportPolicy)
-        NSS_SetExportPolicy();
-    else
-        NSS_SetDomesticPolicy();
-
     /* all SSL3 cipher suites are enabled by default. */
     if (cipherString) {
         /* disable all the ciphers, then enable the ones we want. */
         disableAllSSLCiphers();
     }
 
     /* Create socket */
     s = PR_OpenTCPSocket(addr.raw.family);
--- a/security/nss/cmd/vfyserv/vfyutil.c
+++ b/security/nss/cmd/vfyserv/vfyutil.c
@@ -9,42 +9,42 @@
 #include "secutil.h"
 
 extern PRBool dumpChain;
 extern void dumpCertChain(CERTCertificate *, SECCertUsage);
 
 /* Declare SSL cipher suites. */
 
 int ssl3CipherSuites[] = {
-    -1,                                  /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
-    -1,                                  /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA,	 * b */
-    TLS_RSA_WITH_RC4_128_MD5,            /* c */
-    TLS_RSA_WITH_3DES_EDE_CBC_SHA,       /* d */
-    TLS_RSA_WITH_DES_CBC_SHA,            /* e */
-    TLS_RSA_EXPORT_WITH_RC4_40_MD5,      /* f */
-    TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,  /* g */
-    -1,                                  /* SSL_FORTEZZA_DMS_WITH_NULL_SHA,	 * h */
-    TLS_RSA_WITH_NULL_MD5,               /* i */
-    SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,  /* j */
-    SSL_RSA_FIPS_WITH_DES_CBC_SHA,       /* k */
-    TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
-    TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,  /* m */
-    TLS_RSA_WITH_RC4_128_SHA,            /* n */
-    TLS_DHE_DSS_WITH_RC4_128_SHA,        /* o */
-    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,   /* p */
-    TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,   /* q */
-    TLS_DHE_RSA_WITH_DES_CBC_SHA,        /* r */
-    TLS_DHE_DSS_WITH_DES_CBC_SHA,        /* s */
-    TLS_DHE_DSS_WITH_AES_128_CBC_SHA,    /* t */
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,    /* u */
-    TLS_RSA_WITH_AES_128_CBC_SHA,        /* v */
-    TLS_DHE_DSS_WITH_AES_256_CBC_SHA,    /* w */
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,    /* x */
-    TLS_RSA_WITH_AES_256_CBC_SHA,        /* y */
-    TLS_RSA_WITH_NULL_SHA,               /* z */
+    -1,                                /* SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA* a */
+    -1,                                /* SSL_FORTEZZA_DMS_WITH_RC4_128_SHA     * b */
+    TLS_RSA_WITH_RC4_128_MD5,          /* c */
+    TLS_RSA_WITH_3DES_EDE_CBC_SHA,     /* d */
+    TLS_RSA_WITH_DES_CBC_SHA,          /* e */
+    -1,                                /* TLS_RSA_EXPORT_WITH_RC4_40_MD5        * f */
+    -1,                                /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5    * g */
+    -1,                                /* SSL_FORTEZZA_DMS_WITH_NULL_SHA        * h */
+    TLS_RSA_WITH_NULL_MD5,             /* i */
+    -1,                                /* SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA    * j */
+    -1,                                /* SSL_RSA_FIPS_WITH_DES_CBC_SHA         * k */
+    -1,                                /* TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA   * l */
+    -1,                                /* TLS_RSA_EXPORT1024_WITH_RC4_56_SHA    * m */
+    TLS_RSA_WITH_RC4_128_SHA,          /* n */
+    TLS_DHE_DSS_WITH_RC4_128_SHA,      /* o */
+    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
+    TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
+    TLS_DHE_RSA_WITH_DES_CBC_SHA,      /* r */
+    TLS_DHE_DSS_WITH_DES_CBC_SHA,      /* s */
+    TLS_DHE_DSS_WITH_AES_128_CBC_SHA,  /* t */
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,  /* u */
+    TLS_RSA_WITH_AES_128_CBC_SHA,      /* v */
+    TLS_DHE_DSS_WITH_AES_256_CBC_SHA,  /* w */
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,  /* x */
+    TLS_RSA_WITH_AES_256_CBC_SHA,      /* y */
+    TLS_RSA_WITH_NULL_SHA,             /* z */
     0
 };
 int numSSL3CipherSuites = PR_ARRAY_SIZE(ssl3CipherSuites);
 
 /**************************************************************************
 **
 ** SSL callback routines.
 **
--- a/security/nss/coreconf/Darwin.mk
+++ b/security/nss/coreconf/Darwin.mk
@@ -105,16 +105,22 @@ endif
 ARCH		= darwin
 
 DSO_CFLAGS	= -fPIC
 # May override this with different compatibility and current version numbers.
 DARWIN_DYLIB_VERSIONS = -compatibility_version 1 -current_version 1
 # May override this with -bundle to create a loadable module.
 DSO_LDOPTS	= -dynamiclib $(DARWIN_DYLIB_VERSIONS) -install_name @executable_path/$(notdir $@) -headerpad_max_install_names
 
+ifdef USE_GCOV
+   OS_CFLAGS += --coverage
+   LDFLAGS += --coverage
+   DSO_LDOPTS += --coverage
+endif
+
 MKSHLIB		= $(CC) $(DSO_LDOPTS) $(DARWIN_SDK_SHLIBFLAGS)
 DLL_SUFFIX	= dylib
 ifdef MAPFILE
 	MKSHLIB += -exported_symbols_list $(MAPFILE)
 endif
 PROCESS_MAP_FILE = grep -v ';+' $< | grep -v ';-' | \
                 sed -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,,' -e 's,^,_,' > $@
 
--- a/security/nss/coreconf/Linux.mk
+++ b/security/nss/coreconf/Linux.mk
@@ -210,9 +210,15 @@ ifdef MAPFILE
 endif
 PROCESS_MAP_FILE = grep -v ';-' $< | \
         sed -e 's,;+,,' -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,;,' > $@
 
 ifeq ($(OS_RELEASE),2.4)
 DEFINES += -DNO_FORK_CHECK
 endif
 
+ifdef USE_GCOV
+OS_CFLAGS += --coverage
+LDFLAGS += --coverage
+DSO_LDOPTS += --coverage
+endif
+
 include $(CORE_DEPTH)/coreconf/sanitizers.mk
--- 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/external_tests/nss_bogo_shim/config.json
+++ b/security/nss/external_tests/nss_bogo_shim/config.json
@@ -1,19 +1,27 @@
 {
     "DisabledTests": {
-        "*HelloRetryRequest*":"HRR hasn't landed yet",
-        "SecondClientHelloWrongCurve":"HRR hasn't landed yet",
+        "*TLS13*":"Draft version mismatch (NSS=15, BoGo=14)",
+        "FallbackSCSV-VersionMatch":"Draft version mismatch (NSS=15, BoGo=14)",
+        "SendEmptyRecords-Pass":"Draft version mismatch (NSS=15, BoGo=14)",
+        "SendSNIWarningAlert":"Draft version mismatch (NSS=15, BoGo=14)",
+        "UnknownCipher":"Draft version mismatch (NSS=15, BoGo=14)",
+        "UnknownCurve":"Draft version mismatch (NSS=15, BoGo=14)",
+        "*TrailingMessageData*":"Draft version mismatch (NSS=15, BoGo=14)",
+        "*Downgrade-TLS12*":"Draft version mismatch (NSS=15, BoGo=14)",
+        "UnknownCurve":"Draft version mismatch (NSS=15, BoGo=14)",
+        "*MissingKeyShare*":"Draft version mismatch (NSS=15, BoGo=14)",
+        "SecondClientHelloWrongCurve":"Draft version mismatch (NSS=15, BoGo=14)",
+        "SendHelloRetryRequest":"Expects CurveX25519",
+        "SendHelloRetryRequest-2":"Expects CurveX25519",
         "KeyUpdate":"KeyUpdate Unimplemented",
         "ClientAuth-NoFallback-TLS13":"Disagreement about alerts. Bug 1294975",
         "ClientAuth-SHA1-Fallback":"Disagreement about alerts. Bug 1294975",
         "SendWarningAlerts-TLS13":"NSS needs to trigger on warning alerts",
-        "*SignatureType-TLS13":"SignatureScheme patch",
-        "ECDSACurveMismatch-Verify-TLS13":"SignatureScheme patch",
-        "ServerAuth-NoFallback-TLS13":"PSS",
         "NoSupportedCurves":"This tests a non-spec behavior for TLS 1.2 and expects the wrong alert for TLS 1.3",
         "SendEmptyRecords":"Tests a non-spec behavior in BoGo where it chokes on too many empty records",
         "LargePlaintext":"NSS needs to check for over-long records. Bug 1294978",
         "TLS13-RC4-MD5-server":"This fails properly but returns an unexpected error. Not a bug but needs cleanup",
         "*VersionTolerance":"BoGo expects us to negotiate 1.3 but we negotiate 1.2 because BoGo didn't send draft version",
         "*SSL3*":"NSS disables SSLv3",
         "*SSLv3*":"NSS disables SSLv3",
         "*AES256*":"Inconsistent support for AES256",
@@ -24,18 +32,35 @@
         "SillyDH":"NSS supports 4097-bit DH",
         "SendWarningAlerts":"This appears to be Boring-specific",
         "V2ClientHello-WarningAlertPrefix":"Bug 1292893",
         "TLS12-AES128-GCM-client":"Bug 1292895",
         "*TLS12-AES128-GCM-LargeRecord*":"Bug 1292895",
         "Renegotiate-Client-Forbidden-1":"Bug 1292898",
         "Renegotiate-Server-Forbidden":"NSS doesn't disable renegotiation by default",
         "Renegotiate-Client-NoIgnore":"NSS doesn't disable renegotiation by default",
-        "StrayHelloRequest*":"NSS doesn't disable renegotiation by default"
+        "StrayHelloRequest*":"NSS doesn't disable renegotiation by default",
+        "NoSupportedCurves-TLS13":"wanted SSL_ERROR_NO_CYPHER_OVERLAP, got missing extension error",
+        "FragmentedClientVersion":"received a malformed Client Hello handshake message",
+        "UnofferedExtension-Client-TLS13":"nss updated/broken",
+        "UnknownExtension-Client-TLS13":"nss updated/broken",
+        "WrongMessageType-TLS13-EncryptedExtensions":"nss updated/broken",
+        "WrongMessageType-TLS13-CertificateRequest":"nss updated/broken",
+        "WrongMessageType-TLS13-ServerCertificateVerify":"nss updated/broken",
+        "WrongMessageType-TLS13-ServerCertificate":"nss updated/broken",
+        "WrongMessageType-TLS13-ServerFinished":"nss updated/broken",
+        "EncryptedExtensionsWithKeyShare":"nss updated/broken",
+        "EmptyEncryptedExtensions":"nss updated/broken",
+        "ClientAuth-SHA1-Fallback-RSA":"We fail when the sig_algs_ext is empty",
+        "SendSNIWarningAlert":"Bug 1304574",
+        "Downgrade-TLS12-*":"NSS implements downgrade detection",
+        "TrailingMessageData-*": "Bug 1304575",
+        "DuplicateKeyShares":"Bug 1304578"
     },
     "ErrorMap" : {
         ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:":"SSL_ERROR_NO_CYPHER_OVERLAP",
         ":UNKNOWN_CIPHER_RETURNED:":"SSL_ERROR_NO_CYPHER_OVERLAP",
         ":OLD_SESSION_CIPHER_NOT_RETURNED:":"SSL_ERROR_NO_CYPHER_OVERLAP",
-        ":NO_SHARED_CIPHER:":"SSL_ERROR_NO_CYPHER_OVERLAP"
+        ":NO_SHARED_CIPHER:":"SSL_ERROR_NO_CYPHER_OVERLAP",
+        ":DIGEST_CHECK_FAILED:":"SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE"
     }
 }
 
--- a/security/nss/external_tests/nss_bogo_shim/nss_bogo_shim.cc
+++ b/security/nss/external_tests/nss_bogo_shim/nss_bogo_shim.cc
@@ -170,22 +170,23 @@ class TestAgent {
   }
 
   bool EnableNonExportCiphers() {
     for (size_t i = 0; i < SSL_NumImplementedCiphers; ++i) {
       SSLCipherSuiteInfo csinfo;
 
       SECStatus rv = SSL_GetCipherSuiteInfo(SSL_ImplementedCiphers[i], &csinfo,
                                             sizeof(csinfo));
-      if (rv != SECSuccess) return false;
-      if (!csinfo.isExportable) {
-        rv = SSL_CipherPrefSet(ssl_fd_, SSL_ImplementedCiphers[i], PR_TRUE);
-        if (rv != SECSuccess) {
-          return false;
-        }
+      if (rv != SECSuccess) {
+        return false;
+      }
+
+      rv = SSL_CipherPrefSet(ssl_fd_, SSL_ImplementedCiphers[i], PR_TRUE);
+      if (rv != SECSuccess) {
+        return false;
       }
     }
     return true;
   }
 
   // Dummy auth certificate hook.
   static SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd,
                                        PRBool checksig, PRBool isServer) {
--- a/security/nss/external_tests/pk11_gtest/manifest.mn
+++ b/security/nss/external_tests/pk11_gtest/manifest.mn
@@ -4,16 +4,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 CORE_DEPTH = ../..
 DEPTH      = ../..
 MODULE = nss
 
 CPPSRCS = \
       pk11_aeskeywrap_unittest.cc \
       pk11_chacha20poly1305_unittest.cc \
+      pk11_export_unittest.cc \
       pk11_pbkdf2_unittest.cc \
       pk11_prf_unittest.cc \
       pk11_rsapss_unittest.cc \
       $(NULL)
 
 INCLUDES += -I$(CORE_DEPTH)/external_tests/google_test/gtest/include \
             -I$(CORE_DEPTH)/external_tests/common
 
--- a/security/nss/external_tests/ssl_gtest/libssl_internals.c
+++ b/security/nss/external_tests/ssl_gtest/libssl_internals.c
@@ -21,31 +21,32 @@ SECStatus SSLInt_IncrementClientHandshak
 
   ++ss->clientHelloVersion;
 
   return SECSuccess;
 }
 
 // This function guesses what key exchange strength libssl will choose.
 PRUint32 SSLInt_DetermineKEABits(PRUint16 serverKeyBits,
-                                 const SSLCipherSuiteInfo *info) {
+                                 SSLAuthType authAlgorithm,
+                                 PRUint32 symKeyBits) {
   PRUint32 authBits;
-  SSLAuthType authAlgorithm = info->authType;
+
   if (authAlgorithm == ssl_auth_ecdsa || authAlgorithm == ssl_auth_ecdh_rsa ||
       authAlgorithm == ssl_auth_ecdh_ecdsa) {
     authBits = serverKeyBits;
   } else {
     PORT_Assert(authAlgorithm == ssl_auth_rsa_decrypt ||
                 authAlgorithm == ssl_auth_rsa_sign);
     authBits = SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyBits);
   }
 
   // We expect a curve for key exchange to be selected based on the symmetric
   // key strength (times 2) or the server key size, whichever is smaller.
-  PRUint32 targetKeaBits = PR_MIN(info->symKeyBits * 2, authBits);
+  PRUint32 targetKeaBits = PR_MIN(symKeyBits * 2, authBits);
 
   // P-256 is the preferred curve of minimum size.
   return PR_MAX(256U, targetKeaBits);
 }
 
 /* Use this function to update the ClientRandom of a client's handshake state
  * after replacing its ClientHello message. We for example need to do this
  * when replacing an SSLv3 ClientHello with its SSLv2 equivalent. */
@@ -278,8 +279,15 @@ SECStatus SSLInt_AdvanceWriteSeqByAWindo
   if (!ss) {
     return SECFailure;
   }
   ssl_GetSpecReadLock(ss);
   to = ss->ssl3.cwSpec->write_seq_num + DTLS_RECVD_RECORDS_WINDOW + extra;
   ssl_ReleaseSpecReadLock(ss);
   return SSLInt_AdvanceWriteSeqNum(fd, to & RECORD_SEQ_MAX);
 }
+
+SSLKEAType SSLInt_GetKEAType(SSLNamedGroup group) {
+  const sslNamedGroupDef *groupDef = ssl_LookupNamedGroup(group);
+  if (!groupDef) return ssl_kea_null;
+
+  return groupDef->keaType;
+}
--- a/security/nss/external_tests/ssl_gtest/libssl_internals.h
+++ b/security/nss/external_tests/ssl_gtest/libssl_internals.h
@@ -11,18 +11,18 @@
 
 #include "prio.h"
 #include "seccomon.h"
 #include "sslt.h"
 
 SECStatus SSLInt_IncrementClientHandshakeVersion(PRFileDesc *fd);
 
 PRUint32 SSLInt_DetermineKEABits(PRUint16 serverKeyBits,
-                                 const SSLCipherSuiteInfo *info);
-
+                                 SSLAuthType authAlgorithm,
+                                 PRUint32 symKeyBits);
 SECStatus SSLInt_UpdateSSLv2ClientRandom(PRFileDesc *fd, uint8_t *rnd,
                                          size_t rnd_len, uint8_t *msg,
                                          size_t msg_len);
 
 PRBool SSLInt_ExtensionNegotiated(PRFileDesc *fd, PRUint16 ext);
 void SSLInt_ClearSessionTicketKey();
 PRInt32 SSLInt_CountTls13CipherSpecs(PRFileDesc *fd);
 void SSLInt_ForceTimerExpiry(PRFileDesc *fd);
@@ -31,10 +31,11 @@ PRBool SSLInt_CheckSecretsDestroyed(PRFi
 PRBool SSLInt_DamageHsTrafficSecret(PRFileDesc *fd);
 PRBool SSLInt_DamageEarlyTrafficSecret(PRFileDesc *fd);
 SECStatus SSLInt_Set0RttAlpn(PRFileDesc *fd, PRUint8 *data, unsigned int len);
 PRBool SSLInt_HasCertWithAuthType(PRFileDesc *fd, SSLAuthType authType);
 PRBool SSLInt_SendAlert(PRFileDesc *fd, uint8_t level, uint8_t type);
 SECStatus SSLInt_AdvanceWriteSeqNum(PRFileDesc *fd, PRUint64 to);
 SECStatus SSLInt_AdvanceReadSeqNum(PRFileDesc *fd, PRUint64 to);
 SECStatus SSLInt_AdvanceWriteSeqByAWindow(PRFileDesc *fd, PRInt32 extra);
+SSLKEAType SSLInt_GetKEAType(SSLNamedGroup group);
 
 #endif  // ndef libssl_internals_h_
--- a/security/nss/external_tests/ssl_gtest/ssl_agent_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_agent_unittest.cc
@@ -19,24 +19,24 @@
 namespace nss_test {
 
 // This is a 1-RTT ClientHello with ECDHE and DHE.
 const static uint8_t kCannedTls13ClientHello[] = {
     0x01, 0x00, 0x01, 0xfc, 0x03, 0x04, 0x77, 0x5c, 0x3a, 0xd8, 0x3f, 0x43,
     0x63, 0x98, 0xfa, 0x68, 0xfb, 0x01, 0x39, 0xff, 0x7c, 0x1a, 0x51, 0xa7,
     0x92, 0xda, 0x97, 0xf5, 0x15, 0x78, 0xb3, 0xbb, 0x26, 0xa7, 0xed, 0x6f,
     0x69, 0x71, 0x00, 0x00, 0x2a, 0xc0, 0x2b, 0xc0, 0x2f, 0xcc, 0xa9, 0xcc,
-    0xa8, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x14, 0x00, 0x9e, 0xcc,
+    0xa8, 0x13, 0x01, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x14, 0x00, 0x9e, 0xcc,
     0xaa, 0x00, 0x33, 0x00, 0x32, 0x00, 0x39, 0x00, 0x38, 0x00, 0x16, 0x00,
     0x13, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x04, 0x01,
     0x00, 0x01, 0xa9, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x00, 0x06,
     0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00,
     0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x01,
     0x00, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0xff, 0x02, 0x00, 0x02, 0x00,
-    0x0e, 0x00, 0x28, 0x01, 0x4b, 0x01, 0x49, 0x00, 0x17, 0x00, 0x41, 0x04,
+    0x0f, 0x00, 0x28, 0x01, 0x4b, 0x01, 0x49, 0x00, 0x17, 0x00, 0x41, 0x04,
     0xbf, 0x31, 0xb4, 0x29, 0x96, 0xf4, 0xe6, 0x4a, 0xe3, 0xea, 0x87, 0x05,
     0x38, 0x0e, 0x68, 0x02, 0xbc, 0x4a, 0x5d, 0x90, 0xed, 0xe7, 0xaa, 0x8e,
     0xb8, 0x42, 0x84, 0xaa, 0x3a, 0x4f, 0x2b, 0xe3, 0x52, 0x9a, 0x9a, 0x76,
     0xab, 0xf8, 0x2e, 0x59, 0xea, 0xcd, 0x2b, 0x2f, 0x03, 0x18, 0xd2, 0x0c,
     0xc9, 0x07, 0x15, 0xca, 0xe6, 0x61, 0xf7, 0x79, 0x9f, 0xfe, 0xc5, 0x10,
     0x40, 0x9e, 0x38, 0x33, 0x01, 0x00, 0x01, 0x00, 0xd8, 0x80, 0x1f, 0x06,
     0x9a, 0xbb, 0xf7, 0xbb, 0xd4, 0x5c, 0x75, 0x1d, 0x8e, 0x09, 0x27, 0xad,
     0x08, 0xb8, 0x16, 0x0f, 0x4f, 0x50, 0x79, 0xe1, 0x7e, 0xd4, 0x3b, 0xc0,
@@ -60,27 +60,26 @@ const static uint8_t kCannedTls13ClientH
     0xc8, 0x1b, 0xfe, 0xb4, 0x98, 0xed, 0xa4, 0xa0, 0xee, 0xf9, 0x53, 0x74,
     0x30, 0xac, 0x79, 0x2d, 0xf2, 0x92, 0xd0, 0x5e, 0x10, 0xd7, 0xb9, 0x41,
     0x00, 0x0d, 0x00, 0x18, 0x00, 0x16, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01,
     0x02, 0x01, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02, 0x03, 0x05, 0x02,
     0x04, 0x02, 0x02, 0x02, 0x00, 0x15, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
 const static uint8_t kCannedTls13ServerHello[] = {
-    0x03, 0x04, 0xe9, 0x01, 0xa0, 0x81, 0x37, 0x97, 0xaa, 0x8c, 0x7e, 0x21,
-    0x1c, 0x66, 0x3f, 0xa4, 0x0f, 0x4d, 0x74, 0x7a, 0xcd, 0x4b, 0xe1, 0x7f,
-    0x37, 0x85, 0x14, 0xb5, 0x7e, 0x30, 0x15, 0x91, 0xdf, 0x18, 0xc0, 0x2f,
-    0x00, 0x49, 0x00, 0x28, 0x00, 0x45, 0x00, 0x17, 0x00, 0x41, 0x04, 0x1a,
-    0x53, 0x9b, 0x39, 0xe6, 0xda, 0x66, 0xfc, 0x8a, 0x75, 0x68, 0xb7, 0x73,
-    0xc7, 0x21, 0x1f, 0x01, 0x04, 0x54, 0xb4, 0x99, 0x1f, 0x0b, 0x7e, 0xea,
-    0x95, 0xec, 0x78, 0x5c, 0x37, 0x7c, 0x31, 0x56, 0x04, 0xc8, 0xbf, 0x79,
-    0x47, 0x56, 0xb9, 0x87, 0x06, 0xc1, 0xfc, 0x63, 0x09, 0x5d, 0xfc, 0x1a,
-    0x9e, 0x2b, 0xb9, 0xca, 0xdb, 0x0e, 0x10, 0xec, 0xd5, 0x95, 0x0d, 0x0a,
-    0x5e, 0x3c, 0xf7};
-
+    0x03, 0x04, 0x21, 0x12, 0xa7, 0xa7, 0x0d, 0x85, 0x8b, 0xb8, 0x0c, 0xbb,
+    0xdc, 0xa6, 0xfd, 0x97, 0xfe, 0x31, 0x26, 0x49, 0x2d, 0xa8, 0x6c, 0x7b,
+    0x65, 0x30, 0x71, 0x00, 0x31, 0x03, 0x2b, 0x94, 0xe2, 0x16, 0x13, 0x01,
+    0x00, 0x4d, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x28, 0x00, 0x45, 0x00, 0x17,
+    0x00, 0x41, 0x04, 0x10, 0x97, 0x3d, 0x7a, 0xcf, 0xa2, 0x34, 0xe3, 0x69,
+    0xc4, 0xdd, 0x1e, 0xf2, 0xd6, 0xc0, 0x9a, 0x3e, 0xf5, 0x41, 0xf3, 0x03,
+    0x23, 0x94, 0xd2, 0x31, 0x85, 0xb7, 0xae, 0x5d, 0xfa, 0xc6, 0x9a, 0xd0,
+    0xa5, 0x44, 0xa3, 0x3a, 0xe0, 0xbb, 0x61, 0xaa, 0x0a, 0x6f, 0xe8, 0xaf,
+    0xdf, 0x86, 0xd8, 0x48, 0x36, 0x9c, 0x19, 0x70, 0x55, 0x84, 0xb0, 0x1c,
+    0x8d, 0xfc, 0x6e, 0xd8, 0x86, 0xc3, 0x95};
 static const char *k0RttData = "ABCDEF";
 
 TEST_P(TlsAgentTest, EarlyFinished) {
   DataBuffer buffer;
   MakeTrivialHandshakeRecord(kTlsHandshakeFinished, 0, &buffer);
   ProcessMessage(buffer, TlsAgent::STATE_ERROR,
                  SSL_ERROR_RX_UNEXPECTED_FINISHED);
 }
--- a/security/nss/external_tests/ssl_gtest/ssl_ciphersuite_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_ciphersuite_unittest.cc
@@ -18,190 +18,135 @@ extern "C" {
 
 #include "gtest_utils.h"
 #include "tls_connect.h"
 #include "tls_parser.h"
 
 namespace nss_test {
 
 // mode, version, cipher suite
-typedef std::tuple<std::string, uint16_t, uint16_t> CipherSuiteProfile;
+typedef std::tuple<std::string, uint16_t, uint16_t, SSLNamedGroup,
+                   TlsSignatureScheme>
+    CipherSuiteProfile;
 
 class TlsCipherSuiteTestBase : public TlsConnectTestBase {
  public:
   TlsCipherSuiteTestBase(std::string mode, uint16_t version,
-                         uint16_t cipher_suite)
+                         uint16_t cipher_suite, SSLNamedGroup group,
+                         TlsSignatureScheme signature_scheme)
       : TlsConnectTestBase(TlsConnectTestBase::ToMode(mode), version),
         cipher_suite_(cipher_suite),
+        group_(group),
+        signature_scheme_(signature_scheme),
         csinfo_({0}) {
     SECStatus rv =
         SSL_GetCipherSuiteInfo(cipher_suite_, &csinfo_, sizeof(csinfo_));
     EXPECT_EQ(SECSuccess, rv);
     if (rv == SECSuccess) {
       std::cerr << "Cipher suite: " << csinfo_.cipherSuiteName << std::endl;
     }
+    auth_type_ = csinfo_.authType;
+    kea_type_ = csinfo_.keaType;
   }
 
  protected:
-  uint16_t cipher_suite_;
-  SSLCipherSuiteInfo csinfo_;
-
-  void SetupCertificate() {
-    switch (csinfo_.authType) {
-      case ssl_auth_rsa_sign:
-        Reset(TlsAgent::kServerRsaSign);
-        break;
-      case ssl_auth_rsa_decrypt:
-        Reset(TlsAgent::kServerRsaDecrypt);
-        break;
-      case ssl_auth_ecdsa:
-        Reset(TlsAgent::kServerEcdsa256);
-        break;
-      case ssl_auth_ecdh_ecdsa:
-        Reset(TlsAgent::kServerEcdhEcdsa);
-        break;
-      case ssl_auth_ecdh_rsa:
-        Reset(TlsAgent::kServerEcdhRsa);
-        break;
-      case ssl_auth_dsa:
-        Reset(TlsAgent::kServerDsa);
-        break;
-      default:
-        ASSERT_TRUE(false) << "Unsupported cipher suite: " << cipher_suite_;
-        break;
-    }
-  }
-
   void EnableSingleCipher() {
     EnsureTlsSetup();
     // It doesn't matter which does this, but the test is better if both do it.
     client_->EnableSingleCipher(cipher_suite_);
     server_->EnableSingleCipher(cipher_suite_);
+
+    if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
+      client_->ConfigNamedGroups(&group_, 1);
+      server_->ConfigNamedGroups(&group_, 1);
+      kea_type_ = SSLInt_GetKEAType(group_);
+
+      SSLSignatureAndHashAlg signature_scheme = {
+          static_cast<SSLHashType>(signature_scheme_ >> 8),
+          static_cast<SSLSignType>(signature_scheme_ & 0xff)};
+      client_->SetSignatureAlgorithms(&signature_scheme, 1);
+      server_->SetSignatureAlgorithms(&signature_scheme, 1);
+    }
+  }
+
+  virtual void SetupCertificate() {
+    if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
+      switch (signature_scheme_) {
+        case kTlsSignatureRsaPkcs1Sha256:
+        case kTlsSignatureRsaPkcs1Sha384:
+        case kTlsSignatureRsaPkcs1Sha512:
+          Reset(TlsAgent::kServerRsaSign);
+          auth_type_ = ssl_auth_rsa_sign;
+          break;
+        case kTlsSignatureRsaPssSha256:
+        case kTlsSignatureRsaPssSha384:
+          Reset(TlsAgent::kServerRsaSign);
+          auth_type_ = ssl_auth_rsa_sign;
+          break;
+        case kTlsSignatureRsaPssSha512:
+          // You can't fit SHA-512 PSS in a 1024-bit key.
+          Reset(TlsAgent::kRsa2048);
+          auth_type_ = ssl_auth_rsa_sign;
+          break;
+        case kTlsSignatureEcdsaSecp256r1Sha256:
+          Reset(TlsAgent::kServerEcdsa256);
+          auth_type_ = ssl_auth_ecdsa;
+          break;
+        case kTlsSignatureEcdsaSecp384r1Sha384:
+          Reset(TlsAgent::kServerEcdsa384);
+          auth_type_ = ssl_auth_ecdsa;
+          break;
+        default:
+          ASSERT_TRUE(false) << "Unsupported signature scheme: "
+                             << signature_scheme_;
+          break;
+      }
+    } else {
+      switch (csinfo_.authType) {
+        case ssl_auth_rsa_sign:
+          Reset(TlsAgent::kServerRsaSign);
+          break;
+        case ssl_auth_rsa_decrypt:
+          Reset(TlsAgent::kServerRsaDecrypt);
+          break;
+        case ssl_auth_ecdsa:
+          Reset(TlsAgent::kServerEcdsa256);
+          break;
+        case ssl_auth_ecdh_ecdsa:
+          Reset(TlsAgent::kServerEcdhEcdsa);
+          break;
+        case ssl_auth_ecdh_rsa:
+          Reset(TlsAgent::kServerEcdhRsa);
+          break;
+        case ssl_auth_dsa:
+          Reset(TlsAgent::kServerDsa);
+          break;
+        default:
+          ASSERT_TRUE(false) << "Unsupported cipher suite: " << cipher_suite_;
+          break;
+      }
+    }
   }
 
   void ConnectAndCheckCipherSuite() {
     Connect();
     SendReceive();
 
     // Check that we used the right cipher suite.
     uint16_t actual;
     EXPECT_TRUE(client_->cipher_suite(&actual) && actual == cipher_suite_);
     EXPECT_TRUE(server_->cipher_suite(&actual) && actual == cipher_suite_);
-  }
-};
-
-class TlsCipherSuiteTest
-    : public TlsCipherSuiteTestBase,
-      public ::testing::WithParamInterface<CipherSuiteProfile> {
- public:
-  TlsCipherSuiteTest()
-      : TlsCipherSuiteTestBase(std::get<0>(GetParam()), std::get<1>(GetParam()),
-                               std::get<2>(GetParam())) {}
-};
-
-TEST_P(TlsCipherSuiteTest, SingleCipherSuite) {
-  SetupCertificate();
-  EnableSingleCipher();
-  ConnectAndCheckCipherSuite();
-}
-
-class TlsResumptionTest
-    : public TlsCipherSuiteTestBase,
-      public ::testing::WithParamInterface<CipherSuiteProfile> {
- public:
-  TlsResumptionTest()
-      : TlsCipherSuiteTestBase(std::get<0>(GetParam()), std::get<1>(GetParam()),
-                               std::get<2>(GetParam())) {}
-
-  bool SkipIfCipherSuiteIsDSA() {
-    bool isDSA = csinfo_.authType == ssl_auth_dsa;
-    if (isDSA) {
-      std::cerr << "Skipping DSA suite: " << csinfo_.cipherSuiteName
-                << std::endl;
-    }
-    return isDSA;
+    SSLAuthType auth;
+    EXPECT_TRUE(client_->auth_type(&auth) && auth == auth_type_);
+    EXPECT_TRUE(server_->auth_type(&auth) && auth == auth_type_);
+    SSLKEAType kea;
+    EXPECT_TRUE(client_->kea_type(&kea) && kea == kea_type_);
+    EXPECT_TRUE(server_->kea_type(&kea) && kea == kea_type_);
   }
 
-  void EnablePskCipherSuite() {
-    SSLKEAType targetKea;
-    switch (csinfo_.keaType) {
-      case ssl_kea_ecdh:
-        targetKea = ssl_kea_ecdh_psk;
-        break;
-      case ssl_kea_dh:
-        targetKea = ssl_kea_dh_psk;
-        break;
-      default:
-        EXPECT_TRUE(false) << "Unsupported KEA type for "
-                           << csinfo_.cipherSuiteName;
-        return;
-    }
-
-    size_t count = SSL_GetNumImplementedCiphers();
-    const uint16_t *ciphers = SSL_GetImplementedCiphers();
-    bool found = false;
-    for (size_t i = 0; i < count; ++i) {
-      SSLCipherSuiteInfo candidateInfo;
-      ASSERT_EQ(SECSuccess, SSL_GetCipherSuiteInfo(ciphers[i], &candidateInfo,
-                                                   sizeof(candidateInfo)));
-      if (candidateInfo.authType == ssl_auth_psk &&
-          candidateInfo.keaType == targetKea &&
-          candidateInfo.symCipher == csinfo_.symCipher &&
-          candidateInfo.macAlgorithm == csinfo_.macAlgorithm) {
-        // We aren't able to check that the PRF hash is the same.  This is OK
-        // because there are (currently) no suites that have different PRF
-        // hashes but also use the same symmetric cipher.
-        EXPECT_EQ(SECSuccess,
-                  SSL_CipherPrefSet(client_->ssl_fd(), ciphers[i], PR_TRUE));
-        EXPECT_EQ(SECSuccess,
-                  SSL_CipherPrefSet(server_->ssl_fd(), ciphers[i], PR_TRUE));
-        found = true;
-      }
-    }
-    EXPECT_TRUE(found) << "Can't find matching PSK cipher for "
-                       << csinfo_.cipherSuiteName;
-  }
-};
-
-TEST_P(TlsResumptionTest, ResumeCipherSuite) {
-  if (SkipIfCipherSuiteIsDSA()) {
-    return;  // Tickets don't work with DSA (bug 1174677).
-  }
-
-  SetupCertificate();  // This is only needed once.
-
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  EnableSingleCipher();
-
-  ConnectAndCheckCipherSuite();
-
-  Reset();
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  EnableSingleCipher();
-  // Enable a PSK cipher suite, since EnableSingleCipher() disabled all of them.
-  // On resumption in TLS 1.3, even though a PSK cipher suite is negotiated, the
-  // original cipher suite is reported through the API.  That is what makes this
-  // test work without more tweaks.
-  if (version_ == SSL_LIBRARY_VERSION_TLS_1_3) {
-    EnablePskCipherSuite();
-  }
-
-  ExpectResumption(RESUME_TICKET);
-  ConnectAndCheckCipherSuite();
-}
-
-class TlsCipherLimitTest
-    : public TlsCipherSuiteTestBase,
-      public ::testing::WithParamInterface<CipherSuiteProfile> {
- public:
-  TlsCipherLimitTest()
-      : TlsCipherSuiteTestBase(std::get<0>(GetParam()), std::get<1>(GetParam()),
-                               std::get<2>(GetParam())) {}
-
- protected:
   // Get the expected limit on the number of records that can be sent for the
   // cipher suite.
   uint64_t record_limit() const {
     switch (csinfo_.symCipher) {
       case ssl_calg_rc4:
       case ssl_calg_3des:
         return 1ULL << 20;
       case ssl_calg_aes:
@@ -227,24 +172,77 @@ class TlsCipherLimitTest
     if (version_ < SSL_LIBRARY_VERSION_TLS_1_1 &&
         (csinfo_.symCipher == ssl_calg_3des ||
          csinfo_.symCipher == ssl_calg_aes)) {
       // 1/n-1 record splitting needs space for two records.
       limit--;
     }
     return limit;
   }
+
+ protected:
+  uint16_t cipher_suite_;
+  SSLAuthType auth_type_;
+  SSLKEAType kea_type_;
+  SSLNamedGroup group_;
+  TlsSignatureScheme signature_scheme_;
+  SSLCipherSuiteInfo csinfo_;
 };
 
+class TlsCipherSuiteTest
+    : public TlsCipherSuiteTestBase,
+      public ::testing::WithParamInterface<CipherSuiteProfile> {
+ public:
+  TlsCipherSuiteTest()
+      : TlsCipherSuiteTestBase(std::get<0>(GetParam()), std::get<1>(GetParam()),
+                               std::get<2>(GetParam()), std::get<3>(GetParam()),
+                               std::get<4>(GetParam())) {}
+
+ protected:
+  bool SkipIfCipherSuiteIsDSA() {
+    bool isDSA = csinfo_.authType == ssl_auth_dsa;
+    if (isDSA) {
+      std::cerr << "Skipping DSA suite: " << csinfo_.cipherSuiteName
+                << std::endl;
+    }
+    return isDSA;
+  }
+};
+
+TEST_P(TlsCipherSuiteTest, SingleCipherSuite) {
+  SetupCertificate();
+  EnableSingleCipher();
+  ConnectAndCheckCipherSuite();
+}
+
+TEST_P(TlsCipherSuiteTest, ResumeCipherSuite) {
+  if (SkipIfCipherSuiteIsDSA()) {
+    return;  // Tickets don't work with DSA (bug 1174677).
+  }
+
+  SetupCertificate();  // This is only needed once.
+
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  EnableSingleCipher();
+
+  ConnectAndCheckCipherSuite();
+
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  EnableSingleCipher();
+  ExpectResumption(RESUME_TICKET);
+  ConnectAndCheckCipherSuite();
+}
+
 // This only works for stream ciphers because we modify the sequence number -
 // which is included explicitly in the DTLS record header - and that trips a
 // different error code.  Note that the message that the client sends would not
 // decrypt (the nonce/IV wouldn't match), but the record limit is hit before
 // attempting to decrypt a record.
-TEST_P(TlsCipherLimitTest, ReadLimit) {
+TEST_P(TlsCipherSuiteTest, ReadLimit) {
   SetupCertificate();
   EnableSingleCipher();
   ConnectAndCheckCipherSuite();
   EXPECT_EQ(SECSuccess,
             SSLInt_AdvanceWriteSeqNum(client_->ssl_fd(), last_safe_write()));
   EXPECT_EQ(SECSuccess,
             SSLInt_AdvanceReadSeqNum(server_->ssl_fd(), last_safe_write()));
 
@@ -267,96 +265,117 @@ TEST_P(TlsCipherLimitTest, ReadLimit) {
                                payload, sizeof(payload), &record,
                                (epoch << 48) | record_limit());
   server_->adapter()->PacketReceived(record);
   server_->ExpectReadWriteError();
   server_->ReadBytes();
   EXPECT_EQ(SSL_ERROR_TOO_MANY_RECORDS, server_->error_code());
 }
 
-TEST_P(TlsCipherLimitTest, WriteLimit) {
+TEST_P(TlsCipherSuiteTest, WriteLimit) {
   SetupCertificate();
   EnableSingleCipher();
   ConnectAndCheckCipherSuite();
   EXPECT_EQ(SECSuccess,
             SSLInt_AdvanceWriteSeqNum(client_->ssl_fd(), last_safe_write()));
   client_->SendData(10, 10);
   client_->ExpectReadWriteError();
   client_->SendData(10, 10);
   EXPECT_EQ(SSL_ERROR_TOO_MANY_RECORDS, client_->error_code());
 }
 
 // This awful macro makes the test instantiations easier to read.
-#define INSTANTIATE_CIPHER_TEST_P(name, modes, versions, ...)      \
-  static const uint16_t k##name##CiphersArr[] = {__VA_ARGS__};     \
-  static const ::testing::internal::ParamGenerator<uint16_t>       \
-      k##name##Ciphers = ::testing::ValuesIn(k##name##CiphersArr); \
-  INSTANTIATE_TEST_CASE_P(                                         \
-      CipherSuite##name, TlsCipherSuiteTest,                       \
-      ::testing::Combine(TlsConnectTestBase::kTlsModes##modes,     \
-                         TlsConnectTestBase::kTls##versions,       \
-                         k##name##Ciphers));                       \
-  INSTANTIATE_TEST_CASE_P(                                         \
-      Resume##name, TlsResumptionTest,                             \
-      ::testing::Combine(TlsConnectTestBase::kTlsModes##modes,     \
-                         TlsConnectTestBase::kTls##versions,       \
-                         k##name##Ciphers));                       \
-  INSTANTIATE_TEST_CASE_P(                                         \
-      Limit##name, TlsCipherLimitTest,                             \
-      ::testing::Combine(TlsConnectTestBase::kTlsModes##modes,     \
-                         TlsConnectTestBase::kTls##versions,       \
-                         k##name##Ciphers))
+#define INSTANTIATE_CIPHER_TEST_P(name, modes, versions, groups, sigalgs, ...) \
+  static const uint16_t k##name##CiphersArr[] = {__VA_ARGS__};                 \
+  static const ::testing::internal::ParamGenerator<uint16_t>                   \
+      k##name##Ciphers = ::testing::ValuesIn(k##name##CiphersArr);             \
+  INSTANTIATE_TEST_CASE_P(                                                     \
+      CipherSuite##name, TlsCipherSuiteTest,                                   \
+      ::testing::Combine(TlsConnectTestBase::kTlsModes##modes,                 \
+                         TlsConnectTestBase::kTls##versions, k##name##Ciphers, \
+                         groups, sigalgs));
 
-INSTANTIATE_CIPHER_TEST_P(RC4, Stream, V10ToV12, TLS_RSA_WITH_RC4_128_SHA,
+static const SSLNamedGroup kDummyNamedGroupParamsArr[] = {
+    static_cast<SSLNamedGroup>(0)};
+static const auto kDummyNamedGroupParams =
+    ::testing::ValuesIn(kDummyNamedGroupParamsArr);
+static const TlsSignatureScheme kDummySignatureSchemesParamsArr[] = {
+    kTlsSignatureNone};
+static const auto kDummySignatureSchemesParams =
+    ::testing::ValuesIn(kDummySignatureSchemesParamsArr);
+
+static TlsSignatureScheme kSignatureSchemesParamsArr[] = {
+    kTlsSignatureRsaPkcs1Sha256,       kTlsSignatureRsaPkcs1Sha384,
+    kTlsSignatureRsaPkcs1Sha512,       kTlsSignatureEcdsaSecp256r1Sha256,
+    kTlsSignatureEcdsaSecp384r1Sha384, kTlsSignatureRsaPssSha256,
+    kTlsSignatureRsaPssSha384,         kTlsSignatureRsaPssSha512,
+};
+
+INSTANTIATE_CIPHER_TEST_P(RC4, Stream, V10ToV12, kDummyNamedGroupParams,
+                          kDummySignatureSchemesParams,
+                          TLS_RSA_WITH_RC4_128_SHA,
                           TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
                           TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
                           TLS_ECDH_RSA_WITH_RC4_128_SHA,
                           TLS_ECDHE_RSA_WITH_RC4_128_SHA);
-INSTANTIATE_CIPHER_TEST_P(AEAD12, All, V12, TLS_RSA_WITH_AES_128_GCM_SHA256,
+INSTANTIATE_CIPHER_TEST_P(AEAD12, All, V12, kDummyNamedGroupParams,
+                          kDummySignatureSchemesParams,
+                          TLS_RSA_WITH_AES_128_GCM_SHA256,
                           TLS_RSA_WITH_AES_256_GCM_SHA384,
                           TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
                           TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,
                           TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
                           TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384);
-INSTANTIATE_CIPHER_TEST_P(AEAD, All, V12Plus,
+INSTANTIATE_CIPHER_TEST_P(AEAD, All, V12, kDummyNamedGroupParams,
+                          kDummySignatureSchemesParams,
                           TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                           TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
                           TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                           TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
                           TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
                           TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
                           TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
                           TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
                           TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
-INSTANTIATE_CIPHER_TEST_P(CBC12, All, V12, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
-                          TLS_RSA_WITH_AES_256_CBC_SHA256,
-                          TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
-                          TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
-                          TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
-                          TLS_RSA_WITH_AES_128_CBC_SHA256,
-                          TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
-                          TLS_DHE_DSS_WITH_AES_256_CBC_SHA256);
 INSTANTIATE_CIPHER_TEST_P(
-    CBCStream, Stream, V10ToV12, TLS_ECDH_ECDSA_WITH_NULL_SHA,
+    CBC12, All, V12, kDummyNamedGroupParams, kDummySignatureSchemesParams,
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA256,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+    TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
+    TLS_DHE_DSS_WITH_AES_256_CBC_SHA256);
+INSTANTIATE_CIPHER_TEST_P(
+    CBCStream, Stream, V10ToV12, kDummyNamedGroupParams,
+    kDummySignatureSchemesParams, TLS_ECDH_ECDSA_WITH_NULL_SHA,
     TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
     TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_NULL_SHA,
     TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
     TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_NULL_SHA,
     TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
     TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA,
     TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);
 INSTANTIATE_CIPHER_TEST_P(
-    CBCDatagram, Datagram, V11V12, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+    CBCDatagram, Datagram, V11V12, kDummyNamedGroupParams,
+    kDummySignatureSchemesParams, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
     TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
     TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
     TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
     TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
     TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);
+INSTANTIATE_CIPHER_TEST_P(TLS13, All, V13,
+                          ::testing::ValuesIn(kFasterDHEGroups),
+                          ::testing::ValuesIn(kSignatureSchemesParamsArr),
+                          TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256,
+                          TLS_AES_256_GCM_SHA384);
+INSTANTIATE_CIPHER_TEST_P(TLS13AllGroups, All, V13,
+                          ::testing::ValuesIn(kAllDHEGroups),
+                          ::testing::Values(kTlsSignatureEcdsaSecp384r1Sha384),
+                          TLS_AES_256_GCM_SHA384);
 
 // Fields are: version, cipher suite, bulk cipher name, secretKeySize
 struct SecStatusParams {
   uint16_t version;
   uint16_t cipher_suite;
   std::string name;
   int keySize;
 };
@@ -375,18 +394,19 @@ inline std::ostream &operator<<(std::ost
                 << "\", key size = " << vals.keySize;
 }
 
 class SecurityStatusTest
     : public TlsCipherSuiteTestBase,
       public ::testing::WithParamInterface<SecStatusParams> {
  public:
   SecurityStatusTest()
-      : TlsCipherSuiteTestBase("TLS", GetParam().version,
-                               GetParam().cipher_suite) {}
+      : TlsCipherSuiteTestBase(
+            "TLS", GetParam().version, GetParam().cipher_suite,
+            static_cast<SSLNamedGroup>(0), kTlsSignatureNone) {}
 };
 
 // SSL_SecurityStatus produces fairly useless output when compared to
 // SSL_GetCipherSuiteInfo and SSL_GetChannelInfo, but we can't break it, so we
 // need to check it.
 TEST_P(SecurityStatusTest, CheckSecurityStatus) {
   SetupCertificate();
   EnableSingleCipher();
--- a/security/nss/external_tests/ssl_gtest/ssl_dhe_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_dhe_unittest.cc
@@ -23,19 +23,17 @@ namespace nss_test {
 TEST_P(TlsConnectGeneric, ConnectDhe) {
   EnableOnlyDheCiphers();
   Connect();
   CheckKeys(ssl_kea_dh, ssl_auth_rsa_sign);
 }
 
 TEST_P(TlsConnectTls13, SharesForBothEcdheAndDhe) {
   EnsureTlsSetup();
-  client_->DisableAllCiphers();
-  client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
-  client_->EnableCiphersByKeyExchange(ssl_kea_dh);
+  client_->ConfigNamedGroups(kAllDHEGroups);
 
   auto groups_capture = new TlsExtensionCapture(ssl_supported_groups_xtn);
   auto shares_capture = new TlsExtensionCapture(ssl_tls13_key_share_xtn);
   std::vector<PacketFilter*> captures;
   captures.push_back(groups_capture);
   captures.push_back(shares_capture);
   client_->SetPacketFilter(new ChainedPacketFilter(captures));
 
@@ -52,36 +50,16 @@ TEST_P(TlsConnectTls13, SharesForBothEcd
     }
   };
   CheckGroups(groups_capture->extension(), track_group_type);
   CheckShares(shares_capture->extension(), track_group_type);
   EXPECT_TRUE(ec) << "Should include an EC group and share";
   EXPECT_TRUE(dh) << "Should include an FFDHE group and share";
 }
 
-TEST_P(TlsConnectTls13, NoDheOnEcdheConnections) {
-  EnsureTlsSetup();
-  client_->DisableAllCiphers();
-  client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
-
-  auto groups_capture = new TlsExtensionCapture(ssl_supported_groups_xtn);
-  auto shares_capture = new TlsExtensionCapture(ssl_tls13_key_share_xtn);
-  std::vector<PacketFilter*> captures;
-  captures.push_back(groups_capture);
-  captures.push_back(shares_capture);
-  client_->SetPacketFilter(new ChainedPacketFilter(captures));
-
-  Connect();
-
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-  auto is_ecc = [](SSLNamedGroup group) { EXPECT_NE(0x100U, group & 0xff00U); };
-  CheckGroups(groups_capture->extension(), is_ecc);
-  CheckShares(shares_capture->extension(), is_ecc);
-}
-
 TEST_P(TlsConnectGeneric, ConnectFfdheClient) {
   EnableOnlyDheCiphers();
   EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
                                       SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE));
   auto groups_capture = new TlsExtensionCapture(ssl_supported_groups_xtn);
   auto shares_capture = new TlsExtensionCapture(ssl_tls13_key_share_xtn);
   std::vector<PacketFilter*> captures;
   captures.push_back(groups_capture);
--- a/security/nss/external_tests/ssl_gtest/ssl_drop_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_drop_unittest.cc
@@ -60,24 +60,40 @@ TEST_P(TlsConnectDatagram, DropClientSec
 }
 
 // This drops the server's second flight three times.
 TEST_P(TlsConnectDatagram, DropServerSecondFlightThrice) {
   server_->SetPacketFilter(new SelectiveDropFilter(0xe));
   Connect();
 }
 
+static void GetCipherAndLimit(uint16_t version, uint16_t* cipher,
+                              uint64_t* limit = nullptr) {
+  uint64_t l;
+  if (!limit) limit = &l;
+
+  if (version < SSL_LIBRARY_VERSION_TLS_1_2) {
+    *cipher = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
+    *limit = 0x5aULL << 28;
+  } else if (version == SSL_LIBRARY_VERSION_TLS_1_2) {
+    *cipher = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
+    *limit = (1ULL << 48) - 1;
+  } else {
+    *cipher = TLS_CHACHA20_POLY1305_SHA256;
+    *limit = (1ULL << 48) - 1;
+  }
+}
+
 // This simulates a huge number of drops on one side.
 TEST_P(TlsConnectDatagram, MissLotsOfPackets) {
-  uint16_t cipher = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
-  uint64_t limit = (1ULL << 48) - 1;
-  if (version_ < SSL_LIBRARY_VERSION_TLS_1_2) {
-    cipher = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
-    limit = 0x5aULL << 28;
-  }
+  uint16_t cipher;
+  uint64_t limit;
+
+  GetCipherAndLimit(version_, &cipher, &limit);
+
   EnsureTlsSetup();
   server_->EnableSingleCipher(cipher);
   Connect();
 
   // Note that the limit for ChaCha is 2^48-1.
   EXPECT_EQ(SECSuccess,
             SSLInt_AdvanceWriteSeqNum(client_->ssl_fd(), limit - 10));
   SendReceive();
@@ -86,26 +102,30 @@ TEST_P(TlsConnectDatagram, MissLotsOfPac
 class TlsConnectDatagram12Plus : public TlsConnectDatagram {
  public:
   TlsConnectDatagram12Plus() : TlsConnectDatagram() {}
 };
 
 // This simulates missing a window's worth of packets.
 TEST_P(TlsConnectDatagram12Plus, MissAWindow) {
   EnsureTlsSetup();
-  server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
+  uint16_t cipher;
+  GetCipherAndLimit(version_, &cipher);
+  server_->EnableSingleCipher(cipher);
   Connect();
 
   EXPECT_EQ(SECSuccess, SSLInt_AdvanceWriteSeqByAWindow(client_->ssl_fd(), 0));
   SendReceive();
 }
 
 TEST_P(TlsConnectDatagram12Plus, MissAWindowAndOne) {
   EnsureTlsSetup();
-  server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
+  uint16_t cipher;
+  GetCipherAndLimit(version_, &cipher);
+  server_->EnableSingleCipher(cipher);
   Connect();
 
   EXPECT_EQ(SECSuccess, SSLInt_AdvanceWriteSeqByAWindow(client_->ssl_fd(), 1));
   SendReceive();
 }
 
 INSTANTIATE_TEST_CASE_P(Datagram12Plus, TlsConnectDatagram12Plus,
                         TlsConnectTestBase::kTlsV12Plus);
--- a/security/nss/external_tests/ssl_gtest/ssl_ecdh_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_ecdh_unittest.cc
@@ -44,19 +44,20 @@ TEST_P(TlsConnectGenericPre13, ConnectEc
 }
 
 TEST_P(TlsConnectGeneric, ConnectEcdhe) {
   Connect();
   CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
 }
 
 // If we pick a 256-bit cipher suite and use a P-384 certificate, the server
-// should choose P-384 for key exchange too.  Only valid for TLS >=1.2 because
-// we don't have 256-bit ciphers before then.
-TEST_P(TlsConnectTls12Plus, ConnectEcdheP384) {
+// should choose P-384 for key exchange too.  Only valid for TLS == 1.2 because
+// we don't have 256-bit ciphers before then and 1.3 doesn't try to couple
+// DHE size to symmetric size.
+TEST_P(TlsConnectTls12, ConnectEcdheP384) {
   Reset(TlsAgent::kServerEcdsa384);
   ConnectWithCipherSuite(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);
   CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa, 384);
 }
 
 TEST_P(TlsConnectGeneric, ConnectEcdheP384Client) {
   EnsureTlsSetup();
   const SSLNamedGroup groups[] = {ssl_grp_ec_secp384r1, ssl_grp_ffdhe_2048};
@@ -250,16 +251,37 @@ TEST_P(TlsConnectGenericPre13, P384Prior
   client_model_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
   server_model_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
 
   Connect();
 
   CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign, 384);
 }
 
+// If we only have a lame group, we fall back to static RSA.
+TEST_P(TlsConnectGenericPre13, UseLameGroup) {
+  static const SSLNamedGroup groups[] = {ssl_grp_ec_secp192r1};
+  client_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
+  server_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
+  Connect();
+  CheckKeys(ssl_kea_rsa, ssl_auth_rsa_decrypt);
+}
+
+// In TLS 1.3, we can't generate the ClientHello.
+TEST_P(TlsConnectTls13, UseLameGroup) {
+  static const SSLNamedGroup groups[] = {ssl_grp_ec_sect283k1};
+  client_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
+  server_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
+  client_->StartConnect();
+  client_->Handshake();
+#ifndef NSS_ECC_MORE_THAN_SUITE_B  // TODO: remove this guard
+  client_->CheckErrorCode(SSL_ERROR_NO_CIPHERS_SUPPORTED);
+#endif
+}
+
 TEST_P(TlsConnectStreamPre13, ConfiguredGroupsRenegotiate) {
   EnsureTlsSetup();
   client_->DisableAllCiphers();
   client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
 
   const SSLNamedGroup serverGroups[] = {ssl_grp_ec_secp256r1,
                                         ssl_grp_ec_secp384r1};
   const SSLNamedGroup clientGroups[] = {ssl_grp_ec_secp384r1};
@@ -273,16 +295,48 @@ TEST_P(TlsConnectStreamPre13, Configured
 
   // The renegotiation has to use the same preferences as the original session.
   server_->PrepareForRenegotiate();
   client_->StartRenegotiate();
   Handshake();
   CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign, 384);
 }
 
+TEST_P(TlsKeyExchangeTest, Curve25519) {
+  Reset(TlsAgent::kServerEcdsa256);
+  const SSLNamedGroup groups[] = {ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1,
+                                  ssl_grp_ec_secp521r1};
+  EnsureKeyShareSetup(groups, PR_ARRAY_SIZE(groups));
+  Connect();
+
+  CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa, 255);
+  std::vector<SSLNamedGroup> shares = {ssl_grp_ec_curve25519};
+  std::vector<SSLNamedGroup> expected_groups(groups,
+                                             groups + PR_ARRAY_SIZE(groups));
+  CheckKEXDetails(expected_groups, shares);
+}
+
+TEST_P(TlsConnectGeneric, P256andCurve25519OnlyServer) {
+  EnsureTlsSetup();
+  client_->DisableAllCiphers();
+  client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
+
+  // the client sends a P256 key share while the server prefers 25519
+  const SSLNamedGroup serverGroups[] = {ssl_grp_ec_curve25519,
+                                        ssl_grp_ec_secp256r1};
+  const SSLNamedGroup clientGroups[] = {ssl_grp_ec_secp256r1,
+                                        ssl_grp_ec_curve25519};
+  client_->ConfigNamedGroups(clientGroups, PR_ARRAY_SIZE(clientGroups));
+  server_->ConfigNamedGroups(serverGroups, PR_ARRAY_SIZE(serverGroups));
+
+  Connect();
+
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign, 255);
+}
+
 // Replace the point in the client key exchange message with an empty one
 class ECCClientKEXFilter : public TlsHandshakeFilter {
  public:
   ECCClientKEXFilter() {}
 
  protected:
   virtual PacketFilter::Action FilterHandshake(const HandshakeHeader &header,
                                                const DataBuffer &input,
--- a/security/nss/external_tests/ssl_gtest/ssl_ems_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_ems_unittest.cc
@@ -21,17 +21,17 @@ TEST_P(TlsConnectGenericPre13, ConnectEx
   EnableExtendedMasterSecret();
   Connect();
   Reset();
   ExpectResumption(RESUME_SESSIONID);
   EnableExtendedMasterSecret();
   Connect();
 }
 
-TEST_P(TlsConnectTls12Plus, ConnectExtendedMasterSecretSha384) {
+TEST_P(TlsConnectTls12, ConnectExtendedMasterSecretSha384) {
   EnableExtendedMasterSecret();
   server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
   ConnectWithCipherSuite(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
 }
 
 TEST_P(TlsConnectGenericPre13, ConnectExtendedMasterSecretStaticRSA) {
   EnableOnlyStaticRsaCiphers();
   EnableExtendedMasterSecret();
--- a/security/nss/external_tests/ssl_gtest/ssl_extension_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_extension_unittest.cc
@@ -537,28 +537,198 @@ TEST_P(TlsExtensionTest13, ModifyDraftVe
   // As above, dropping back to 1.2 fails.
   client_->SetPacketFilter(
       new TlsExtensionDamager(ssl_tls13_draft_version_xtn, 1));
   ConnectExpectFail();
   EXPECT_EQ(SSL_ERROR_PROTOCOL_VERSION_ALERT, client_->error_code());
   EXPECT_EQ(SSL_ERROR_UNSUPPORTED_VERSION, server_->error_code());
 }
 
-// This test only works in stream mode because the MAC error causes a timeout on
-// the server with datagram.
+// These tests only work in stream mode because the client sends a
+// cleartext alert which causes a MAC error on the server. With
+// stream this causes handshake failure but with datagram, the
+// packet gets dropped.
 TEST_F(TlsExtensionTest13Stream, DropServerKeyShare) {
   EnsureTlsSetup();
   server_->SetPacketFilter(new TlsExtensionDropper(ssl_tls13_key_share_xtn));
   ConnectExpectFail();
   EXPECT_EQ(SSL_ERROR_MISSING_KEY_SHARE, client_->error_code());
-  // We are trying to decrypt but we can't. Kind of a screwy error
-  // from the TLS 1.3 stack.
+  EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
+}
+
+TEST_F(TlsExtensionTest13Stream, DropServerSignatureAlgorithms) {
+  EnsureTlsSetup();
+  server_->SetPacketFilter(
+      new TlsExtensionDropper(ssl_signature_algorithms_xtn));
+  ConnectExpectFail();
+  EXPECT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
+  EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
+}
+
+TEST_F(TlsExtensionTest13Stream, NonEmptySignatureAlgorithms) {
+  EnsureTlsSetup();
+  DataBuffer sig_algs;
+  size_t index = 0;
+  index = sig_algs.Write(index, 2, 2);
+  index = sig_algs.Write(index, kTlsSignatureRsaPssSha256, 2);
+  server_->SetPacketFilter(
+      new TlsExtensionReplacer(ssl_signature_algorithms_xtn, sig_algs));
+  ConnectExpectFail();
+  EXPECT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
+  EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
+}
+
+TEST_F(TlsExtensionTest13Stream, AddServerSignatureAlgorithmsOnResumption) {
+  SetupForResume();
+  DataBuffer empty;
+  server_->SetPacketFilter(
+      new TlsExtensionInjector(ssl_signature_algorithms_xtn, empty));
+  ConnectExpectFail();
+  EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_EXTENSION, client_->error_code());
   EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
 }
 
+class TlsPreSharedKeyReplacer : public TlsExtensionFilter {
+ public:
+  TlsPreSharedKeyReplacer(const uint8_t* psk, size_t psk_len,
+                          const uint8_t* ke_modes, size_t ke_modes_len,
+                          const uint8_t* auth_modes, size_t auth_modes_len) {
+    if (psk) {
+      psk_.reset(new DataBuffer(psk, psk_len));
+    }
+    if (ke_modes) {
+      ke_modes_.reset(new DataBuffer(ke_modes, ke_modes_len));
+    }
+    if (auth_modes) {
+      auth_modes_.reset(new DataBuffer(auth_modes, auth_modes_len));
+    }
+  }
+
+  static size_t CopyAndMaybeReplace(TlsParser* parser, size_t size,
+                                    const std::unique_ptr<DataBuffer>& replace,
+                                    size_t index, DataBuffer* output) {
+    DataBuffer tmp;
+    bool ret = parser->ReadVariable(&tmp, size);
+    EXPECT_EQ(true, ret);
+    if (!ret) return 0;
+    if (replace) {
+      tmp = *replace;
+    }
+
+    return WriteVariable(output, index, tmp, size);
+    ;
+  }
+
+  PacketFilter::Action FilterExtension(uint16_t extension_type,
+                                       const DataBuffer& input,
+                                       DataBuffer* output) {
+    if (extension_type != ssl_tls13_pre_shared_key_xtn) {
+      return KEEP;
+    }
+
+    TlsParser parser(input);
+    uint32_t len;          // Length of the overall vector.
+    parser.Read(&len, 2);  // We only allow one entry.
+    EXPECT_EQ(parser.remaining(), len);
+    if (len != parser.remaining()) {
+      return DROP;
+    }
+    DataBuffer buf;
+    size_t index = 0;
+    index = CopyAndMaybeReplace(&parser, 1, ke_modes_, index, &buf);
+    if (!index) {
+      return DROP;
+    }
+
+    index = CopyAndMaybeReplace(&parser, 1, auth_modes_, index, &buf);
+    if (!index) {
+      return DROP;
+    }
+
+    index = CopyAndMaybeReplace(&parser, 2, psk_, index, &buf);
+    if (!index) {
+      return DROP;
+    }
+
+    output->Truncate(0);
+    WriteVariable(output, 0, buf, 2);
+
+    return CHANGE;
+  }
+
+ private:
+  std::unique_ptr<DataBuffer> psk_;
+  std::unique_ptr<DataBuffer> ke_modes_;
+  std::unique_ptr<DataBuffer> auth_modes_;
+};
+
+// The following three tests produce bogus (ill-formatted) PreSharedKey
+// extensions so generate errors.
+TEST_F(TlsExtensionTest13Stream, ResumeEmptyPskLabel) {
+  SetupForResume();
+  const static uint8_t psk[1] = {0};
+
+  DataBuffer empty;
+  client_->SetPacketFilter(
+      new TlsPreSharedKeyReplacer(&psk[0], 0, nullptr, 0, nullptr, 0));
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+}
+
+TEST_F(TlsExtensionTest13Stream, ResumeNoKeModes) {
+  SetupForResume();
+  const static uint8_t ke_modes[1] = {0};
+
+  DataBuffer empty;
+  client_->SetPacketFilter(
+      new TlsPreSharedKeyReplacer(nullptr, 0, &ke_modes[0], 0, nullptr, 0));
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+}
+
+TEST_F(TlsExtensionTest13Stream, ResumeNoAuthModes) {
+  SetupForResume();
+  const static uint8_t auth_modes[1] = {0};
+
+  DataBuffer empty;
+  client_->SetPacketFilter(
+      new TlsPreSharedKeyReplacer(nullptr, 0, nullptr, 0, &auth_modes[0], 0));
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+}
+
+// The following two tests are valid but unacceptable PreSharedKey
+// modes and therefore produce non-resumption followed by MAC errors.
+TEST_F(TlsExtensionTest13Stream, ResumeBogusKeModes) {
+  SetupForResume();
+  const static uint8_t ke_modes = kTls13PskKe;
+
+  DataBuffer empty;
+  client_->SetPacketFilter(
+      new TlsPreSharedKeyReplacer(nullptr, 0, &ke_modes, 1, nullptr, 0));
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
+  server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
+}
+
+TEST_F(TlsExtensionTest13Stream, ResumeBogusAuthModes) {
+  SetupForResume();
+  const static uint8_t auth_modes = kTls13PskSignAuth;
+
+  DataBuffer empty;
+  client_->SetPacketFilter(
+      new TlsPreSharedKeyReplacer(nullptr, 0, nullptr, 0, &auth_modes, 1));
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
+  server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
+}
+
 INSTANTIATE_TEST_CASE_P(ExtensionStream, TlsExtensionTestGeneric,
                         ::testing::Combine(TlsConnectTestBase::kTlsModesStream,
                                            TlsConnectTestBase::kTlsVAll));
 INSTANTIATE_TEST_CASE_P(ExtensionDatagram, TlsExtensionTestGeneric,
                         ::testing::Combine(TlsConnectTestBase::kTlsModesAll,
                                            TlsConnectTestBase::kTlsV11Plus));
 INSTANTIATE_TEST_CASE_P(ExtensionDatagramOnly, TlsExtensionTestDtls,
                         TlsConnectTestBase::kTlsV11Plus);
--- a/security/nss/external_tests/ssl_gtest/ssl_hrr_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_hrr_unittest.cc
@@ -108,18 +108,22 @@ TEST_F(TlsConnectDatagram13, DropClientS
 }
 
 TEST_F(TlsConnectTest, Select12AfterHelloRetryRequest) {
   EnsureTlsSetup();
   client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                            SSL_LIBRARY_VERSION_TLS_1_3);
-  const SSLNamedGroup groups[2] = {ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1};
-  server_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
+  const SSLNamedGroup client_groups[] = {ssl_grp_ec_secp256r1,
+                                         ssl_grp_ec_secp521r1};
+  client_->ConfigNamedGroups(client_groups, PR_ARRAY_SIZE(client_groups));
+  const SSLNamedGroup server_groups[] = {ssl_grp_ec_secp384r1,
+                                         ssl_grp_ec_secp521r1};
+  server_->ConfigNamedGroups(server_groups, PR_ARRAY_SIZE(server_groups));
   client_->StartConnect();
   server_->StartConnect();
 
   client_->Handshake();
   server_->Handshake();
 
   // Here we replace the TLS server with one that does TLS 1.2 only.
   // This will happily send the client a TLS 1.2 ServerHello.
@@ -127,18 +131,18 @@ TEST_F(TlsConnectTest, Select12AfterHell
       new TlsAgent(server_->name(), TlsAgent::SERVER, mode_);
   delete server_;
   server_ = replacement_server;
   server_->Init();
   client_->SetPeer(server_);
   server_->SetPeer(client_);
   server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                            SSL_LIBRARY_VERSION_TLS_1_2);
-
-  ConnectExpectFail();
+  server_->StartConnect();
+  Handshake();
   EXPECT_EQ(SSL_ERROR_ILLEGAL_PARAMETER_ALERT, server_->error_code());
   EXPECT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
 }
 
 class HelloRetryRequestAgentTest : public TlsAgentTestClient {
  protected:
   void MakeHelloRetryRequestRecord(SSLNamedGroup group, DataBuffer* hrr_record,
                                    uint32_t seq_num = 0) const {
--- a/security/nss/external_tests/ssl_gtest/ssl_resumption_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_resumption_unittest.cc
@@ -307,16 +307,64 @@ TEST_P(TlsConnectGenericPre13, ConnectEc
   EXPECT_TRUE(dhe2.Parse(i2->buffer()));
 
   // Make sure they are different.
   EXPECT_FALSE((dhe1.public_key_.len() == dhe2.public_key_.len()) &&
                (!memcmp(dhe1.public_key_.data(), dhe2.public_key_.data(),
                         dhe1.public_key_.len())));
 }
 
+// Verify that TLS 1.3 reports an accurate group on resumption.
+TEST_P(TlsConnectTls13, TestTls13ResumeDifferentGroup) {
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  Connect();
+  SendReceive();  // Need to read so that we absorb the session ticket.
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  ExpectResumption(RESUME_TICKET);
+  client_->ConfigNamedGroups(kFFDHEGroups);
+  server_->ConfigNamedGroups(kFFDHEGroups);
+  Connect();
+  CheckKeys(ssl_kea_dh, ssl_auth_rsa_sign);
+}
+
+// Test that we don't resume when we can't negotiate the same cipher.
+TEST_P(TlsConnectTls13, TestTls13ResumeClientDifferentCipher) {
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  client_->EnableSingleCipher(TLS_AES_128_GCM_SHA256);
+  Connect();
+  SendReceive();  // Need to read so that we absorb the session ticket.
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  ExpectResumption(RESUME_NONE);
+  client_->EnableSingleCipher(TLS_AES_256_GCM_SHA384);
+  Connect();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+}
+
+// Test that we don't resume when we can't negotiate the same cipher.
+TEST_P(TlsConnectTls13, TestTls13ResumeServerDifferentCipher) {
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  server_->EnableSingleCipher(TLS_AES_128_GCM_SHA256);
+  Connect();
+  SendReceive();  // Need to read so that we absorb the session ticket.
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  ExpectResumption(RESUME_NONE);
+  server_->EnableSingleCipher(TLS_AES_256_GCM_SHA384);
+  Connect();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+}
+
 // Test that two TLS resumptions work and produce the same ticket.
 // This will change after bug 1257047 is fixed.
 TEST_F(TlsConnectTest, TestTls13ResumptionTwice) {
   ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
   client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_3);
@@ -371,73 +419,9 @@ TEST_F(TlsConnectTest, TestTls13Resumpti
   EXPECT_TRUE(server_->cipher_suite(&resumed_suite));
   EXPECT_EQ(original_suite, resumed_suite);
   EXPECT_TRUE(client_->cipher_suite(&resumed_suite));
   EXPECT_EQ(original_suite, resumed_suite);
 
   // TODO(ekr@rtfm.com): This will change when we fix bug 1257047.
   ASSERT_EQ(initialTicket, c2->extension());
 }
-
-TEST_F(TlsConnectTest, DisableClientPSKAndFailToResume) {
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  Connect();
-  SendReceive();  // Need to read so that we absorb the session ticket.
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-
-  Reset();
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  TlsExtensionCapture* capture =
-      new TlsExtensionCapture(ssl_tls13_pre_shared_key_xtn);
-  client_->SetPacketFilter(capture);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  // We need to disable ALL PSK cipher suites with the same symmetric cipher and
-  // PRF hash.  Otherwise the server will just use a different key exchange.
-  client_->DisableAllCiphers();
-  client_->EnableCiphersByAuthType(ssl_auth_rsa_sign);
-  ExpectResumption(RESUME_NONE);
-  Connect();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-  EXPECT_EQ(0U, capture->extension().len());
-}
-
-TEST_F(TlsConnectTest, DisableServerPSKAndFailToResume) {
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  Connect();
-  SendReceive();  // Need to read so that we absorb the session ticket.
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-
-  Reset();
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  TlsExtensionCapture* clientCapture =
-      new TlsExtensionCapture(ssl_tls13_pre_shared_key_xtn);
-  client_->SetPacketFilter(clientCapture);
-  TlsExtensionCapture* serverCapture =
-      new TlsExtensionCapture(ssl_tls13_pre_shared_key_xtn);
-  server_->SetPacketFilter(serverCapture);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  // We need to disable ALL PSK cipher suites with the same symmetric cipher and
-  // PRF hash.  Otherwise the server will just use a different key exchange.
-  server_->DisableAllCiphers();
-  server_->EnableCiphersByAuthType(ssl_auth_rsa_sign);
-  ExpectResumption(RESUME_NONE);
-  Connect();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-  // The client should have the extension, but the server should not.
-  EXPECT_LT(0U, clientCapture->extension().len());
-  EXPECT_EQ(0U, serverCapture->extension().len());
-}
-
 }  // namespace nss_test
--- a/security/nss/external_tests/ssl_gtest/tls_agent.cc
+++ b/security/nss/external_tests/ssl_gtest/tls_agent.cc
@@ -119,27 +119,16 @@ bool TlsAgent::ConfigServerCert(const st
   SECStatus rv =
       SSL_ConfigSecureServer(ssl_fd_, nullptr, nullptr, ssl_kea_null);
   EXPECT_EQ(SECFailure, rv);
   rv = SSL_ConfigServerCert(ssl_fd_, cert.get(), priv.get(), serverCertData,
                             serverCertData ? sizeof(*serverCertData) : 0);
   return rv == SECSuccess;
 }
 
-// The tests expect that only curves secp256r1, secp384r1, and secp521r1
-// (NIST P-256, P-384, and P-521) are enabled. Disable all other curves.
-void TlsAgent::DisableLameGroups() {
-#ifdef NSS_ECC_MORE_THAN_SUITE_B
-  static const SSLNamedGroup groups[] = {
-      ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1,
-      ssl_grp_ffdhe_2048,   ssl_grp_ffdhe_3072,   ssl_grp_ffdhe_4096};
-  ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
-#endif
-}
-
 bool TlsAgent::EnsureTlsSetup(PRFileDesc* modelSocket) {
   // Don't set up twice
   if (ssl_fd_) return true;
 
   if (adapter_->mode() == STREAM) {
     ssl_fd_ = SSL_ImportFD(modelSocket, pr_fd_);
   } else {
     ssl_fd_ = DTLS_ImportFD(modelSocket, pr_fd_);
@@ -173,17 +162,16 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc
   rv = SSL_AuthCertificateHook(ssl_fd_, AuthCertificateHook, this);
   EXPECT_EQ(SECSuccess, rv);
   if (rv != SECSuccess) return false;
 
   rv = SSL_HandshakeCallback(ssl_fd_, HandshakeCallback, this);
   EXPECT_EQ(SECSuccess, rv);
   if (rv != SECSuccess) return false;
 
-  DisableLameGroups();
   return true;
 }
 
 void TlsAgent::SetupClientAuth() {
   EXPECT_TRUE(EnsureTlsSetup());
   ASSERT_EQ(CLIENT, role_);
 
   EXPECT_EQ(SECSuccess,
@@ -243,45 +231,89 @@ void TlsAgent::StartConnect(PRFileDesc* 
 void TlsAgent::DisableAllCiphers() {
   for (size_t i = 0; i < SSL_NumImplementedCiphers; ++i) {
     SECStatus rv =
         SSL_CipherPrefSet(ssl_fd_, SSL_ImplementedCiphers[i], PR_FALSE);
     EXPECT_EQ(SECSuccess, rv);
   }
 }
 
+// Not actually all groups, just the onece that we are actually willing
+// to use.
+const std::vector<SSLNamedGroup> kAllDHEGroups = {
+    ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1,
+    ssl_grp_ffdhe_2048,   ssl_grp_ffdhe_3072,   ssl_grp_ffdhe_4096,
+    ssl_grp_ffdhe_6144,   ssl_grp_ffdhe_8192};
+
+const std::vector<SSLNamedGroup> kECDHEGroups = {
+    ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1};
+
+const std::vector<SSLNamedGroup> kFFDHEGroups = {
+    ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072, ssl_grp_ffdhe_4096,
+    ssl_grp_ffdhe_6144, ssl_grp_ffdhe_8192};
+
+// Defined because the big DHE groups are ridiculously slow.
+const std::vector<SSLNamedGroup> kFasterDHEGroups = {
+    ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1,
+    ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072};
+
+void TlsAgent::ConfigNamedGroups(const std::vector<SSLNamedGroup>& groups) {
+  ConfigNamedGroups(&groups[0], groups.size());
+}
+
 void TlsAgent::EnableCiphersByKeyExchange(SSLKEAType kea) {
   EXPECT_TRUE(EnsureTlsSetup());
 
   for (size_t i = 0; i < SSL_NumImplementedCiphers; ++i) {
     SSLCipherSuiteInfo csinfo;
 
     SECStatus rv = SSL_GetCipherSuiteInfo(SSL_ImplementedCiphers[i], &csinfo,
                                           sizeof(csinfo));
     ASSERT_EQ(SECSuccess, rv);
     EXPECT_EQ(sizeof(csinfo), csinfo.length);
 
-    if (csinfo.keaType == kea && !csinfo.isExportable) {
+    if ((csinfo.keaType == kea) || (csinfo.keaType == ssl_kea_tls13_any)) {
       rv = SSL_CipherPrefSet(ssl_fd_, SSL_ImplementedCiphers[i], PR_TRUE);
       EXPECT_EQ(SECSuccess, rv);
     }
   }
 }
 
+void TlsAgent::EnableGroupsByKeyExchange(SSLKEAType kea) {
+  switch (kea) {
+    case ssl_kea_dh:
+      ConfigNamedGroups(kFFDHEGroups);
+      break;
+    case ssl_kea_ecdh:
+      ConfigNamedGroups(kECDHEGroups);
+      break;
+    default:
+      break;
+  }
+}
+
+void TlsAgent::EnableGroupsByAuthType(SSLAuthType authType) {
+  if (authType == ssl_auth_ecdh_rsa || authType == ssl_auth_ecdh_ecdsa ||
+      authType == ssl_auth_ecdsa || authType == ssl_auth_tls13_any) {
+    ConfigNamedGroups(kECDHEGroups);
+  }
+}
+
 void TlsAgent::EnableCiphersByAuthType(SSLAuthType authType) {
   EXPECT_TRUE(EnsureTlsSetup());
 
   for (size_t i = 0; i < SSL_NumImplementedCiphers; ++i) {
     SSLCipherSuiteInfo csinfo;
 
     SECStatus rv = SSL_GetCipherSuiteInfo(SSL_ImplementedCiphers[i], &csinfo,
                                           sizeof(csinfo));
     ASSERT_EQ(SECSuccess, rv);
 
-    if (csinfo.authType == authType && !csinfo.isExportable) {
+    if ((csinfo.authType == authType) ||
+        (csinfo.keaType == ssl_kea_tls13_any)) {
       rv = SSL_CipherPrefSet(ssl_fd_, SSL_ImplementedCiphers[i], PR_TRUE);
       EXPECT_EQ(SECSuccess, rv);
     }
   }
 }
 
 void TlsAgent::EnableSingleCipher(uint16_t cipher) {
   DisableAllCiphers();
@@ -377,22 +409,23 @@ void TlsAgent::SetSignatureAlgorithms(co
       ++i;
     }
   }
   EXPECT_EQ(i, configuredCount) << "algorithms in use were all set";
 }
 
 void TlsAgent::CheckKEA(SSLKEAType type, size_t kea_size) const {
   EXPECT_EQ(STATE_CONNECTED, state_);
-  EXPECT_EQ(type, csinfo_.keaType);
+  EXPECT_EQ(type, info_.keaType);
   EXPECT_EQ(kea_size, info_.keaKeyBits);
 }
 
 void TlsAgent::CheckKEA(SSLKEAType type) const {
-  PRUint32 ecKEAKeyBits = SSLInt_DetermineKEABits(server_key_bits_, &csinfo_);
+  PRUint32 ecKEAKeyBits = SSLInt_DetermineKEABits(
+      server_key_bits_, info_.authType, csinfo_.symKeyBits);
   switch (type) {
     case ssl_kea_ecdh:
       CheckKEA(type, ecKEAKeyBits);
       break;
     case ssl_kea_dh:
       CheckKEA(type, 2048);
       break;
     case ssl_kea_rsa:
@@ -401,19 +434,23 @@ void TlsAgent::CheckKEA(SSLKEAType type)
     default:
       EXPECT_TRUE(false) << "Unknown KEA type";
       break;
   }
 }
 
 void TlsAgent::CheckAuthType(SSLAuthType type) const {
   EXPECT_EQ(STATE_CONNECTED, state_);
-  EXPECT_EQ(type, csinfo_.authType);
+  EXPECT_EQ(type, info_.authType);
   EXPECT_EQ(server_key_bits_, info_.authKeyBits);
 
+  if (info_.protocolVersion >= SSL_LIBRARY_VERSION_TLS_1_3) {
+    return;
+  }
+
   // Check authAlgorithm, which is the old value for authType.  This is a second
   // switch
   // statement because default label is different.
   switch (type) {
     case ssl_auth_rsa_sign:
       EXPECT_EQ(ssl_auth_rsa_decrypt, csinfo_.authAlgorithm)
           << "authAlgorithm for RSA is always decrypt";
       break;
--- a/security/nss/external_tests/ssl_gtest/tls_agent.h
+++ b/security/nss/external_tests/ssl_gtest/tls_agent.h
@@ -32,16 +32,21 @@ enum SessionResumptionMode {
   RESUME_NONE = 0,
   RESUME_SESSIONID = 1,
   RESUME_TICKET = 2,
   RESUME_BOTH = RESUME_SESSIONID | RESUME_TICKET
 };
 
 class TlsAgent;
 
+const extern std::vector<SSLNamedGroup> kAllDHEGroups;
+const extern std::vector<SSLNamedGroup> kECDHEGroups;
+const extern std::vector<SSLNamedGroup> kFFDHEGroups;
+const extern std::vector<SSLNamedGroup> kFasterDHEGroups;
+
 typedef std::function<SECStatus(TlsAgent* agent, bool checksig, bool isServer)>
     AuthCertificateCallbackFunction;
 
 typedef std::function<void(TlsAgent* agent)> HandshakeCallbackFunction;
 
 typedef std::function<int32_t(TlsAgent* agent, const SECItem* srvNameArr,
                               PRUint32 srvNameArrSize)>
     SniCallbackFunction;
@@ -85,16 +90,18 @@ class TlsAgent : public PollTarget {
   void StartConnect(PRFileDesc* model = nullptr);
   void CheckKEA(SSLKEAType type) const;
   void CheckKEA(SSLKEAType type, size_t kea_size) const;
   void CheckAuthType(SSLAuthType type) const;
 
   void DisableAllCiphers();
   void EnableCiphersByAuthType(SSLAuthType authType);
   void EnableCiphersByKeyExchange(SSLKEAType kea);
+  void EnableGroupsByKeyExchange(SSLKEAType kea);
+  void EnableGroupsByAuthType(SSLAuthType authType);
   void EnableSingleCipher(uint16_t cipher);
 
   void Handshake();
   // Marks the internal state as CONNECTING in anticipation of renegotiation.
   void PrepareForRenegotiate();
   // Prepares for renegotiation, then actually triggers it.
   void StartRenegotiate();
   bool ConfigServerCert(const std::string& name, bool updateKeyBits = false,
@@ -137,16 +144,17 @@ class TlsAgent : public PollTarget {
   void EnableExtendedMasterSecret();
   void CheckExtendedMasterSecret(bool expected);
   void CheckEarlyDataAccepted(bool expected);
   void DisableRollbackDetection();
   void EnableCompression();
   void SetDowngradeCheckVersion(uint16_t version);
   void CheckSecretsDestroyed();
   void ConfigNamedGroups(const SSLNamedGroup* groups, size_t num);
+  void ConfigNamedGroups(const std::vector<SSLNamedGroup>& groups);
 
   const std::string& name() const { return name_; }
 
   Role role() const { return role_; }
   std::string role_str() const { return role_ == SERVER ? "server" : "client"; }
 
   State state() const { return state_; }
 
@@ -185,16 +193,30 @@ class TlsAgent : public PollTarget {
     return csinfo_.cipherSuiteName;
   }
 
   std::vector<uint8_t> session_id() const {
     return std::vector<uint8_t>(info_.sessionID,
                                 info_.sessionID + info_.sessionIDLength);
   }
 
+  bool auth_type(SSLAuthType* auth_type) const {
+    if (state_ != STATE_CONNECTED) return false;
+
+    *auth_type = info_.authType;
+    return true;
+  }
+
+  bool kea_type(SSLKEAType* kea_type) const {
+    if (state_ != STATE_CONNECTED) return false;
+
+    *kea_type = info_.keaType;
+    return true;
+  }
+
   size_t received_bytes() const { return recv_ctr_; }
   PRErrorCode error_code() const { return error_code_; }
 
   bool can_falsestart_hook_called() const {
     return can_falsestart_hook_called_;
   }
 
   void SetHandshakeCallback(HandshakeCallbackFunction handshake_callback) {
@@ -296,16 +318,18 @@ class TlsAgent : public PollTarget {
     agent->handshake_callback_called_ = true;
     agent->Connected();
     if (agent->handshake_callback_) {
       agent->handshake_callback_(agent);
     }
   }
 
   void DisableLameGroups();
+  void ConfigStrongECGroups(bool en);
+  void ConfigAllDHGroups(bool en);
   void CheckCallbacks() const;
   void Connected();
 
   const std::string name_;
   Mode mode_;
   uint16_t server_key_bits_;
   PRFileDesc* pr_fd_;
   DummyPrSocket* adapter_;
--- a/security/nss/external_tests/ssl_gtest/tls_connect.cc
+++ b/security/nss/external_tests/ssl_gtest/tls_connect.cc
@@ -343,29 +343,36 @@ void TlsConnectTestBase::DisableAllCiphe
 void TlsConnectTestBase::EnableOnlyStaticRsaCiphers() {
   DisableAllCiphers();
 
   client_->EnableCiphersByKeyExchange(ssl_kea_rsa);
   server_->EnableCiphersByKeyExchange(ssl_kea_rsa);
 }
 
 void TlsConnectTestBase::EnableOnlyDheCiphers() {
-  DisableAllCiphers();
-
-  client_->EnableCiphersByKeyExchange(ssl_kea_dh);
-  client_->EnableCiphersByKeyExchange(ssl_kea_dh_psk);
-  server_->EnableCiphersByKeyExchange(ssl_kea_dh);
-  server_->EnableCiphersByKeyExchange(ssl_kea_dh_psk);
+  if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
+    DisableAllCiphers();
+    client_->EnableCiphersByKeyExchange(ssl_kea_dh);
+    server_->EnableCiphersByKeyExchange(ssl_kea_dh);
+  } else {
+    client_->ConfigNamedGroups(kFFDHEGroups);
+    server_->ConfigNamedGroups(kFFDHEGroups);
+  }
 }
 
 void TlsConnectTestBase::EnableSomeEcdhCiphers() {
-  client_->EnableCiphersByAuthType(ssl_auth_ecdh_rsa);
-  client_->EnableCiphersByAuthType(ssl_auth_ecdh_ecdsa);
-  server_->EnableCiphersByAuthType(ssl_auth_ecdh_rsa);
-  server_->EnableCiphersByAuthType(ssl_auth_ecdh_ecdsa);
+  if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
+    client_->EnableCiphersByAuthType(ssl_auth_ecdh_rsa);
+    client_->EnableCiphersByAuthType(ssl_auth_ecdh_ecdsa);
+    server_->EnableCiphersByAuthType(ssl_auth_ecdh_rsa);
+    server_->EnableCiphersByAuthType(ssl_auth_ecdh_ecdsa);
+  } else {
+    client_->ConfigNamedGroups(kECDHEGroups);
+    server_->ConfigNamedGroups(kECDHEGroups);
+  }
 }
 
 void TlsConnectTestBase::ConfigureSessionCache(SessionResumptionMode client,
                                                SessionResumptionMode server) {
   client_->ConfigureSessionCache(client);
   server_->ConfigureSessionCache(server);
   if ((server & RESUME_TICKET) != 0) {
     // This is an abomination.  NSS encrypts session tickets with the server's
@@ -462,16 +469,27 @@ void TlsConnectTestBase::SetupForZeroRtt
   client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->StartConnect();
   client_->StartConnect();
 }
 
+// Do a first connection so we can do resumption
+void TlsConnectTestBase::SetupForResume() {
+  EnsureTlsSetup();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  Connect();
+  SendReceive();  // Need to read so that we absorb the session ticket.
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+
+  Reset();
+}
+
 void TlsConnectTestBase::ZeroRttSendReceive(
     bool expect_readable, std::function<bool()> post_clienthello_check) {
   const char* k0RttData = "ABCDEF";
   const PRInt32 k0RttDataLen = static_cast<PRInt32>(strlen(k0RttData));
 
   client_->Handshake();  // Send ClientHello.
   if (post_clienthello_check) {
     if (!post_clienthello_check()) return;
--- a/security/nss/external_tests/ssl_gtest/tls_connect.h
+++ b/security/nss/external_tests/ssl_gtest/tls_connect.h
@@ -91,16 +91,17 @@ class TlsConnectTestBase : public ::test
   void EnableAlpn();
   void EnableAlpn(const uint8_t* val, size_t len);
   void EnsureModelSockets();
   void CheckAlpn(const std::string& val);
   void EnableSrtp();
   void CheckSrtp() const;
   void SendReceive();
   void SetupForZeroRtt();
+  void SetupForResume();
   void ZeroRttSendReceive(
       bool expect_readable,
       std::function<bool()> post_clienthello_check = nullptr);
   void Receive(size_t amount);
   void ExpectExtendedMasterSecret(bool expected);
   void ExpectEarlyDataAccepted(bool expected);
 
  protected:
--- a/security/nss/external_tests/ssl_gtest/tls_parser.h
+++ b/security/nss/external_tests/ssl_gtest/tls_parser.h
@@ -43,17 +43,17 @@ const uint8_t kTlsAlertHandshakeFailure 
 const uint8_t kTlsAlertIllegalParameter = 47;
 const uint8_t kTlsAlertDecodeError = 50;
 const uint8_t kTlsAlertDecryptError = 51;
 const uint8_t kTlsAlertMissingExtension = 109;
 const uint8_t kTlsAlertUnsupportedExtension = 110;
 const uint8_t kTlsAlertNoApplicationProtocol = 120;
 
 const uint16_t kTlsSigSchemeRsaPkcs1Sha1 = 0x0201;
-const uint16_t kTlsSigSchemeRsaPssSha256 = 0x0700;
+const uint16_t kTlsSigSchemeRsaPssSha256 = 0x0804;
 
 const uint8_t kTlsFakeChangeCipherSpec[] = {
     kTlsChangeCipherSpecType,  // Type
     0xfe,
     0xff,  // Version
     0x00,
     0x00,
     0x00,
@@ -62,16 +62,43 @@ const uint8_t kTlsFakeChangeCipherSpec[]
     0x00,
     0x00,
     0x10,  // Fictitious sequence #
     0x00,
     0x01,  // Length
     0x01   // Value
 };
 
+// We don't export this yet. Yuck.
+enum TlsSignatureScheme {
+  kTlsSignatureNone = 0,
+  kTlsSignatureRsaPkcs1Sha1 = 0x0201,
+  kTlsSignatureRsaPkcs1Sha256 = 0x0401,
+  kTlsSignatureRsaPkcs1Sha384 = 0x0501,
+  kTlsSignatureRsaPkcs1Sha512 = 0x0601,
+  kTlsSignatureEcdsaSecp256r1Sha256 = 0x0403,
+  kTlsSignatureEcdsaSecp384r1Sha384 = 0x0503,
+  kTlsSignatureEcdsaSecp521r1Sha512 = 0x0603,
+  kTlsSignatureRsaPssSha256 = 0x0804,
+  kTlsSignatureRsaPssSha384 = 0x0805,
+  kTlsSignatureRsaPssSha512 = 0x0806,
+  kTlsSignatureEd25519 = 0x0807,
+  kTlsSignatureEd448 = 0x0808,
+  kTlsSignatureDsaSha1 = 0x0202,
+  kTlsSignatureDsaSha256 = 0x0402,
+  kTlsSignatureDsaSha384 = 0x0502,
+  kTlsSignatureDsaSha512 = 0x0602,
+  kTlsSignatureEcdsaSha1 = 0x0203
+};
+
+static const uint8_t kTls13PskKe = 0;
+static const uint8_t kTls13PskDhKe = 1;
+static const uint8_t kTls13PskAuth = 0;
+static const uint8_t kTls13PskSignAuth = 1;
+
 inline bool IsDtls(uint16_t version) { return (version & 0x8000) == 0x8000; }
 
 inline uint16_t NormalizeTlsVersion(uint16_t version) {
   if (version == 0xfeff) {
     return 0x0302;  // special: DTLS 1.0 == TLS 1.1
   }
   if (IsDtls(version)) {
     return (version ^ 0xffff) + 0x0201;
@@ -81,20 +108,20 @@ inline uint16_t NormalizeTlsVersion(uint
 
 inline uint16_t TlsVersionToDtlsVersion(uint16_t version) {
   if (version == 0x0302) {
     return 0xfeff;
   }
   return 0xffff - version + 0x0201;
 }
 
-inline void WriteVariable(DataBuffer* target, size_t index,
-                          const DataBuffer& buf, size_t len_size) {
-  target->Write(index, static_cast<uint32_t>(buf.len()), len_size);
-  target->Write(index + len_size, buf.data(), buf.len());
+inline size_t WriteVariable(DataBuffer* target, size_t index,
+                            const DataBuffer& buf, size_t len_size) {
+  index = target->Write(index, static_cast<uint32_t>(buf.len()), len_size);
+  return target->Write(index, buf.data(), buf.len());
 }
 
 class TlsParser {
  public:
   TlsParser(const uint8_t* data, size_t len) : buffer_(data, len), offset_(0) {}
   explicit TlsParser(const DataBuffer& buf) : buffer_(buf), offset_(0) {}
 
   bool Read(uint8_t* val);
--- a/security/nss/lib/ckfw/builtins/certdata.txt
+++ b/security/nss/lib/ckfw/builtins/certdata.txt
@@ -8742,165 +8742,16 @@ END
 CKA_SERIAL_NUMBER MULTILINE_OCTAL
 \002\001\102
 END
 CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_NOT_TRUSTED
 CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_NOT_TRUSTED
 CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_NOT_TRUSTED
 CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
 
-#
-# Certificate "IGC/A"
-#
-# Issuer: E=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR
-# Serial Number:39:11:45:10:94
-# Subject: E=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR
-# Not Valid Before: Fri Dec 13 14:29:23 2002
-# Not Valid After : Sat Oct 17 14:29:22 2020
-# Fingerprint (MD5): 0C:7F:DD:6A:F4:2A:B9:C8:9B:BD:20:7E:A9:DB:5C:37
-# Fingerprint (SHA1): 60:D6:89:74:B5:C2:65:9E:8A:0F:C1:88:7C:88:D2:46:69:1B:18:2C
-CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
-CKA_TOKEN CK_BBOOL CK_TRUE
-CKA_PRIVATE CK_BBOOL CK_FALSE
-CKA_MODIFIABLE CK_BBOOL CK_FALSE
-CKA_LABEL UTF8 "IGC/A"
-CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
-CKA_SUBJECT MULTILINE_OCTAL
-\060\201\205\061\013\060\011\006\003\125\004\006\023\002\106\122
-\061\017\060\015\006\003\125\004\010\023\006\106\162\141\156\143
-\145\061\016\060\014\006\003\125\004\007\023\005\120\141\162\151
-\163\061\020\060\016\006\003\125\004\012\023\007\120\115\057\123
-\107\104\116\061\016\060\014\006\003\125\004\013\023\005\104\103
-\123\123\111\061\016\060\014\006\003\125\004\003\023\005\111\107
-\103\057\101\061\043\060\041\006\011\052\206\110\206\367\015\001
-\011\001\026\024\151\147\143\141\100\163\147\144\156\056\160\155
-\056\147\157\165\166\056\146\162
-END
-CKA_ID UTF8 "0"
-CKA_ISSUER MULTILINE_OCTAL
-\060\201\205\061\013\060\011\006\003\125\004\006\023\002\106\122
-\061\017\060\015\006\003\125\004\010\023\006\106\162\141\156\143
-\145\061\016\060\014\006\003\125\004\007\023\005\120\141\162\151
-\163\061\020\060\016\006\003\125\004\012\023\007\120\115\057\123
-\107\104\116\061\016\060\014\006\003\125\004\013\023\005\104\103
-\123\123\111\061\016\060\014\006\003\125\004\003\023\005\111\107
-\103\057\101\061\043\060\041\006\011\052\206\110\206\367\015\001
-\011\001\026\024\151\147\143\141\100\163\147\144\156\056\160\155
-\056\147\157\165\166\056\146\162
-END
-CKA_SERIAL_NUMBER MULTILINE_OCTAL
-\002\005\071\021\105\020\224
-END
-CKA_VALUE MULTILINE_OCTAL
-\060\202\004\002\060\202\002\352\240\003\002\001\002\002\005\071
-\021\105\020\224\060\015\006\011\052\206\110\206\367\015\001\001
-\005\005\000\060\201\205\061\013\060\011\006\003\125\004\006\023
-\002\106\122\061\017\060\015\006\003\125\004\010\023\006\106\162
-\141\156\143\145\061\016\060\014\006\003\125\004\007\023\005\120
-\141\162\151\163\061\020\060\016\006\003\125\004\012\023\007\120
-\115\057\123\107\104\116\061\016\060\014\006\003\125\004\013\023
-\005\104\103\123\123\111\061\016\060\014\006\003\125\004\003\023
-\005\111\107\103\057\101\061\043\060\041\006\011\052\206\110\206
-\367\015\001\011\001\026\024\151\147\143\141\100\163\147\144\156
-\056\160\155\056\147\157\165\166\056\146\162\060\036\027\015\060
-\062\061\062\061\063\061\064\062\071\062\063\132\027\015\062\060
-\061\060\061\067\061\064\062\071\062\062\132\060\201\205\061\013
-\060\011\006\003\125\004\006\023\002\106\122\061\017\060\015\006
-\003\125\004\010\023\006\106\162\141\156\143\145\061\016\060\014
-\006\003\125\004\007\023\005\120\141\162\151\163\061\020\060\016
-\006\003\125\004\012\023\007\120\115\057\123\107\104\116\061\016
-\060\014\006\003\125\004\013\023\005\104\103\123\123\111\061\016
-\060\014\006\003\125\004\003\023\005\111\107\103\057\101\061\043
-\060\041\006\011\052\206\110\206\367\015\001\011\001\026\024\151
-\147\143\141\100\163\147\144\156\056\160\155\056\147\157\165\166
-\056\146\162\060\202\001\042\060\015\006\011\052\206\110\206\367
-\015\001\001\001\005\000\003\202\001\017\000\060\202\001\012\002
-\202\001\001\000\262\037\321\320\142\305\063\073\300\004\206\210
-\263\334\370\210\367\375\337\103\337\172\215\232\111\134\366\116
-\252\314\034\271\241\353\047\211\362\106\351\073\112\161\325\035
-\216\055\317\346\255\253\143\120\307\124\013\156\022\311\220\066
-\306\330\057\332\221\252\150\305\162\376\027\012\262\027\176\171
-\265\062\210\160\312\160\300\226\112\216\344\125\315\035\047\224
-\277\316\162\052\354\134\371\163\040\376\275\367\056\211\147\270
-\273\107\163\022\367\321\065\151\072\362\012\271\256\377\106\102
-\106\242\277\241\205\032\371\277\344\377\111\205\367\243\160\206
-\062\034\135\237\140\367\251\255\245\377\317\321\064\371\175\133
-\027\306\334\326\016\050\153\302\335\361\365\063\150\235\116\374
-\207\174\066\022\326\243\200\350\103\015\125\141\224\352\144\067
-\107\352\167\312\320\262\130\005\303\135\176\261\250\106\220\061
-\126\316\160\052\226\262\060\270\167\346\171\300\275\051\073\375
-\224\167\114\275\040\315\101\045\340\056\307\033\273\356\244\004
-\101\322\135\255\022\152\212\233\107\373\311\335\106\100\341\235
-\074\063\320\265\002\003\001\000\001\243\167\060\165\060\017\006
-\003\125\035\023\001\001\377\004\005\060\003\001\001\377\060\013
-\006\003\125\035\017\004\004\003\002\001\106\060\025\006\003\125
-\035\040\004\016\060\014\060\012\006\010\052\201\172\001\171\001
-\001\001\060\035\006\003\125\035\016\004\026\004\024\243\005\057
-\030\140\120\302\211\012\335\053\041\117\377\216\116\250\060\061
-\066\060\037\006\003\125\035\043\004\030\060\026\200\024\243\005
-\057\030\140\120\302\211\012\335\053\041\117\377\216\116\250\060
-\061\066\060\015\006\011\052\206\110\206\367\015\001\001\005\005
-\000\003\202\001\001\000\005\334\046\330\372\167\025\104\150\374
-\057\146\072\164\340\135\344\051\377\006\007\023\204\112\253\317
-\155\240\037\121\224\370\111\313\164\066\024\274\025\335\333\211
-\057\335\217\240\135\174\365\022\353\237\236\070\244\107\314\263
-\226\331\276\234\045\253\003\176\063\017\225\201\015\375\026\340
-\210\276\067\360\154\135\320\061\233\062\053\135\027\145\223\230
-\140\274\156\217\261\250\074\036\331\034\363\251\046\102\371\144
-\035\302\347\222\366\364\036\132\252\031\122\135\257\350\242\367
-\140\240\366\215\360\211\365\156\340\012\005\001\225\311\213\040
-\012\272\132\374\232\054\074\275\303\267\311\135\170\045\005\077
-\126\024\233\014\332\373\072\110\376\227\151\136\312\020\206\367
-\116\226\004\010\115\354\260\276\135\334\073\216\117\301\375\232
-\066\064\232\114\124\176\027\003\110\225\010\021\034\007\157\205
-\010\176\135\115\304\235\333\373\256\316\262\321\263\270\203\154
-\035\262\263\171\361\330\160\231\176\360\023\002\316\136\335\121
-\323\337\066\201\241\033\170\057\161\263\361\131\114\106\030\050
-\253\205\322\140\126\132
-END
-
-# Trust for Certificate "IGC/A"
-# Issuer: E=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR
-# Serial Number:39:11:45:10:94
-# Subject: E=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR
-# Not Valid Before: Fri Dec 13 14:29:23 2002
-# Not Valid After : Sat Oct 17 14:29:22 2020
-# Fingerprint (MD5): 0C:7F:DD:6A:F4:2A:B9:C8:9B:BD:20:7E:A9:DB:5C:37
-# Fingerprint (SHA1): 60:D6:89:74:B5:C2:65:9E:8A:0F:C1:88:7C:88:D2:46:69:1B:18:2C
-CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
-CKA_TOKEN CK_BBOOL CK_TRUE
-CKA_PRIVATE CK_BBOOL CK_FALSE
-CKA_MODIFIABLE CK_BBOOL CK_FALSE
-CKA_LABEL UTF8 "IGC/A"
-CKA_CERT_SHA1_HASH MULTILINE_OCTAL
-\140\326\211\164\265\302\145\236\212\017\301\210\174\210\322\106
-\151\033\030\054
-END
-CKA_CERT_MD5_HASH MULTILINE_OCTAL
-\014\177\335\152\364\052\271\310\233\275\040\176\251\333\134\067
-END
-CKA_ISSUER MULTILINE_OCTAL
-\060\201\205\061\013\060\011\006\003\125\004\006\023\002\106\122
-\061\017\060\015\006\003\125\004\010\023\006\106\162\141\156\143
-\145\061\016\060\014\006\003\125\004\007\023\005\120\141\162\151
-\163\061\020\060\016\006\003\125\004\012\023\007\120\115\057\123
-\107\104\116\061\016\060\014\006\003\125\004\013\023\005\104\103
-\123\123\111\061\016\060\014\006\003\125\004\003\023\005\111\107
-\103\057\101\061\043\060\041\006\011\052\206\110\206\367\015\001
-\011\001\026\024\151\147\143\141\100\163\147\144\156\056\160\155
-\056\147\157\165\166\056\146\162
-END
-CKA_SERIAL_NUMBER MULTILINE_OCTAL
-\002\005\071\021\105\020\224
-END
-CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
-CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
-CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
-CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
-
 # Distrust "Distrusted AC DG Tresor SSL"
 # Issuer: CN=AC DGTPE Signature Authentification,O=DGTPE,C=FR
 # Serial Number: 204199 (0x31da7)
 # Subject: CN=AC DG Tr..sor SSL,O=DG Tr..sor,C=FR
 # Not Valid Before: Thu Jul 18 10:05:28 2013
 # Not Valid After : Fri Jul 18 10:05:28 2014
 # Fingerprint (MD5): 3A:EA:9E:FC:00:0C:E2:06:6C:E0:AC:39:C1:31:DE:C8
 # Fingerprint (SHA1): 5C:E3:39:46:5F:41:A1:E4:23:14:9F:65:54:40:95:40:4D:E6:EB:E2
--- a/security/nss/lib/ckfw/builtins/config.mk
+++ b/security/nss/lib/ckfw/builtins/config.mk
@@ -27,8 +27,12 @@ endif
 INCLUDES += -I.
 
 #
 # To create a loadable module on Darwin, we must use -bundle.
 #
 ifeq ($(OS_TARGET),Darwin)
 DSO_LDOPTS = -bundle
 endif
+
+ifdef USE_GCOV
+DSO_LDOPTS += --coverage
+endif
--- a/security/nss/lib/cryptohi/keyi.h
+++ b/security/nss/lib/cryptohi/keyi.h
@@ -12,11 +12,18 @@ SEC_BEGIN_PROTOS
 KeyType seckey_GetKeyType(SECOidTag pubKeyOid);
 
 /* extract the 'encryption' (could be signing) and hash oids from and
  * algorithm, key and parameters (parameters is the parameters field
  * of a algorithm ID structure (SECAlgorithmID)*/
 SECStatus sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
                            const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg);
 
+/*
+ * Set the point encoding of a SECKEYPublicKey from the OID.
+ * This has to be called on any SECKEYPublicKey holding a SECKEYECPublicKey
+ * before it can be used. The encoding is used to dermine the public key size.
+ */
+SECStatus seckey_SetPointEncoding(PLArenaPool *arena, SECKEYPublicKey *pubKey);
+
 SEC_END_PROTOS
 
 #endif /* _KEYHI_H_ */
--- a/security/nss/lib/cryptohi/keythi.h
+++ b/security/nss/lib/cryptohi/keythi.h
@@ -1,14 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef _KEYTHI_H_
 #define _KEYTHI_H_ 1
 
+#include "eccutil.h"
 #include "plarena.h"
 #include "pkcs11t.h"
 #include "secmodt.h"
 #include "prclist.h"
 
 /*
 ** RFC 4055 Section 1.2 specifies three different RSA key types.
 **
@@ -121,22 +122,17 @@ typedef struct SECKEYDHPublicKeyStr SECK
 ** parameters value
 */
 typedef SECItem SECKEYECParams;
 
 struct SECKEYECPublicKeyStr {
     SECKEYECParams DEREncodedParams;
     int size;            /* size in bits */
     SECItem publicValue; /* encoded point */
-    /* XXX Even though the PKCS#11 interface takes encoded parameters,
-     * we may still wish to decode them above PKCS#11 for things like
-     * printing key information. For named curves, which is what
-     * we initially support, we ought to have the curve name at the
-     * very least.
-     */
+    ECPointEncoding encoding;
 };
 typedef struct SECKEYECPublicKeyStr SECKEYECPublicKey;
 
 /*
 ** FORTEZZA Public Key structures
 */
 struct SECKEYFortezzaPublicKeyStr {
     int KEAversion;
--- a/security/nss/lib/cryptohi/manifest.mn
+++ b/security/nss/lib/cryptohi/manifest.mn
@@ -1,29 +1,32 @@
 # 
 # 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/.
 CORE_DEPTH = ../..
 
 MODULE = nss
 
+REQUIRES = nssutil
+
 LIBRARY_NAME = cryptohi
 
 EXPORTS = \
 	cryptohi.h \
 	cryptoht.h \
 	key.h     \
 	keyhi.h   \
 	keyt.h    \
 	keythi.h  \
 	sechash.h \
 	$(NULL)
 
 PRIVATE_EXPORTS = \
+	keyi.h    \
 	$(NULL)
 
 CSRCS = \
 	sechash.c \
 	seckey.c  \
 	secsign.c \
 	secvfy.c  \
 	dsautil.c \
--- a/security/nss/lib/cryptohi/seckey.c
+++ b/security/nss/lib/cryptohi/seckey.c
@@ -629,21 +629,27 @@ seckey_ExtractPublicKey(const CERTSubjec
                 pubk->keyType = ecKey;
                 pubk->u.ec.size = 0;
 
                 /* Since PKCS#11 directly takes the DER encoding of EC params
                  * and public value, we don't need any decoding here.
                  */
                 rv = SECITEM_CopyItem(arena, &pubk->u.ec.DEREncodedParams,
                                       &spki->algorithm.parameters);
-                if (rv != SECSuccess)
+                if (rv != SECSuccess) {
                     break;
+                }
                 rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs);
-                if (rv == SECSuccess)
+                if (rv != SECSuccess) {
+                    break;
+                }
+                rv = seckey_SetPointEncoding(arena, pubk);
+                if (rv == SECSuccess) {
                     return pubk;
+                }
                 break;
 
             default:
                 PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
                 rv = SECFailure;
                 break;
         }
 
@@ -782,16 +788,19 @@ SECKEY_ECParamsToKeySize(const SECItem *
 
         case SEC_OID_SECG_EC_SECP521R1:
             return 521;
 
         case SEC_OID_SECG_EC_SECT571K1:
         case SEC_OID_SECG_EC_SECT571R1:
             return 571;
 
+        case SEC_OID_CURVE25519:
+            return 255;
+
         default:
             PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
             return 0;
     }
 }
 
 int
 SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams)
@@ -929,16 +938,19 @@ SECKEY_ECParamsToBasePointOrderLen(const
 
         case SEC_OID_SECG_EC_SECP521R1:
             return 521;
 
         case SEC_OID_SECG_EC_SECT571K1:
         case SEC_OID_SECG_EC_SECT571R1:
             return 570;
 
+        case SEC_OID_CURVE25519:
+            return 255;
+
         default:
             PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
             return 0;
     }
 }
 
 /* The number of bits in the number from the first non-zero bit onward. */
 unsigned
@@ -1150,18 +1162,24 @@ SECKEY_CopyPublicKey(const SECKEYPublicK
                 break;
             rv = SECITEM_CopyItem(arena, &copyk->u.dh.publicValue,
                                   &pubk->u.dh.publicValue);
             break;
         case ecKey:
             copyk->u.ec.size = pubk->u.ec.size;
             rv = SECITEM_CopyItem(arena, &copyk->u.ec.DEREncodedParams,
                                   &pubk->u.ec.DEREncodedParams);
-            if (rv != SECSuccess)
+            if (rv != SECSuccess) {
                 break;
+            }
+            rv = seckey_SetPointEncoding(arena, copyk);
+            if (rv != SECSuccess) {
+                break;
+            }
+            PORT_Assert(copyk->u.ec.encoding == pubk->u.ec.encoding);
             rv = SECITEM_CopyItem(arena, &copyk->u.ec.publicValue,
                                   &pubk->u.ec.publicValue);
             break;
         case nullKey:
             return copyk;
         default:
             PORT_SetError(SEC_ERROR_INVALID_KEY);
             rv = SECFailure;
@@ -1923,8 +1941,44 @@ SECKEY_GetECCOid(const SECKEYECParams *p
         return 0;
     oid.len = params->len - 2;
     oid.data = params->data + 2;
     if ((oidData = SECOID_FindOID(&oid)) == NULL)
         return 0;
 
     return oidData->offset;
 }
+
+/* Set curve encoding in SECKEYECPublicKey in pubKey from OID.
+ * If the encoding is not set, determining the key size of EC public keys will
+ * fail.
+ */
+SECStatus
+seckey_SetPointEncoding(PLArenaPool *arena, SECKEYPublicKey *pubKey)
+{
+    SECItem oid;
+    SECOidTag tag;
+    SECStatus rv;
+
+    /* decode the OID tag */
+    rv = SEC_QuickDERDecodeItem(arena, &oid, SEC_ASN1_GET(SEC_ObjectIDTemplate),
+                                &pubKey->u.ec.DEREncodedParams);
+    if (rv != SECSuccess) {
+        return SECFailure;
+    }
+
+    tag = SECOID_FindOIDTag(&oid);
+    switch (tag) {
+        case SEC_OID_CURVE25519:
+            pubKey->u.ec.encoding = ECPoint_XOnly;
+            break;
+        case SEC_OID_SECG_EC_SECP256R1:
+        /* fall through */
+        case SEC_OID_SECG_EC_SECP384R1:
+        /* fall through */
+        case SEC_OID_SECG_EC_SECP521R1:
+        /* fall through */
+        default:
+            /* unknown curve, default to uncompressed */
+            pubKey->u.ec.encoding = ECPoint_Uncompressed;
+    }
+    return SECSuccess;
+}
--- a/security/nss/lib/freebl/Makefile
+++ b/security/nss/lib/freebl/Makefile
@@ -499,24 +499,29 @@ ifndef NSS_DISABLE_ECC
 	DEFINES  += -DECL_USE_FP
 	ECL_SRCS += ecp_fp160.c ecp_fp192.c ecp_fp224.c ecp_fp.c
 	ECL_HDRS += ecp_fp.h
     endif
 endif
 
 # poly1305-donna-x64-sse2-incremental-source.c requires __int128 support
 # in GCC 4.6.0.
-ifdef CC_IS_CLANG
-    HAVE_INT128_SUPPORT = 1
-else ifeq (1,$(CC_IS_GCC))
-    ifneq (,$(filter 4.6 4.7 4.8 4.9,$(word 1,$(GCC_VERSION)).$(word 2,$(GCC_VERSION))))
-        HAVE_INT128_SUPPORT = 1
-    endif
-    ifeq (,$(filter 0 1 2 3 4,$(word 1,$(GCC_VERSION))))
-        HAVE_INT128_SUPPORT = 1
+ifdef USE_64
+    ifdef CC_IS_CLANG
+            HAVE_INT128_SUPPORT = 1
+            DEFINES += -DHAVE_INT128_SUPPORT
+    else ifeq (1,$(CC_IS_GCC))
+        ifneq (,$(filter 4.6 4.7 4.8 4.9,$(word 1,$(GCC_VERSION)).$(word 2,$(GCC_VERSION))))
+            HAVE_INT128_SUPPORT = 1
+            DEFINES += -DHAVE_INT128_SUPPORT
+        endif
+        ifeq (,$(filter 0 1 2 3 4,$(word 1,$(GCC_VERSION))))
+            HAVE_INT128_SUPPORT = 1
+            DEFINES += -DHAVE_INT128_SUPPORT
+        endif
     endif
 endif
 
 ifndef NSS_DISABLE_CHACHAPOLY
     ifeq ($(CPU_ARCH),x86_64)
         ifdef HAVE_INT128_SUPPORT
             EXTRA_SRCS += poly1305-donna-x64-sse2-incremental-source.c
         else
@@ -529,16 +534,29 @@ ifndef NSS_DISABLE_CHACHAPOLY
             EXTRA_SRCS += chacha20_vec.c
         endif
     else
         EXTRA_SRCS += poly1305.c
         EXTRA_SRCS += chacha20.c
     endif # x86_64
 endif # NSS_DISABLE_CHACHAPOLY
 
+ifeq (,$(filter-out i386 x386 x86 x86_64,$(CPU_ARCH)))
+    # All intel architectures get the 64 bit version
+    # With custom uint128 if necessary (faster than generic 32 bit version).
+    ECL_SRCS += curve25519_64.c
+else
+    # All non intel architectures get the generic 32 bit implementation (slow!)
+    ECL_SRCS += curve25519_32.c
+endif
+
+ifndef HAVE_INT128_SUPPORT
+    ECL_SRCS += uint128.c
+endif
+
 #######################################################################
 # (5) Execute "global" rules. (OPTIONAL)                              #
 #######################################################################
 
 include $(CORE_DEPTH)/coreconf/rules.mk
 
 #######################################################################
 # (6) Execute "component" rules. (OPTIONAL)                           #
--- a/security/nss/lib/freebl/blapit.h
+++ b/security/nss/lib/freebl/blapit.h
@@ -338,17 +338,18 @@ typedef struct DHPrivateKeyStr DHPrivate
 ** parameters for both GFp and GF2m curves.
 */
 
 typedef enum { ec_params_explicit,
                ec_params_named
 } ECParamsType;
 
 typedef enum { ec_field_GFp = 1,
-               ec_field_GF2m
+               ec_field_GF2m,
+               ec_field_plain
 } ECFieldType;
 
 struct ECFieldIDStr {
     int size; /* field size in bits */
     ECFieldType type;
     union {
         SECItem prime; /* prime p for (GFp) */
         SECItem poly;  /* irreducible binary polynomial for (GF2m) */
@@ -376,16 +377,17 @@ struct ECParamsStr {
     ECFieldID fieldID;
     ECCurve curve;
     SECItem base;
     SECItem order;
     int cofactor;
     SECItem DEREncoding;
     ECCurveName name;
     SECItem curveOID;
+    int pointSize;
 };
 typedef struct ECParamsStr ECParams;
 
 struct ECPublicKeyStr {
     ECParams ecParams;
     SECItem publicValue; /* elliptic curve point encoded as
                 * octet stream.
                 */
--- a/security/nss/lib/freebl/ec.c
+++ b/security/nss/lib/freebl/ec.c
@@ -12,16 +12,34 @@
 #include "secmpi.h"
 #include "secitem.h"
 #include "mplogic.h"
 #include "ec.h"
 #include "ecl.h"
 
 #ifndef NSS_DISABLE_ECC
 
+static const ECMethod kMethods[] = {
+    { ECCurve25519,
+      ec_Curve25519_pt_mul,
+      ec_Curve25519_pt_validate }
+};
+
+static const ECMethod *
+ec_get_method_from_name(ECCurveName name)
+{
+    int i;
+    for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); ++i) {
+        if (kMethods[i].name == name) {
+            return &kMethods[i];
+        }
+    }
+    return NULL;
+}
+
 /*
  * Returns true if pointP is the point at infinity, false otherwise
  */
 PRBool
 ec_point_at_infinity(SECItem *pointP)
 {
     unsigned int i;
 
@@ -183,17 +201,18 @@ ec_NewKey(ECParams *ecParams, ECPrivateK
     mp_err err = MP_OKAY;
     int len;
 
 #if EC_DEBUG
     printf("ec_NewKey called\n");
 #endif
     MP_DIGITS(&k) = 0;
 
-    if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) {
+    if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0) ||
+        !ecParams->name) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
     /* Initialize an arena for the EC key. */
     if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
         return SECFailure;
 
@@ -209,17 +228,19 @@ ec_NewKey(ECParams *ecParams, ECPrivateK
 
     /* Copy all of the fields from the ECParams argument to the
      * ECParams structure within the private key.
      */
     key->ecParams.arena = arena;
     key->ecParams.type = ecParams->type;
     key->ecParams.fieldID.size = ecParams->fieldID.size;
     key->ecParams.fieldID.type = ecParams->fieldID.type;
-    if (ecParams->fieldID.type == ec_field_GFp) {
+    key->ecParams.pointSize = ecParams->pointSize;
+    if (ecParams->fieldID.type == ec_field_GFp ||
+        ecParams->fieldID.type == ec_field_plain) {
         CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
                                       &ecParams->fieldID.u.prime));
     } else {
         CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly,
                                       &ecParams->fieldID.u.poly));
     }
     key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
     key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
@@ -236,43 +257,59 @@ ec_NewKey(ECParams *ecParams, ECPrivateK
                                   &ecParams->order));
     key->ecParams.cofactor = ecParams->cofactor;
     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
                                   &ecParams->DEREncoding));
     key->ecParams.name = ecParams->name;
     CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
                                   &ecParams->curveOID));
 
-    len = (ecParams->fieldID.size + 7) >> 3;
-    SECITEM_AllocItem(arena, &key->publicValue, 2 * len + 1);
+    SECITEM_AllocItem(arena, &key->publicValue, ecParams->pointSize);
     len = ecParams->order.len;
     SECITEM_AllocItem(arena, &key->privateValue, len);
 
     /* Copy private key */
     if (privKeyLen >= len) {
         memcpy(key->privateValue.data, privKeyBytes, len);
     } else {
         memset(key->privateValue.data, 0, (len - privKeyLen));
         memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen);
     }
 
     /* Compute corresponding public key */
+
+    /* Use curve specific code for point multiplication */
+    if (ecParams->fieldID.type == ec_field_plain) {
+        const ECMethod *method = ec_get_method_from_name(ecParams->name);
+        if (method == NULL || method->mul == NULL) {
+            /* unknown curve */
+            rv = SECFailure;
+            goto cleanup;
+        }
+        rv = method->mul(&key->publicValue, &key->privateValue, NULL);
+        goto done;
+    }
+
     CHECK_MPI_OK(mp_init(&k));
     CHECK_MPI_OK(mp_read_unsigned_octets(&k, key->privateValue.data,
                                          (mp_size)len));
 
     rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue));
-    if (rv != SECSuccess)
+    if (rv != SECSuccess) {
         goto cleanup;
+    }
+
+done:
     *privKey = key;
 
 cleanup:
     mp_clear(&k);
-    if (rv)
+    if (rv) {
         PORT_FreeArena(arena, PR_TRUE);
+    }
 
 #if EC_DEBUG
     printf("ec_NewKey returning %s\n",
            (rv == SECSuccess) ? "success" : "failure");
 #endif
 #else
     PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
 #endif /* NSS_DISABLE_ECC */
@@ -407,21 +444,32 @@ EC_ValidatePublicKey(ECParams *ecParams,
 {
 #ifndef NSS_DISABLE_ECC
     mp_int Px, Py;
     ECGroup *group = NULL;
     SECStatus rv = SECFailure;
     mp_err err = MP_OKAY;
     int len;
 
-    if (!ecParams || !publicValue) {
+    if (!ecParams || !publicValue || !ecParams->name) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
+    /* Uses curve specific code for point validation. */
+    if (ecParams->fieldID.type == ec_field_plain) {
+        const ECMethod *method = ec_get_method_from_name(ecParams->name);
+        if (method == NULL || method->validate == NULL) {
+            /* unknown curve */
+            PORT_SetError(SEC_ERROR_INVALID_ARGS);
+            return SECFailure;
+        }
+        return method->validate(publicValue);
+    }
+
     /* NOTE: We only support uncompressed points for now */
     len = (ecParams->fieldID.size + 7) >> 3;
     if (publicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
         PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
         return SECFailure;
     } else if (publicValue->len != (2 * len + 1)) {
         PORT_SetError(SEC_ERROR_BAD_KEY);
         return SECFailure;
@@ -507,53 +555,76 @@ ECDH_Derive(SECItem *publicValue,
     SECItem pointQ = { siBuffer, NULL, 0 };
     mp_int k; /* to hold the private value */
     mp_int cofactor;
     mp_err err = MP_OKAY;
 #if EC_DEBUG
     int i;
 #endif
 
-    if (!publicValue || !ecParams || !privateValue ||
-        !derivedSecret) {
+    if (!publicValue || !ecParams || !privateValue || !derivedSecret ||
+        !ecParams->name) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
+    /* Perform curve specific multiplication using ECMethod */
+    if (ecParams->fieldID.type == ec_field_plain) {
+        const ECMethod *method;
+        memset(derivedSecret, 0, sizeof(*derivedSecret));
+        derivedSecret = SECITEM_AllocItem(NULL, derivedSecret, ecParams->pointSize);
+        if (derivedSecret == NULL) {
+            PORT_SetError(SEC_ERROR_NO_MEMORY);
+            return SECFailure;
+        }
+        method = ec_get_method_from_name(ecParams->name);
+        if (method == NULL || method->validate == NULL ||
+            method->mul == NULL) {
+            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+            return SECFailure;
+        }
+        if (method->validate(publicValue) != SECSuccess) {
+            PORT_SetError(SEC_ERROR_BAD_KEY);
+            return SECFailure;
+        }
+        return method->mul(derivedSecret, privateValue, publicValue);
+    }
+
     /*
      * We fail if the public value is the point at infinity, since
      * this produces predictable results.
      */
     if (ec_point_at_infinity(publicValue)) {
         PORT_SetError(SEC_ERROR_BAD_KEY);
         return SECFailure;
     }
 
     MP_DIGITS(&k) = 0;
     memset(derivedSecret, 0, sizeof *derivedSecret);
     len = (ecParams->fieldID.size + 7) >> 3;
-    pointQ.len = 2 * len + 1;
-    if ((pointQ.data = PORT_Alloc(2 * len + 1)) == NULL)
+    pointQ.len = ecParams->pointSize;
+    if ((pointQ.data = PORT_Alloc(ecParams->pointSize)) == NULL)
         goto cleanup;
 
     CHECK_MPI_OK(mp_init(&k));
     CHECK_MPI_OK(mp_read_unsigned_octets(&k, privateValue->data,
                                          (mp_size)privateValue->len));
 
     if (withCofactor && (ecParams->cofactor != 1)) {
         /* multiply k with the cofactor */
         MP_DIGITS(&cofactor) = 0;
         CHECK_MPI_OK(mp_init(&cofactor));
         mp_set(&cofactor, ecParams->cofactor);
         CHECK_MPI_OK(mp_mul(&k, &cofactor, &k));
     }
 
     /* Multiply our private key and peer's public point */
-    if (ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ) != SECSuccess)
+    if (ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ) != SECSuccess) {
         goto cleanup;
+    }
     if (ec_point_at_infinity(&pointQ)) {
         PORT_SetError(SEC_ERROR_BAD_KEY); /* XXX better error code? */
         goto cleanup;
     }
 
     /* Allocate memory for the derived secret and copy
      * the x co-ordinate of pointQ into it.
      */
@@ -572,17 +643,17 @@ ECDH_Derive(SECItem *publicValue,
 cleanup:
     mp_clear(&k);
 
     if (err) {
         MP_TO_SEC_ERROR(err);
     }
 
     if (pointQ.data) {
-        PORT_ZFree(pointQ.data, 2 * len + 1);
+        PORT_ZFree(pointQ.data, ecParams->pointSize);
     }
 #else
     PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
 #endif /* NSS_DISABLE_ECC */
 
     return rv;
 }
 
@@ -687,18 +758,18 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *k
         CHECK_MPI_OK(mp_add(&k, &n, &k));
     }
 
     /*
     ** ANSI X9.62, Section 5.3.2, Step 2
     **
     ** Compute kG
     */
-    kGpoint.len = 2 * flen + 1;
-    kGpoint.data = PORT_Alloc(2 * flen + 1);
+    kGpoint.len = ecParams->pointSize;
+    kGpoint.data = PORT_Alloc(ecParams->pointSize);
     if ((kGpoint.data == NULL) ||
         (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint) != SECSuccess))
         goto cleanup;
 
     /*
     ** ANSI X9.62, Section 5.3.3, Step 1
     **
     ** Extract the x co-ordinate of kG into x1
@@ -807,17 +878,17 @@ cleanup:
     mp_clear(&n);
     mp_clear(&t);
 
     if (t2) {
         PORT_Free(t2);
     }
 
     if (kGpoint.data) {
-        PORT_ZFree(kGpoint.data, 2 * flen + 1);
+        PORT_ZFree(kGpoint.data, ecParams->pointSize);
     }
 
     if (err) {
         MP_TO_SEC_ERROR(err);
         rv = SECFailure;
     }
 
 #if EC_DEBUG
@@ -926,17 +997,17 @@ ECDSA_VerifyDigest(ECPublicKey *key, con
     olen = ecParams->order.len;
     if (signature->len == 0 || signature->len % 2 != 0 ||
         signature->len > 2 * olen) {
         PORT_SetError(SEC_ERROR_INPUT_LEN);
         goto cleanup;
     }
     slen = signature->len / 2;
 
-    SECITEM_AllocItem(NULL, &pointC, 2 * flen + 1);
+    SECITEM_AllocItem(NULL, &pointC, ecParams->pointSize);
     if (pointC.data == NULL)
         goto cleanup;
 
     CHECK_MPI_OK(mp_init(&r_));
     CHECK_MPI_OK(mp_init(&s_));
     CHECK_MPI_OK(mp_init(&c));
     CHECK_MPI_OK(mp_init(&u1));
     CHECK_MPI_OK(mp_init(&u2));
--- a/security/nss/lib/freebl/ec.h
+++ b/security/nss/lib/freebl/ec.h
@@ -4,10 +4,18 @@
 
 #ifndef __ec_h_
 #define __ec_h_
 
 #define EC_DEBUG 0
 
 #define ANSI_X962_CURVE_OID_TOTAL_LEN 10
 #define SECG_CURVE_OID_TOTAL_LEN 7
+#define PKIX_NEWCURVES_OID_TOTAL_LEN 11
+
+struct ECMethodStr {
+    ECCurveName name;
+    SECStatus (*mul)(SECItem *result, SECItem *scalar, SECItem *point);
+    SECStatus (*validate)(const SECItem *point);
+};
+typedef struct ECMethodStr ECMethod;
 
 #endif /* __ec_h_ */
--- a/security/nss/lib/freebl/ecdecode.c
+++ b/security/nss/lib/freebl/ecdecode.c
@@ -30,16 +30,19 @@
  */
 static SECItem *
 hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
 {
     int i = 0;
     int byteval = 0;
     int tmp = PORT_Strlen(str);
 
+    PORT_Assert(arena);
+    PORT_Assert(item);
+
     if ((tmp % 2) != 0)
         return NULL;
 
     /* skip leading 00's unless the hex string is "00" */
     while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) {
         str += 2;
         tmp -= 2;
     }
@@ -77,17 +80,19 @@ EC_CopyParams(PLArenaPool *arena, ECPara
               const ECParams *srcParams)
 {
     SECStatus rv = SECFailure;
 
     dstParams->arena = arena;
     dstParams->type = srcParams->type;
     dstParams->fieldID.size = srcParams->fieldID.size;
     dstParams->fieldID.type = srcParams->fieldID.type;
-    if (srcParams->fieldID.type == ec_field_GFp) {
+    dstParams->pointSize = srcParams->pointSize;
+    if (srcParams->fieldID.type == ec_field_GFp ||
+        srcParams->fieldID.type == ec_field_plain) {
         CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime,
                                       &srcParams->fieldID.u.prime));
     } else {
         CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.poly,
                                       &srcParams->fieldID.u.poly));
     }
     dstParams->fieldID.k1 = srcParams->fieldID.k1;
     dstParams->fieldID.k2 = srcParams->fieldID.k2;
@@ -125,17 +130,19 @@ gf_populate_params(ECCurveName name, ECF
 
     if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve))
         goto cleanup;
     params->name = name;
     curveParams = ecCurve_map[params->name];
     CHECK_OK(curveParams);
     params->fieldID.size = curveParams->size;
     params->fieldID.type = field_type;
-    if (field_type == ec_field_GFp) {
+    params->pointSize = curveParams->pointSize;
+    if (field_type == ec_field_GFp ||
+        field_type == ec_field_plain) {
         CHECK_OK(hexString2SECItem(params->arena, &params->fieldID.u.prime,
                                    curveParams->irr));
     } else {
         CHECK_OK(hexString2SECItem(params->arena, &params->fieldID.u.poly,
                                    curveParams->irr));
     }
     CHECK_OK(hexString2SECItem(params->arena, &params->curve.a,
                                curveParams->curvea));
@@ -171,17 +178,18 @@ EC_FillParams(PLArenaPool *arena, const 
     printf("Encoded params in EC_DecodeParams: ");
     for (i = 0; i < encodedParams->len; i++) {
         printf("%02x:", encodedParams->data[i]);
     }
     printf("\n");
 #endif
 
     if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) &&
-        (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN)) {
+        (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN) &&
+        (encodedParams->len != PKIX_NEWCURVES_OID_TOTAL_LEN)) {
         PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
         return SECFailure;
     };
 
     oid.len = encodedParams->len - 2;
     oid.data = encodedParams->data + 2;
     if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
         ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) {
@@ -560,16 +568,21 @@ EC_FillParams(PLArenaPool *arena, const 
         case SEC_OID_SECG_EC_SECP521R1:
             /* Populate params for secp521r1
      * (the NIST P-521 curve)
      */
             CHECK_SEC_OK(gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp,
                                             params));
             break;
 
+        case SEC_OID_CURVE25519:
+            /* Populate params for Curve25519 */
+            CHECK_SEC_OK(gf_populate_params(ECCurve25519, ec_field_plain, params));
+            break;
+
         default:
             break;
     };
 
 cleanup:
     if (!params->cofactor) {
         PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
 #if EC_DEBUG
--- a/security/nss/lib/freebl/ecl/ecl-curve.h
+++ b/security/nss/lib/freebl/ecl/ecl-curve.h
@@ -1,12 +1,13 @@
 /* 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 "certt.h"
 #include "ecl-exp.h"
 #include <stdlib.h>
 
 #ifndef __ecl_curve_h_
 #define __ecl_curve_h_
 
 #ifdef NSS_ECC_MORE_THAN_SUITE_B
 #error This source file is for Basic ECC only .
@@ -14,39 +15,51 @@
 
 static const ECCurveParams ecCurve_NIST_P256 = {
     "NIST-P256", ECField_GFp, 256,
     "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
     "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
     "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
     "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
     "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
-    "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 1
+    "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+    1, 128, 65, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
 };
 
 static const ECCurveParams ecCurve_NIST_P384 = {
     "NIST-P384", ECField_GFp, 384,
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
     "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
     "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
     "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
-    1
+    1, 192, 97, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
 };
 
 static const ECCurveParams ecCurve_NIST_P521 = {
     "NIST-P521", ECField_GFp, 521,
     "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
     "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
     "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
     "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
     "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
     "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
-    1
+    1, 256, 133, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
+};
+
+static const ECCurveParams ecCurve25519 = {
+    "Curve25519", ECField_GFp, 255,
+    "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
+    "076D06",
+    "00",
+    "0900000000000000000000000000000000000000000000000000000000000000",
+    "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9",
+    "1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed",
+    8, 128, 32, KU_KEY_AGREEMENT
 };
 
 /* mapping between ECCurveName enum and pointers to ECCurveParams */
 static const ECCurveParams *ecCurve_map[] = {
     NULL,               /* ECCurve_noName */
     NULL,               /* ECCurve_NIST_P192 */
     NULL,               /* ECCurve_NIST_P224 */
     &ecCurve_NIST_P256, /* ECCurve_NIST_P256 */
@@ -99,12 +112,13 @@ static const ECCurveParams *ecCurve_map[
     NULL,               /* ECCurve_SECG_CHAR2_131R2 */
     NULL,               /* ECCurve_SECG_CHAR2_163R1 */
     NULL,               /* ECCurve_SECG_CHAR2_193R1 */
     NULL,               /* ECCurve_SECG_CHAR2_193R2 */
     NULL,               /* ECCurve_SECG_CHAR2_239K1 */
     NULL,               /* ECCurve_WTLS_1 */
     NULL,               /* ECCurve_WTLS_8 */
     NULL,               /* ECCurve_WTLS_9 */
+    &ecCurve25519,      /* ECCurve25519 */
     NULL                /* ECCurve_pastLastCurve */
 };
 
 #endif
--- a/security/nss/lib/freebl/ecl/ecl-exp.h
+++ b/security/nss/lib/freebl/ecl/ecl-exp.h
@@ -18,16 +18,19 @@ struct ECCurveParamsStr {
     unsigned int size;
     char *irr;
     char *curvea;
     char *curveb;
     char *genx;
     char *geny;
     char *order;
     int cofactor;
+    int security;
+    int pointSize;
+    unsigned int usage;
 };
 typedef struct ECCurveParamsStr ECCurveParams;
 
 /* Named curve parameters */
 typedef enum {
 
     ECCurve_noName = 0,
 
@@ -123,16 +126,18 @@ typedef enum {
     /* ECCurve_WTLS_6 == ECCurve_SECG_PRIME_112R1 */
     /* ECCurve_WTLS_7 == ECCurve_SECG_PRIME_160R1 */
     ECCurve_WTLS_8,
     ECCurve_WTLS_9,
     /* ECCurve_WTLS_10 == ECCurve_NIST_K233 */
     /* ECCurve_WTLS_11 == ECCurve_NIST_B233 */
     /* ECCurve_WTLS_12 == ECCurve_NIST_P224 */
 
+    ECCurve25519,
+
     ECCurve_pastLastCurve
 } ECCurveName;
 
 /* Aliased named curves */
 
 #define ECCurve_X9_62_PRIME_192V1 ECCurve_NIST_P192
 #define ECCurve_X9_62_PRIME_256V1 ECCurve_NIST_P256
 #define ECCurve_SECG_PRIME_192R1 ECCurve_NIST_P192
--- a/security/nss/lib/freebl/ecl/ecl-priv.h
+++ b/security/nss/lib/freebl/ecl/ecl-priv.h
@@ -248,9 +248,10 @@ mp_err ec_group_set_gfp256_32(ECGroup *g
 
 /* Optimized floating-point arithmetic */
 #ifdef ECL_USE_FP
 mp_err ec_group_set_secp160r1_fp(ECGroup *group);
 mp_err ec_group_set_nistp192_fp(ECGroup *group);
 mp_err ec_group_set_nistp224_fp(ECGroup *group);
 #endif
 
+SECStatus ec_Curve25519_mul(PRUint8 *q, const PRUint8 *s, const PRUint8 *p);
 #endif /* __ecl_priv_h_ */
--- a/security/nss/lib/freebl/ecl/ecl.h
+++ b/security/nss/lib/freebl/ecl/ecl.h
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* Although this is not an exported header file, code which uses elliptic
  * curve point operations will need to include it. */
 
 #ifndef __ecl_h_
 #define __ecl_h_
 
+#include "blapi.h"
 #include "ecl-exp.h"
 #include "mpi.h"
 
 struct ECGroupStr;
 typedef struct ECGroupStr ECGroup;
 
 /* Construct ECGroup from hexadecimal representations of parameters. */
 ECGroup *ECGroup_fromHex(const ECCurveParams *params);
@@ -48,9 +49,12 @@ mp_err ECPoints_mul(const ECGroup *group
                     mp_int *qx, mp_int *qy);
 
 /* Validates an EC public key as described in Section 5.2.2 of X9.62.
  * Returns MP_YES if the public key is valid, MP_NO if the public key
  * is invalid, or an error code if the validation could not be
  * performed. */
 mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const mp_int *py);
 
+SECStatus ec_Curve25519_pt_mul(SECItem *X, SECItem *k, SECItem *P);
+SECStatus ec_Curve25519_pt_validate(const SECItem *px);
+
 #endif /* __ecl_h_ */
--- a/security/nss/lib/freebl/ecl/tests/ecp_test.c
+++ b/security/nss/lib/freebl/ecl/tests/ecp_test.c
@@ -392,16 +392,17 @@ main(int argv, char **argc)
     ECTEST_NAMED_GFP("SECP-256R1", ECCurve_SECG_PRIME_256R1);
     ECTEST_NAMED_GFP("SECP-384R1", ECCurve_SECG_PRIME_384R1);
     ECTEST_NAMED_GFP("SECP-521R1", ECCurve_SECG_PRIME_521R1);
     ECTEST_NAMED_GFP("WTLS-6 (112)", ECCurve_WTLS_6);
     ECTEST_NAMED_GFP("WTLS-7 (160)", ECCurve_WTLS_7);
     ECTEST_NAMED_GFP("WTLS-8 (112)", ECCurve_WTLS_8);
     ECTEST_NAMED_GFP("WTLS-9 (160)", ECCurve_WTLS_9);
     ECTEST_NAMED_GFP("WTLS-12 (224)", ECCurve_WTLS_12);
+    ECTEST_NAMED_GFP("Curve25519", ECCurve25519);
 
 CLEANUP:
     EC_FreeCurveParams(params);
     ECGroup_free(group);
     if (res != MP_OKAY) {
         printf("Error: exiting with error value %i\n", res);
     }
     return res;
--- a/security/nss/lib/freebl/manifest.mn
+++ b/security/nss/lib/freebl/manifest.mn
@@ -100,17 +100,17 @@ MPI_HDRS = mpi-config.h mpi.h mpi-priv.h
 MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c
 
 
 ECL_HDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h
 ifndef NSS_DISABLE_ECC
 ECL_SRCS = ecl.c ecl_curve.c ecl_mult.c ecl_gf.c \
 	ecp_aff.c ecp_jac.c ecp_mont.c \
 	ec_naf.c ecp_jm.c ecp_256.c ecp_384.c ecp_521.c \
-	ecp_256_32.c
+	ecp_256_32.c ecp_25519.c
 ifdef NSS_ECC_MORE_THAN_SUITE_B
 ECL_SRCS += ec2_aff.c ec2_mont.c ec2_proj.c \
 	ec2_163.c ec2_193.c ec2_233.c \
 	ecp_192.c ecp_224.c
 endif
 else
 ECL_SRCS = $(NULL)
 endif
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -17,19 +17,19 @@
 
 /*
  * NSS's major version, minor version, patch level, build number, and whether
  * this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define NSS_VERSION "3.27" _NSS_CUSTOMIZED " Beta"
+#define NSS_VERSION "3.28" _NSS_CUSTOMIZED " Beta"
 #define NSS_VMAJOR 3
-#define NSS_VMINOR 27
+#define NSS_VMINOR 28
 #define NSS_VPATCH 0
 #define NSS_VBUILD 0
 #define NSS_BETA PR_TRUE
 
 #ifndef RC_INVOKED
 
 #include "seccomon.h"
 
--- a/security/nss/lib/pk11wrap/pk11akey.c
+++ b/security/nss/lib/pk11wrap/pk11akey.c
@@ -9,16 +9,17 @@
 #include "secmod.h"
 #include "secmodi.h"
 #include "secmodti.h"
 #include "pkcs11.h"
 #include "pkcs11t.h"
 #include "pk11func.h"
 #include "cert.h"
 #include "key.h"
+#include "keyi.h"
 #include "secitem.h"
 #include "secasn1.h" 
 #include "secoid.h" 
 #include "secerr.h"
 #include "sechash.h"
 
 #include "secpkcs5.h"  
 #include "blapit.h"
@@ -248,17 +249,18 @@ pk11_Attr2SecItem(PLArenaPool *arena, co
  *
  * This function will only work for curves we recognized as of March 2009.
  * The assumption is curves in use after March of 2009 would be supplied by
  * PKCS #11 modules that already pass the correct encoding to us.
  *
  * Point length = (Roundup(curveLenInBits/8)*2+1)
  */
 static int
-pk11_get_EC_PointLenInBytes(PLArenaPool *arena, const SECItem *ecParams)
+pk11_get_EC_PointLenInBytes(PLArenaPool *arena, const SECItem *ecParams,
+                            PRBool *plain)
 {
    SECItem oid;
    SECOidTag tag;
    SECStatus rv;
 
    /* decode the OID tag */
    rv = SEC_QuickDERDecodeItem(arena, &oid,
 		SEC_ASN1_GET(SEC_ObjectIDTemplate), ecParams);
@@ -266,16 +268,17 @@ pk11_get_EC_PointLenInBytes(PLArenaPool 
 	/* could be explict curves, allow them to work if the 
 	 * PKCS #11 module support them. If we try to parse the
 	 * explicit curve value in the future, we may return -1 here
 	 * to indicate an invalid parameter if the explicit curve
 	 * decode fails. */
 	return 0;
    }
 
+   *plain = PR_FALSE;
    tag = SECOID_FindOIDTag(&oid);
    switch (tag) {
     case SEC_OID_SECG_EC_SECP112R1:
     case SEC_OID_SECG_EC_SECP112R2:
 	return 29; /* curve len in bytes = 14 bytes */
     case SEC_OID_SECG_EC_SECT113R1:
     case SEC_OID_SECG_EC_SECT113R2:
 	return 31; /* curve len in bytes = 15 bytes */
@@ -345,16 +348,19 @@ pk11_get_EC_PointLenInBytes(PLArenaPool 
 	return 105; /*curve len in bytes = 52 bytes */
     case SEC_OID_ANSIX962_EC_C2TNB431R1:
 	return 109; /*curve len in bytes = 54 bytes */
     case SEC_OID_SECG_EC_SECP521R1:
 	return 133; /*curve len in bytes = 66 bytes */
     case SEC_OID_SECG_EC_SECT571K1:
     case SEC_OID_SECG_EC_SECT571R1:
 	return 145; /*curve len in bytes = 72 bytes */
+    case SEC_OID_CURVE25519:
+        *plain = PR_TRUE;
+	return 32; /* curve len in bytes = 32 bytes (only X) */
     /* unknown or unrecognized OIDs. return unknown length */
     default:
 	break;
    }
    return 0;
 }
 
 /*
@@ -366,16 +372,17 @@ pk11_get_EC_PointLenInBytes(PLArenaPool 
  */
 static CK_RV
 pk11_get_Decoded_ECPoint(PLArenaPool *arena, const SECItem *ecParams,
 	const CK_ATTRIBUTE *ecPoint, SECItem *publicKeyValue)
 {
     SECItem encodedPublicValue;
     SECStatus rv;
     int keyLen;
+    PRBool plain = PR_FALSE;
 
     if (ecPoint->ulValueLen == 0) {
 	return CKR_ATTRIBUTE_VALUE_INVALID;
     }
 
     /*
      * The PKCS #11 spec requires ecPoints to be encoded as a DER OCTET String.
      * NSS has mistakenly passed unencoded values, and some PKCS #11 vendors
@@ -388,21 +395,29 @@ pk11_get_Decoded_ECPoint(PLArenaPool *ar
 
     /* get the expected key length for the passed in curve.
      * pk11_get_EC_PointLenInBytes only returns valid values for curves
      * NSS has traditionally recognized. If the curve is not recognized,
      * it will return '0', and we have to figure out if the key was
      * encoded or not heuristically. If the ecParams are invalid, it
      * will return -1 for the keyLen.
      */
-    keyLen = pk11_get_EC_PointLenInBytes(arena, ecParams);
+    keyLen = pk11_get_EC_PointLenInBytes(arena, ecParams, &plain);
     if (keyLen < 0) {
 	return CKR_ATTRIBUTE_VALUE_INVALID;
     }
 
+    /*
+     * Some curves are not encoded but we don't have the name here.
+     * Instead, pk11_get_EC_PointLenInBytes returns true plain if this is the
+     * case.
+     */
+    if (plain && ecPoint->ulValueLen == (unsigned int)keyLen) {
+        return pk11_Attr2SecItem(arena, ecPoint, publicKeyValue);
+    }
 
     /* If the point is uncompressed and the lengths match, it
      * must be an unencoded point */
     if ((*((char *)ecPoint->pValue) == EC_POINT_FORM_UNCOMPRESSED) 
 	&& (ecPoint->ulValueLen == (unsigned int)keyLen)) {
 	    return pk11_Attr2SecItem(arena, ecPoint, publicKeyValue);
     }
 
@@ -697,16 +712,19 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot
 	} 
 
 	crv = pk11_Attr2SecItem(arena,ecparams,
 	                        &pubKey->u.ec.DEREncodedParams);
 	if (crv != CKR_OK) break;
 	crv = pk11_get_Decoded_ECPoint(arena,
 		 &pubKey->u.ec.DEREncodedParams, value, 
 		 &pubKey->u.ec.publicValue);
+	if (seckey_SetPointEncoding(arena, pubKey) != SECSuccess) {
+		crv |= CKR_GENERAL_ERROR;
+	}
 	break;
     case fortezzaKey:
     case nullKey:
     default:
 	crv = CKR_OBJECT_HANDLE_INVALID;
 	break;
     }
 
--- a/security/nss/lib/pk11wrap/pk11skey.c
+++ b/security/nss/lib/pk11wrap/pk11skey.c
@@ -1982,28 +1982,29 @@ PK11_PubDerive(SECKEYPrivateKey *privKey
 
    PK11_FreeSymKey(symKey);
    return NULL;
 }
 
 /* Returns the size of the public key, or 0 if there
  * is an error. */
 static CK_ULONG
-pk11_ECPubKeySize(SECItem *publicValue)
+pk11_ECPubKeySize(SECKEYPublicKey *pubKey)
 {
+    SECItem *publicValue = &pubKey->u.ec.publicValue;
+
+    if (pubKey->u.ec.encoding == ECPoint_XOnly) {
+        return publicValue->len;
+    }
     if (publicValue->data[0] == 0x04) {
-	/* key encoded in uncompressed form */
-	return((publicValue->len - 1)/2);
-    } else if ( (publicValue->data[0] == 0x02) ||
-		(publicValue->data[0] == 0x03)) {
-	/* key encoded in compressed form */
-	return(publicValue->len - 1);
+        /* key encoded in uncompressed form */
+        return((publicValue->len - 1)/2);
     }
     /* key encoding not recognized */
-    return(0);
+    return 0;
 }
 
 static PK11SymKey *
 pk11_PubDeriveECKeyWithKDF(
 		    SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
 		    PRBool isSender, SECItem *randomA, SECItem *randomB,
 		    CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
 		    CK_ATTRIBUTE_TYPE operation, int keySize,
@@ -2054,17 +2055,17 @@ pk11_PubDeriveECKeyWithKDF(
     if (key_size == 0) {
 	if ((key_size = pk11_GetPredefinedKeyLength(keyType))) {
 	    templateCount --;
 	} else {
 	    /* sigh, some tokens can't figure this out and require
 	     * CKA_VALUE_LEN to be set */
 	    switch (kdf) {
 	    case CKD_NULL:
-		key_size = pk11_ECPubKeySize(&pubKey->u.ec.publicValue);
+                key_size = pk11_ECPubKeySize(pubKey);
 		if (key_size == 0) {
 		    PK11_FreeSymKey(symKey);
 		    return NULL;
 		}
 		break;
 	    case CKD_SHA1_KDF:
 		key_size = SHA1_LENGTH;
 		break;
@@ -2135,17 +2136,17 @@ pk11_PubDeriveECKeyWithKDF(
 	if ((crv != CKR_OK) && (kdf != CKD_NULL)) {
 	    /* Some PKCS #11 libraries cannot perform the key derivation
 	     * function. So, try calling C_DeriveKey with CKD_NULL and then
 	     * performing the KDF separately.
 	     */
 	    CK_ULONG derivedKeySize = key_size;
 
 	    keyType = CKK_GENERIC_SECRET;
-	    key_size = pk11_ECPubKeySize(&pubKey->u.ec.publicValue);
+            key_size = pk11_ECPubKeySize(pubKey);
 	    if (key_size == 0) {
 		SECITEM_FreeItem(pubValue,PR_TRUE);
 		goto loser;
 	    }
 	    SharedSecret = symKey;
 	    SharedSecret->size = key_size;
 
 	    mechParams->kdf             = CKD_NULL;
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -1790,34 +1790,36 @@ sftk_GetPubKey(SFTKObject *object, CK_KE
                               &pubKey->u.ec.ecParams) != SECSuccess) {
                 crv = CKR_DOMAIN_PARAMS_INVALID;
                 break;
             }
 
             crv = sftk_Attribute2SSecItem(arena, &pubKey->u.ec.publicValue,
                                           object, CKA_EC_POINT);
             if (crv == CKR_OK) {
-                unsigned int keyLen, curveLen;
-
-                curveLen = (pubKey->u.ec.ecParams.fieldID.size + 7) / 8;
-                keyLen = (2 * curveLen) + 1;
-
-                /* special note: We can't just use the first byte to determine
-                 * between these 2 cases because both EC_POINT_FORM_UNCOMPRESSED
-                 * and SEC_ASN1_OCTET_STRING are 0x04 */
-
-                /* handle the non-DER encoded case (UNCOMPRESSED only) */
-                if (pubKey->u.ec.publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED && pubKey->u.ec.publicValue.len == keyLen) {
+                unsigned int keyLen = pubKey->u.ec.ecParams.pointSize;
+
+                /* special note: We can't just use the first byte to distinguish
+                 * between EC_POINT_FORM_UNCOMPRESSED and SEC_ASN1_OCTET_STRING.
+                 * Both are 0x04. */
+
+                /* Handle the non-DER encoded case.
+                 * Some curves are always pressumed to be non-DER.
+                 */
+                if (pubKey->u.ec.publicValue.len == keyLen &&
+                    (pubKey->u.ec.ecParams.fieldID.type == ec_field_plain ||
+                     pubKey->u.ec.publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED)) {
                     break; /* key was not DER encoded, no need to unwrap */
                 }
 
-                /* if we ever support compressed, handle it here */
+                PORT_Assert(pubKey->u.ec.ecParams.name != ECCurve25519);
 
                 /* handle the encoded case */
-                if ((pubKey->u.ec.publicValue.data[0] == SEC_ASN1_OCTET_STRING) && pubKey->u.ec.publicValue.len > keyLen) {
+                if ((pubKey->u.ec.publicValue.data[0] == SEC_ASN1_OCTET_STRING) &&
+                    pubKey->u.ec.publicValue.len > keyLen) {
                     SECItem publicValue;
                     SECStatus rv;
 
                     rv = SEC_QuickDERDecodeItem(arena, &publicValue,
                                                 SEC_ASN1_GET(SEC_OctetStringTemplate),
                                                 &pubKey->u.ec.publicValue);
                     /* nope, didn't decode correctly */
                     if ((rv != SECSuccess) || (publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) || (publicValue.len != keyLen)) {
--- a/security/nss/lib/softoken/pkcs11c.c
+++ b/security/nss/lib/softoken/pkcs11c.c
@@ -4538,16 +4538,24 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
         }
     }
 
     /**********************************************/
     /* Pairwise Consistency Check of Sign/Verify. */
     /**********************************************/
 
     canSignVerify = sftk_isTrue(privateKey, CKA_SIGN);
+    /* Unfortunately CKA_SIGN is always true in lg dbs. We have to check the
+     * actual curve to determine if we can do sign/verify. */
+    if (canSignVerify && keyType == CKK_EC) {
+        NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(privateKey, CKK_EC, &crv);
+        if (privKey && privKey->u.ec.ecParams.name == ECCurve25519) {
+            canSignVerify = PR_FALSE;
+        }
+    }
 
     if (canSignVerify) {
         /* Determine length of signature. */
         switch (keyType) {
             case CKK_RSA:
                 signature_length = modulusLen;
                 mech.mechanism = CKM_RSA_PKCS;
                 break;
@@ -5052,29 +5060,32 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS
             /* Decode ec params before calling EC_NewKey */
             rv = EC_DecodeParams(&ecEncodedParams, &ecParams);
             PORT_Free(ecEncodedParams.data);
             if (rv != SECSuccess) {
                 crv = sftk_MapCryptError(PORT_GetError());
                 break;
             }
             rv = EC_NewKey(ecParams, &ecPriv);
-            PORT_FreeArena(ecParams->arena, PR_TRUE);
             if (rv != SECSuccess) {
                 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
                     sftk_fatalError = PR_TRUE;
                 }
+                PORT_FreeArena(ecParams->arena, PR_TRUE);
                 crv = sftk_MapCryptError(PORT_GetError());
                 break;
             }
 
-            if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT")) {
+            if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") ||
+                ecParams->fieldID.type == ec_field_plain) {
+                PORT_FreeArena(ecParams->arena, PR_TRUE);
                 crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
                                             sftk_item_expand(&ecPriv->publicValue));
             } else {
+                PORT_FreeArena(ecParams->arena, PR_TRUE);
                 SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
                                                        &ecPriv->publicValue,
                                                        SEC_ASN1_GET(SEC_OctetStringTemplate));
                 if (!pubValue) {
                     crv = CKR_ARGUMENTS_BAD;
                     goto ecgn_done;
                 }
                 crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
@@ -6245,17 +6256,16 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
     PRBool isTLS = PR_FALSE;
     PRBool isDH = PR_FALSE;
     HASH_HashType tlsPrfHash = HASH_AlgNULL;
     SECStatus rv;
     int i;
     unsigned int outLen;
     unsigned char sha_out[SHA1_LENGTH];
     unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH];
-    unsigned char key_block2[MD5_LENGTH];
     PRBool isFIPS;
     HASH_HashType hashType;
     PRBool extractValue = PR_TRUE;
 
     CHECK_FORK();
 
     if (!slot) {
         return CKR_SESSION_HANDLE_INVALID;
@@ -6663,17 +6673,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
             sftk_FreeAttribute(att2);
             md5 = MD5_NewContext();
             if (md5 == NULL) {
                 crv = CKR_HOST_MEMORY;
                 break;
             }
             sha = SHA1_NewContext();
             if (sha == NULL) {
-                PORT_Free(md5);
+                MD5_DestroyContext(md5, PR_TRUE);
                 crv = CKR_HOST_MEMORY;
                 break;
             }
             ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter;
 
             PORT_Memcpy(srcrdata,
                         ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
             PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH,
@@ -6697,18 +6707,26 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
              * How much key material do we need?
              */
             macSize = ssl3_keys->ulMacSizeInBits / 8;
             effKeySize = ssl3_keys->ulKeySizeInBits / 8;
             IVSize = ssl3_keys->ulIVSizeInBits / 8;
             if (keySize == 0) {
                 effKeySize = keySize;
             }
-            block_needed = 2 * (macSize + effKeySize +
-                                ((!ssl3_keys->bIsExport) * IVSize));
+
+            /* bIsExport must be false. */
+            if (ssl3_keys->bIsExport) {
+                MD5_DestroyContext(md5, PR_TRUE);
+                SHA1_DestroyContext(sha, PR_TRUE);
+                crv = CKR_MECHANISM_PARAM_INVALID;
+                break;
+            }
+
+            block_needed = 2 * (macSize + effKeySize + IVSize);
             PORT_Assert(block_needed <= sizeof key_block);
             if (block_needed > sizeof key_block)
                 block_needed = sizeof key_block;
 
             /*
              * generate the key material: This looks amazingly similar to the
              * PMS code, and is clearly crying out for a function to provide it.
              */
@@ -6786,187 +6804,55 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
             crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize,
                                    &ssl3_keys_out->hServerMacSecret);
             if (crv != CKR_OK) {
                 goto key_and_mac_derive_fail;
             }
             i += macSize;
 
             if (keySize) {
-                if (!ssl3_keys->bIsExport) {
-                    /*
-                    ** Generate Domestic write keys and IVs.
-                    ** client_write_key[CipherSpec.key_material]
-                    */
-                    crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
-                                           keySize, &ssl3_keys_out->hClientKey);
-                    if (crv != CKR_OK) {
-                        goto key_and_mac_derive_fail;
-                    }
-                    i += keySize;
-
-                    /*
-                    ** server_write_key[CipherSpec.key_material]
-                    */
-                    crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
-                                           keySize, &ssl3_keys_out->hServerKey);
-                    if (crv != CKR_OK) {
-                        goto key_and_mac_derive_fail;
-                    }
-                    i += keySize;
-
-                    /*
-                    ** client_write_IV[CipherSpec.IV_size]
-                    */
-                    if (IVSize > 0) {
-                        PORT_Memcpy(ssl3_keys_out->pIVClient,
-                                    &key_block[i], IVSize);
-                        i += IVSize;
-                    }
-
-                    /*
-                    ** server_write_IV[CipherSpec.IV_size]
-                    */
-                    if (IVSize > 0) {
-                        PORT_Memcpy(ssl3_keys_out->pIVServer,
-                                    &key_block[i], IVSize);
-                        i += IVSize;
-                    }
-                    PORT_Assert(i <= sizeof key_block);
-
-                } else if (!isTLS) {
-
-                    /*
-                    ** Generate SSL3 Export write keys and IVs.
-                    ** client_write_key[CipherSpec.key_material]
-                    ** final_client_write_key = MD5(client_write_key +
-                    **                   ClientHello.random + ServerHello.random);
-                    */
-                    MD5_Begin(md5);
-                    MD5_Update(md5, &key_block[i], effKeySize);
-                    MD5_Update(md5, crsrdata, sizeof crsrdata);
-                    MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
-                    i += effKeySize;
-                    crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2,
-                                           keySize, &ssl3_keys_out->hClientKey);
-                    if (crv != CKR_OK) {
-                        goto key_and_mac_derive_fail;
-                    }
-
-                    /*
-                    ** server_write_key[CipherSpec.key_material]
-                    ** final_server_write_key = MD5(server_write_key +
-                    **                    ServerHello.random + ClientHello.random);
-                    */
-                    MD5_Begin(md5);
-                    MD5_Update(md5, &key_block[i], effKeySize);
-                    MD5_Update(md5, srcrdata, sizeof srcrdata);
-                    MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
-                    i += effKeySize;
-                    crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2,
-                                           keySize, &ssl3_keys_out->hServerKey);
-                    if (crv != CKR_OK) {
-                        goto key_and_mac_derive_fail;
-                    }
-
-                    /*
-                    ** client_write_IV =
-                    **      MD5(ClientHello.random + ServerHello.random);
-                    */
-                    MD5_Begin(md5);
-                    MD5_Update(md5, crsrdata, sizeof crsrdata);
-                    MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
-                    PORT_Memcpy(ssl3_keys_out->pIVClient, key_block2, IVSize);
-
-                    /*
-                    ** server_write_IV =
-                    **      MD5(ServerHello.random + ClientHello.random);
-                    */
-                    MD5_Begin(md5);
-                    MD5_Update(md5, srcrdata, sizeof srcrdata);
-                    MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
-                    PORT_Memcpy(ssl3_keys_out->pIVServer, key_block2, IVSize);
-
-                } else {
-
-                    /*
-                    ** Generate TLS 1.0 Export write keys and IVs.
-                    */
-                    SECStatus status;
-                    SECItem secret = { siBuffer, NULL, 0 };
-                    SECItem crsr = { siBuffer, NULL, 0 };
-                    SECItem keyblk = { siBuffer, NULL, 0 };
-
-                    /*
-                    ** client_write_key[CipherSpec.key_material]
-                    ** final_client_write_key = PRF(client_write_key,
-                    **                              "client write key",
-                    **                              client_random + server_random);
-                    */
-                    secret.data = &key_block[i];
-                    secret.len = effKeySize;
-                    i += effKeySize;
-                    crsr.data = crsrdata;
-                    crsr.len = sizeof crsrdata;
-                    keyblk.data = key_block2;
-                    keyblk.len = sizeof key_block2;
-                    status = TLS_PRF(&secret, "client write key", &crsr, &keyblk,
-                                     isFIPS);
-                    if (status != SECSuccess) {
-                        goto key_and_mac_derive_fail;
-                    }
-                    crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2,
-                                           keySize, &ssl3_keys_out->hClientKey);
-                    if (crv != CKR_OK) {
-                        goto key_and_mac_derive_fail;
-                    }
-
-                    /*
-                    ** server_write_key[CipherSpec.key_material]
-                    ** final_server_write_key = PRF(server_write_key,
-                    **                              "server write key",
-                    **                              client_random + server_random);
-                    */
-                    secret.data = &key_block[i];
-                    secret.len = effKeySize;
-                    i += effKeySize;
-                    keyblk.data = key_block2;
-                    keyblk.len = sizeof key_block2;
-                    status = TLS_PRF(&secret, "server write key", &crsr, &keyblk,
-                                     isFIPS);
-                    if (status != SECSuccess) {
-                        goto key_and_mac_derive_fail;
-                    }
-                    crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2,
-                                           keySize, &ssl3_keys_out->hServerKey);
-                    if (crv != CKR_OK) {
-                        goto key_and_mac_derive_fail;
-                    }
-
-                    /*
-                    ** iv_block = PRF("", "IV block",
-                    **                    client_random + server_random);
-                    ** client_write_IV[SecurityParameters.IV_size]
-                    ** server_write_IV[SecurityParameters.IV_size]
-                    */
-                    if (IVSize) {
-                        secret.data = NULL;
-                        secret.len = 0;
-                        keyblk.data = &key_block[i];
-                        keyblk.len = 2 * IVSize;
-                        status = TLS_PRF(&secret, "IV block", &crsr, &keyblk,
-                                         isFIPS);
-                        if (status != SECSuccess) {
-                            goto key_and_mac_derive_fail;
-                        }
-                        PORT_Memcpy(ssl3_keys_out->pIVClient, keyblk.data, IVSize);
-                        PORT_Memcpy(ssl3_keys_out->pIVServer, keyblk.data + IVSize,
-                                    IVSize);
-                    }
+                /*
+                ** Generate Domestic write keys and IVs.
+                ** client_write_key[CipherSpec.key_material]
+                */
+                crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
+                                       keySize, &ssl3_keys_out->hClientKey);
+                if (crv != CKR_OK) {
+                    goto key_and_mac_derive_fail;
+                }
+                i += keySize;
+
+                /*
+                ** server_write_key[CipherSpec.key_material]
+                */
+                crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
+                                       keySize, &ssl3_keys_out->hServerKey);
+                if (crv != CKR_OK) {
+                    goto key_and_mac_derive_fail;
                 }
+                i += keySize;
+
+                /*
+                ** client_write_IV[CipherSpec.IV_size]
+                */
+                if (IVSize > 0) {
+                    PORT_Memcpy(ssl3_keys_out->pIVClient,
+                                &key_block[i], IVSize);
+                    i += IVSize;
+                }
+
+                /*
+                ** server_write_IV[CipherSpec.IV_size]
+                */
+                if (IVSize > 0) {
+                    PORT_Memcpy(ssl3_keys_out->pIVServer,
+                                &key_block[i], IVSize);
+                    i += IVSize;
+                }
+                PORT_Assert(i <= sizeof key_block);
             }
 
             crv = CKR_OK;
 
             if (0) {
             key_and_mac_derive_fail:
                 if (crv == CKR_OK)
                     crv = CKR_FUNCTION_FAILED;
@@ -7298,17 +7184,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
 #ifndef NSS_DISABLE_ECC
         case CKM_ECDH1_DERIVE:
         case CKM_ECDH1_COFACTOR_DERIVE: {
             SECItem ecScalar, ecPoint;
             SECItem tmp;
             PRBool withCofactor = PR_FALSE;
             unsigned char *secret;
             unsigned char *keyData = NULL;
-            unsigned int secretlen, curveLen, pubKeyLen;
+            unsigned int secretlen, pubKeyLen;
             CK_ECDH1_DERIVE_PARAMS *mechParams;
             NSSLOWKEYPrivateKey *privKey;
             PLArenaPool *arena = NULL;
 
             /* Check mechanism parameters */
             mechParams = (CK_ECDH1_DERIVE_PARAMS *)pMechanism->pParameter;
             if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) ||
                 ((mechParams->kdf == CKD_NULL) &&
@@ -7324,18 +7210,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
             }
 
             /* Now we are working with a non-NULL private key */
             SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue);
 
             ecPoint.data = mechParams->pPublicData;
             ecPoint.len = mechParams->ulPublicDataLen;
 
-            curveLen = (privKey->u.ec.ecParams.fieldID.size + 7) / 8;
-            pubKeyLen = (2 * curveLen) + 1;
+            pubKeyLen = privKey->u.ec.ecParams.pointSize;
 
             /* if the len is too small, can't be a valid point */
             if (ecPoint.len < pubKeyLen) {
                 goto ec_loser;
             }
             /* if the len is too large, must be an encoded point (length is
              * equal case just falls through */
             if (ecPoint.len > pubKeyLen) {
--- a/security/nss/lib/softoken/softkver.h
+++ b/security/nss/lib/softoken/softkver.h
@@ -20,16 +20,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.27" SOFTOKEN_ECC_STRING " Beta"
+#define SOFTOKEN_VERSION "3.28" SOFTOKEN_ECC_STRING " Beta"
 #define SOFTOKEN_VMAJOR 3
-#define SOFTOKEN_VMINOR 27
+#define SOFTOKEN_VMINOR 28
 #define SOFTOKEN_VPATCH 0
 #define SOFTOKEN_VBUILD 0
 #define SOFTOKEN_BETA PR_TRUE
 
 #endif /* _SOFTKVER_H_ */
--- a/security/nss/lib/sqlite/Makefile
+++ b/security/nss/lib/sqlite/Makefile
@@ -9,16 +9,17 @@
 #######################################################################
 
 include manifest.mn
 
 #######################################################################
 # (2) Include "global" configuration information. (OPTIONAL)          #
 #######################################################################
 
+USE_GCOV =
 include $(CORE_DEPTH)/coreconf/config.mk
 
 #######################################################################
 # (3) Include "component" configuration information. (OPTIONAL)       #
 #######################################################################
 
 
 
--- a/security/nss/lib/ssl/derive.c
+++ b/security/nss/lib/ssl/derive.c
@@ -63,40 +63,35 @@ static const char *const mixers[NUM_MIXE
 };
 
 SECStatus
 ssl3_KeyAndMacDeriveBypass(
     ssl3CipherSpec *pwSpec,
     const unsigned char *cr,
     const unsigned char *sr,
     PRBool isTLS,
-    HASH_HashType tls12HashType,
-    PRBool isExport)
+    HASH_HashType tls12HashType)
 {
     const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def;
     unsigned char *key_block = pwSpec->key_block;
-    unsigned char *key_block2 = NULL;
-    unsigned int block_bytes = 0;
     unsigned int block_needed = 0;
     unsigned int i;
     unsigned int keySize;    /* actual    size of cipher keys */
     unsigned int effKeySize; /* effective size of cipher keys */
     unsigned int macSize;    /* size of MAC secret */
     unsigned int IVSize;     /* size of IV */
     PRBool explicitIV = PR_FALSE;
     SECStatus rv = SECFailure;
     SECStatus status = SECSuccess;
     PRBool isFIPS = PR_FALSE;
     PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2;
 
     SECItem srcr;
-    SECItem crsr;
 
     unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
-    unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
     PRUint64 md5buf[22];
     PRUint64 shabuf[40];
 
 #define md5Ctx ((MD5Context *)md5buf)
 #define shaCtx ((SHA1Context *)shabuf)
 
     static const SECItem zed = { siBuffer, NULL, 0 };
 
@@ -118,41 +113,33 @@ ssl3_KeyAndMacDeriveBypass(
         effKeySize = IVSize = 0; /* only MACing */
     }
     if (cipher_def->type == type_block &&
         pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
         /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */
         explicitIV = PR_TRUE;
     }
     block_needed =
-        2 * (macSize + effKeySize + ((!isExport && !explicitIV) * IVSize));
+        2 * (macSize + effKeySize + ((!explicitIV) * IVSize));
 
     /*
      * clear out our returned keys so we can recover on failure
      */
     pwSpec->client.write_key_item = zed;
     pwSpec->client.write_mac_key_item = zed;
     pwSpec->server.write_key_item = zed;
     pwSpec->server.write_mac_key_item = zed;
 
     /* initialize the server random, client random block */
     srcr.type = siBuffer;
     srcr.data = srcrdata;
     srcr.len = sizeof srcrdata;
     PORT_Memcpy(srcrdata, sr, SSL3_RANDOM_LENGTH);
     PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, cr, SSL3_RANDOM_LENGTH);
 
-    /* initialize the client random, server random block */
-    crsr.type = siBuffer;
-    crsr.data = crsrdata;
-    crsr.len = sizeof crsrdata;
-    PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH);
-    PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH);
-    PRINT_BUF(100, (NULL, "Key & MAC CRSR", crsr.data, crsr.len));
-
     /*
      * generate the key material:
      */
     if (isTLS) {
         SECItem keyblk;
 
         keyblk.type = siBuffer;
         keyblk.data = key_block;
@@ -163,17 +150,16 @@ ssl3_KeyAndMacDeriveBypass(
                                 "key expansion", &srcr, &keyblk, isFIPS);
         } else {
             status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk,
                              isFIPS);
         }
         if (status != SECSuccess) {
             goto key_and_mac_derive_fail;
         }
-        block_bytes = keyblk.len;
     } else {
         /* key_block =
         *     MD5(master_secret + SHA('A' + master_secret +
         *                      ServerHello.random + ClientHello.random)) +
         *     MD5(master_secret + SHA('BB' + master_secret +
         *                      ServerHello.random + ClientHello.random)) +
         *     MD5(master_secret + SHA('CCC' + master_secret +
         *                      ServerHello.random + ClientHello.random)) +
@@ -193,26 +179,18 @@ ssl3_KeyAndMacDeriveBypass(
 
             MD5_Begin(md5Ctx);
             MD5_Update(md5Ctx, pwSpec->msItem.data, pwSpec->msItem.len);
             MD5_Update(md5Ctx, sha_out, outLen);
             MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH);
             PORT_Assert(outLen == MD5_LENGTH);
             made += MD5_LENGTH;
         }
-        block_bytes = made;
     }
-    PORT_Assert(block_bytes >= block_needed);
-    PORT_Assert(block_bytes <= sizeof pwSpec->key_block);
-    PRINT_BUF(100, (NULL, "key block", key_block, block_bytes));
 
-    /*
-     * Put the key material where it goes.
-     */
-    key_block2 = key_block + block_bytes;
     i = 0; /* now shows how much consumed */
 
     /*
      * The key_block is partitioned as follows:
      * client_write_MAC_secret[CipherSpec.hash_size]
      */
     buildSSLKey(&key_block[i], macSize, &pwSpec->client.write_mac_key_item,
                 "Client Write MAC Secret");
@@ -230,17 +208,17 @@ ssl3_KeyAndMacDeriveBypass(
         buildSSLKey(NULL, 0, &pwSpec->client.write_key_item,
                     "Client Write Key (MAC only)");
         buildSSLKey(NULL, 0, &pwSpec->server.write_key_item,
                     "Server Write Key (MAC only)");
         buildSSLKey(NULL, 0, &pwSpec->client.write_iv_item,
                     "Client Write IV (MAC only)");
         buildSSLKey(NULL, 0, &pwSpec->server.write_iv_item,
                     "Server Write IV (MAC only)");
-    } else if (!isExport) {
+    } else {
         /*
         ** Generate Domestic write keys and IVs.
         ** client_write_key[CipherSpec.key_material]
         */
         buildSSLKey(&key_block[i], keySize, &pwSpec->client.write_key_item,
                     "Domestic Client Write Key");
         i += keySize;
 
@@ -271,149 +249,18 @@ ssl3_KeyAndMacDeriveBypass(
                 i += IVSize;
 
                 /*
                 ** server_write_IV[CipherSpec.IV_size]
                 */
                 buildSSLKey(&key_block[i], IVSize,
                             &pwSpec->server.write_iv_item,
                             "Domestic Server Write IV");
-                i += IVSize;
             }
         }
-        PORT_Assert(i <= block_bytes);
-    } else if (!isTLS) {
-        /*
-        ** Generate SSL3 Export write keys and IVs.
-        */
-        unsigned int outLen;
-
-        /*
-        ** client_write_key[CipherSpec.key_material]
-        ** final_client_write_key = MD5(client_write_key +
-        **                   ClientHello.random + ServerHello.random);
-        */
-        MD5_Begin(md5Ctx);
-        MD5_Update(md5Ctx, &key_block[i], effKeySize);
-        MD5_Update(md5Ctx, crsr.data, crsr.len);
-        MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
-        i += effKeySize;
-        buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item,
-                    "SSL3 Export Client Write Key");
-        key_block2 += keySize;
-
-        /*
-        ** server_write_key[CipherSpec.key_material]
-        ** final_server_write_key = MD5(server_write_key +
-        **                    ServerHello.random + ClientHello.random);
-        */
-        MD5_Begin(md5Ctx);
-        MD5_Update(md5Ctx, &key_block[i], effKeySize);
-        MD5_Update(md5Ctx, srcr.data, srcr.len);
-        MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
-        i += effKeySize;
-        buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item,
-                    "SSL3 Export Server Write Key");
-        key_block2 += keySize;
-        PORT_Assert(i <= block_bytes);
-
-        if (IVSize) {
-            /*
-            ** client_write_IV =
-            **  MD5(ClientHello.random + ServerHello.random);
-            */
-            MD5_Begin(md5Ctx);
-            MD5_Update(md5Ctx, crsr.data, crsr.len);
-            MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
-            buildSSLKey(key_block2, IVSize, &pwSpec->client.write_iv_item,
-                        "SSL3 Export Client Write IV");
-            key_block2 += IVSize;
-
-            /*
-            ** server_write_IV =
-            **  MD5(ServerHello.random + ClientHello.random);
-            */
-            MD5_Begin(md5Ctx);
-            MD5_Update(md5Ctx, srcr.data, srcr.len);
-            MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
-            buildSSLKey(key_block2, IVSize, &pwSpec->server.write_iv_item,
-                        "SSL3 Export Server Write IV");
-            key_block2 += IVSize;
-        }
-
-        PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block);
-    } else {
-        /*
-        ** Generate TLS Export write keys and IVs.
-        */
-        SECItem secret;
-        SECItem keyblk;
-
-        secret.type = siBuffer;
-        keyblk.type = siBuffer;
-        /*
-        ** client_write_key[CipherSpec.key_material]
-        ** final_client_write_key = PRF(client_write_key,
-        **                              "client write key",
-        **                              client_random + server_random);
-        */
-        secret.data = &key_block[i];
-        secret.len = effKeySize;
-        i += effKeySize;
-        keyblk.data = key_block2;
-        keyblk.len = keySize;
-        status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, isFIPS);
-        if (status != SECSuccess) {
-            goto key_and_mac_derive_fail;
-        }
-        buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item,
-                    "TLS Export Client Write Key");
-        key_block2 += keySize;
-
-        /*
-        ** server_write_key[CipherSpec.key_material]
-        ** final_server_write_key = PRF(server_write_key,
-        **                              "server write key",
-        **                              client_random + server_random);
-        */
-        secret.data = &key_block[i];
-        secret.len = effKeySize;
-        keyblk.data = key_block2;
-        keyblk.len = keySize;
-        status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, isFIPS);
-        if (status != SECSuccess) {
-            goto key_and_mac_derive_fail;
-        }
-        buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item,
-                    "TLS Export Server Write Key");
-        key_block2 += keySize;
-
-        /*
-        ** iv_block = PRF("", "IV block", client_random + server_random);
-        ** client_write_IV[SecurityParameters.IV_size]
-        ** server_write_IV[SecurityParameters.IV_size]
-        */
-        if (IVSize) {
-            secret.data = NULL;
-            secret.len = 0;
-            keyblk.data = key_block2;
-            keyblk.len = 2 * IVSize;
-            status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, isFIPS);
-            if (status != SECSuccess) {
-                goto key_and_mac_derive_fail;
-            }
-            buildSSLKey(key_block2, IVSize,
-                        &pwSpec->client.write_iv_item,
-                        "TLS Export Client Write IV");
-            buildSSLKey(key_block2 + IVSize, IVSize,
-                        &pwSpec->server.write_iv_item,
-                        "TLS Export Server Write IV");
-            key_block2 += 2 * IVSize;
-        }
-        PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block);
     }
     rv = SECSuccess;
 
 key_and_mac_derive_fail:
 
     MD5_DestroyContext(md5Ctx, PR_FALSE);
     SHA1_DestroyContext(shaCtx, PR_FALSE);
 
@@ -612,17 +459,16 @@ SSL_CanBypass(CERTCertificate *cert, SEC
     PK11SlotInfo *slot = NULL;
     SECItem param;
     CK_VERSION version;
     CK_MECHANISM_TYPE mechanism_array[2];
     SECItem enc_pms = { siBuffer, NULL, 0 };
     PRBool isTLS = PR_FALSE;
     SSLCipherSuiteInfo csdef;
     PRBool testrsa = PR_FALSE;
-    PRBool testrsa_export = PR_FALSE;
     PRBool testecdh = PR_FALSE;
     PRBool testecdhe = PR_FALSE;
     SECKEYECParams ecParams = { siBuffer, NULL, 0 };
 
     if (!cert || !srvPrivkey || !ciphersuites || !pcanbypass) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
@@ -638,25 +484,17 @@ SSL_CanBypass(CERTCertificate *cert, SEC
      * SSL3 and TLS specs forbid negotiating that cipher suite number.
      */
     for (i = 0; i < nsuites && (suite = *ciphersuites++) != 0; i++) {
         /* skip cipher suites NSS doesn't support */
         if (SSL_GetCipherSuiteInfo(suite, &csdef, sizeof(csdef)) != SECSuccess)
             continue;
         switch (csdef.keaType) {
             case ssl_kea_rsa:
-                switch (csdef.cipherSuite) {
-                    case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA:
-                    case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA:
-                    case TLS_RSA_EXPORT_WITH_RC4_40_MD5:
-                    case TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
-                        testrsa_export = PR_TRUE;
-                }
-                if (!testrsa_export)
-                    testrsa = PR_TRUE;
+                testrsa = PR_TRUE;
                 break;
             case ssl_kea_ecdh:
                 if (strcmp(csdef.keaTypeName, "ECDHE") == 0) /* ephemeral? */
                     testecdhe = PR_TRUE;
                 else
                     testecdh = PR_TRUE;
                 break;
             case ssl_kea_dh:
@@ -677,23 +515,16 @@ SSL_CanBypass(CERTCertificate *cert, SEC
         if (protocolmask & SSL_CBP_SSL3) {
             isTLS = PR_FALSE;
             protocolmask ^= SSL_CBP_SSL3;
         } else {
             isTLS = PR_TRUE;
             protocolmask ^= SSL_CBP_TLS1_0;
         }
 
-        if (privKeytype == rsaKey && testrsa_export) {
-            if (PK11_GetPrivateModulusLen(srvPrivkey) > EXPORT_RSA_KEY_LENGTH) {
-                *pcanbypass = PR_FALSE;
-                break;
-            } else
-                testrsa = PR_TRUE;
-        }
         for (; privKeytype == rsaKey && testrsa;) {
             /* TLS_RSA */
             unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
             unsigned int outLen = 0;
             CK_MECHANISM_TYPE target;
             SECStatus irv;
 
             mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN;
@@ -762,17 +593,17 @@ SSL_CanBypass(CERTCertificate *cert, SEC
             SECKEYPrivateKey *cpriv = NULL;
             SECKEYECParams *pecParams = NULL;
 
             if (privKeytype == ecKey && testecdhe) {
                 /* TLS_ECDHE_ECDSA */
                 pecParams = &srvPubkey->u.ec.DEREncodedParams;
             } else if (privKeytype == rsaKey && testecdhe) {
                 /* TLS_ECDHE_RSA */
-                const namedGroupDef *ecGroup;
+                const sslNamedGroupDef *ecGroup;
                 int serverKeyStrengthInBits;
                 int signatureKeyStrength;
                 int requiredECCbits;
 
                 /* find a curve of equivalent strength to the RSA key's */
                 requiredECCbits = PK11_GetPrivateModulusLen(srvPrivkey);
                 if (requiredECCbits < 0)
                     break;
--- a/security/nss/lib/ssl/dtlscon.c
+++ b/security/nss/lib/ssl/dtlscon.c
@@ -35,18 +35,16 @@ static const PRUint16 COMMON_MTU_VALUES[
 static const ssl3CipherSuite nonDTLSSuites[] = {
     TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
     TLS_ECDHE_RSA_WITH_RC4_128_SHA,
     TLS_DHE_DSS_WITH_RC4_128_SHA,
     TLS_ECDH_RSA_WITH_RC4_128_SHA,
     TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
     TLS_RSA_WITH_RC4_128_MD5,
     TLS_RSA_WITH_RC4_128_SHA,
-    TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
-    TLS_RSA_EXPORT_WITH_RC4_40_MD5,
     0 /* End of list marker */
 };
 
 /* Map back and forth between TLS and DTLS versions in wire format.
  * Mapping table is:
  *
  * TLS             DTLS
  * 1.1 (0302)      1.0 (feff)
--- a/security/nss/lib/ssl/manifest.mn
+++ b/security/nss/lib/ssl/manifest.mn
@@ -1,55 +1,56 @@
-# 
+#
 # 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/.
 CORE_DEPTH = ../..
 
 # DEFINES = -DTRACE
 
 EXPORTS = \
-	ssl.h \
-	sslt.h \
-	sslerr.h \
-	sslproto.h \
-	preenc.h \
-	$(NULL)
+        ssl.h \
+        sslt.h \
+        sslerr.h \
+        sslproto.h \
+        preenc.h \
+        $(NULL)
 
 MODULE = nss
 MAPFILE = $(OBJDIR)/ssl.def
 
 CSRCS = \
-	derive.c \
-	dtlscon.c \
-	prelib.c \
-	ssl3con.c \
-	ssl3gthr.c \
-	sslauth.c \
-	sslcon.c \
-	ssldef.c \
-	sslenum.c \
-	sslerr.c \
-	sslerrstrs.c \
-	sslinit.c \
-	ssl3ext.c \
-	sslmutex.c \
-	sslnonce.c \
-	sslreveal.c \
-	sslsecur.c \
-	sslsnce.c \
-	sslsock.c \
-	ssltrace.c \
-	sslver.c \
-	authcert.c \
-	cmpcert.c \
-	sslinfo.c \
-	ssl3ecc.c \
+        derive.c \
+        dtlscon.c \
+        prelib.c \
+        ssl3con.c \
+        ssl3gthr.c \
+        sslauth.c \
+        sslcon.c \
+        ssldef.c \
+        sslenum.c \
+        sslerr.c \
+        sslerrstrs.c \
+        sslinit.c \
+        ssl3ext.c \
+        sslmutex.c \
+        sslnonce.c \
+        sslreveal.c \
+        sslsecur.c \
+        sslsnce.c \
+        sslsock.c \
+        ssltrace.c \
+        sslver.c \
+        authcert.c \
+        cmpcert.c \
+        sslinfo.c \
+        ssl3ecc.c \
         tls13con.c \
         tls13hkdf.c \
         sslcert.c \
-	$(NULL)
+        sslgrp.c \
+        $(NULL)
 
 LIBRARY_NAME = ssl
 LIBRARY_VERSION = 3
 
 # This part of the code, including all sub-dirs, can be optimized for size
 export ALLOW_OPT_CODE_SIZE = 1
--- a/security/nss/lib/ssl/ssl.h
+++ b/security/nss/lib/ssl/ssl.h
@@ -97,20 +97,17 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRF
                                    /* (off by default) */
 
 /* OBSOLETE: See "SSL Version Range API" below for the replacement and a
 ** description of the non-obvious semantics of using SSL_ENABLE_TLS.
 */
 #define SSL_ENABLE_TLS 13 /* enable TLS (on by default) */
 
 #define SSL_ROLLBACK_DETECTION 14       /* for compatibility, default: on */
-#define SSL_NO_STEP_DOWN 15             /* Disable export cipher suites   */
-                                        /* if step-down keys are needed.  */
-                                        /* default: off, generate         */
-                                        /* step-down keys if needed.      */
+#define SSL_NO_STEP_DOWN 15             /* (unsupported, deprecated, off) */
 #define SSL_BYPASS_PKCS11 16            /* use PKCS#11 for pub key only   */
 #define SSL_NO_LOCKS 17                 /* Don't use locks for protection */
 #define SSL_ENABLE_SESSION_TICKETS 18   /* Enable TLS SessionTicket       */
                                         /* extension (off by default)     */
 #define SSL_ENABLE_DEFLATE 19           /* Enable TLS compression with    */
                                         /* DEFLATE (off by default)       */
 #define SSL_ENABLE_RENEGOTIATION 20     /* Values below (default: never)  */
 #define SSL_REQUIRE_SAFE_NEGOTIATION 21 /* Peer must send Signaling       */
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -94,26 +94,20 @@ PRBool ssl_IsRsaPssSignatureScheme(Signa
  * in this table must match the ordering in SSL_ImplementedCiphers (sslenum.c)
  *
  * Important: See bug 946147 before enabling, reordering, or adding any cipher
  * suites to this list.
  */
 /* clang-format off */
 static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
    /*      cipher_suite                     policy       enabled   isPresent */
-
- /* ECDHE-PSK from [draft-mattsson-tls-ecdhe-psk-aead]. We only enable PSK if we
-  * are doing TLS 1.3 PSK-resumption.
-  */
- { TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE },
- { TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE },
- { TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_TRUE, PR_FALSE },
- { TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE },
- { TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE },
- { TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_TRUE, PR_FALSE },
+ /* Special TLS 1.3 suites. */
+ { TLS_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE },
+ { TLS_CHACHA20_POLY1305_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE },
+ { TLS_AES_256_GCM_SHA384, SSL_ALLOWED, PR_TRUE, PR_FALSE },
 
  { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
  { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,   SSL_ALLOWED, PR_TRUE, PR_FALSE},
  { TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
  { TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,   SSL_ALLOWED, PR_TRUE, PR_FALSE},
  { TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_FALSE, PR_FALSE},
  { TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,   SSL_ALLOWED, PR_FALSE, PR_FALSE},
    /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA is out of order to work around
@@ -167,35 +161,25 @@ static ssl3CipherSuiteCfg cipherSuites[s
  { TLS_RSA_WITH_AES_256_GCM_SHA384,         SSL_ALLOWED, PR_FALSE, PR_FALSE},
  { TLS_RSA_WITH_AES_128_CBC_SHA,            SSL_ALLOWED, PR_TRUE,  PR_FALSE},
  { TLS_RSA_WITH_AES_128_CBC_SHA256,         SSL_ALLOWED, PR_TRUE,  PR_FALSE},
  { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,       SSL_ALLOWED, PR_FALSE, PR_FALSE},
  { TLS_RSA_WITH_AES_256_CBC_SHA,            SSL_ALLOWED, PR_TRUE,  PR_FALSE},
  { TLS_RSA_WITH_AES_256_CBC_SHA256,         SSL_ALLOWED, PR_TRUE,  PR_FALSE},
  { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,       SSL_ALLOWED, PR_FALSE, PR_FALSE},
  { TLS_RSA_WITH_SEED_CBC_SHA,               SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,      SSL_ALLOWED, PR_FALSE, PR_FALSE},
  { TLS_RSA_WITH_3DES_EDE_CBC_SHA,           SSL_ALLOWED, PR_TRUE,  PR_FALSE},
  { TLS_RSA_WITH_RC4_128_SHA,                SSL_ALLOWED, PR_TRUE,  PR_FALSE},
  { TLS_RSA_WITH_RC4_128_MD5,                SSL_ALLOWED, PR_TRUE,  PR_FALSE},
 
  /* 56-bit DES "domestic" cipher suites */
  { TLS_DHE_RSA_WITH_DES_CBC_SHA,            SSL_ALLOWED, PR_FALSE, PR_FALSE},
  { TLS_DHE_DSS_WITH_DES_CBC_SHA,            SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { SSL_RSA_FIPS_WITH_DES_CBC_SHA,           SSL_ALLOWED, PR_FALSE, PR_FALSE},
  { TLS_RSA_WITH_DES_CBC_SHA,                SSL_ALLOWED, PR_FALSE, PR_FALSE},
 
- /* export ciphersuites with 1024-bit public key exchange keys */
- { TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,      SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,     SSL_ALLOWED, PR_FALSE, PR_FALSE},
-
- /* export ciphersuites with 512-bit public key exchange keys */
- { TLS_RSA_EXPORT_WITH_RC4_40_MD5,          SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,      SSL_ALLOWED, PR_FALSE, PR_FALSE},
-
  /* ciphersuites with no encryption */
  { TLS_ECDHE_ECDSA_WITH_NULL_SHA,           SSL_ALLOWED, PR_FALSE, PR_FALSE},
  { TLS_ECDHE_RSA_WITH_NULL_SHA,             SSL_ALLOWED, PR_FALSE, PR_FALSE},
  { TLS_ECDH_RSA_WITH_NULL_SHA,              SSL_ALLOWED, PR_FALSE, PR_FALSE},
  { TLS_ECDH_ECDSA_WITH_NULL_SHA,            SSL_ALLOWED, PR_FALSE, PR_FALSE},
  { TLS_RSA_WITH_NULL_SHA,                   SSL_ALLOWED, PR_FALSE, PR_FALSE},
  { TLS_RSA_WITH_NULL_SHA256,                SSL_ALLOWED, PR_FALSE, PR_FALSE},
  { TLS_RSA_WITH_NULL_MD5,                   SSL_ALLOWED, PR_FALSE, PR_FALSE},
@@ -280,18 +264,16 @@ compressionEnabled(sslSocket *ss, SSLCom
 }
 
 static const /*SSL3ClientCertificateType */ PRUint8 certificate_types[] = {
     ct_RSA_sign,
     ct_ECDSA_sign,
     ct_DSS_sign,
 };
 
-#define EXPORT_RSA_KEY_LENGTH 64 /* bytes */
-
 /* This global item is used only in servers.  It is is initialized by
 ** SSL_ConfigSecureServer(), and is used in ssl3_SendCertificateRequest().
 */
 CERTDistNames *ssl3_server_ca_list = NULL;
 static SSL3Statistics ssl3stats;
 
 /* Record protection algorithms, indexed by SSL3BulkCipher.
  *
@@ -345,57 +327,46 @@ static const ssl3BulkCipherDef bulk_ciph
     {cipher_chacha20,     calg_chacha20, 32,32, type_aead,  12, 0,16, 0,
      SEC_OID_CHACHA20_POLY1305, "ChaCha20-Poly1305", MR_MAX},
     {cipher_missing,      calg_null,      0, 0, type_stream, 0, 0, 0, 0,
      SEC_OID_UNKNOWN,     "missing", 0U},
 };
 
 static const ssl3KEADef kea_defs[] =
 { /* indexed by SSL3KeyExchangeAlgorithm */
-    /* kea            exchKeyType signKeyType authKeyType, is_limited limit tls_keygen ephemeral  oid */
-    {kea_null,           ssl_kea_null, nullKey, ssl_auth_null, PR_FALSE,   0, PR_FALSE, PR_FALSE, 0},
-    {kea_rsa,            ssl_kea_rsa,  nullKey, ssl_auth_rsa_decrypt,  PR_FALSE,   0, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA},
-    /* note: export suites abuse RSA, but these will be removed soon */
-    {kea_rsa_export,     ssl_kea_rsa,  rsaKey, ssl_auth_rsa_sign, PR_TRUE,  512, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA_EXPORT},
-    {kea_rsa_export_1024,ssl_kea_rsa,  rsaKey, ssl_auth_rsa_sign, PR_TRUE, 1024, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA_EXPORT},
-    {kea_dh_dss,         ssl_kea_dh,   dsaKey, ssl_auth_dsa,  PR_FALSE,   0, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_DSS},
-    {kea_dh_dss_export,  ssl_kea_dh,   dsaKey, ssl_auth_dsa,   PR_TRUE,  512, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_DSS_EXPORT},
-    {kea_dh_rsa,         ssl_kea_dh,   rsaKey, ssl_auth_rsa_sign,   PR_FALSE,   0, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_RSA},
-    {kea_dh_rsa_export,  ssl_kea_dh,   rsaKey, ssl_auth_rsa_sign,   PR_TRUE,  512, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_RSA_EXPORT},
-    {kea_dhe_dss,        ssl_kea_dh,   dsaKey, ssl_auth_dsa,   PR_FALSE,   0, PR_FALSE, PR_TRUE,  SEC_OID_TLS_DHE_DSS},
-    {kea_dhe_dss_export, ssl_kea_dh,   dsaKey, ssl_auth_dsa,   PR_TRUE,  512, PR_FALSE, PR_TRUE,  SEC_OID_TLS_DHE_DSS_EXPORT},
-    {kea_dhe_rsa,        ssl_kea_dh,   rsaKey, ssl_auth_rsa_sign,   PR_FALSE,   0, PR_FALSE, PR_TRUE,  SEC_OID_TLS_DHE_RSA},
-    {kea_dhe_rsa_export, ssl_kea_dh,   rsaKey, ssl_auth_rsa_sign,   PR_TRUE,  512, PR_FALSE, PR_TRUE,  SEC_OID_TLS_DHE_RSA_EXPORT},
-    {kea_dh_anon,        ssl_kea_dh,   nullKey, ssl_auth_null, PR_FALSE,   0, PR_FALSE, PR_TRUE,  SEC_OID_TLS_DH_ANON},
-    {kea_dh_anon_export, ssl_kea_dh,   nullKey, ssl_auth_null, PR_TRUE,  512, PR_FALSE, PR_TRUE,  SEC_OID_TLS_DH_ANON_EXPORT},
-    {kea_rsa_fips,       ssl_kea_rsa,  rsaKey, ssl_auth_rsa_decrypt,   PR_FALSE,   0, PR_TRUE,  PR_FALSE, SEC_OID_TLS_RSA},
-    {kea_ecdh_ecdsa,     ssl_kea_ecdh, nullKey, ssl_auth_ecdh_ecdsa, PR_FALSE,   0, PR_FALSE, PR_FALSE, SEC_OID_TLS_ECDH_ECDSA},
-    {kea_ecdhe_ecdsa,    ssl_kea_ecdh, ecKey, ssl_auth_ecdsa, PR_FALSE,   0, PR_FALSE, PR_TRUE,  SEC_OID_TLS_ECDHE_ECDSA},
-    {kea_ecdh_rsa,       ssl_kea_ecdh, nullKey, ssl_auth_ecdh_rsa, PR_FALSE,   0, PR_FALSE, PR_FALSE, SEC_OID_TLS_ECDH_RSA},
-    {kea_ecdhe_rsa,      ssl_kea_ecdh, rsaKey, ssl_auth_rsa_sign,   PR_FALSE,   0, PR_FALSE, PR_TRUE,  SEC_OID_TLS_ECDHE_RSA},
-    {kea_ecdh_anon,      ssl_kea_ecdh, nullKey, ssl_auth_null, PR_FALSE,   0, PR_FALSE, PR_TRUE,  SEC_OID_TLS_ECDH_ANON},
-    {kea_ecdhe_psk,      ssl_kea_ecdh_psk, nullKey, ssl_auth_psk, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_ECDHE_PSK},
-    {kea_dhe_psk,      ssl_kea_dh_psk, nullKey, ssl_auth_psk, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_DHE_PSK},
+    /* kea            exchKeyType signKeyType authKeyType ephemeral  oid */
+    {kea_null,           ssl_kea_null, nullKey, ssl_auth_null, PR_FALSE, 0},
+    {kea_rsa,            ssl_kea_rsa,  nullKey, ssl_auth_rsa_decrypt, PR_FALSE, SEC_OID_TLS_RSA},
+    {kea_dh_dss,         ssl_kea_dh,   dsaKey, ssl_auth_dsa, PR_FALSE, SEC_OID_TLS_DH_DSS},
+    {kea_dh_rsa,         ssl_kea_dh,   rsaKey, ssl_auth_rsa_sign, PR_FALSE, SEC_OID_TLS_DH_RSA},
+    {kea_dhe_dss,        ssl_kea_dh,   dsaKey, ssl_auth_dsa, PR_TRUE,  SEC_OID_TLS_DHE_DSS},
+    {kea_dhe_rsa,        ssl_kea_dh,   rsaKey, ssl_auth_rsa_sign, PR_TRUE,  SEC_OID_TLS_DHE_RSA},
+    {kea_dh_anon,        ssl_kea_dh,   nullKey, ssl_auth_null, PR_TRUE,  SEC_OID_TLS_DH_ANON},
+    {kea_ecdh_ecdsa,     ssl_kea_ecdh, nullKey, ssl_auth_ecdh_ecdsa, PR_FALSE, SEC_OID_TLS_ECDH_ECDSA},
+    {kea_ecdhe_ecdsa,    ssl_kea_ecdh, ecKey, ssl_auth_ecdsa, PR_TRUE,  SEC_OID_TLS_ECDHE_ECDSA},
+    {kea_ecdh_rsa,       ssl_kea_ecdh, nullKey, ssl_auth_ecdh_rsa, PR_FALSE, SEC_OID_TLS_ECDH_RSA},
+    {kea_ecdhe_rsa,      ssl_kea_ecdh, rsaKey, ssl_auth_rsa_sign, PR_TRUE,  SEC_OID_TLS_ECDHE_RSA},
+    {kea_ecdh_anon,      ssl_kea_ecdh, nullKey, ssl_auth_null, PR_TRUE,  SEC_OID_TLS_ECDH_ANON},
+    {kea_ecdhe_psk,      ssl_kea_ecdh_psk, nullKey, ssl_auth_psk, PR_TRUE, SEC_OID_TLS_ECDHE_PSK},
+    {kea_dhe_psk,      ssl_kea_dh_psk, nullKey, ssl_auth_psk, PR_TRUE, SEC_OID_TLS_DHE_PSK},
+    {kea_tls13_any,      ssl_kea_tls13_any, nullKey, ssl_auth_tls13_any, PR_TRUE, SEC_OID_TLS13_KEA_ANY},    
 };
 
 /* must use ssl_LookupCipherSuiteDef to access */
 static const ssl3CipherSuiteDef cipher_suite_defs[] =
 {
 /*  cipher_suite                    bulk_cipher_alg mac_alg key_exchange_alg prf_hash_alg */
 /*  Note that the prf_hash_alg is the hash function used by the PRF, see sslimpl.h.  */
 
     {TLS_NULL_WITH_NULL_NULL,       cipher_null,   mac_null, kea_null, ssl_hash_none},
     {TLS_RSA_WITH_NULL_MD5,         cipher_null,   mac_md5, kea_rsa, ssl_hash_none},
     {TLS_RSA_WITH_NULL_SHA,         cipher_null,   mac_sha, kea_rsa, ssl_hash_none},
     {TLS_RSA_WITH_NULL_SHA256,      cipher_null,   hmac_sha256, kea_rsa, ssl_hash_sha256},
-    {TLS_RSA_EXPORT_WITH_RC4_40_MD5,cipher_rc4_40, mac_md5, kea_rsa_export, ssl_hash_none},
     {TLS_RSA_WITH_RC4_128_MD5,      cipher_rc4,    mac_md5, kea_rsa, ssl_hash_none},
     {TLS_RSA_WITH_RC4_128_SHA,      cipher_rc4,    mac_sha, kea_rsa, ssl_hash_none},
-    {TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
-                                    cipher_rc2_40, mac_md5, kea_rsa_export, ssl_hash_none},
     {TLS_RSA_WITH_DES_CBC_SHA,      cipher_des,    mac_sha, kea_rsa, ssl_hash_none},
     {TLS_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des,   mac_sha, kea_rsa, ssl_hash_none},
     {TLS_DHE_DSS_WITH_DES_CBC_SHA,  cipher_des,    mac_sha, kea_dhe_dss, ssl_hash_none},
     {TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
                                     cipher_3des,   mac_sha, kea_dhe_dss, ssl_hash_none},
     {TLS_DHE_DSS_WITH_RC4_128_SHA,  cipher_rc4,    mac_sha, kea_dhe_dss, ssl_hash_none},
     {TLS_DHE_RSA_WITH_DES_CBC_SHA,  cipher_des,    mac_sha, kea_dhe_rsa, ssl_hash_none},
     {TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
@@ -423,24 +394,16 @@ static const ssl3CipherSuiteDef cipher_s
     {TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
      cipher_camellia_128, mac_sha, kea_dhe_rsa, ssl_hash_none},
     {TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, cipher_camellia_256, mac_sha, kea_rsa, ssl_hash_none},
     {TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
      cipher_camellia_256, mac_sha, kea_dhe_dss, ssl_hash_none},
     {TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
      cipher_camellia_256, mac_sha, kea_dhe_rsa, ssl_hash_none},
 
-    {TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,
-                                    cipher_des,    mac_sha,kea_rsa_export_1024, ssl_hash_none},
-    {TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
-                                    cipher_rc4_56, mac_sha,kea_rsa_export_1024, ssl_hash_none},
-
-    {SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_rsa_fips, ssl_hash_none},
-    {SSL_RSA_FIPS_WITH_DES_CBC_SHA, cipher_des,    mac_sha, kea_rsa_fips, ssl_hash_none},
-
     {TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_dhe_rsa, ssl_hash_sha256},
     {TLS_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_rsa, ssl_hash_sha256},
 
     {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_rsa, ssl_hash_sha256},
     {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_ecdsa, ssl_hash_sha256},
     {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, cipher_aes_256_gcm, mac_aead, kea_ecdhe_ecdsa, ssl_hash_sha384},
     {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, cipher_aes_256_gcm, mac_aead, kea_ecdhe_rsa, ssl_hash_sha384},
     {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, cipher_aes_256, hmac_sha384, kea_ecdhe_ecdsa, ssl_hash_sha384},
@@ -477,47 +440,46 @@ static const ssl3CipherSuiteDef cipher_s
 
     {TLS_ECDHE_RSA_WITH_NULL_SHA,         cipher_null,    mac_sha, kea_ecdhe_rsa, ssl_hash_none},
     {TLS_ECDHE_RSA_WITH_RC4_128_SHA,      cipher_rc4,     mac_sha, kea_ecdhe_rsa, ssl_hash_none},
     {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des,    mac_sha, kea_ecdhe_rsa, ssl_hash_none},
     {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,  cipher_aes_128, mac_sha, kea_ecdhe_rsa, ssl_hash_none},
     {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_ecdhe_rsa, ssl_hash_sha256},
     {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,  cipher_aes_256, mac_sha, kea_ecdhe_rsa, ssl_hash_none},
 
-    {TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_psk, ssl_hash_sha256},
-    {TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, cipher_chacha20, mac_aead, kea_ecdhe_psk, ssl_hash_sha256},
-    {TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384, cipher_aes_256_gcm, mac_aead, kea_ecdhe_psk, ssl_hash_sha384},
-    {TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_dhe_psk, ssl_hash_sha256},
-    {TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, cipher_chacha20, mac_aead, kea_dhe_psk, ssl_hash_sha256},
-    {TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, cipher_aes_256_gcm, mac_aead, kea_dhe_psk, ssl_hash_sha384},
+    {TLS_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_tls13_any, ssl_hash_sha256},
+    {TLS_CHACHA20_POLY1305_SHA256, cipher_chacha20, mac_aead, kea_tls13_any, ssl_hash_sha256},
+    {TLS_AES_256_GCM_SHA384, cipher_aes_256_gcm, mac_aead, kea_tls13_any, ssl_hash_sha384},
 };
 /* clang-format on */
 
 static const CK_MECHANISM_TYPE auth_alg_defs[] = {
     CKM_INVALID_MECHANISM, /* ssl_auth_null */
     CKM_RSA_PKCS,          /* ssl_auth_rsa_decrypt */
     CKM_DSA, /* ? _SHA1 */ /* ssl_auth_dsa */
     CKM_INVALID_MECHANISM, /* ssl_auth_kea (unused) */
     CKM_ECDSA,             /* ssl_auth_ecdsa */
     CKM_ECDH1_DERIVE,      /* ssl_auth_ecdh_rsa */
     CKM_ECDH1_DERIVE,      /* ssl_auth_ecdh_ecdsa */
     CKM_RSA_PKCS,          /* ssl_auth_rsa_sign */
     CKM_RSA_PKCS_PSS,      /* ssl_auth_rsa_pss */
-    CKM_NSS_HKDF_SHA256    /* ssl_auth_psk (just check for HKDF) */
+    CKM_NSS_HKDF_SHA256,   /* ssl_auth_psk (just check for HKDF) */
+    CKM_INVALID_MECHANISM  /* ssl_auth_tls13_any */
 };
 PR_STATIC_ASSERT(PR_ARRAY_SIZE(auth_alg_defs) == ssl_auth_size);
 
 static const CK_MECHANISM_TYPE kea_alg_defs[] = {
     CKM_INVALID_MECHANISM, /* ssl_kea_null */
     CKM_RSA_PKCS,          /* ssl_kea_rsa */
     CKM_DH_PKCS_DERIVE,    /* ssl_kea_dh */
     CKM_INVALID_MECHANISM, /* ssl_kea_fortezza (unused) */
     CKM_ECDH1_DERIVE,      /* ssl_kea_ecdh */
     CKM_ECDH1_DERIVE,      /* ssl_kea_ecdh_psk */
-    CKM_DH_PKCS_DERIVE     /* ssl_kea_dh_psk */
+    CKM_DH_PKCS_DERIVE,    /* ssl_kea_dh_psk */
+    CKM_INVALID_MECHANISM, /* ssl_kea_tls13_any */
 };
 PR_STATIC_ASSERT(PR_ARRAY_SIZE(kea_alg_defs) == ssl_kea_size);
 
 typedef struct SSLCipher2MechStr {
     SSLCipherAlgorithm calg;
     CK_MECHANISM_TYPE cmech;
 } SSLCipher2Mech;
 
@@ -713,59 +675,42 @@ SSL_AtomicIncrementLong(long *x)
 }
 
 static PRBool
 ssl3_CipherSuiteAllowedForVersionRange(
     ssl3CipherSuite cipherSuite,
     const SSLVersionRange *vrange)
 {
     switch (cipherSuite) {
-        /* See RFC 4346 A.5. Export cipher suites must not be used in TLS 1.1 or
-         * later. This set of cipher suites is similar to, but different from, the
-         * set of cipher suites considered exportable by SSL_IsExportCipherSuite.
-         */
-        case TLS_RSA_EXPORT_WITH_RC4_40_MD5:
-        case TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
-            /*   TLS_RSA_EXPORT_WITH_DES40_CBC_SHA:      never implemented
-             *   TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:   never implemented
-             *   TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:   never implemented
-             *   TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:  never implemented
-             *   TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:  never implemented
-             *   TLS_DH_anon_EXPORT_WITH_RC4_40_MD5:     never implemented
-             *   TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA:  never implemented
-             */
-            return vrange->min <= SSL_LIBRARY_VERSION_TLS_1_0;
-
         case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
         case TLS_RSA_WITH_AES_256_CBC_SHA256:
         case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
         case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
         case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
         case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
         case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
         case TLS_RSA_WITH_AES_128_CBC_SHA256:
         case TLS_RSA_WITH_AES_128_GCM_SHA256:
         case TLS_RSA_WITH_AES_256_GCM_SHA384:
         case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
         case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
         case TLS_RSA_WITH_NULL_SHA256:
         case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
         case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
-            return vrange->max == SSL_LIBRARY_VERSION_TLS_1_2;
-
         case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
         case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
         case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
         case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
         case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
         case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
         case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
         case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
         case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
-            return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_2;
+            return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_2 &&
+                   vrange->min < SSL_LIBRARY_VERSION_TLS_1_3;
 
         /* RFC 4492: ECC cipher suites need TLS extensions to negotiate curves and
          * point formats.*/
         case TLS_ECDH_ECDSA_WITH_NULL_SHA:
         case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
         case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
         case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
         case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
@@ -782,22 +727,19 @@ ssl3_CipherSuiteAllowedForVersionRange(
         case TLS_ECDHE_RSA_WITH_NULL_SHA:
         case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
         case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
         case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
         case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
             return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_0 &&
                    vrange->min < SSL_LIBRARY_VERSION_TLS_1_3;
 
-        case TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256:
-        case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
-        case TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384:
-        case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
-        case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
-        case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+        case TLS_AES_128_GCM_SHA256:
+        case TLS_AES_256_GCM_SHA384:
+        case TLS_CHACHA20_POLY1305_SHA256:
             return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_3;
 
         default:
             return vrange->min < SSL_LIBRARY_VERSION_TLS_1_3;
     }
 }
 
 /* return pointer to ssl3CipherSuiteDef for suite, or NULL */
@@ -830,23 +772,22 @@ ssl_LookupCipherSuiteCfg(ssl3CipherSuite
             return &suites[i];
     }
     /* return NULL and let the caller handle it.  */
     PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
     return NULL;
 }
 
 static PRBool
-ssl_NamedGroupTypeEnabled(const sslSocket *ss, NamedGroupType groupType)
+ssl_NamedGroupTypeEnabled(const sslSocket *ss, SSLKEAType keaType)
 {
     unsigned int i;
     for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
         if (ss->namedGroupPreferences[i] &&
-            ss->namedGroupPreferences[i]->type == groupType &&
-            ssl_NamedGroupEnabled(ss, ss->namedGroupPreferences[i])) {
+            ss->namedGroupPreferences[i]->keaType == keaType) {
             return PR_TRUE;
         }
     }
     return PR_FALSE;
 }
 
 static PRBool
 ssl_KEAEnabled(const sslSocket *ss, SSLKEAType keaType)
@@ -856,52 +797,59 @@ ssl_KEAEnabled(const sslSocket *ss, SSLK
             return PR_TRUE;
 
         case ssl_kea_dh:
         case ssl_kea_dh_psk: {
             if (ss->sec.isServer && !ss->opt.enableServerDhe) {
                 return PR_FALSE;
             }
 
-            /* No need to check for a common FFDHE group if we are in TLS 1.2 or
-             * earlier and named groups aren't required. */
-            if (!ss->opt.requireDHENamedGroups &&
-                ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-                /* If the client indicates support for named FFDHE groups, check
-                 * that we have one in common. */
-                if (ss->sec.isServer && ss->ssl3.hs.peerSupportsFfdheGroups) {
-                    return ssl_NamedGroupTypeEnabled(ss, group_type_ff);
+            if (ss->sec.isServer) {
+                /* If the server requires named FFDHE groups, then the client
+                 * must have included an FFDHE group. peerSupportsFfdheGroups
+                 * is set to true in ssl_HandleSupportedGroupsXtn(). */
+                if (ss->opt.requireDHENamedGroups &&
+                    !ss->ssl3.hs.peerSupportsFfdheGroups) {
+                    return PR_FALSE;
                 }
-                return PR_TRUE;
-            }
-            /* If the server requires the extension, then the client must have
-             * already sent a ffdhe group. peerSupportsFfdheGroups is set to true in
-             * ssl_HandleSupportedGroupsXtn(). */
-            if (ss->sec.isServer && !ss->ssl3.hs.peerSupportsFfdheGroups) {
-                return PR_FALSE;
-            }
-            return ssl_NamedGroupTypeEnabled(ss, group_type_ff);
+
+                /* We can use the weak DH group if all of these are true:
+                 * 1. We don't require named groups.
+                 * 2. The peer doesn't support named groups.
+                 * 3. This isn't TLS 1.3.
+                 * 4. The weak group is enabled. */
+                if (!ss->opt.requireDHENamedGroups &&
+                    !ss->ssl3.hs.peerSupportsFfdheGroups &&
+                    ss->version < SSL_LIBRARY_VERSION_TLS_1_3 &&
+                    ss->ssl3.dheWeakGroupEnabled) {
+                    return PR_TRUE;
+                }
+            }
+            return ssl_NamedGroupTypeEnabled(ss, ssl_kea_dh);
         }
 
         case ssl_kea_ecdh:
         case ssl_kea_ecdh_psk:
-            return ssl_NamedGroupTypeEnabled(ss, group_type_ec);
+            return ssl_NamedGroupTypeEnabled(ss, ssl_kea_ecdh);
+
+        case ssl_kea_tls13_any:
+            return PR_TRUE;
 
         case ssl_kea_fortezza:
         default:
             PORT_Assert(0);
     }
     return PR_FALSE;
 }
 
 static PRBool
 ssl_HasCert(const sslSocket *ss, SSLAuthType authType)
 {
     PRCList *cursor;
-    if (authType == ssl_auth_null || authType == ssl_auth_psk) {
+    if (authType == ssl_auth_null || authType == ssl_auth_psk || authType == ssl_auth_tls13_any) {
         return PR_TRUE;
     }
     for (cursor = PR_NEXT_LINK(&ss->serverCerts);
          cursor != &ss->serverCerts;
          cursor = PR_NEXT_LINK(cursor)) {
         sslServerCert *cert = (sslServerCert *)cursor;
         if (cert->certType.authType != authType) {
             continue;
@@ -976,27 +924,28 @@ ssl3_config_match_init(sslSocket *ss)
             }
             cipher_alg = ssl_GetBulkCipherDef(cipher_def)->calg;
             cipher_mech = ssl3_Alg2Mech(cipher_alg);
 
             /* Mark the suites that are backed by real tokens, certs and keys */
             suite->isPresent = PR_TRUE;
 
             authType = kea_defs[cipher_def->key_exchange_alg].authKeyType;
-            if (authType != ssl_auth_null) {
+            if (authType != ssl_auth_null && authType != ssl_auth_tls13_any) {
                 if (ss->sec.isServer && !ssl_HasCert(ss, authType)) {
                     suite->isPresent = PR_FALSE;
                 }
                 if (!PK11_TokenExists(auth_alg_defs[authType])) {
                     suite->isPresent = PR_FALSE;
                 }
             }
 
             keaType = kea_defs[cipher_def->key_exchange_alg].exchKeyType;
             if (keaType != ssl_kea_null &&
+                keaType != ssl_kea_tls13_any &&
                 !PK11_TokenExists(kea_alg_defs[keaType])) {
                 suite->isPresent = PR_FALSE;
             }
 
             if (cipher_alg != calg_null &&
                 !PK11_TokenExists(cipher_mech)) {
                 suite->isPresent = PR_FALSE;
             }
@@ -1042,22 +991,16 @@ config_match(ssl3CipherSuiteCfg *suite, 
     if (!ssl_KEAEnabled(ss, kea_def->exchKeyType)) {
         return PR_FALSE;
     }
 
     if (ss->sec.isServer && !ssl_HasCert(ss, kea_def->authKeyType)) {
         return PR_FALSE;
     }
 
-    /* We only allow PSK for TLS 1.3 and only if there is resumption. */
-    if (kea_def->authKeyType == ssl_auth_psk &&
-        !tls13_AllowPskCipher(ss, cipher_def)) {
-        return PR_FALSE;
-    }
-
     return ssl3_CipherSuiteAllowedForVersionRange(suite->cipher_suite, vrange);
 }
 
 /* Return the number of cipher suites that are usable. */
 /* called from ssl3_SendClientHello */
 static int
 count_cipher_suites(sslSocket *ss, int policy)
 {
@@ -1071,38 +1014,19 @@ count_cipher_suites(sslSocket *ss, int p
             count++;
     }
     if (count <= 0) {
         PORT_SetError(SSL_ERROR_SSL_DISABLED);
     }
     return count;
 }
 
-PRBool
-tls13_PskSuiteEnabled(sslSocket *ss)
-{
-    int i;
-    const ssl3CipherSuiteDef *cipher_def;
-
-    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; ++i) {
-        ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
-
-        cipher_def = ssl_LookupCipherSuiteDef(suite->cipher_suite);
-        if (ssl_auth_psk == kea_defs[cipher_def->key_exchange_alg].authKeyType &&
-            config_match(suite, ss->ssl3.policy, &ss->vrange, ss)) {
-            return PR_TRUE;
-        }
-    }
-    return PR_FALSE;
-}
-
 /*
  * Null compression, mac and encryption functions
  */
-
 static SECStatus
 Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen,
             const unsigned char *input, int inputLen)
 {
     if (inputLen > maxOutputLen) {
         *outputLen = 0; /* Match PK11_CipherOp in setting outputLen */
         PORT_SetError(SEC_ERROR_OUTPUT_LEN);
         return SECFailure;
@@ -1377,18 +1301,17 @@ ssl3_VerifySignedHashes(sslSocket *ss, S
     }
     if (rv != SECSuccess) {
         ssl_MapLowLevelError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
     }
     return rv;
 }
 
 /* Caller must set hiLevel error code. */
-/* Called from ssl3_ComputeExportRSAKeyHash
- *             ssl3_ComputeDHKeyHash
+/* Called from ssl3_ComputeDHKeyHash
  * which are called from ssl3_HandleServerKeyExchange.
  *
  * hashAlg: ssl_hash_none indicates the pre-1.2, MD5/SHA1 combination hash.
  */
 SECStatus
 ssl3_ComputeCommonKeyHash(SSLHashType hashAlg,
                           PRUint8 *hashBuf, unsigned int bufLen,
                           SSL3Hashes *hashes, PRBool bypassPKCS11)
@@ -1446,83 +1369,16 @@ ssl3_ComputeCommonKeyHash(SSLHashType ha
                 return rv;
             }
         }
     }
     hashes->hashAlg = hashAlg;
     return SECSuccess;
 }
 
-/* Caller must set hiLevel error code.
-** Called from ssl3_SendServerKeyExchange and
-**             ssl3_HandleServerKeyExchange.
-*/
-static SECStatus
-ssl3_ComputeExportRSAKeyHash(SSLHashType hashAlg,
-                             SECItem modulus, SECItem publicExponent,
-                             SSL3Random *client_rand, SSL3Random *server_rand,
-                             SSL3Hashes *hashes, PRBool bypassPKCS11)
-{
-    PRUint8 *hashBuf;
-    PRUint8 *pBuf;
-    SECStatus rv = SECSuccess;
-    unsigned int bufLen;
-    PRUint8 buf[2 * SSL3_RANDOM_LENGTH + 2 + 4096 / 8 + 2 + 4096 / 8];
-
-    PORT_Assert(publicExponent.data);
-    PORT_Assert(modulus.data);
-
-    bufLen = 2 * SSL3_RANDOM_LENGTH + 2 + modulus.len + 2 + publicExponent.len;
-    if (bufLen <= sizeof buf) {
-        hashBuf = buf;
-    } else {
-        hashBuf = PORT_Alloc(bufLen);
-        if (!hashBuf) {
-            return SECFailure;
-        }
-    }
-
-    memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
-    pBuf = hashBuf + SSL3_RANDOM_LENGTH;
-    memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
-    pBuf += SSL3_RANDOM_LENGTH;
-    pBuf[0] = (PRUint8)(modulus.len >> 8);
-    pBuf[1] = (PRUint8)(modulus.len);
-    pBuf += 2;
-    memcpy(pBuf, modulus.data, modulus.len);
-    pBuf += modulus.len;
-    pBuf[0] = (PRUint8)(publicExponent.len >> 8);
-    pBuf[1] = (PRUint8)(publicExponent.len);
-    pBuf += 2;
-    memcpy(pBuf, publicExponent.data, publicExponent.len);
-    pBuf += publicExponent.len;
-    PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
-
-    rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes,
-                                   bypassPKCS11);
-
-    PRINT_BUF(95, (NULL, "RSAkey hash: ", hashBuf, bufLen));
-    if (rv == SECSuccess) {
-        if (hashAlg == ssl_hash_none) {
-            PRINT_BUF(95, (NULL, "RSAkey hash: MD5 result",
-                           hashes->u.s.md5, MD5_LENGTH));
-            PRINT_BUF(95, (NULL, "RSAkey hash: SHA1 result",
-                           hashes->u.s.sha, SHA1_LENGTH));
-        } else {
-            PRINT_BUF(95, (NULL, "RSAkey hash: result",
-                           hashes->u.raw, hashes->len));
-        }
-    }
-
-    if (hashBuf != buf && hashBuf != NULL) {
-        PORT_Free(hashBuf);
-    }
-    return rv;
-}
-
 /* Caller must set hiLevel error code. */
 /* Called from ssl3_HandleServerKeyExchange. */
 static SECStatus
 ssl3_ComputeDHKeyHash(sslSocket *ss, SSLHashType hashAlg, SSL3Hashes *hashes,
                       SECItem dh_p, SECItem dh_g, SECItem dh_Ys, PRBool padY)
 {
     PRUint8 *hashBuf;
     PRUint8 *pBuf;
@@ -2570,27 +2426,24 @@ ssl3_InitPendingCipherSpec(sslSocket *ss
         if (rv != SECSuccess) {
             goto done; /* err code set by ssl3_DeriveMasterSecret */
         }
     }
 #ifndef NO_PKCS11_BYPASS
     if (ss->opt.bypassPKCS11 && pwSpec->msItem.len && pwSpec->msItem.data &&
         ssl3_CanBypassCipher(ss->ssl3.pwSpec->cipher_def->calg)) {
         /* Double Bypass succeeded in extracting the master_secret */
-        const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
-        PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
-                                (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
+        PRBool isTLS = (PRBool)(pwSpec->version > SSL_LIBRARY_VERSION_3_0);
         HASH_HashType hashType = ssl3_GetTls12HashType(ss);
         pwSpec->bypassCiphers = PR_TRUE;
         rv = ssl3_KeyAndMacDeriveBypass(pwSpec,
                                         (const unsigned char *)&ss->ssl3.hs.client_random,
                                         (const unsigned char *)&ss->ssl3.hs.server_random,
                                         isTLS,
-                                        hashType,
-                                        (PRBool)(kea_def->is_limited));
+                                        hashType);
         if (rv == SECSuccess) {
             rv = ssl3_InitPendingContextsBypass(ss);
         }
     } else
 #endif
         if (pwSpec->master_secret) {
         rv = ssl3_DeriveConnectionKeysPKCS11(ss);
         if (rv == SECSuccess) {
@@ -3568,18 +3421,17 @@ ssl3_HandleNoCertificate(sslSocket *ss)
      * first handshake because if we're redoing the handshake we
      * know the server is paying attention to the certificate.
      */
     if ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) ||
         (!ss->firstHsDone &&
          (ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE))) {
         PRFileDesc *lower;
 
-        if (ss->sec.uncache)
-            ss->sec.uncache(ss->sec.ci.sid);
+        ss->sec.uncache(ss->sec.ci.sid);
         SSL3_SendAlert(ss, alert_fatal, bad_certificate);
 
         lower = ss->fd->lower;
 #ifdef _WIN32
         lower->methods->shutdown(lower, PR_SHUTDOWN_SEND);
 #else
         lower->methods->shutdown(lower, PR_SHUTDOWN_BOTH);
 #endif
@@ -3625,17 +3477,17 @@ SSL3_SendAlert(sslSocket *ss, SSL3AlertL
     SSL_TRC(3, ("%d: SSL3[%d]: send alert record, level=%d desc=%d",
                 SSL_GETPID(), ss->fd, level, desc));
 
     bytes[0] = level;
     bytes[1] = desc;
 
     ssl_GetSSL3HandshakeLock(ss);
     if (level == alert_fatal) {
-        if (!ss->opt.noCache && ss->sec.ci.sid && ss->sec.uncache) {
+        if (!ss->opt.noCache && ss->sec.ci.sid) {
             ss->sec.uncache(ss->sec.ci.sid);
         }
     }
     ssl_GetXmitBufLock(ss);
     rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
     if (rv == SECSuccess) {
         PRInt32 sent;
         sent = ssl3_SendRecord(ss, NULL, content_alert, bytes, 2,
@@ -3874,18 +3726,17 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffe
             case end_of_early_data:
                 break;
             default:
                 level = alert_fatal;
         }
     }
     if (level == alert_fatal) {
         if (!ss->opt.noCache) {
-            if (ss->sec.uncache)
-                ss->sec.uncache(ss->sec.ci.sid);
+            ss->sec.uncache(ss->sec.ci.sid);
         }
         if ((ss->ssl3.hs.ws == wait_server_hello) &&
             (desc == handshake_failure)) {
             /* XXX This is a hack.  We're assuming that any handshake failure
              * XXX on the client hello is a failure to match ciphers.
              */
             error = SSL_ERROR_NO_CYPHER_OVERLAP;
         }
@@ -4164,21 +4015,19 @@ ssl3_ComputeMasterSecretFinish(sslSocket
  **
  ** Called from: ssl3_ComputeMasterSecret
  */
 static SECStatus
 ssl3_ComputeMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
                             PK11SymKey **msp)
 {
     ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
-    const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
     unsigned char *cr = (unsigned char *)&ss->ssl3.hs.client_random;
     unsigned char *sr = (unsigned char *)&ss->ssl3.hs.server_random;
-    PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
-                            (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
+    PRBool isTLS = (PRBool)(pwSpec->version > SSL_LIBRARY_VERSION_3_0);
     PRBool isTLS12 =
         (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
     /*
      * Whenever isDH is true, we need to use CKM_TLS_MASTER_KEY_DERIVE_DH
      * which, unlike CKM_TLS_MASTER_KEY_DERIVE, converts arbitrary size
      * data into a 48-byte value, and does not expect to return the version.
      */
     PRBool isDH = (PRBool)((ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_dh) ||
@@ -4394,21 +4243,19 @@ ssl3_DeriveMasterSecret(sslSocket *ss, P
  * Caller MUST hold the specWriteLock, and SSL3HandshakeLock.
  * ssl3_InitPendingCipherSpec does that.
  *
  */
 static SECStatus
 ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss)
 {
     ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
-    const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
     unsigned char *cr = (unsigned char *)&ss->ssl3.hs.client_random;
     unsigned char *sr = (unsigned char *)&ss->ssl3.hs.server_random;
-    PRBool isTLS = (PRBool)(kea_def->tls_keygen ||
-                            (pwSpec->version > SSL_LIBRARY_VERSION_3_0));
+    PRBool isTLS = (PRBool)(pwSpec->version > SSL_LIBRARY_VERSION_3_0);
     PRBool isTLS12 =
         (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
     /* following variables used in PKCS11 path */
     const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def;
     PK11SlotInfo *slot = NULL;
     PK11SymKey *symKey = NULL;
     void *pwArg = ss->pkcs11PinArg;
     int keySize;
@@ -4439,18 +4286,17 @@ ssl3_DeriveConnectionKeysPKCS11(sslSocke
     if (cipher_def->type == type_block &&
         pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
         /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */
         key_material_params.ulIVSizeInBits = 0;
         memset(pwSpec->client.write_iv, 0, cipher_def->iv_size);
         memset(pwSpec->server.write_iv, 0, cipher_def->iv_size);
     }
 
-    key_material_params.bIsExport = (CK_BBOOL)(kea_def->is_limited);
-
+    key_material_params.bIsExport = PR_FALSE;
     key_material_params.RandomInfo.pClientRandom = cr;
     key_material_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
     key_material_params.RandomInfo.pServerRandom = sr;
     key_material_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
     key_material_params.pReturnedKeyMaterial = &returnedKeys;
 
     returnedKeys.pIVClient = pwSpec->client.write_iv;
     returnedKeys.pIVServer = pwSpec->server.write_iv;
@@ -5058,17 +4904,17 @@ ssl_SignatureSchemeToHashType(SignatureS
         case ssl_sig_ed25519:
         case ssl_sig_ed448:
             break;
     }
     PORT_Assert(0);
     return ssl_hash_none;
 }
 
-static KeyType
+KeyType
 ssl_SignatureSchemeToKeyType(SignatureScheme scheme)
 {
     switch (scheme) {
         case ssl_sig_rsa_pkcs1_sha256:
         case ssl_sig_rsa_pkcs1_sha384:
         case ssl_sig_rsa_pkcs1_sha512:
         case ssl_sig_rsa_pkcs1_sha1:
         case ssl_sig_rsa_pss_sha256:
@@ -5118,17 +4964,17 @@ ssl_NamedGroupForSignatureScheme(Signatu
             break;
     }
     PORT_Assert(0);
     return 0;
 }
 
 static PRBool
 ssl_SignatureSchemeValidForKey(PRBool isTLS13, KeyType keyType,
-                               const namedGroupDef *ecGroup,
+                               const sslNamedGroupDef *ecGroup,
                                SignatureScheme scheme)
 {
     if (!ssl_ValidateSignatureScheme(isTLS13, keyType, scheme)) {
         return PR_FALSE;
     }
     if (keyType != ecKey) {
         return PR_TRUE;
     }
@@ -5146,17 +4992,17 @@ ssl_SignatureSchemeValidForKey(PRBool is
  * |cert|. It also checks the hash algorithm against the configured signature
  * algorithms.  If all the tests pass, SECSuccess is returned. Otherwise,
  * PORT_SetError is called and SECFailure is returned. */
 SECStatus
 ssl_CheckSignatureSchemeConsistency(
     sslSocket *ss, SignatureScheme scheme, CERTCertificate *cert)
 {
     unsigned int i;
-    const namedGroupDef *group = NULL;
+    const sslNamedGroupDef *group = NULL;
     SECKEYPublicKey *key;
     KeyType keyType;
     PRBool isTLS13 = ss->version == SSL_LIBRARY_VERSION_TLS_1_3;
 
     key = CERT_ExtractPublicKey(cert);
     if (key == NULL) {
         ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
         return SECFailure;
@@ -5165,17 +5011,19 @@ ssl_CheckSignatureSchemeConsistency(
     keyType = SECKEY_GetPublicKeyType(key);
     if (keyType == ecKey) {
         group = ssl_ECPubKey2NamedGroup(key);
     }
     SECKEY_DestroyPublicKey(key);
 
     /* If we're a client, check that the signature algorithm matches the signing
      * key type of the cipher suite. */
-    if (!ss->sec.isServer && ss->ssl3.hs.kea_def->signKeyType != keyType) {
+    if (!isTLS13 &&
+        !ss->sec.isServer &&
+        ss->ssl3.hs.kea_def->signKeyType != keyType) {
         PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
         return SECFailure;
     }
 
     /* Verify that the signature scheme matches the signing key. */
     if (!ssl_SignatureSchemeValidForKey(isTLS13, keyType, group, scheme)) {
         PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
         return SECFailure;
@@ -5826,18 +5674,17 @@ ssl3_SendClientHello(sslSocket *ss, sslC
                         return rv; /* error code was set */
                     }
                 }
             }
         }
 
         if (!sidOK) {
             SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_not_ok);
-            if (ss->sec.uncache)
-                (*ss->sec.uncache)(sid);
+            ss->sec.uncache(sid);
             ssl_FreeSID(sid);
             sid = NULL;
         }
     }
 
     if (sid) {
         requestingResume = PR_TRUE;
         SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_hits);
@@ -5867,27 +5714,16 @@ ssl3_SendClientHello(sslSocket *ss, sslC
         }
 
         sid = ssl3_NewSessionID(ss, PR_FALSE);
         if (!sid) {
             return SECFailure; /* memory error is set */
         }
     }
 
-    if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3 &&
-        type == client_hello_initial) {
-        rv = tls13_SetupClientHello(ss);
-        if (rv != SECSuccess) {
-            if (sid) {
-                ssl_FreeSID(sid);
-            }
-            return rv;
-        }
-    }
-
     isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0);
     ssl_GetSpecWriteLock(ss);
     cwSpec = ss->ssl3.cwSpec;
     if (cwSpec->mac_def->mac == mac_null) {
         /* SSL records are not being MACed. */
         cwSpec->version = ss->version;
     }
     ssl_ReleaseSpecWriteLock(ss);
@@ -5925,16 +5761,24 @@ ssl3_SendClientHello(sslSocket *ss, sslC
      * Once we've copied the session ticket into our ClientHello message, it
      * is OK for the ticket to change, so we just need to make sure we hold
      * the lock across the calls to ssl3_CallHelloExtensionSenders.
      */
     if (sid->u.ssl3.lock) {
         PR_RWLock_Rlock(sid->u.ssl3.lock);
     }
 
+    if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3 &&
+        type == client_hello_initial) {
+        rv = tls13_SetupClientHello(ss);
+        if (rv != SECSuccess) {
+            return rv;
+        }
+    }
+
     if (isTLS || (ss->firstHsDone && ss->peerRequestedProtection)) {
         PRUint32 maxBytes = 65535; /* 2^16 - 1 */
         PRInt32 extLen;
 
         extLen = ssl3_CallHelloExtensionSenders(ss, PR_FALSE, maxBytes, NULL);
         if (extLen < 0) {
             if (sid->u.ssl3.lock) {
                 PR_RWLock_Unlock(sid->u.ssl3.lock);
@@ -6268,18 +6112,17 @@ ssl3_HandleHelloRequest(sslSocket *ss)
     }
     if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
         (void)SSL3_SendAlert(ss, alert_warning, no_renegotiation);
         PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
         return SECFailure;
     }
 
     if (sid) {
-        if (ss->sec.uncache)
-            ss->sec.uncache(sid);
+        ss->sec.uncache(sid);
         ssl_FreeSID(sid);
         ss->sec.ci.sid = NULL;
     }
 
     if (IS_DTLS(ss)) {
         dtls_RehandshakeCleanup(ss);
     }
 
@@ -6409,18 +6252,18 @@ ssl_UnwrapSymWrappingKey(
             unwrappedWrappingKey = PK11_UnwrapSymKey(Ks, masterWrapMech, NULL,
                                                      &wrappedKey, masterWrapMech,
                                                      CKA_UNWRAP, 0);
             PK11_FreeSymKey(Ks);
 
             break;
 
         default:
-            /* Assert? */
-            SET_ERROR_CODE
+            PORT_Assert(0);
+            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
             goto loser;
     }
 loser:
     return unwrappedWrappingKey;
 }
 
 /* Each process sharing the server session ID cache has its own array of SymKey
  * pointers for the symmetric wrapping keys that are used to wrap the master
@@ -6894,20 +6737,19 @@ ssl3_SendDHClientKeyExchange(sslSocket *
 {
     PK11SymKey *pms = NULL;
     SECStatus rv;
     PRBool isTLS;
     CK_MECHANISM_TYPE target;
 
     const ssl3DHParams *params;
     ssl3DHParams customParams;
-    const namedGroupDef *groupDef;
-    namedGroupDef customGroupDef = {
-        0, ssl_grp_ffdhe_custom, 0, group_type_ff,
-        SEC_OID_TLS_DHE_CUSTOM, PR_FALSE
+    const sslNamedGroupDef *groupDef;
+    sslNamedGroupDef customGroupDef = {
+        ssl_grp_ffdhe_custom, 0, ssl_kea_dh, SEC_OID_TLS_DHE_CUSTOM, PR_FALSE
     };
     sslEphemeralKeyPair *keyPair = NULL;
     SECKEYPublicKey *pubKey;
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
     isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
@@ -6994,17 +6836,16 @@ loser:
 }
 
 /* Called from ssl3_HandleServerHelloDone(). */
 static SECStatus
 ssl3_SendClientKeyExchange(sslSocket *ss)
 {
     SECKEYPublicKey *serverKey = NULL;
     SECStatus rv = SECFailure;
-    PRBool isTLS;
 
     SSL_TRC(3, ("%d: SSL3[%d]: send client_key_exchange handshake",
                 SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     if (ss->sec.peerKey == NULL) {
@@ -7013,31 +6854,16 @@ ssl3_SendClientKeyExchange(sslSocket *ss
             ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
             return SECFailure;
         }
     } else {
         serverKey = ss->sec.peerKey;
         ss->sec.peerKey = NULL; /* we're done with it now */
     }
 
-    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
-    /* enforce limits on kea key sizes. */
-    if (ss->ssl3.hs.kea_def->is_limited) {
-        unsigned int keyLen = SECKEY_PublicKeyStrengthInBits(serverKey);
-
-        if (keyLen > ss->ssl3.hs.kea_def->key_size_limit) {
-            if (isTLS)
-                (void)SSL3_SendAlert(ss, alert_fatal, export_restriction);
-            else
-                (void)ssl3_HandshakeFailure(ss);
-            PORT_SetError(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED);
-            goto loser;
-        }
-    }
-
     ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
     ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(serverKey);
 
     switch (ss->ssl3.hs.kea_def->exchKeyType) {
         case ssl_kea_rsa:
             rv = ssl3_SendRSAClientKeyExchange(ss, serverKey);
             break;
 
@@ -7045,39 +6871,36 @@ ssl3_SendClientKeyExchange(sslSocket *ss
             rv = ssl3_SendDHClientKeyExchange(ss, serverKey);
             break;
 
         case ssl_kea_ecdh:
             rv = ssl3_SendECDHClientKeyExchange(ss, serverKey);
             break;
 
         default:
-            /* got an unknown or unsupported Key Exchange Algorithm.  */
-            SEND_ALERT
-            PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
+            PORT_Assert(0);
+            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
             break;
     }
 
     SSL_TRC(3, ("%d: SSL3[%d]: DONE sending client_key_exchange",
                 SSL_GETPID(), ss->fd));
 
-loser:
-    if (serverKey)
-        SECKEY_DestroyPublicKey(serverKey);
+    SECKEY_DestroyPublicKey(serverKey);
     return rv; /* err code already set. */
 }
 
-static SECStatus
+SECStatus
 ssl_PickSignatureScheme(sslSocket *ss, SECKEYPublicKey *key,
                         const SignatureScheme *peerSchemes,
                         unsigned int peerSchemeCount,
                         PRBool requireSha1)
 {
     unsigned int i, j;
-    const namedGroupDef *group = NULL;
+    const sslNamedGroupDef *group = NULL;
     KeyType keyType;
     PRBool isTLS13 = ss->version == SSL_LIBRARY_VERSION_TLS_1_3;
 
     if (!key) {
         PORT_Assert(0);
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
@@ -7530,18 +7353,18 @@ ssl3_HandleServerHello(sslSocket *ss, SS
      */
     if (length != 0) {
         SECItem extensions;
         rv = ssl3_ConsumeHandshakeVariable(ss, &extensions, 2, &b, &length);
         if (rv != SECSuccess || length != 0) {
             if (isTLS)
                 goto alert_loser;
         } else {
-            rv = ssl3_HandleHelloExtensions(ss, &extensions.data,
-                                            &extensions.len, server_hello);
+            rv = ssl3_HandleExtensions(ss, &extensions.data,
+                                       &extensions.len, server_hello);
             if (rv != SECSuccess)
                 goto alert_loser;
         }
     }
 
     if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
         rv = tls13_HandleServerHelloPart2(ss);
         if (rv != SECSuccess) {
@@ -7755,18 +7578,17 @@ ssl3_HandleServerHelloPart2(sslSocket *s
 
     if (sid_match)
         SSL_AtomicIncrementLong(&ssl3stats.hsh_sid_cache_not_ok);
     else
         SSL_AtomicIncrementLong(&ssl3stats.hsh_sid_cache_misses);
 
     /* throw the old one away */
     sid->u.ssl3.keys.resumable = PR_FALSE;
-    if (ss->sec.uncache)
-        (*ss->sec.uncache)(sid);
+    ss->sec.uncache(sid);
     ssl_FreeSID(sid);
 
     /* get a new sid */
     ss->sec.ci.sid = sid = ssl3_NewSessionID(ss, PR_FALSE);
     if (sid == NULL) {
         goto alert_loser; /* memory error is set. */
     }
 
@@ -7806,137 +7628,16 @@ alert_loser:
     (void)SSL3_SendAlert(ss, alert_fatal, desc);
 
 loser:
     *retErrCode = errCode;
     return SECFailure;
 }
 
 static SECStatus
-ssl_HandleRSAServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
-{
-    SECStatus rv;
-    int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
-    SSL3AlertDescription desc = illegal_parameter;
-    SSLHashType hashAlg;
-    PRBool isTLS = ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0;
-    SignatureScheme sigScheme = ssl_sig_none;
-
-    SECItem modulus = { siBuffer, NULL, 0 };
-    SECItem exponent = { siBuffer, NULL, 0 };
-
-    SSL3Hashes hashes;
-    SECItem signature = { siBuffer, NULL, 0 };
-    PLArenaPool *arena = NULL;
-    SECKEYPublicKey *peerKey = NULL;
-
-    PORT_Assert(ss->version <= SSL_LIBRARY_VERSION_TLS_1_2);
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &modulus, 2, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* malformed. */
-    }
-    /* This exchange method is only used by export cipher suites.
-     * Those are broken and so this code will eventually be removed. */
-    if (SECKEY_BigIntegerBitLength(&modulus) < 512) {
-        desc = isTLS ? insufficient_security : illegal_parameter;
-        goto alert_loser;
-    }
-    rv = ssl3_ConsumeHandshakeVariable(ss, &exponent, 2, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* malformed. */
-    }
-    if (ss->version == SSL_LIBRARY_VERSION_TLS_1_2) {
-        rv = ssl_ConsumeSignatureScheme(ss, &b, &length, &sigScheme);
-        if (rv != SECSuccess) {
-            goto loser; /* malformed or unsupported. */
-        }
-        rv = ssl_CheckSignatureSchemeConsistency(ss, sigScheme,
-                                                 ss->sec.peerCert);
-        if (rv != SECSuccess) {
-            goto loser;
-        }
-        hashAlg = ssl_SignatureSchemeToHashType(sigScheme);
-    } else {
-        /* Use ssl_hash_none to represent the MD5+SHA1 combo. */
-        hashAlg = ssl_hash_none;
-    }
-    rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
-    if (rv != SECSuccess) {
-        goto loser; /* malformed. */
-    }
-    if (length != 0) {
-        if (isTLS)
-            desc = decode_error;
-        goto alert_loser; /* malformed. */
-    }
-
-    /* failures after this point are not malformed handshakes. */
-    /* TLS: send decrypt_error if signature failed. */
-    desc = isTLS ? decrypt_error : handshake_failure;
-
-    /*
-     *  check to make sure the hash is signed by right guy
-     */
-    rv = ssl3_ComputeExportRSAKeyHash(hashAlg, modulus, exponent,
-                                      &ss->ssl3.hs.client_random,
-                                      &ss->ssl3.hs.server_random,
-                                      &hashes, ss->opt.bypassPKCS11);
-    if (rv != SECSuccess) {
-        errCode =
-            ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-        goto alert_loser;
-    }
-    rv = ssl3_VerifySignedHashes(ss, sigScheme, &hashes, &signature);
-    if (rv != SECSuccess) {
-        errCode =
-            ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-        goto alert_loser;
-    }
-
-    /*
-     * we really need to build a new key here because we can no longer
-     * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate
-     * pkcs11 slots and ID's.
-     */
-    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if (arena == NULL) {
-        errCode = SEC_ERROR_NO_MEMORY;
-        goto loser;
-    }
-
-    peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
-    if (peerKey == NULL) {
-        errCode = SEC_ERROR_NO_MEMORY;
-        goto loser;
-    }
-
-    peerKey->arena = arena;
-    peerKey->keyType = rsaKey;
-    peerKey->pkcs11Slot = NULL;
-    peerKey->pkcs11ID = CK_INVALID_HANDLE;
-    if (SECITEM_CopyItem(arena, &peerKey->u.rsa.modulus, &modulus) ||
-        SECITEM_CopyItem(arena, &peerKey->u.rsa.publicExponent, &exponent)) {
-        errCode = SEC_ERROR_NO_MEMORY;
-        goto loser;
-    }
-    ss->sec.peerKey = peerKey;
-    return SECSuccess;
-
-alert_loser:
-    (void)SSL3_SendAlert(ss, alert_fatal, desc);
-loser:
-    if (arena) {
-        PORT_FreeArena(arena, PR_FALSE);
-    }
-    PORT_SetError(ssl_MapLowLevelError(errCode));
-    return SECFailure;
-}
-
-static SECStatus
 ssl_HandleDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 {
     SECStatus rv;
     int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
     SSL3AlertDescription desc = illegal_parameter;
     SSLHashType hashAlg;
     PRBool isTLS = ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0;
     SignatureScheme sigScheme;
@@ -8103,20 +7804,16 @@ ssl3_HandleServerKeyExchange(sslSocket *
 
     if (ss->ssl3.hs.ws != wait_server_key) {
         SSL3_SendAlert(ss, alert_fatal, unexpected_message);
         PORT_SetError(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH);
         return SECFailure;
     }
 
     switch (ss->ssl3.hs.kea_def->exchKeyType) {
-        case ssl_kea_rsa:
-            rv = ssl_HandleRSAServerKeyExchange(ss, b, length);
-            break;
-
         case ssl_kea_dh:
             rv = ssl_HandleDHServerKeyExchange(ss, b, length);
             break;
 
         case ssl_kea_ecdh:
             rv = ssl3_HandleECDHServerKeyExchange(ss, b, length);
             break;
 
@@ -8834,53 +8531,18 @@ ssl3_SendServerHelloSequence(sslSocket *
     rv = ssl3_SendCertificateStatus(ss);
     if (rv != SECSuccess) {
         return rv; /* error code is set. */
     }
     /* We have to do this after the call to ssl3_SendServerHello,
      * because kea_def is set up by ssl3_SendServerHello().
      */
     kea_def = ss->ssl3.hs.kea_def;
-    ss->ssl3.hs.usedStepDownKey = PR_FALSE;
-
-    if (kea_def->is_limited) {
-        /* see if we can legally use the key in the cert. */
-        unsigned int keyBits;
-        const sslServerCert *cert;
-
-        /* Note that all ciphers that are limited use a SSLAuthType of
-         * ssl_auth_rsa_sign.  This isn't even remotely correct, but these keys
-         * need to do either signing or decryption on demand. */
-        PORT_Assert(kea_def->authKeyType == ssl_auth_rsa_sign);
-
-        cert = ssl_FindServerCertByAuthType(ss, ssl_auth_rsa_sign);
-        if (!cert || !cert->serverKeyPair || !cert->serverKeyPair->pubKey) {
-            PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
-            return SECFailure;
-        }
-
-        keyBits = SECKEY_PublicKeyStrengthInBits(cert->serverKeyPair->pubKey);
-        PORT_Assert(keyBits);
-
-        if (keyBits <= kea_def->key_size_limit) {
-            /* XXX AND cert is not signing only!! */
-            /* just fall through and use it. */
-        } else if (ss->stepDownKeyPair != NULL) {
-            ss->ssl3.hs.usedStepDownKey = PR_TRUE;
-            rv = ssl3_SendServerKeyExchange(ss);
-            if (rv != SECSuccess) {
-                return rv; /* err code was set. */
-            }
-        } else {
-#ifndef HACKED_EXPORT_SERVER
-            PORT_SetError(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED);
-            return rv;
-#endif
-        }
-    } else if (kea_def->ephemeral) {
+
+    if (kea_def->ephemeral) {
         rv = ssl3_SendServerKeyExchange(ss);
         if (rv != SECSuccess) {
             return rv; /* err code was set. */
         }
     }
 
     if (ss->opt.requestCertificate) {
         rv = ssl3_SendCertificateRequest(ss);
@@ -9357,17 +9019,17 @@ ssl3_HandleClientHello(sslSocket *ss, SS
         extension_length = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
         if (extension_length < 0) {
             goto loser; /* alert already sent */
         }
         if (extension_length != length) {
             ssl3_DecodeError(ss); /* send alert */
             goto loser;
         }
-        rv = ssl3_HandleHelloExtensions(ss, &b, &length, client_hello);
+        rv = ssl3_HandleExtensions(ss, &b, &length, client_hello);
         if (rv != SECSuccess) {
             goto loser; /* malformed */
         }
     }
 
     /* TODO: For TLS 1.3 final, downgrade when the extension IS present. */
     if (ss->version == SSL_LIBRARY_VERSION_TLS_1_3 &&
         !ssl3_ExtensionNegotiated(ss, ssl_tls13_draft_version_xtn)) {
@@ -9389,17 +9051,17 @@ ssl3_HandleClientHello(sslSocket *ss, SS
          * and if found, treat it just like an empty RI extension
          * by processing a local copy of an empty RI extension.
          */
         for (i = 0; i + 1 < suites.len; i += 2) {
             PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
             if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) {
                 SSL3Opaque *b2 = (SSL3Opaque *)emptyRIext;
                 PRUint32 L2 = sizeof emptyRIext;
-                (void)ssl3_HandleHelloExtensions(ss, &b2, &L2, client_hello);
+                (void)ssl3_HandleExtensions(ss, &b2, &L2, client_hello);
                 break;
             }
         }
     }
     /* This is a second check for TLS 1.3 and re-handshake to stop us
      * from re-handshake up to TLS 1.3, so it happens after version
      * negotiation. */
     if (ss->firstHsDone && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
@@ -9495,18 +9157,17 @@ ssl3_HandleClientHello(sslSocket *ss, SS
          */
         if ((sid->peerCert == NULL) && ss->opt.requestCertificate &&
             ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) ||
              (ss->opt.requireCertificate == SSL_REQUIRE_NO_ERROR) ||
              ((ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE) &&
               !ss->firstHsDone))) {
 
             SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_not_ok);
-            if (ss->sec.uncache)
-                ss->sec.uncache(sid);
+            ss->sec.uncache(sid);
             ssl_FreeSID(sid);
             sid = NULL;
         }
     }
 
     if (IS_DTLS(ss)) {
         ssl3_DisableNonDTLSSuites(ss);
     }
@@ -9712,18 +9373,17 @@ compression_found:
                     /* Note: we do not destroy the session */
                     desc = handshake_failure;
                     errCode = SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET;
                     goto alert_loser;
                 }
             }
 
             if (ss->sec.ci.sid) {
-                if (ss->sec.uncache)
-                    ss->sec.uncache(ss->sec.ci.sid);
+                ss->sec.uncache(ss->sec.ci.sid);
                 PORT_Assert(ss->sec.ci.sid != sid); /* should be impossible, but ... */
                 if (ss->sec.ci.sid != sid) {
                     ssl_FreeSID(ss->sec.ci.sid);
                 }
                 ss->sec.ci.sid = NULL;
             }
             /* we need to resurrect the master secret.... */
 
@@ -9881,18 +9541,17 @@ compression_found:
 
     if (haveSpecWriteLock) {
         ssl_ReleaseSpecWriteLock(ss);
         haveSpecWriteLock = PR_FALSE;
     }
 
     if (sid) { /* we had a sid, but it's no longer valid, free it */
         SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_not_ok);
-        if (ss->sec.uncache)
-            ss->sec.uncache(sid);
+        ss->sec.uncache(sid);
         ssl_FreeSID(sid);
         sid = NULL;
     }
     SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_misses);
 
     rv = ssl3_ServerCallSNICallback(ss);
     if (rv != SECSuccess) {
         /* The alert has already been sent. */
@@ -9937,19 +9596,17 @@ alert_loser:
     if (haveSpecWriteLock) {
         ssl_ReleaseSpecWriteLock(ss);
         haveSpecWriteLock = PR_FALSE;
     }
     (void)SSL3_SendAlert(ss, alert_fatal, desc);
 /* FALLTHRU */
 loser:
     if (sid && sid != ss->sec.ci.sid) {
-        if (ss->sec.uncache) {
-            ss->sec.uncache(sid);
-        }
+        ss->sec.uncache(sid);
         ssl_FreeSID(sid);
     }
 
     if (haveSpecWriteLock) {
         ssl_ReleaseSpecWriteLock(ss);
     }
 
     if (haveXmitBufLock) {
@@ -10117,17 +9774,17 @@ suite_found:
     /* Look for the SCSV, and if found, treat it just like an empty RI
      * extension by processing a local copy of an empty RI extension.
      */
     for (i = 0; i + 2 < suite_length; i += 3) {
         PRUint32 suite_i = (suites[i] << 16) | (suites[i + 1] << 8) | suites[i + 2];
         if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) {
             SSL3Opaque *b2 = (SSL3Opaque *)emptyRIext;
             PRUint32 L2 = sizeof emptyRIext;
-            (void)ssl3_HandleHelloExtensions(ss, &b2, &L2, client_hello);
+            (void)ssl3_HandleExtensions(ss, &b2, &L2, client_hello);
             break;
         }
     }
 
     if (ss->opt.requireSafeNegotiation &&
         !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
         desc = handshake_failure;
         errCode = SSL_ERROR_UNSAFE_NEGOTIATION;
@@ -10300,17 +9957,17 @@ ssl3_SendServerHello(sslSocket *ss)
     if (rv != SECSuccess) {
         return rv; /* err set by ssl3_SetupPendingCipherSpec */
     }
 
     return SECSuccess;
 }
 
 SECStatus
-ssl_CreateDHEKeyPair(const namedGroupDef *groupDef,
+ssl_CreateDHEKeyPair(const sslNamedGroupDef *groupDef,
                      const ssl3DHParams *params,
                      sslEphemeralKeyPair **keyPair)
 {
     SECKEYDHParams dhParam;
     SECKEYPublicKey *pubKey = NULL;   /* Ephemeral DH key */
     SECKEYPrivateKey *privKey = NULL; /* Ephemeral DH key */
     sslEphemeralKeyPair *pair;
 
@@ -10352,17 +10009,17 @@ ssl3_SendDHServerKeyExchange(sslSocket *
     SECItem signed_hash = { siBuffer, NULL, 0 };
     SSL3Hashes hashes;
     SSLHashType hashAlg;
 
     const ssl3DHParams *params;
     sslEphemeralKeyPair *keyPair;
     SECKEYPublicKey *pubKey;
     SECKEYPrivateKey *certPrivateKey;
-    const namedGroupDef *groupDef;
+    const sslNamedGroupDef *groupDef;
 
     if (kea_def->kea != kea_dhe_dss && kea_def->kea != kea_dhe_rsa) {
         /* TODO: Support DH_anon. It might be sufficient to drop the signature.
                  See bug 1170510. */
         PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
         return SECFailure;
     }
 
@@ -10461,128 +10118,39 @@ loser:
         PORT_Free(signed_hash.data);
     return SECFailure;
 }
 
 static SECStatus
 ssl3_SendServerKeyExchange(sslSocket *ss)
 {
     const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
-    SECStatus rv = SECFailure;
-    int length;
-    SECItem signed_hash = { siBuffer, NULL, 0 };
-    SSL3Hashes hashes;
-    SECKEYPublicKey *sdPub; /* public key for step-down */
-    SSLHashType hashAlg;
 
     SSL_TRC(3, ("%d: SSL3[%d]: send server_key_exchange handshake",
                 SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
-    if (ss->ssl3.pwSpec->version == SSL_LIBRARY_VERSION_TLS_1_2) {
-        hashAlg = ssl_SignatureSchemeToHashType(ss->ssl3.hs.signatureScheme);
-    } else {
-        /* Use ssl_hash_none to represent the MD5+SHA1 combo. */
-        hashAlg = ssl_hash_none;
-    }
-
     switch (kea_def->exchKeyType) {
-        case ssl_kea_rsa:
-            /* Perform SSL Step-Down here. */
-            sdPub = ss->stepDownKeyPair->pubKey;
-            PORT_Assert(sdPub != NULL);
-            if (!sdPub) {
-                PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-                return SECFailure;
-            }
-            rv = ssl3_ComputeExportRSAKeyHash(hashAlg,
-                                              sdPub->u.rsa.modulus,
-                                              sdPub->u.rsa.publicExponent,
-                                              &ss->ssl3.hs.client_random,
-                                              &ss->ssl3.hs.server_random,
-                                              &hashes, ss->opt.bypassPKCS11);
-            if (rv != SECSuccess) {
-                ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-                return rv;
-            }
-
-            rv = ssl3_SignHashes(ss, &hashes,
-                                 ss->sec.serverCert->serverKeyPair->privKey,
-                                 &signed_hash);
-            if (rv != SECSuccess) {
-                goto loser; /* ssl3_SignHashes has set err. */
-            }
-            if (signed_hash.data == NULL) {
-                /* how can this happen and rv == SECSuccess ?? */
-                PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-                goto loser;
-            }
-            length = 2 + sdPub->u.rsa.modulus.len +
-                     2 + sdPub->u.rsa.publicExponent.len +
-                     2 + signed_hash.len;
-
-            if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
-                length += 2;
-            }
-
-            rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
-            if (rv != SECSuccess) {
-                goto loser; /* err set by AppendHandshake. */
-            }
-
-            rv = ssl3_AppendHandshakeVariable(ss, sdPub->u.rsa.modulus.data,
-                                              sdPub->u.rsa.modulus.len, 2);
-            if (rv != SECSuccess) {
-                goto loser; /* err set by AppendHandshake. */
-            }
-
-            rv = ssl3_AppendHandshakeVariable(
-                ss, sdPub->u.rsa.publicExponent.data,
-                sdPub->u.rsa.publicExponent.len, 2);
-            if (rv != SECSuccess) {
-                goto loser; /* err set by AppendHandshake. */
-            }
-
-            if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
-                rv = ssl3_AppendHandshakeNumber(ss,
-                                                ss->ssl3.hs.signatureScheme,
-                                                2);
-                if (rv != SECSuccess) {
-                    goto loser; /* err set by AppendHandshake. */
-                }
-            }
-
-            rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
-                                              signed_hash.len, 2);
-            if (rv != SECSuccess) {
-                goto loser; /* err set by AppendHandshake. */
-            }
-            PORT_Free(signed_hash.data);
-            return SECSuccess;
-
         case ssl_kea_dh: {
-            rv = ssl3_SendDHServerKeyExchange(ss);
-            return rv;
+            return ssl3_SendDHServerKeyExchange(ss);
         }
 
         case ssl_kea_ecdh: {
-            rv = ssl3_SendECDHServerKeyExchange(ss);
-            return rv;
-        }
-
+            return ssl3_SendECDHServerKeyExchange(ss);
+        }
+
+        case ssl_kea_rsa:
         case ssl_kea_null:
         default:
-            PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
-            break;
-    }
-loser:
-    if (signed_hash.data != NULL)
-        PORT_Free(signed_hash.data);
+            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+            break;
+    }
+
     return SECFailure;
 }
 
 SECStatus
 ssl3_EncodeSigAlgs(sslSocket *ss, PRUint8 *buf, unsigned maxLen, PRUint32 *len)
 {
     unsigned int i;
     PRUint8 *p = buf;
@@ -10962,20 +10530,16 @@ ssl3_HandleRSAClientKeyExchange(sslSocke
             return SECFailure;
         }
         if ((unsigned)kLen < enc_pms.len) {
             enc_pms.len = kLen;
         }
 #ifndef NO_PKCS11_BYPASS
         isTLS = PR_TRUE;
 #endif
-    } else {
-#ifndef NO_PKCS11_BYPASS
-        isTLS = (PRBool)(ss->ssl3.hs.kea_def->tls_keygen != 0);
-#endif
     }
 
 #ifndef NO_PKCS11_BYPASS
     if (ss->opt.bypassPKCS11) {
         /* We have not implemented a tls_ExtendedMasterKeyDeriveBypass
          * and will not negotiate this extension in bypass mode. This
          * assert just double-checks that.
          */
@@ -11107,17 +10671,17 @@ ssl3_HandleRSAClientKeyExchange(sslSocke
         }
 
         /* This step will derive the MS from the PMS, among other things. */
         rv = ssl3_InitPendingCipherSpec(ss, currentPms);
         PK11_FreeSymKey(currentPms);
     }
 
     if (rv != SECSuccess) {
-        SEND_ALERT
+        (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
         return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
     }
 
 #undef currentPms
 #undef unusedPms
 #undef realPms
 #undef fauxPms
 
@@ -11199,43 +10763,30 @@ ssl3_HandleClientKeyExchange(sslSocket *
     if (ss->ssl3.hs.ws != wait_client_key) {
         SSL3_SendAlert(ss, alert_fatal, unexpected_message);
         PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH);
         return SECFailure;
     }
 
     kea_def = ss->ssl3.hs.kea_def;
 
-    if (ss->ssl3.hs.usedStepDownKey) {
-        PORT_Assert(kea_def->is_limited /* XXX OR cert is signing only */
-                    && kea_def->authKeyType == ssl_auth_rsa_sign && ss->stepDownKeyPair != NULL);
-        if (!kea_def->is_limited ||
-            kea_def->authKeyType != ssl_auth_rsa_sign ||
-            ss->stepDownKeyPair == NULL) {
-            /* shouldn't happen, don't use step down if it does */
-            goto skip;
-        }
-        serverKeyPair = ss->stepDownKeyPair;
-        ss->sec.keaKeyBits = EXPORT_RSA_KEY_LENGTH * BPB;
-    } else
-    skip:
-        if (kea_def->ephemeral) {
-            sslEphemeralKeyPair *keyPair;
-            /* There should be exactly one pair. */
-            PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
-            PORT_Assert(PR_PREV_LINK(&ss->ephemeralKeyPairs) ==
-                        PR_NEXT_LINK(&ss->ephemeralKeyPairs));
-            keyPair = (sslEphemeralKeyPair *)PR_NEXT_LINK(&ss->ephemeralKeyPairs);
-            serverKeyPair = keyPair->keys;
-            ss->sec.keaKeyBits =
-                SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey);
-        } else {
-            serverKeyPair = ss->sec.serverCert->serverKeyPair;
-            ss->sec.keaKeyBits = ss->sec.serverCert->serverKeyBits;
-        }
+    if (kea_def->ephemeral) {
+        sslEphemeralKeyPair *keyPair;
+        /* There should be exactly one pair. */
+        PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
+        PORT_Assert(PR_PREV_LINK(&ss->ephemeralKeyPairs) ==
+                    PR_NEXT_LINK(&ss->ephemeralKeyPairs));
+        keyPair = (sslEphemeralKeyPair *)PR_NEXT_LINK(&ss->ephemeralKeyPairs);
+        serverKeyPair = keyPair->keys;
+        ss->sec.keaKeyBits =
+            SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey);
+    } else {
+        serverKeyPair = ss->sec.serverCert->serverKeyPair;
+        ss->sec.keaKeyBits = ss->sec.serverCert->serverKeyBits;
+    }
 
     if (!serverKeyPair) {
         SSL3_SendAlert(ss, alert_fatal, handshake_failure);
         PORT_SetError(SSL_ERROR_NO_SERVER_KEY_FOR_ALG);
         return SECFailure;
     }
     PORT_Assert(serverKeyPair->pubKey);
     PORT_Assert(serverKeyPair->privKey);
@@ -11263,17 +10814,19 @@ ssl3_HandleClientKeyExchange(sslSocket *
     ssl_FreeEphemeralKeyPairs(ss);
     if (rv == SECSuccess) {
         ss->ssl3.hs.ws = ss->sec.peerCert ? wait_cert_verify : wait_change_cipher;
     } else {
         /* PORT_SetError has been called by all the Handle*ClientKeyExchange
          * functions above.  However, not all error paths result in an alert, so
          * this ensures that the server knows about the error.  Note that if an
          * alert was already sent, SSL3_SendAlert() is a noop. */
+        PRErrorCode errCode = PORT_GetError();
         (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
+        PORT_SetError(errCode);
     }
     return rv;
 }
 
 /* This is TLS's equivalent of sending a no_certificate alert. */
 SECStatus
 ssl3_SendEmptyCertificate(sslSocket *ss)
 {
@@ -11944,18 +11497,22 @@ ssl3_AuthCertificate(sslSocket *ss)
     ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
 
     if (!ss->sec.isServer) {
         CERTCertificate *cert = ss->sec.peerCert;
 
         /* set the server authentication type and size from the value
         ** in the cert. */
         SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(cert);
-        ss->sec.authType = ss->ssl3.hs.kea_def->authKeyType;
-        ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
+        if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+            /* These are filled in in the tls13_HandleCertificateVerify and
+             * tls13_HandleServerKeyShare. */
+            ss->sec.authType = ss->ssl3.hs.kea_def->authKeyType;
+            ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
+        }
         if (pubKey) {
             KeyType pubKeyType;
             PRInt32 minKey;
             /* This partly fixes Bug 124230 and may cause problems for
              * callers which depend on the old (wrong) behavior. */
             ss->sec.authKeyBits = SECKEY_PublicKeyStrengthInBits(pubKey);
             pubKeyType = SECKEY_GetPublicKeyType(pubKey);
             minKey = ss->sec.authKeyBits;
@@ -12007,23 +11564,18 @@ ssl3_AuthCertificate(sslSocket *ss)
             }
             SECKEY_DestroyPublicKey(pubKey);
             pubKey = NULL;
         }
 
         if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
             TLS13_SET_HS_STATE(ss, wait_cert_verify);
         } else {
-            /* Ephemeral suites require ServerKeyExchange. Export cipher suites
-             * with RSA key exchange also require ServerKeyExchange if the
-             * authentication key exceeds the key size limit. */
-            if (ss->ssl3.hs.kea_def->ephemeral ||
-                (ss->ssl3.hs.kea_def->is_limited &&
-                 ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_rsa &&
-                 ss->sec.authKeyBits > ss->ssl3.hs.kea_def->key_size_limit)) {
+            /* Ephemeral suites require ServerKeyExchange. */
+            if (ss->ssl3.hs.kea_def->ephemeral) {
                 /* require server_key_exchange */
                 ss->ssl3.hs.ws = wait_server_key;
             } else {
                 /* disallow server_key_exchange */
                 ss->ssl3.hs.ws = wait_cert_request;
                 /* This is static RSA key exchange so set the key bits to
                  * auth bits. */
                 ss->sec.keaKeyBits = ss->sec.authKeyBits;
@@ -12626,17 +12178,17 @@ ssl3_HandleFinished(sslSocket *ss, SSL3O
     }
 
 xmit_loser:
     ssl_ReleaseXmitBufLock(ss); /*************************************/
     if (rv != SECSuccess) {
         return rv;
     }
 
-    if (sid->cached == never_cached && !ss->opt.noCache && ss->sec.cache) {
+    if (sid->cached == never_cached && !ss->opt.noCache) {
         rv = ssl3_FillInCachedSID(ss, sid);
 
         /* If the wrap failed, we don't cache the sid.
          * The connection continues normally however.
          */
         ss->ssl3.hs.cacheSID = rv == SECSuccess;
     }
 
@@ -12656,18 +12208,17 @@ xmit_loser:
 }
 
 SECStatus
 ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid)
 {
     SECStatus rv;
 
     /* fill in the sid */
-    sid->u.ssl3.cipherSuite =
-        ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 ? ss->ssl3.hs.origCipherSuite : ss->ssl3.hs.cipher_suite;
+    sid->u.ssl3.cipherSuite = ss->ssl3.hs.cipher_suite;
     sid->u.ssl3.compression = ss->ssl3.hs.compression;
     sid->u.ssl3.policy = ss->ssl3.policy;
     sid->version = ss->version;
     sid->authType = ss->sec.authType;
     sid->authKeyBits = ss->sec.authKeyBits;
     sid->keaType = ss->sec.keaType;
     sid->keaKeyBits = ss->sec.keaKeyBits;
     sid->lastAccessTime = sid->creationTime = ssl_Time();
@@ -12723,33 +12274,32 @@ ssl3_FinishHandshake(sslSocket *ss)
     ss->handshake = NULL;
 
     /* RFC 5077 Section 3.3: "The client MUST NOT treat the ticket as valid
      * until it has verified the server's Finished message." When the server
      * sends a NewSessionTicket in a resumption handshake, we must wait until
      * the handshake is finished (we have verified the server's Finished
      * AND the server's certificate) before we update the ticket in the sid.
      *
-     * This must be done before we call (*ss->sec.cache)(ss->sec.ci.sid)
+     * This must be done before we call ss->sec.cache(ss->sec.ci.sid)
      * because CacheSID requires the session ticket to already be set, and also
      * because of the lazy lock creation scheme used by CacheSID and
      * ssl3_SetSIDSessionTicket.
      */
     if (ss->ssl3.hs.receivedNewSessionTicket) {
         PORT_Assert(!ss->sec.isServer);
         ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &ss->ssl3.hs.newSessionTicket);
         /* The sid took over the ticket data */
         PORT_Assert(!ss->ssl3.hs.newSessionTicket.ticket.data);
         ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
     }
 
     if (ss->ssl3.hs.cacheSID) {
         PORT_Assert(ss->sec.ci.sid->cached == never_cached);
-        PORT_Assert(ss->sec.cache);
-        (*ss->sec.cache)(ss->sec.ci.sid);
+        ss->sec.cache(ss->sec.ci.sid);
         ss->ssl3.hs.cacheSID = PR_FALSE;
     }
 
     ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */
     ss->ssl3.hs.ws = idle_handshake;
 
     ssl_FinishHandshake(ss);
 
@@ -13999,59 +13549,22 @@ ssl3_InitState(sslSocket *ss)
     ss->ssl3.hs.messages.space = 0;
 
     ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
     PORT_Memset(&ss->ssl3.hs.newSessionTicket, 0,
                 sizeof(ss->ssl3.hs.newSessionTicket));
 
     ss->ssl3.hs.zeroRttState = ssl_0rtt_none;
 
-    ssl_DisableNonSuiteBGroups(ss);
+    ssl_FilterSupportedGroups(ss);
 
     ss->ssl3.initialized = PR_TRUE;
     return SECSuccess;
 }
 
-/*
- * Creates the public and private RSA keys for SSL Step down.
- * Called from SSL_ConfigSecureServer in sslsecur.c
- */
-SECStatus
-ssl3_CreateRSAStepDownKeys(sslSocket *ss)
-{
-    SECStatus rv = SECSuccess;
-    SECKEYPrivateKey *privKey; /* RSA step down key */
-    SECKEYPublicKey *pubKey;   /* RSA step down key */
-    const sslServerCert *cert;
-    unsigned int len;
-
-    if (ss->stepDownKeyPair)
-        ssl_FreeKeyPair(ss->stepDownKeyPair);
-    ss->stepDownKeyPair = NULL;
-#ifndef HACKED_EXPORT_SERVER
-    cert = ssl_FindServerCertByAuthType(ss, ssl_auth_rsa_decrypt);
-    if (!cert || !cert->serverKeyPair) {
-        return SECFailure;
-    }
-    len = PK11_GetPrivateModulusLen(cert->serverKeyPair->privKey);
-    /* Sigh, should have a get key strength call for private keys */
-    if (len > EXPORT_RSA_KEY_LENGTH) {
-        /* need to ask for the key size in bits */
-        privKey = SECKEY_CreateRSAPrivateKey(EXPORT_RSA_KEY_LENGTH * BPB,
-                                             &pubKey, NULL);
-        if (!privKey || !pubKey ||
-            !(ss->stepDownKeyPair = ssl_NewKeyPair(privKey, pubKey))) {
-            ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
-            rv = SECFailure;
-        }
-    }
-#endif
-    return rv;
-}
-
 /* record the export policy for this cipher suite */
 SECStatus
 ssl3_SetPolicy(ssl3CipherSuite which, int policy)
 {
     ssl3CipherSuiteCfg *suite;
 
     suite = ssl_LookupCipherSuiteCfg(which, cipherSuites);
     if (suite == NULL) {
@@ -14260,19 +13773,18 @@ ssl3_RedoHandshake(sslSocket *ss, PRBool
     }
 
     if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER ||
         ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
         PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
         return SECFailure;
     }
     if (sid && flushCache) {
-        if (ss->sec.uncache)
-            ss->sec.uncache(sid); /* remove it from whichever cache it's in. */
-        ssl_FreeSID(sid);         /* dec ref count and free if zero. */
+        ss->sec.uncache(sid); /* remove it from whichever cache it's in. */
+        ssl_FreeSID(sid);     /* dec ref count and free if zero. */
         ss->sec.ci.sid = NULL;
     }
 
     ssl_GetXmitBufLock(ss); /**************************************/
 
     /* start off a new handshake. */
     if (ss->sec.isServer) {
         rv = ssl3_SendHelloRequest(ss);
--- a/security/nss/lib/ssl/ssl3ecc.c
+++ b/security/nss/lib/ssl/ssl3ecc.c
@@ -3,17 +3,16 @@
  * SSL3 Protocol
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* ECC code moved here from ssl3con.c */
 
-#include "nss.h"
 #include "cert.h"
 #include "ssl.h"
 #include "cryptohi.h" /* for DSAU_ stuff */
 #include "keyhi.h"
 #include "secder.h"
 #include "secitem.h"
 
 #include "sslimpl.h"
@@ -33,58 +32,34 @@
 
 #ifndef PK11_SETATTRS
 #define PK11_SETATTRS(x, id, v, l) \
     (x)->type = (id);              \
     (x)->pValue = (v);             \
     (x)->ulValueLen = (l);
 #endif
 
-static SECStatus ssl_CreateECDHEphemeralKeys(sslSocket *ss,
-                                             const namedGroupDef *ecGroup);
-
-typedef struct ECDHEKeyPairStr {
-    sslEphemeralKeyPair *pair;
-    int error; /* error code of the call-once function */
-    PRCallOnceType once;
-} ECDHEKeyPair;
-
-/* arrays of ECDHE KeyPairs */
-static PRCallOnceType gECDHEInitOnce;
-static int gECDHEInitError;
-/* This must be the same as ssl_named_groups_count.  ssl_ECRegister() asserts
- * this at runtime; no compile-time error, sorry. */
-static ECDHEKeyPair gECDHEKeyPairs[30];
-
 SECStatus
-ssl_NamedGroup2ECParams(PLArenaPool *arena, const namedGroupDef *ecGroup,
+ssl_NamedGroup2ECParams(PLArenaPool *arena, const sslNamedGroupDef *ecGroup,
                         SECKEYECParams *params)
 {
     SECOidData *oidData = NULL;
-    PRUint32 policyFlags = 0;
-    SECStatus rv;
 
     if (!params) {
         PORT_Assert(0);
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
-    if (!ecGroup || ecGroup->type != group_type_ec ||
+    if (!ecGroup || ecGroup->keaType != ssl_kea_ecdh ||
         (oidData = SECOID_FindOIDByTag(ecGroup->oidTag)) == NULL) {
         PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
         return SECFailure;
     }
 
-    rv = NSS_GetAlgorithmPolicy(ecGroup->oidTag, &policyFlags);
-    if (rv == SECSuccess && !(policyFlags & NSS_USE_ALG_IN_SSL_KX)) {
-        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
-        return SECFailure;
-    }
-
     if (SECITEM_AllocItem(arena, params, (2 + oidData->oid.len)) == NULL) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         return SECFailure;
     }
 
     /*
      * params->data needs to contain the ASN encoding of an object ID (OID)
      * representing the named curve. The actual OID is in
@@ -92,17 +67,17 @@ ssl_NamedGroup2ECParams(PLArenaPool *are
      */
     params->data[0] = SEC_ASN1_OBJECT_ID;
     params->data[1] = oidData->oid.len;
     memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
 
     return SECSuccess;
 }
 
-const namedGroupDef *
+const sslNamedGroupDef *
 ssl_ECPubKey2NamedGroup(const SECKEYPublicKey *pubKey)
 {
     SECItem oid = { siBuffer, NULL, 0 };
     SECOidData *oidData = NULL;
     PRUint32 policyFlags = 0;
     unsigned int i;
     const SECKEYECParams *params;
 
@@ -145,20 +120,19 @@ ssl3_ComputeECDHKeyHash(SSLHashType hash
                         SSL3Random *client_rand, SSL3Random *server_rand,
                         SSL3Hashes *hashes, PRBool bypassPKCS11)
 {
     PRUint8 *hashBuf;
     PRUint8 *pBuf;
     SECStatus rv = SECSuccess;
     unsigned int bufLen;
     /*
-     * XXX For now, we only support named curves (the appropriate
-     * checks are made before this method is called) so ec_params
-     * takes up only two bytes. ECPoint needs to fit in 256 bytes
-     * (because the spec says the length must fit in one byte)
+     * We only support named curves (the appropriate checks are made before this
+     * method is called) so ec_params takes up only two bytes. ECPoint needs to
+     * fit in 256 bytes because the spec says the length must fit in one byte.
      */
     PRUint8 buf[2 * SSL3_RANDOM_LENGTH + 2 + 1 + 256];
 
     bufLen = 2 * SSL3_RANDOM_LENGTH + ec_params.len + 1 + server_ecpoint.len;
     if (bufLen <= sizeof buf) {
         hashBuf = buf;
     } else {
         hashBuf = PORT_Alloc(bufLen);
@@ -196,17 +170,17 @@ ssl3_ComputeECDHKeyHash(SSLHashType hash
 /* Called from ssl3_SendClientKeyExchange(). */
 SECStatus
 ssl3_SendECDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey)
 {
     PK11SymKey *pms = NULL;
     SECStatus rv = SECFailure;
     PRBool isTLS, isTLS12;
     CK_MECHANISM_TYPE target;
-    const namedGroupDef *groupDef;
+    const sslNamedGroupDef *groupDef;
     sslEphemeralKeyPair *keyPair = NULL;
     SECKEYPublicKey *pubKey;
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
     isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
     isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
@@ -323,16 +297,17 @@ ssl3_HandleECDHClientKeyExchange(sslSock
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     clntPubKey.keyType = ecKey;
     clntPubKey.u.ec.DEREncodedParams.len =
         serverKeyPair->pubKey->u.ec.DEREncodedParams.len;
     clntPubKey.u.ec.DEREncodedParams.data =
         serverKeyPair->pubKey->u.ec.DEREncodedParams.data;
+    clntPubKey.u.ec.encoding = serverKeyPair->pubKey->u.ec.encoding;
 
     rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue,
                                        1, &b, &length);
     if (rv != SECSuccess) {
         PORT_SetError(errCode);
         return SECFailure;
     }
 
@@ -373,88 +348,91 @@ ssl3_HandleECDHClientKeyExchange(sslSock
         /* error code set by ssl3_InitPendingCipherSpec */
         return SECFailure;
     }
     return SECSuccess;
 }
 
 /*
 ** Take an encoded key share and make a public key out of it.
-** returns NULL on error.
 */
 SECStatus
-tls13_ImportECDHKeyShare(sslSocket *ss, SECKEYPublicKey *peerKey,
-                         SSL3Opaque *b, PRUint32 length,
-                         const namedGroupDef *ecGroup)
+ssl_ImportECDHKeyShare(sslSocket *ss, SECKEYPublicKey *peerKey,
+                       SSL3Opaque *b, PRUint32 length,
+                       const sslNamedGroupDef *ecGroup)
 {
     SECStatus rv;
     SECItem ecPoint = { siBuffer, NULL, 0 };
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     if (!length) {
         PORT_SetError(SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE);
         return SECFailure;
     }
 
     /* Fail if the ec point uses compressed representation */
-    if (b[0] != EC_POINT_FORM_UNCOMPRESSED) {
+    if (b[0] != EC_POINT_FORM_UNCOMPRESSED &&
+        ecGroup->name != ssl_grp_ec_curve25519) {
         PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
         return SECFailure;
     }
 
     peerKey->keyType = ecKey;
     /* Set up the encoded params */
     rv = ssl_NamedGroup2ECParams(peerKey->arena, ecGroup,
                                  &peerKey->u.ec.DEREncodedParams);
     if (rv != SECSuccess) {
         ssl_MapLowLevelError(SSL_ERROR_RX_MALFORMED_ECDHE_KEY_SHARE);
         return SECFailure;
     }
+    if (ecGroup->name == ssl_grp_ec_curve25519) {
+        peerKey->u.ec.encoding = ECPoint_XOnly;
+    } else {
+        peerKey->u.ec.encoding = ECPoint_Uncompressed;
+    }
 
     /* copy publicValue in peerKey */
     ecPoint.data = b;
     ecPoint.len = length;
 
     rv = SECITEM_CopyItem(peerKey->arena, &peerKey->u.ec.publicValue, &ecPoint);
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
     return SECSuccess;
 }
 
-const namedGroupDef *
+const sslNamedGroupDef *
 ssl_GetECGroupWithStrength(sslSocket *ss, unsigned int requiredECCbits)
 {
     int i;
 
     for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
-        const namedGroupDef *group;
+        const sslNamedGroupDef *group;
         if (ss) {
             group = ss->namedGroupPreferences[i];
         } else {
             group = &ssl_named_groups[i];
         }
-        if (!group || group->type != group_type_ec ||
+        if (!group || group->keaType != ssl_kea_ecdh ||
             group->bits < requiredECCbits) {
             continue;
         }
-        if (!ss || ssl_NamedGroupEnabled(ss, group)) {
-            return group;
-        }
+        return group;
     }
     PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
     return NULL;
 }
 
 /* Find the "weakest link".  Get the strength of the signature and symmetric
  * keys and choose a curve based on the weakest of those two. */
-const namedGroupDef *
+const sslNamedGroupDef *
 ssl_GetECGroupForServerSocket(sslSocket *ss)
 {
     const sslServerCert *cert = ss->sec.serverCert;
     unsigned int certKeySize;
     const ssl3BulkCipherDef *bulkCipher;
     unsigned int requiredECCbits;
 
     PORT_Assert(cert);
@@ -465,21 +443,21 @@ ssl_GetECGroupForServerSocket(sslSocket 
 
     if (cert->certType.authType == ssl_auth_rsa_sign) {
         certKeySize = SECKEY_PublicKeyStrengthInBits(cert->serverKeyPair->pubKey);
         certKeySize =
             SSL_RSASTRENGTH_TO_ECSTRENGTH(certKeySize);
     } else if (cert->certType.authType == ssl_auth_ecdsa ||
                cert->certType.authType == ssl_auth_ecdh_rsa ||
                cert->certType.authType == ssl_auth_ecdh_ecdsa) {
-        const namedGroupDef *groupDef = cert->certType.namedCurve;
+        const sslNamedGroupDef *groupDef = cert->certType.namedCurve;
 
         /* We won't select a certificate unless the named curve has been
          * negotiated (or supported_curves was absent), double check that. */
-        PORT_Assert(groupDef->type == group_type_ec);
+        PORT_Assert(groupDef->keaType == ssl_kea_ecdh);
         PORT_Assert(ssl_NamedGroupEnabled(ss, groupDef));
         if (!ssl_NamedGroupEnabled(ss, groupDef)) {
             return NULL;
         }
         certKeySize = groupDef->bits;
     } else {
         PORT_Assert(0);
         return NULL;
@@ -490,46 +468,19 @@ ssl_GetECGroupForServerSocket(sslSocket 
                 ss->ssl3.hs.suite_def->bulk_cipher_alg == cipher_null);
     if (requiredECCbits > certKeySize) {
         requiredECCbits = certKeySize;
     }
 
     return ssl_GetECGroupWithStrength(ss, requiredECCbits);
 }
 
-/* function to clear out the lists */
-static SECStatus
-ssl_ShutdownECDHECurves(void *appData, void *nssData)
-{
-    int i;
-
-    for (i = 0; i < PR_ARRAY_SIZE(gECDHEKeyPairs); i++) {
-        if (gECDHEKeyPairs[i].pair) {
-            ssl_FreeEphemeralKeyPair(gECDHEKeyPairs[i].pair);
-        }
-    }
-    memset(gECDHEKeyPairs, 0, sizeof(gECDHEKeyPairs));
-    return SECSuccess;
-}
-
-static PRStatus
-ssl_ECRegister(void)
-{
-    SECStatus rv;
-    PORT_Assert(PR_ARRAY_SIZE(gECDHEKeyPairs) == SSL_NAMED_GROUP_COUNT);
-    rv = NSS_RegisterShutdown(ssl_ShutdownECDHECurves, gECDHEKeyPairs);
-    if (rv != SECSuccess) {
-        gECDHEInitError = PORT_GetError();
-    }
-    return (PRStatus)rv;
-}
-
 /* Create an ECDHE key pair for a given curve */
 SECStatus
-ssl_CreateECDHEphemeralKeyPair(const namedGroupDef *ecGroup,
+ssl_CreateECDHEphemeralKeyPair(const sslNamedGroupDef *ecGroup,
                                sslEphemeralKeyPair **keyPair)
 {
     SECKEYPrivateKey *privKey = NULL;
     SECKEYPublicKey *pubKey = NULL;
     SECKEYECParams ecParams = { siBuffer, NULL, 0 };
     sslEphemeralKeyPair *pair;
 
     if (ssl_NamedGroup2ECParams(NULL, ecGroup, &ecParams) != SECSuccess) {
@@ -549,98 +500,34 @@ ssl_CreateECDHEphemeralKeyPair(const nam
         ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
         return SECFailure;
     }
 
     *keyPair = pair;
     return SECSuccess;
 }
 
-/* CallOnce function, called once for each named curve. */
-static PRStatus
-ssl_CreateECDHEphemeralKeyPairOnce(void *arg)
-{
-    const namedGroupDef *groupDef = (const namedGroupDef *)arg;
-    sslEphemeralKeyPair *keyPair = NULL;
-    SECStatus rv;
-
-    PORT_Assert(groupDef->type == group_type_ec);
-    PORT_Assert(gECDHEKeyPairs[groupDef->index].pair == NULL);
-
-    /* ok, no one has generated a global key for this curve yet, do so */
-    rv = ssl_CreateECDHEphemeralKeyPair(groupDef, &keyPair);
-    if (rv != SECSuccess) {
-        gECDHEKeyPairs[groupDef->index].error = PORT_GetError();
-        return PR_FAILURE;
-    }
-
-    gECDHEKeyPairs[groupDef->index].pair = keyPair;
-    return PR_SUCCESS;
-}
-
-/*
- * Creates the ephemeral public and private ECDH keys used by
- * server in ECDHE_RSA and ECDHE_ECDSA handshakes.
- * For now, the elliptic curve is chosen to be the same
- * strength as the signing certificate (ECC or RSA).
- * We need an API to specify the curve. This won't be a real
- * issue until we further develop server-side support for ECC
- * cipher suites.
- */
-static SECStatus
-ssl_CreateECDHEphemeralKeys(sslSocket *ss, const namedGroupDef *ecGroup)
-{
-    sslEphemeralKeyPair *keyPair = NULL;
-
-    /* if there's no global key for this curve, make one. */
-    if (gECDHEKeyPairs[ecGroup->index].pair == NULL) {
-        PRStatus status;
-
-        status = PR_CallOnce(&gECDHEInitOnce, ssl_ECRegister);
-        if (status != PR_SUCCESS) {
-            PORT_SetError(gECDHEInitError);
-            return SECFailure;
-        }
-        status = PR_CallOnceWithArg(&gECDHEKeyPairs[ecGroup->index].once,
-                                    ssl_CreateECDHEphemeralKeyPairOnce,
-                                    (void *)ecGroup);
-        if (status != PR_SUCCESS) {
-            PORT_SetError(gECDHEKeyPairs[ecGroup->index].error);
-            return SECFailure;
-        }
-    }
-
-    keyPair = ssl_CopyEphemeralKeyPair(gECDHEKeyPairs[ecGroup->index].pair);
-    PORT_Assert(keyPair != NULL);
-    if (!keyPair)
-        return SECFailure;
-
-    PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
-    PR_APPEND_LINK(&keyPair->link, &ss->ephemeralKeyPairs);
-    return SECSuccess;
-}
-
 SECStatus
 ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 {
     PLArenaPool *arena = NULL;
     SECKEYPublicKey *peerKey = NULL;
     PRBool isTLS;
     SECStatus rv;
     int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
     SSL3AlertDescription desc = illegal_parameter;
     SSL3Hashes hashes;
     SECItem signature = { siBuffer, NULL, 0 };
     SSLHashType hashAlg;
     SignatureScheme sigScheme;
 
     SECItem ec_params = { siBuffer, NULL, 0 };
     SECItem ec_point = { siBuffer, NULL, 0 };
-    unsigned char paramBuf[3]; /* only for curve_type == named_curve */
-    const namedGroupDef *ecGroup;
+    unsigned char paramBuf[3];
+    const sslNamedGroupDef *ecGroup;
 
     isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
 
     ec_params.len = sizeof paramBuf;
     ec_params.data = paramBuf;
     rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, &b, &length);
     if (rv != SECSuccess) {
         goto loser; /* malformed. */
@@ -648,35 +535,36 @@ ssl3_HandleECDHServerKeyExchange(sslSock
 
     /* Fail if the curve is not a named curve */
     if (ec_params.data[0] != ec_type_named) {
         errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
         desc = handshake_failure;
         goto alert_loser;
     }
     ecGroup = ssl_LookupNamedGroup(ec_params.data[1] << 8 | ec_params.data[2]);
-    if (!ecGroup || ecGroup->type != group_type_ec) {
+    if (!ecGroup || ecGroup->keaType != ssl_kea_ecdh) {
         errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
         desc = handshake_failure;
         goto alert_loser;
     }
 
     rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length);
     if (rv != SECSuccess) {
         goto loser; /* malformed. */
     }
 
     /* Fail if the provided point has length 0. */
     if (!ec_point.len) {
         /* desc and errCode are initialized already */
         goto alert_loser;
     }
 
-    /* Fail if the ec point uses compressed representation. */
-    if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
+    /* Fail if the ec point is not uncompressed for any curve that's not 25519. */
+    if (ecGroup->name != ssl_grp_ec_curve25519 &&
+        ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
         errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM;
         desc = handshake_failure;
         goto alert_loser;
     }
 
     PORT_Assert(ss->ssl3.prSpec->version <= SSL_LIBRARY_VERSION_TLS_1_2);
     if (ss->ssl3.prSpec->version == SSL_LIBRARY_VERSION_TLS_1_2) {
         rv = ssl_ConsumeSignatureScheme(ss, &b, &length, &sigScheme);
@@ -701,18 +589,17 @@ ssl3_HandleECDHServerKeyExchange(sslSock
     }
 
     if (length != 0) {
         if (isTLS)
             desc = decode_error;
         goto alert_loser; /* malformed. */
     }
 
-    PRINT_BUF(60, (NULL, "Server EC params", ec_params.data,
-                   ec_params.len));
+    PRINT_BUF(60, (NULL, "Server EC params", ec_params.data, ec_params.len));
     PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len));
 
     /* failures after this point are not malformed handshakes. */
     /* TLS: send decrypt_error if signature failed. */
     desc = isTLS ? decrypt_error : handshake_failure;
 
     /*
      *  check to make sure the hash is signed by right guy
@@ -740,36 +627,27 @@ ssl3_HandleECDHServerKeyExchange(sslSock
         goto loser;
     }
 
     peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
     if (peerKey == NULL) {
         errCode = SEC_ERROR_NO_MEMORY;
         goto loser;
     }
-
     peerKey->arena = arena;
-    peerKey->keyType = ecKey;
 
-    /* set up EC parameters in peerKey */
-    rv = ssl_NamedGroup2ECParams(arena, ecGroup,
-                                 &peerKey->u.ec.DEREncodedParams);
+    /* create public key from point data */
+    rv = ssl_ImportECDHKeyShare(ss, peerKey, ec_point.data, ec_point.len,
+                                ecGroup);
     if (rv != SECSuccess) {
-        /* we should never get here since we already
-         * checked that we are dealing with a supported curve
-         */
-        errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
+        /* error code is set */
+        desc = handshake_failure;
+        errCode = PORT_GetError();
         goto alert_loser;
     }
-
-    /* copy publicValue in peerKey */
-    if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue, &ec_point)) {
-        errCode = SEC_ERROR_NO_MEMORY;
-        goto loser;
-    }
     peerKey->pkcs11Slot = NULL;
     peerKey->pkcs11ID = CK_INVALID_HANDLE;
 
     ss->sec.peerKey = peerKey;
     return SECSuccess;
 
 alert_loser:
     (void)SSL3_SendAlert(ss, alert_fatal, desc);
@@ -788,29 +666,29 @@ ssl3_SendECDHServerKeyExchange(sslSocket
     int length;
     PRBool isTLS12;
     SECItem signed_hash = { siBuffer, NULL, 0 };
     SSLHashType hashAlg = ssl_hash_none;
     SSL3Hashes hashes;
 
     SECItem ec_params = { siBuffer, NULL, 0 };
     unsigned char paramBuf[3];
-    const namedGroupDef *ecGroup;
+    const sslNamedGroupDef *ecGroup;
     sslEphemeralKeyPair *keyPair;
     SECKEYPublicKey *pubKey;
 
     /* Generate ephemeral ECDH key pair and send the public key */
     ecGroup = ssl_GetECGroupForServerSocket(ss);
     if (!ecGroup) {
         goto loser;
     }
 
     PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
     if (ss->opt.reuseServerECDHEKey) {
-        rv = ssl_CreateECDHEphemeralKeys(ss, ecGroup);
+        rv = ssl_CreateStaticECDHEKey(ss, ecGroup);
         if (rv != SECSuccess) {
             goto loser;
         }
         keyPair = (sslEphemeralKeyPair *)PR_NEXT_LINK(&ss->ephemeralKeyPairs);
     } else {
         rv = ssl_CreateECDHEphemeralKeyPair(ecGroup, &keyPair);
         if (rv != SECSuccess) {
             goto loser;
@@ -822,17 +700,17 @@ ssl3_SendECDHServerKeyExchange(sslSocket
     if (!keyPair) {
         PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
         return SECFailure;
     }
 
     ec_params.len = sizeof(paramBuf);
     ec_params.data = paramBuf;
     PORT_Assert(keyPair->group);
-    PORT_Assert(keyPair->group->type == group_type_ec);
+    PORT_Assert(keyPair->group->keaType == ssl_kea_ecdh);
     ec_params.data[0] = ec_type_named;
     ec_params.data[1] = keyPair->group->name >> 8;
     ec_params.data[2] = keyPair->group->name & 0xff;
 
     pubKey = keyPair->keys->pubKey;
     if (ss->ssl3.pwSpec->version == SSL_LIBRARY_VERSION_TLS_1_2) {
         hashAlg = ssl_SignatureSchemeToHashType(ss->ssl3.hs.signatureScheme);
     } else {
@@ -999,88 +877,66 @@ ssl_IsECCEnabled(sslSocket *ss)
 }
 
 PRBool
 ssl_IsDHEEnabled(sslSocket *ss)
 {
     return ssl_IsSuiteEnabled(ss, ssl_dhe_suites);
 }
 
-void
-ssl_DisableNonSuiteBGroups(sslSocket *ss)
-{
-    unsigned int i;
-    PK11SlotInfo *slot;
-
-    /* See if we can support small curves (like 163). If not, assume we can
-     * only support Suite-B curves (P-256, P-384, P-521). */
-    slot = PK11_GetBestSlotWithAttributes(CKM_ECDH1_DERIVE, 0, 163,
-                                          ss->pkcs11PinArg);
-    if (slot) {
-        /* Looks like we're committed to having lots of curves. */
-        PK11_FreeSlot(slot);
-        return;
-    }
-
-    for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
-        if (ss->namedGroupPreferences[i] &&
-            ss->namedGroupPreferences[i]->type == group_type_ec &&
-            !ss->namedGroupPreferences[i]->suiteb) {
-            ss->namedGroupPreferences[i] = NULL;
-        }
-    }
-}
-
 /* Send our Supported Groups extension. */
 PRInt32
 ssl_SendSupportedGroupsXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
 {
     PRInt32 extension_length;
     unsigned char enabledGroups[64];
     unsigned int enabledGroupsLen = 0;
     unsigned int i;
     PRBool ec;
     PRBool ff = PR_FALSE;
 
     if (!ss)
         return 0;
 
-    ec = ssl_IsECCEnabled(ss);
-    /* We only send FF supported groups if we require DH named groups or if TLS
-     * 1.3 is a possibility. */
-    if (ss->opt.requireDHENamedGroups ||
-        ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3) {
-        ff = ssl_IsDHEEnabled(ss);
-    }
-    if (!ec && !ff) {
-        return 0;
+    /* We only send FF supported groups if we require DH named groups
+     * or if TLS 1.3 is a possibility. */
+    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+        ec = ssl_IsECCEnabled(ss);
+        if (ss->opt.requireDHENamedGroups) {
+            ff = ssl_IsDHEEnabled(ss);
+        }
+        if (!ec && !ff)
+            return 0;
+    } else {
+        ec = ff = PR_TRUE;
     }
 
     PORT_Assert(sizeof(enabledGroups) > SSL_NAMED_GROUP_COUNT * 2);
     for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
-        const namedGroupDef *group = ss->namedGroupPreferences[i];
+        const sslNamedGroupDef *group = ss->namedGroupPreferences[i];
         if (!group) {
             continue;
         }
-        if (group->type == group_type_ec && !ec) {
+        if (group->keaType == ssl_kea_ecdh && !ec) {
             continue;
         }
-        if (group->type == group_type_ff && !ff) {
-            continue;
-        }
-        if (!ssl_NamedGroupEnabled(ss, group)) {
+        if (group->keaType == ssl_kea_dh && !ff) {
             continue;
         }
 
         if (append) {
             (void)ssl_EncodeUintX(group->name, 2, &enabledGroups[enabledGroupsLen]);
         }
         enabledGroupsLen += 2;
     }
 
+    if (enabledGroupsLen == 0) {
+        return 0;
+    }
+
     extension_length =
         2 /* extension type */ +
         2 /* extension length */ +
         2 /* enabled groups length */ +
         enabledGroupsLen;
 
     if (maxBytes < (PRUint32)extension_length) {
         return 0;
@@ -1171,17 +1027,17 @@ ssl3_HandleSupportedPointFormatsXtn(sslS
     return SECFailure;
 }
 
 static SECStatus
 ssl_UpdateSupportedGroups(sslSocket *ss, SECItem *data)
 {
     PRInt32 list_len;
     unsigned int i;
-    const namedGroupDef *enabled[SSL_NAMED_GROUP_COUNT] = { 0 };
+    const sslNamedGroupDef *enabled[SSL_NAMED_GROUP_COUNT] = { 0 };
     PORT_Assert(SSL_NAMED_GROUP_COUNT == PR_ARRAY_SIZE(enabled));
 
     if (!data->data || data->len < 4) {
         (void)ssl3_DecodeError(ss);
         return SECFailure;
     }
 
     /* get the length of elliptic_curve_list */
@@ -1194,17 +1050,17 @@ ssl_UpdateSupportedGroups(sslSocket *ss,
     /* disable all groups and remember the enabled groups */
     for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
         enabled[i] = ss->namedGroupPreferences[i];
         ss->namedGroupPreferences[i] = NULL;
     }
 
     /* Read groups from data and enable if in |enabled| */
     while (data->len) {
-        const namedGroupDef *group;
+        const sslNamedGroupDef *group;
         PRInt32 curve_name =
             ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
         if (curve_name < 0) {
             return SECFailure; /* fatal alert already sent */
         }
         group = ssl_LookupNamedGroup(curve_name);
         if (group) {
             for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
@@ -1225,17 +1081,17 @@ ssl_UpdateSupportedGroups(sslSocket *ss,
     }
 
     /* Note: if ss->opt.requireDHENamedGroups is set, we disable DHE cipher
      * suites, but we do that in ssl3_config_match(). */
     if (!ss->opt.requireDHENamedGroups && !ss->ssl3.hs.peerSupportsFfdheGroups) {
         /* If we don't require that DHE use named groups, and no FFDHE was
          * included, we pretend that they support all the FFDHE groups we do. */
         for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
-            if (enabled[i] && enabled[i]->type == group_type_ff) {
+            if (enabled[i] && enabled[i]->keaType == ssl_kea_dh) {
                 ss->namedGroupPreferences[i] = enabled[i];
             }
         }
     }
 
     return SECSuccess;
 }
 
--- a/security/nss/lib/ssl/ssl3ext.c
+++ b/security/nss/lib/ssl/ssl3ext.c
@@ -128,16 +128,21 @@ static SECStatus tls13_ClientHandlePreSh
                                                    SECItem *data);
 static PRInt32 tls13_ClientSendEarlyDataXtn(sslSocket *ss,
                                             PRBool append,
                                             PRUint32 maxBytes);
 static SECStatus tls13_ServerHandleEarlyDataXtn(sslSocket *ss, PRUint16 ex_type,
                                                 SECItem *data);
 static SECStatus tls13_ClientHandleEarlyDataXtn(sslSocket *ss, PRUint16 ex_type,
                                                 SECItem *data);
+static SECStatus tls13_ClientHandleTicketEarlyDataInfoXtn(
+    sslSocket *ss, PRUint16 ex_type,
+    SECItem *data);
+static SECStatus tls13_ClientHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type,
+                                              SECItem *data);
 
 /*
  * Write bytes.  Using this function means the SECItem structure
  * cannot be freed.  The caller is expected to call this function
  * on a shallow copy of the structure.
  */
 static SECStatus
 ssl3_AppendToItem(SECItem *item, const unsigned char *buf, PRUint32 bytes)
@@ -290,17 +295,17 @@ ssl3_GetSessionTicketKeys(const unsigned
 }
 #endif
 
 /* Table of handlers for received TLS hello extensions, one per extension.
  * In the second generation, this table will be dynamic, and functions
  * will be registered here.
  */
 /* This table is used by the server, to handle client hello extensions. */
-static const ssl3HelloExtensionHandler clientHelloHandlers[] = {
+static const ssl3ExtensionHandler clientHelloHandlers[] = {
     { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
     { ssl_supported_groups_xtn, &ssl_HandleSupportedGroupsXtn },
     { ssl_ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn },
     { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn },
     { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
     { ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn },
     { ssl_app_layer_protocol_xtn, &ssl3_ServerHandleAppProtoXtn },
     { ssl_use_srtp_xtn, &ssl3_ServerHandleUseSRTPXtn },
@@ -312,38 +317,45 @@ static const ssl3HelloExtensionHandler c
     { ssl_tls13_key_share_xtn, &tls13_ServerHandleKeyShareXtn },
     { ssl_tls13_pre_shared_key_xtn, &tls13_ServerHandlePreSharedKeyXtn },
     { ssl_tls13_early_data_xtn, &tls13_ServerHandleEarlyDataXtn },
     { -1, NULL }
 };
 
 /* These two tables are used by the client, to handle server hello
  * extensions. */
-static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
+static const ssl3ExtensionHandler serverHelloHandlersTLS[] = {
     { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
     /* TODO: add a handler for ssl_ec_point_formats_xtn */
     { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
     { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
     { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
     { 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_signature_algorithms_xtn, &tls13_ClientHandleSigAlgsXtn },
     { -1, NULL }
 };
 
-static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = {
+static const ssl3ExtensionHandler serverHelloHandlersSSL3[] = {
     { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
     { -1, NULL }
 };
 
+static const ssl3ExtensionHandler newSessionTicketHandlers[] = {
+    { ssl_tls13_ticket_early_data_info_xtn,
+      &tls13_ClientHandleTicketEarlyDataInfoXtn },
+    { -1, NULL }
+};
+
 /* Tables of functions to format TLS hello extensions, one function per
  * extension.
  * These static tables are for the formatting of client hello extensions.
  * The server's table of hello senders is dynamic, in the socket struct,
  * and sender functions are registered there.
  * NB: the order of these extensions can have an impact on compatibility. Some
  * servers (e.g. Tomcat) will terminate the connection if the last extension in
  * the client hello is empty (for example, the extended master secret
@@ -1398,17 +1410,17 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
     /* certificate type */
     certType = &ss->sec.serverCert->certType;
     PORT_Assert(certType->authType == ss->sec.authType);
     switch (ss->sec.authType) {
         case ssl_auth_ecdsa:
         case ssl_auth_ecdh_rsa:
         case ssl_auth_ecdh_ecdsa:
             PORT_Assert(certType->namedCurve);
-            PORT_Assert(certType->namedCurve->type == group_type_ec);
+            PORT_Assert(certType->namedCurve->keaType == ssl_kea_ecdh);
             /* EC curves only use the second of the two bytes. */
             PORT_Assert(certType->namedCurve->name < 256);
             rv = ssl3_AppendNumberToItem(&plaintext,
                                          certType->namedCurve->name, 1);
             break;
         default:
             rv = ssl3_AppendNumberToItem(&plaintext, 0, 1);
             break;
@@ -1719,18 +1731,17 @@ ssl3_ProcessSessionTicketCommon(sslSocke
     SECItem alpn_item;
 
     /* Turn off stateless session resumption if the client sends a
      * SessionTicket extension, even if the extension turns out to be
      * malformed (ss->sec.ci.sid is non-NULL when doing session
      * renegotiation.)
      */
     if (ss->sec.ci.sid != NULL) {
-        if (ss->sec.uncache)
-            ss->sec.uncache(ss->sec.ci.sid);
+        ss->sec.uncache(ss->sec.ci.sid);
         ssl_FreeSID(ss->sec.ci.sid);
         ss->sec.ci.sid = NULL;
     }
 
     extension_data.data = data->data; /* Keep a copy for future use. */
     extension_data.len = data->len;
 
     if (ssl3_ParseEncryptedSessionTicket(ss, data, &enc_session_ticket) !=
@@ -1950,24 +1961,24 @@ ssl3_ProcessSessionTicketCommon(sslSocke
     /* Read certificate slot */
     parsed_session_ticket->certType.authType = parsed_session_ticket->authType;
     temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
     if (temp < 0)
         goto no_ticket;
     switch (parsed_session_ticket->authType) {
         case ssl_auth_ecdsa:
         case ssl_auth_ecdh_rsa:
-        case ssl_auth_ecdh_ecdsa:
-            parsed_session_ticket->certType.namedCurve =
+        case ssl_auth_ecdh_ecdsa: {
+            const sslNamedGroupDef *group =
                 ssl_LookupNamedGroup((SSLNamedGroup)temp);
-            if (!parsed_session_ticket->certType.namedCurve ||
-                parsed_session_ticket->certType.namedCurve->type != group_type_ec) {
+            if (!group || group->keaType != ssl_kea_ecdh) {
                 goto no_ticket;
             }
-            break;
+            parsed_session_ticket->certType.namedCurve = group;
+        } break;
         default:
             break;
     }
 
     /* Read wrapped master_secret. */
     temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
     if (temp < 0)
         goto no_ticket;
@@ -2248,35 +2259,40 @@ ssl3_ParseEncryptedSessionTicket(sslSock
         SECSuccess)
         return SECFailure;
     if (data->len != 0) /* Make sure that we have consumed all bytes. */
         return SECFailure;
 
     return SECSuccess;
 }
 
-/* go through hello extensions in buffer "b".
+/* go through extensions in buffer "b".
  * For each one, find the extension handler in the table, and
  * if present, invoke that handler.
  * Servers ignore any extensions with unknown extension types.
- * Clients reject any extensions with unadvertised extension types.
+ * Clients reject any extensions with unadvertised extension types
+ *
  * In TLS >= 1.3, the client checks that extensions appear in the
  * right phase.
  */
 SECStatus
-ssl3_HandleHelloExtensions(sslSocket *ss, SSL3Opaque **b, PRUint32 *length,
-                           SSL3HandshakeType handshakeMessage)
+ssl3_HandleExtensions(sslSocket *ss, SSL3Opaque **b, PRUint32 *length,
+                      SSL3HandshakeType handshakeMessage)
 {
-    const ssl3HelloExtensionHandler *handlers;
+    const ssl3ExtensionHandler *handlers;
     PRBool isTLS13 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
 
     switch (handshakeMessage) {
         case client_hello:
             handlers = clientHelloHandlers;
             break;
+        case new_session_ticket:
+            PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
+            handlers = newSessionTicketHandlers;
+            break;
         case encrypted_extensions:
             PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
         /* fall through */
         case server_hello:
             if (ss->version > SSL_LIBRARY_VERSION_3_0) {
                 handlers = serverHelloHandlersTLS;
             } else {
                 handlers = serverHelloHandlersSSL3;
@@ -2284,17 +2300,17 @@ ssl3_HandleHelloExtensions(sslSocket *ss
             break;
         default:
             PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
             PORT_Assert(0);
             return SECFailure;
     }
 
     while (*length) {
-        const ssl3HelloExtensionHandler *handler;
+        const ssl3ExtensionHandler *handler;
         SECStatus rv;
         PRInt32 extension_type;
         SECItem extension_data;
 
         /* Get the extension's type field */
         extension_type = ssl3_ConsumeHandshakeNumber(ss, 2, b, length);
         if (extension_type < 0) /* failure to decode extension_type */
             return SECFailure;  /* alert already sent */
@@ -2302,17 +2318,18 @@ ssl3_HandleHelloExtensions(sslSocket *ss
         /* get the data for this extension, so we can pass it or skip it. */
         rv = ssl3_ConsumeHandshakeVariable(ss, &extension_data, 2, b, length);
         if (rv != SECSuccess)
             return rv; /* alert already sent */
 
         /* Check whether the server sent an extension which was not advertised
          * in the ClientHello */
         if (!ss->sec.isServer &&
-            !ssl3_ClientExtensionAdvertised(ss, extension_type)) {
+            !ssl3_ClientExtensionAdvertised(ss, extension_type) &&
+            (handshakeMessage != new_session_ticket)) {
             (void)SSL3_SendAlert(ss, alert_fatal, unsupported_extension);
             PORT_SetError(SSL_ERROR_RX_UNEXPECTED_EXTENSION);
             return SECFailure;
         }
 
         /* Check whether an extension has been sent multiple times. */
         if (ssl3_ExtensionNegotiated(ss, extension_type)) {
             (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
@@ -3288,17 +3305,17 @@ loser:
     return -1;
 }
 
 static SECStatus
 tls13_HandleKeyShareEntry(sslSocket *ss, SECItem *data)
 {
     SECStatus rv;
     PRInt32 group;
-    const namedGroupDef *groupDef;
+    const sslNamedGroupDef *groupDef;
     TLS13KeyShareEntry *ks = NULL;
     SECItem share = { siBuffer, NULL, 0 };
 
     group = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
     if (group < 0) {
         PORT_SetError(SSL_ERROR_RX_MALFORMED_KEY_SHARE);
         goto loser;
     }
@@ -3446,100 +3463,85 @@ tls13_ServerSendKeyShareXtn(sslSocket *s
     return extension_length;
 
 loser:
     return -1;
 }
 
 /* Called by clients.
  *
- *   opaque psk_identity<0..2^16-1>;
+ *   struct {
+ *     PskKeyExchangeMode ke_modes<1..255>;
+ *     PskAuthMode auth_modes<1..255>;
+ *     opaque identity<0..2^16-1>;
+ *  } PskIdentity;
  *
- *   struct {
- *        select (Role) {
- *            case client:
- *                psk_identity identities<2..2^16-1>;
- *
+ *  struct {
+ *       select (Role) {
+ *           case client:
+ *               PskIdentity identities<2..2^16-1>;
  *            case server:
- *                 uint16 selected_identity;
- *        }
+ *               uint16 selected_identity;
+ *       }
  *   } PreSharedKeyExtension;
  *
  * Presently the only way to get a PSK is by resumption, so this is
  * really a ticket label and there wll be at most one.
  */
 static PRInt32
 tls13_ClientSendPreSharedKeyXtn(sslSocket *ss,
                                 PRBool append,
                                 PRUint32 maxBytes)
 {
     PRInt32 extension_length;
-    NewSessionTicket *session_ticket = NULL;
-    sslSessionID *sid = ss->sec.ci.sid;
-
-    if (sid->cached == never_cached ||
-        sid->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        return 0;
-    }
-
-    if (!tls13_PskSuiteEnabled(ss)) {
+    static const PRUint8 auth_modes[] = { tls13_psk_auth };
+    static const unsigned long auth_modes_len = sizeof(auth_modes);
+    static const PRUint8 ke_modes[] = { tls13_psk_dh_ke };
+    static const unsigned long ke_modes_len = sizeof(ke_modes);
+    NewSessionTicket *session_ticket;
+
+    if (!ss->statelessResume)
         return 0;
-    }
-
-    /* The caller must be holding sid->u.ssl3.lock for reading. We cannot
-     * just acquire and release the lock within this function because the
-     * caller will call this function twice, and we need the inputs to be
-     * consistent between the two calls. Note that currently the caller
-     * will only be holding the lock when we are the client and when we're
-     * attempting to resume an existing session.
-     */
-    session_ticket = &sid->u.ssl3.locked.sessionTicket;
-    PORT_Assert(session_ticket && session_ticket->ticket.data);
-
-    /* In our first pass through, set the ticket to be verified if
-     * it is still valid. */
-    if (!append && (session_ticket->ticket_lifetime_hint == 0 ||
-                    (session_ticket->ticket_lifetime_hint +
-                         session_ticket->received_timestamp >
-                     ssl_Time()))) {
-        ss->xtnData.ticketTimestampVerified = PR_TRUE;
-    }
-
-    /* Ticket out of date so don't send PSK. */
-    if (!ss->xtnData.ticketTimestampVerified) {
-        return 0;
-    }
-
-    /* Type + length + vector length + identity length + ticket. */
-    extension_length = 2 + 2 + 2 + 2 +
-                       session_ticket->ticket.len;
+
+    session_ticket = &ss->sec.ci.sid->u.ssl3.locked.sessionTicket;
+
+    extension_length =
+        2 + 2 + 2 +                     /* Type + length + vector length */
+        1 + ke_modes_len +              /* key exchange modes vector */
+        1 + auth_modes_len +            /* auth modes vector */
+        2 + session_ticket->ticket.len; /* identity length + ticket len */
 
     if (maxBytes < (PRUint32)extension_length) {
         PORT_Assert(0);
         return 0;
     }
 
     if (append) {
         SECStatus rv;
         /* extension_type */
         rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_pre_shared_key_xtn, 2);
         if (rv != SECSuccess)
             goto loser;
         rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
         if (rv != SECSuccess)
             goto loser;
-        rv = ssl3_AppendHandshakeNumber(ss, session_ticket->ticket.len + 2, 2);
+        rv = ssl3_AppendHandshakeNumber(ss, extension_length - 6, 2);
+        if (rv != SECSuccess)
+            goto loser;
+        rv = ssl3_AppendHandshakeVariable(ss, ke_modes, ke_modes_len, 1);
+        if (rv != SECSuccess)
+            goto loser;
+        rv = ssl3_AppendHandshakeVariable(ss, auth_modes, auth_modes_len, 1);
         if (rv != SECSuccess)
             goto loser;
         rv = ssl3_AppendHandshakeVariable(ss, session_ticket->ticket.data,
                                           session_ticket->ticket.len, 2);
         PRINT_BUF(50, (ss, "Sending PreSharedKey value",
                        session_ticket->ticket.data,
                        session_ticket->ticket.len));
-        ss->xtnData.ticketTimestampVerified = PR_FALSE;
         ss->xtnData.sentSessionTicketInClientHello = PR_TRUE;
         if (rv != SECSuccess)
             goto loser;
 
         ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
             ssl_tls13_pre_shared_key_xtn;
     }
     return extension_length;
@@ -3550,17 +3552,16 @@ loser:
 }
 
 /* Handle a TLS 1.3 PreSharedKey Extension. We only accept PSKs
  * that contain session tickets. */
 static SECStatus
 tls13_ServerHandlePreSharedKeyXtn(sslSocket *ss, PRUint16 ex_type,
                                   SECItem *data)
 {
-    SECItem label;
     PRInt32 len;
     PRBool first = PR_TRUE;
     SECStatus rv;
 
     SSL_TRC(3, ("%d: SSL3[%d]: handle pre_shared_key extension",
                 SSL_GETPID(), ss->fd));
 
     /* If we are doing < TLS 1.3, then ignore this. */
@@ -3573,42 +3574,66 @@ tls13_ServerHandlePreSharedKeyXtn(sslSoc
         return SECFailure;
 
     if (len != data->len) {
         PORT_SetError(SSL_ERROR_MALFORMED_PRE_SHARED_KEY);
         return SECFailure;
     }
 
     while (data->len) {
+        SECItem label;
+
+        /* IMPORTANT: We aren't copying these values, just setting pointers.
+         * They will only be valid as long as the ClientHello is in memory. */
+        rv = ssl3_ConsumeHandshakeVariable(ss, &ss->xtnData.psk_ke_modes, 1,
+                                           &data->data, &data->len);
+        if (rv != SECSuccess)
+            return rv;
+        if (!ss->xtnData.psk_ke_modes.len) {
+            goto alert_loser;
+        }
+        rv = ssl3_ConsumeHandshakeVariable(ss, &ss->xtnData.psk_auth_modes, 1,
+                                           &data->data, &data->len);
+        if (rv != SECSuccess)
+            return rv;
+        if (!ss->xtnData.psk_auth_modes.len) {
+            goto alert_loser;
+        }
         rv = ssl3_ConsumeHandshakeVariable(ss, &label, 2,
                                            &data->data, &data->len);
         if (rv != SECSuccess)
             return rv;
-
+        if (!label.len) {
+            goto alert_loser;
+        }
         if (first) {
             first = PR_FALSE; /* Continue to read through the extension to check
                                * the format. */
 
             PRINT_BUF(50, (ss, "Handling PreSharedKey value",
                            label.data, label.len));
-
             rv = ssl3_ProcessSessionTicketCommon(ss, &label);
             /* This only happens if we have an internal error, not
              * a malformed ticket. Bogus tickets just don't resume
              * and return SECSuccess. */
             if (rv != SECSuccess)
                 return rv;
         }
     }
 
     /* Keep track of negotiated extensions. Note that this does not
      * mean we are resuming. */
     ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
 
     return SECSuccess;
+
+alert_loser:
+    (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
+    PORT_SetError(SSL_ERROR_MALFORMED_PRE_SHARED_KEY);
+    return SECFailure;
 }
 
 PRInt32
 tls13_ServerSendPreSharedKeyXtn(sslSocket *ss,
                                 PRBool append,
                                 PRUint32 maxBytes)
 {
     PRInt32 extension_length =
@@ -3690,29 +3715,30 @@ tls13_ClientHandlePreSharedKeyXtn(sslSoc
  */
 static PRInt32
 tls13_ClientSendEarlyDataXtn(sslSocket *ss,
                              PRBool append,
                              PRUint32 maxBytes)
 {
     PRInt32 extension_length;
     SECStatus rv;
-    sslSessionID *sid = ss->sec.ci.sid;
-    NewSessionTicket *session_ticket = &sid->u.ssl3.locked.sessionTicket;
-    if (!tls13_ClientAllow0Rtt(ss, sid))
+    NewSessionTicket *session_ticket;
+
+    if (!tls13_ClientAllow0Rtt(ss, ss->sec.ci.sid))
         return 0;
 
     /* type + length + obfuscated ticket age. */
     extension_length = 2 + 2 + 4;
 
     if (maxBytes < (PRUint32)extension_length) {
         PORT_Assert(0);
         return 0;
     }
 
+    session_ticket = &ss->sec.ci.sid->u.ssl3.locked.sessionTicket;
     if (append) {
         PRUint32 age;
 
         rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_early_data_xtn, 2);
         if (rv != SECSuccess)
             return -1;
 
         rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
@@ -3818,19 +3844,106 @@ tls13_ClientHandleEarlyDataXtn(sslSocket
                 SSL_GETPID(), ss->fd));
 
     /* If we are doing < TLS 1.3, then ignore this. */
     if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
         PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION);
         return SECFailure;
     }
 
-    if (data->len != 0) {
+    if (data->len) {
         PORT_SetError(SSL_ERROR_MALFORMED_EARLY_DATA);
         return SECFailure;
     }
 
     /* Keep track of negotiated extensions. */
     ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
     ss->ssl3.hs.zeroRttState = ssl_0rtt_accepted;
 
     return SECSuccess;
 }
+
+static SECStatus
+tls13_ClientHandleTicketEarlyDataInfoXtn(sslSocket *ss, PRUint16 ex_type,
+                                         SECItem *data)
+{
+    PRUint32 utmp;
+    SECStatus rv;
+
+    SSL_TRC(3, ("%d: TLS13[%d]: handle early_data_info extension",
+                SSL_GETPID(), ss->fd));
+
+    /* If we are doing < TLS 1.3, then ignore this. */
+    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+        PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION);
+        return SECFailure;
+    }
+
+    rv = ssl3_ConsumeHandshake(ss, &utmp, sizeof(utmp),
+                               &data->data, &data->len);
+    if (rv != SECSuccess) {
+        PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET);
+        return SECFailure;
+    }
+    if (data->len) {
+        PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET);
+        return SECFailure;
+    }
+
+    ss->xtnData.ticket_age_add_found = PR_TRUE;
+    ss->xtnData.ticket_age_add = PR_ntohl(utmp);
+
+    return SECSuccess;
+}
+
+/* This is only registered if we are sending it. */
+SECStatus
+tls13_ServerSendSigAlgsXtn(sslSocket *ss,
+                           PRBool append,
+                           PRUint32 maxBytes)
+{
+    SSL_TRC(3, ("%d: TLS13[%d]: send signature_algorithms extension",
+                SSL_GETPID(), ss->fd));
+
+    if (maxBytes < 4) {
+        PORT_Assert(0);
+        return 0;
+    }
+
+    if (append) {
+        SECStatus rv;
+
+        rv = ssl3_AppendHandshakeNumber(ss, ssl_signature_algorithms_xtn, 2);
+        if (rv != SECSuccess)
+            return -1;
+
+        rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
+        if (rv != SECSuccess)
+            return -1;
+    }
+
+    return 4;
+}
+
+/* This will only be called if we also offered the extension. */
+static SECStatus
+tls13_ClientHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type,
+                             SECItem *data)
+{
+    SSL_TRC(3, ("%d: TLS13[%d]: handle signature_algorithms extension",
+                SSL_GETPID(), ss->fd));
+
+    /* If we are doing < TLS 1.3, then ignore this. */
+    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+        PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION);
+        return SECFailure;
+    }
+
+    if (data->len != 0) {
+        PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
+        return SECFailure;
+    }
+
+    /* Keep track of negotiated extensions. */
+    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
+
+    return SECSuccess;
+}
--- a/security/nss/lib/ssl/ssl3prot.h
+++ b/security/nss/lib/ssl/ssl3prot.h
@@ -13,17 +13,17 @@
 typedef PRUint8 SSL3Opaque;
 
 typedef PRUint16 SSL3ProtocolVersion;
 /* version numbers are defined in sslproto.h */
 
 /* The TLS 1.3 draft version. Used to avoid negotiating
  * between incompatible pre-standard TLS 1.3 drafts.
  * TODO(ekr@rtfm.com): Remove when TLS 1.3 is published. */
-#define TLS_1_3_DRAFT_VERSION 14
+#define TLS_1_3_DRAFT_VERSION 15
 
 typedef PRUint16 ssl3CipherSuite;
 /* The cipher suites are defined in sslproto.h */
 
 #define MAX_CERT_TYPES 10
 #define MAX_COMPRESSION_METHODS 10
 #define MAX_MAC_LENGTH 64
 #define MAX_PADDING_LENGTH 64
@@ -180,36 +180,29 @@ typedef struct {
 } SSL3Certificate;
 
 /* SSL3SignType moved to ssl.h */
 
 /* The SSL key exchange method used */
 typedef enum {
     kea_null,
     kea_rsa,
-    kea_rsa_export,
-    kea_rsa_export_1024,
     kea_dh_dss,
-    kea_dh_dss_export,
     kea_dh_rsa,
-    kea_dh_rsa_export,
     kea_dhe_dss,
-    kea_dhe_dss_export,
     kea_dhe_rsa,
-    kea_dhe_rsa_export,
     kea_dh_anon,
-    kea_dh_anon_export,
-    kea_rsa_fips,
     kea_ecdh_ecdsa,
     kea_ecdhe_ecdsa,
     kea_ecdh_rsa,
     kea_ecdhe_rsa,
     kea_ecdh_anon,
     kea_ecdhe_psk,
     kea_dhe_psk,
+    kea_tls13_any,
 } SSL3KeyExchangeAlgorithm;
 
 typedef struct {
     SECItem modulus;
     SECItem exponent;
 } SSL3ServerRSAParams;
 
 typedef struct {
@@ -294,20 +287,24 @@ typedef struct {
     PRUint32 received_timestamp;
     PRUint32 ticket_lifetime_hint;
     PRUint32 flags;
     PRUint32 ticket_age_add;
     SECItem ticket;
 } NewSessionTicket;
 
 typedef enum {
-    ticket_allow_early_data = 1,
-    ticket_allow_dhe_resumption = 2,
-    ticket_allow_psk_resumption = 4
-} TLS13SessionTicketFlags;
+    tls13_psk_ke = 0,
+    tls13_psk_dh_ke = 1
+} TLS13PskKEModes;
+
+typedef enum {
+    tls13_psk_auth = 0,
+    tls13_psk_sign_auth = 1
+} TLS13PskAuthModes;
 
 typedef enum {
     CLIENT_AUTH_ANONYMOUS = 0,
     CLIENT_AUTH_CERTIFICATE = 1
 } ClientAuthenticationType;
 
 typedef struct {
     ClientAuthenticationType client_auth_type;
@@ -338,21 +335,21 @@ typedef enum {
     ssl_sig_rsa_pkcs1_sha256 = 0x0401,
     ssl_sig_rsa_pkcs1_sha384 = 0x0501,
     ssl_sig_rsa_pkcs1_sha512 = 0x0601,
     /* For ECDSA, the pairing of the hash with a specific curve is only enforced
      * in TLS 1.3; in TLS 1.2 any curve can be used with each of these. */
     ssl_sig_ecdsa_secp256r1_sha256 = 0x0403,
     ssl_sig_ecdsa_secp384r1_sha384 = 0x0503,
     ssl_sig_ecdsa_secp521r1_sha512 = 0x0603,
-    ssl_sig_rsa_pss_sha256 = 0x0700,
-    ssl_sig_rsa_pss_sha384 = 0x0701,
-    ssl_sig_rsa_pss_sha512 = 0x0702,
-    ssl_sig_ed25519 = 0x0703,
-    ssl_sig_ed448 = 0x0704,
+    ssl_sig_rsa_pss_sha256 = 0x0804,
+    ssl_sig_rsa_pss_sha384 = 0x0805,
+    ssl_sig_rsa_pss_sha512 = 0x0806,
+    ssl_sig_ed25519 = 0x0807,
+    ssl_sig_ed448 = 0x0808,
 
     ssl_sig_dsa_sha1 = 0x0202,
     ssl_sig_dsa_sha256 = 0x0402,
     ssl_sig_dsa_sha384 = 0x0502,
     ssl_sig_dsa_sha512 = 0x0602,
     ssl_sig_ecdsa_sha1 = 0x0203
 } SignatureScheme;
 
--- a/security/nss/lib/ssl/sslcert.c
+++ b/security/nss/lib/ssl/sslcert.c
@@ -170,25 +170,16 @@ ssl_FindServerCertByAuthType(const sslSo
      * are matched when searching for this slot. */
     certType.namedCurve = NULL;
     return ssl_FindServerCert(ss, &certType);
 }
 
 SECStatus
 ssl_OneTimeCertSetup(sslSocket *ss, const sslServerCert *sc)
 {
-    /* Generate a step-down RSA key. */
-    if (sc->certType.authType == ssl_auth_rsa_decrypt &&
-        sc->serverKeyBits > 512 &&
-        !ss->opt.noStepDown && !ss->stepDownKeyPair) {
-        if (ssl3_CreateRSAStepDownKeys(ss) != SECSuccess) {
-            return SECFailure;
-        }
-    }
-
     if (PR_SUCCESS != PR_CallOnceWithArg(&setupServerCAListOnce,
                                          &serverCAListSetup,
                                          (void *)(ss->dbHandle))) {
         return SECFailure;
     }
     return SECSuccess;
 }
 
--- a/security/nss/lib/ssl/sslcert.h
+++ b/security/nss/lib/ssl/sslcert.h
@@ -21,17 +21,17 @@
 ** the named curve of the key.
 */
 typedef struct sslServerCertTypeStr {
     SSLAuthType authType;
     /* For ssl_auth_ecdsa and ssl_auth_ecdh_*.  This is only the named curve
      * of the end-entity certificate key.  The keys in other certificates in
      * the chain aren't directly relevant to the operation of TLS (though it
      * might make certificate validation difficult, libssl doesn't care). */
-    const namedGroupDef *namedCurve;
+    const sslNamedGroupDef *namedCurve;
 } sslServerCertType;
 
 typedef struct sslServerCertStr {
     PRCList link; /* The linked list link */
 
     sslServerCertType certType; /* The certificate slot this occupies */
 
     /* Configuration state for server sockets */
--- a/security/nss/lib/ssl/sslcon.c
+++ b/security/nss/lib/ssl/sslcon.c
@@ -15,19 +15,16 @@
 #include "sslimpl.h"
 #include "sslproto.h"
 #include "ssl3prot.h"
 #include "sslerr.h"
 #include "pk11func.h"
 #include "prinit.h"
 #include "prtime.h" /* for PR_Now() */
 
-#define SET_ERROR_CODE   /* reminder */
-#define TEST_FOR_FAILURE /* reminder */
-
 /*
 ** Put a string tag in the library so that we can examine an executable
 ** and see what kind of security it supports.
 */
 const char *ssl_version = "SECURITY_VERSION:"
                           " +us"
                           " +export"
 #ifdef TRACE
@@ -166,18 +163,17 @@ ssl_BeginClientHandshake(sslSocket *ss)
         sid = ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID,
                             ss->url);
     }
     if (sid) {
         if (sid->version >= ss->vrange.min && sid->version <= ss->vrange.max) {
             PORT_Assert(!ss->sec.localCert);
             ss->sec.localCert = CERT_DupCertificate(sid->localCert);
         } else {
-            if (ss->sec.uncache)
-                ss->sec.uncache(sid);
+            ss->sec.uncache(sid);
             ssl_FreeSID(sid);
             sid = NULL;
         }
     }
     if (!sid) {
         sid = PORT_ZNew(sslSessionID);
         if (!sid) {
             goto loser;
--- a/security/nss/lib/ssl/sslenum.c
+++ b/security/nss/lib/ssl/sslenum.c
@@ -41,33 +41,28 @@
  *      algorithm: GCM, then HMAC-SHA1, then HMAC-SHA256, then HMAC-MD5.
  *    * Within message authentication algorithm sections, order by asymmetric
  *      signature algorithm: ECDSA, then RSA, then DSS.
  *    * As a special case, the PSK ciphers, which are only enabled when
  *      TLS 1.3 PSK-resumption is in use, come first.
  *
  * Exception: Because some servers ignore the high-order byte of the cipher
  * suite ID, we must be careful about adding cipher suites with IDs larger
- * than 0x00ff; see bug 946147. For these broken servers, the first four cipher
- * suites, with the MSB zeroed, look like:
- *      TLS_KRB5_EXPORT_WITH_RC4_40_MD5 { 0x00,0x2B }
+ * than 0x00ff; see bug 946147. For these broken servers, the first three
+ * cipher suites, with the MSB zeroed, look like:
  *      TLS_RSA_WITH_AES_128_CBC_SHA { 0x00,0x2F }
  *      TLS_RSA_WITH_3DES_EDE_CBC_SHA { 0x00,0x0A }
  *      TLS_RSA_WITH_DES_CBC_SHA { 0x00,0x09 }
  * The broken server only supports the third and fourth ones and will select
  * the third one.
  */
 const PRUint16 SSL_ImplementedCiphers[] = {
-    /* ECDHE-PSK from [draft-mattsson-tls-ecdhe-psk-aead]. */
-    TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256,
-    TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
-    TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384,
-    TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
-    TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
-    TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
+    TLS_AES_128_GCM_SHA256,
+    TLS_CHACHA20_POLY1305_SHA256,
+    TLS_AES_256_GCM_SHA384,
 
     TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
     TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
     TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
     TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
     TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
     TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
     /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA must appear before
@@ -120,35 +115,25 @@ const PRUint16 SSL_ImplementedCiphers[] 
     TLS_RSA_WITH_AES_256_GCM_SHA384,
     TLS_RSA_WITH_AES_128_CBC_SHA,
     TLS_RSA_WITH_AES_128_CBC_SHA256,
     TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
     TLS_RSA_WITH_AES_256_CBC_SHA,
     TLS_RSA_WITH_AES_256_CBC_SHA256,
     TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
     TLS_RSA_WITH_SEED_CBC_SHA,
-    SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,
     TLS_RSA_WITH_3DES_EDE_CBC_SHA,
     TLS_RSA_WITH_RC4_128_SHA,
     TLS_RSA_WITH_RC4_128_MD5,
 
     /* 56-bit DES "domestic" cipher suites */
     TLS_DHE_RSA_WITH_DES_CBC_SHA,
     TLS_DHE_DSS_WITH_DES_CBC_SHA,
-    SSL_RSA_FIPS_WITH_DES_CBC_SHA,
     TLS_RSA_WITH_DES_CBC_SHA,
 
-    /* export ciphersuites with 1024-bit public key exchange keys */
-    TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
-    TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA,
-
-    /* export ciphersuites with 512-bit public key exchange keys */
-    TLS_RSA_EXPORT_WITH_RC4_40_MD5,
-    TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
-
     /* ciphersuites with no encryption */
     TLS_ECDHE_ECDSA_WITH_NULL_SHA,
     TLS_ECDHE_RSA_WITH_NULL_SHA,
     TLS_ECDH_RSA_WITH_NULL_SHA,
     TLS_ECDH_ECDSA_WITH_NULL_SHA,
     TLS_RSA_WITH_NULL_SHA,
     TLS_RSA_WITH_NULL_SHA256,
     TLS_RSA_WITH_NULL_MD5,
--- a/security/nss/lib/ssl/sslerr.h
+++ b/security/nss/lib/ssl/sslerr.h
@@ -132,16 +132,17 @@ typedef enum {
     SSL_ERROR_SOCKET_WRITE_FAILURE          = (SSL_ERROR_BASE + 72),
 
     SSL_ERROR_MD5_DIGEST_FAILURE            = (SSL_ERROR_BASE + 73),
     SSL_ERROR_SHA_DIGEST_FAILURE            = (SSL_ERROR_BASE + 74),
     SSL_ERROR_MAC_COMPUTATION_FAILURE       = (SSL_ERROR_BASE + 75),
     SSL_ERROR_SYM_KEY_CONTEXT_FAILURE       = (SSL_ERROR_BASE + 76),
     SSL_ERROR_SYM_KEY_UNWRAP_FAILURE        = (SSL_ERROR_BASE + 77),
     SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED   = (SSL_ERROR_BASE + 78),
+                                            /* error 78 is obsolete */
     SSL_ERROR_IV_PARAM_FAILURE              = (SSL_ERROR_BASE + 79),
     SSL_ERROR_INIT_CIPHER_SUITE_FAILURE     = (SSL_ERROR_BASE + 80),
     SSL_ERROR_SESSION_KEY_GEN_FAILURE       = (SSL_ERROR_BASE + 81),
     SSL_ERROR_NO_SERVER_KEY_FOR_ALG         = (SSL_ERROR_BASE + 82),
     SSL_ERROR_TOKEN_INSERTION_REMOVAL       = (SSL_ERROR_BASE + 83),
     SSL_ERROR_TOKEN_SLOT_NOT_FOUND          = (SSL_ERROR_BASE + 84),
     SSL_ERROR_NO_COMPRESSION_OVERLAP        = (SSL_ERROR_BASE + 85),
     SSL_ERROR_HANDSHAKE_NOT_COMPLETED       = (SSL_ERROR_BASE + 86),
--- a/security/nss/lib/ssl/sslimpl.h
+++ b/security/nss/lib/ssl/sslimpl.h
@@ -55,21 +55,16 @@ typedef SSLMACAlgorithm SSL3MACAlgorithm
 #define mac_md5 ssl_mac_md5
 #define mac_sha ssl_mac_sha
 #define hmac_md5 ssl_hmac_md5
 #define hmac_sha ssl_hmac_sha
 #define hmac_sha256 ssl_hmac_sha256
 #define hmac_sha384 ssl_hmac_sha384
 #define mac_aead ssl_mac_aead
 
-#define SET_ERROR_CODE    /* reminder */
-#define SEND_ALERT        /* reminder */
-#define TEST_FOR_FAILURE  /* reminder */
-#define DEAL_WITH_FAILURE /* reminder */
-
 #if defined(DEBUG) || defined(TRACE)
 #ifdef __cplusplus
 #define Debug 1
 #else
 extern int Debug;
 #endif
 #else
 #undef Debug
@@ -133,57 +128,54 @@ typedef enum { SSLAppOpRead = 0,
 #define SSL_MAX_CACHED_CERT_LEN 4060
 
 #define NUM_MIXERS 9
 
 #ifndef BPB
 #define BPB 8 /* Bits Per Byte */
 #endif
 
-#define EXPORT_RSA_KEY_LENGTH 64 /* bytes */
-
 /* The default value from RFC 4347 is 1s, which is too slow. */
 #define DTLS_RETRANSMIT_INITIAL_MS 50
 /* The maximum time to wait between retransmissions. */
 #define DTLS_RETRANSMIT_MAX_MS 10000
 /* Time to wait in FINISHED state for retransmissions. */
 #define DTLS_RETRANSMIT_FINISHED_MS 30000
 
 /* default number of entries in namedGroupPreferences */
-#define SSL_NAMED_GROUP_COUNT 30
+#define SSL_NAMED_GROUP_COUNT 31
 
 /* Types and names of elliptic curves used in TLS */
 typedef enum {
     ec_type_explicitPrime = 1,      /* not supported */
     ec_type_explicitChar2Curve = 2, /* not supported */
     ec_type_named = 3
 } ECType;
 
-/* TODO: decide if SSLKEAType might be better here. */
 typedef enum {
-    group_type_ec,
-    group_type_ff
-} NamedGroupType;
+    ticket_allow_early_data = 1,
+    ticket_allow_psk_ke = 2,
+    ticket_allow_psk_dhe_ke = 4,
+    ticket_allow_psk_auth = 8,
+    ticket_allow_psk_sign_auth = 16
+} TLS13SessionTicketFlags;
 
 typedef struct {
-    /* This is the index of the curve into the bit mask that we use to track
-     * what has been negotiated on the socket. */
-    PRUint8 index;
     /* The name is the value that is encoded on the wire in TLS. */
     SSLNamedGroup name;
     /* The number of bits in the group. */
     unsigned int bits;
-    /* Whether the group is Elliptic or Finite-Field. */
-    NamedGroupType type;
+    /* The key exchange algorithm this group provides. */
+    SSLKEAType keaType;
     /* The OID that identifies the group to PKCS11.  This also determines
      * whether the group is enabled in policy. */
     SECOidTag oidTag;
-    /* Non-suite-B groups are enabled by patching NSS. Yuck. */
-    PRBool suiteb;
-} namedGroupDef;
+    /* Assume that the group is always supported. */
+    PRBool assumeSupported;
+} sslNamedGroupDef;
 
 typedef struct sslBufferStr sslBuffer;
 typedef struct sslConnectInfoStr sslConnectInfo;
 typedef struct sslGatherStr sslGather;
 typedef struct sslSecurityInfoStr sslSecurityInfo;
 typedef struct sslSessionIDStr sslSessionID;
 typedef struct sslSocketStr sslSocket;
 typedef struct sslSocketOpsStr sslSocketOps;
@@ -213,31 +205,31 @@ typedef sslSessionID *(*sslSessionIDLook
  * or returns length of data that it would have appended.
  */
 typedef PRInt32 (*ssl3HelloExtensionSenderFunc)(sslSocket *ss, PRBool append,
                                                 PRUint32 maxBytes);
 
 /* registerable callback function that handles a received extension,
  * of the given type.
  */
-typedef SECStatus (*ssl3HelloExtensionHandlerFunc)(sslSocket *ss,
-                                                   PRUint16 ex_type,
-                                                   SECItem *data);
+typedef SECStatus (*ssl3ExtensionHandlerFunc)(sslSocket *ss,
+                                              PRUint16 ex_type,
+                                              SECItem *data);
 
 /* row in a table of hello extension senders */
 typedef struct {
     PRInt32 ex_type;
     ssl3HelloExtensionSenderFunc ex_sender;
 } ssl3HelloExtensionSender;
 
 /* row in a table of hello extension handlers */
 typedef struct {
     PRInt32 ex_type;
-    ssl3HelloExtensionHandlerFunc ex_handler;
-} ssl3HelloExtensionHandler;
+    ssl3ExtensionHandlerFunc ex_handler;
+} ssl3ExtensionHandler;
 
 extern SECStatus
 ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type,
                                         ssl3HelloExtensionSenderFunc cb);
 
 extern PRInt32
 ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
                                const ssl3HelloExtensionSender *sender);
@@ -298,17 +290,17 @@ typedef struct {
 #else
     ssl3CipherSuite cipher_suite;
     PRUint8 policy;
     unsigned char enabled : 1;
     unsigned char isPresent : 1;
 #endif
 } ssl3CipherSuiteCfg;
 
-#define ssl_V3_SUITES_IMPLEMENTED 80
+#define ssl_V3_SUITES_IMPLEMENTED 71
 
 #define MAX_DTLS_SRTP_CIPHER_SUITES 4
 
 /* MAX_SIGNATURE_SCHEMES allows for all the values we support. */
 #define MAX_SIGNATURE_SCHEMES 15
 
 typedef struct sslOptionsStr {
     /* If SSL_SetNextProtoNego has been called, then this contains the
@@ -319,17 +311,16 @@ typedef struct sslOptionsStr {
     unsigned int useSocks : 1;
     unsigned int requestCertificate : 1;
     unsigned int requireCertificate : 2;
     unsigned int handshakeAsClient : 1;
     unsigned int handshakeAsServer : 1;
     unsigned int noCache : 1;
     unsigned int fdx : 1;
     unsigned int detectRollBack : 1;
-    unsigned int noStepDown : 1;
     unsigned int bypassPKCS11 : 1;
     unsigned int noLocks : 1;
     unsigned int enableSessionTickets : 1;
     unsigned int enableDeflate : 1;
     unsigned int enableRenegotiation : 2;
     unsigned int requireSafeNegotiation : 1;
     unsigned int enableFalseStart : 1;
     unsigned int cbcRandomIV : 1;
@@ -702,22 +693,16 @@ typedef struct {
     /* The type of key exchange used by the cipher suite. */
     SSLKEAType exchKeyType;
     /* If the cipher suite uses a signature, the type of key used in the
      * signature. */
     KeyType signKeyType;
     /* In most cases, cipher suites depend on their signature type for
      * authentication, ECDH certificates being the exception. */
     SSLAuthType authKeyType;
-    /* For export cipher suites:
-     * is_limited identifies a suite as having a limit on the key size.
-     * key_size_limit provides the corresponding limit. */
-    PRBool is_limited;
-    unsigned int key_size_limit;
-    PRBool tls_keygen;
     /* True if the key exchange for the suite is ephemeral.  Or to be more
      * precise: true if the ServerKeyExchange message is always required. */
     PRBool ephemeral;
     /* An OID describing the key exchange */
     SECOidTag oid;
 } ssl3KEADef;
 
 /*
@@ -808,16 +793,20 @@ struct TLSExtensionDataStr {
     PRUint16 numNegotiated;
     PRUint16 advertised[SSL_MAX_EXTENSIONS];
     PRUint16 negotiated[SSL_MAX_EXTENSIONS];
 
     /* SessionTicket Extension related data. */
     PRBool ticketTimestampVerified;
     PRBool emptySessionTicket;
     PRBool sentSessionTicketInClientHello;
+    SECItem psk_ke_modes;
+    SECItem psk_auth_modes;
+    PRUint32 ticket_age_add;
+    PRBool ticket_age_add_found;
 
     /* SNI Extension related data
      * Names data is not coppied from the input buffer. It can not be
      * used outside the scope where input buffer is defined and that
      * is beyond ssl3_HandleClientHello function. */
     SECItem *sniNameArr;
     PRUint32 sniNameArrSize;
 
@@ -847,19 +836,19 @@ typedef struct DTLSQueuedMessageStr {
     PRCList link;           /* The linked list link */
     ssl3CipherSpec *cwSpec; /* The cipher spec to use, null for none */
     SSL3ContentType type;   /* The message type */
     unsigned char *data;    /* The data */
     PRUint16 len;           /* The data length */
 } DTLSQueuedMessage;
 
 typedef struct TLS13KeyShareEntryStr {
-    PRCList link;               /* The linked list link */
-    const namedGroupDef *group; /* The group for the entry */
-    SECItem key_exchange;       /* The share itself */
+    PRCList link;                  /* The linked list link */
+    const sslNamedGroupDef *group; /* The group for the entry */
+    SECItem key_exchange;          /* The share itself */
 } TLS13KeyShareEntry;
 
 typedef struct TLS13EarlyDataStr {
     PRCList link; /* The linked list link */
     SECItem data; /* The data */
 } TLS13EarlyData;
 
 typedef struct {
@@ -922,21 +911,20 @@ typedef struct SSL3HandshakeStateStr {
     SSLCompressionMethod compression;
     sslBuffer msg_body; /* protected by recvBufLock */
                         /* partial handshake message from record layer */
     unsigned int header_bytes;
     /* number of bytes consumed from handshake */
     /* message for message type and header length */
     SSL3HandshakeType msg_type;
     unsigned long msg_len;
-    PRBool isResuming;      /* we are resuming (not used in TLS 1.3) */
-    PRBool usedStepDownKey; /* we did a server key exchange. */
-    PRBool sendingSCSV;     /* instead of empty RI */
-    sslBuffer msgState;     /* current state for handshake messages*/
-                            /* protected by recvBufLock */
+    PRBool isResuming;  /* we are resuming (not used in TLS 1.3) */
+    PRBool sendingSCSV; /* instead of empty RI */
+    sslBuffer msgState; /* current state for handshake messages*/
+                        /* protected by recvBufLock */
 
     /* The session ticket received in a NewSessionTicket message is temporarily
      * stored in newSessionTicket until the handshake is finished; then it is
      * moved to the sid.
      */
     PRBool receivedNewSessionTicket;
     NewSessionTicket newSessionTicket;
 
@@ -1001,27 +989,27 @@ typedef struct SSL3HandshakeStateStr {
     SECItem resumptionContext;      /* The resumption context. */
     PK11SymKey *dheSecret;          /* The (EC)DHE shared secret. */
     PK11SymKey *earlyTrafficSecret; /* The secret we use for 0-RTT. */
     PK11SymKey *hsTrafficSecret;    /* The handshake traffic secret. */
     PK11SymKey *trafficSecret;      /* The source key to use to generate
                                         * traffic keys */
     /* The certificate request from the server. */
     TLS13CertificateRequest *certificateRequest;
-    ssl3CipherSuite origCipherSuite; /* The cipher suite from the original
-                                        * connection if we are resuming. */
-    PRCList cipherSpecs;             /* The cipher specs in the sequence they
+    PRCList cipherSpecs;            /* The cipher specs in the sequence they
                                         * will be applied. */
-    ssl3CipherSpec *nullSpec;        /* In case 0-RTT is rejected. */
-    sslZeroRttState zeroRttState;    /* Are we doing a 0-RTT handshake? */
-    sslZeroRttIgnore zeroRttIgnore;  /* Are we ignoring 0-RTT? */
-    PRCList bufferedEarlyData;       /* Buffered TLS 1.3 early data
+    ssl3CipherSpec *nullSpec;       /* In case 0-RTT is rejected. */
+    sslZeroRttState zeroRttState;   /* Are we doing a 0-RTT handshake? */
+    sslZeroRttIgnore zeroRttIgnore; /* Are we ignoring 0-RTT? */
+    PRCList bufferedEarlyData;      /* Buffered TLS 1.3 early data
                                         * on server.*/
-    PRBool helloRetry;               /* True if HelloRetryRequest has been sent
+    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 */
 } 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.
@@ -1066,17 +1054,17 @@ struct ssl3StateStr {
     PRUint16 mtu; /* Our estimate of the MTU */
 
     /* DTLS-SRTP cipher suite preferences (if any) */
     PRUint16 dtlsSRTPCiphers[MAX_DTLS_SRTP_CIPHER_SUITES];
     PRUint16 dtlsSRTPCipherCount;
     PRUint16 dtlsSRTPCipherSuite; /* 0 if not selected */
     PRBool fatalAlertSent;
     PRBool dheWeakGroupEnabled; /* used by server */
-    const namedGroupDef *dhePreferredGroup;
+    const sslNamedGroupDef *dhePreferredGroup;
 
     /* TLS 1.2 introduces separate signature algorithm negotiation.
      * TLS 1.3 combined signature and hash into a single enum.
      * This is our preference order. */
     SignatureScheme signatureSchemes[MAX_SIGNATURE_SCHEMES];
     unsigned int signatureSchemeCount;
 
     /* The version to check if we fell back from our highest version
@@ -1100,17 +1088,17 @@ typedef struct {
 struct sslKeyPairStr {
     SECKEYPrivateKey *privKey;
     SECKEYPublicKey *pubKey;
     PRInt32 refCount; /* use PR_Atomic calls for this. */
 };
 
 typedef struct {
     PRCList link;
-    const namedGroupDef *group;
+    const sslNamedGroupDef *group;
     sslKeyPair *keys;
 } sslEphemeralKeyPair;
 
 struct ssl3DHParamsStr {
     SSLNamedGroup name;
     SECItem prime; /* p */
     SECItem base;  /* g */
 };
@@ -1250,18 +1238,16 @@ struct sslSocketStr {
     /* protected by firstHandshakeLock AND ssl3HandshakeLock. */
     const char *url;
 
     sslHandshakeFunc handshake; /*firstHandshakeLock*/
 
     /* the following variable is only used with socks or other proxies. */
     char *peerID; /* String uniquely identifies target server. */
 
-    sslKeyPair *stepDownKeyPair; /* RSA step down keys */
-
     /* ECDHE and DHE keys: In TLS 1.3, we might have to maintain multiple of
      * these on the client side.  The server inserts a single value into this
      * list for all versions. */
     PRCList /*<sslEphemeralKeyPair>*/ ephemeralKeyPairs;
 
     /* Callbacks */
     SSLAuthCertificate authCertificate;
     void *authCertificateArg;
@@ -1333,17 +1319,17 @@ struct sslSocketStr {
      * to all elements in ssl_named_groups in the default order.
      * This list also determines which groups are enabled. This
      * starts with all being enabled and can be modified either by negotiation
      * (in which case groups not supported by a peer are masked off), or by
      * calling SSL_DHEGroupPrefSet().
      * Note that renegotiation will ignore groups that were disabled in the
      * first handshake.
      */
-    const namedGroupDef *namedGroupPreferences[SSL_NAMED_GROUP_COUNT];
+    const sslNamedGroupDef *namedGroupPreferences[SSL_NAMED_GROUP_COUNT];
 
     /* SSL3 state info.  Formerly was a pointer */
     ssl3State ssl3;
 
     /*
      * TLS extension related data.
      */
     /* True when the current session is a stateless resume. */
@@ -1367,17 +1353,17 @@ extern PRUint32 ssl_sid_timeout;
 extern PRUint32 ssl3_sid_timeout;
 
 extern const char *const ssl3_cipherName[];
 
 extern sslSessionIDLookupFunc ssl_sid_lookup;
 extern sslSessionIDCacheFunc ssl_sid_cache;
 extern sslSessionIDUncacheFunc ssl_sid_uncache;
 
-extern const namedGroupDef ssl_named_groups[];
+extern const sslNamedGroupDef ssl_named_groups[];
 
 /************************************************************************/
 
 SEC_BEGIN_PROTOS
 
 /* Internal initialization and installation of the SSL error tables */
 extern SECStatus ssl_Init(void);
 extern SECStatus ssl_InitializePRErrorTable(void);
@@ -1648,17 +1634,17 @@ extern PRInt32 ssl3_SendRecord(sslSocket
 #define SSL_ALL_VERSIONS_DISABLED(vrange) \
     ((vrange)->min == SSL_LIBRARY_VERSION_NONE)
 
 extern PRBool ssl3_VersionIsSupported(SSLProtocolVariant protocolVariant,
                                       SSL3ProtocolVersion version);
 
 extern SECStatus ssl3_KeyAndMacDeriveBypass(ssl3CipherSpec *pwSpec,
                                             const unsigned char *cr, const unsigned char *sr,
-                                            PRBool isTLS, HASH_HashType tls12HashType, PRBool isExport);
+                                            PRBool isTLS, HASH_HashType tls12HashType);
 extern SECStatus ssl3_MasterSecretDeriveBypass(ssl3CipherSpec *pwSpec,
                                                const unsigned char *cr, const unsigned char *sr,
                                                const SECItem *pms, PRBool isTLS,
                                                HASH_HashType tls12HashType, PRBool isRSA);
 
 /* These functions are called from secnav, even though they're "private". */
 
 extern int SSL_RestartHandshakeAfterCertReq(struct sslSocketStr *ss,
@@ -1685,85 +1671,76 @@ SECStatus ssl3_SendClientHello(sslSocket
  * input into the SSL3 machinery from the actualy network reading code
  */
 SECStatus ssl3_HandleRecord(
     sslSocket *ss, SSL3Ciphertext *cipher, sslBuffer *out);
 SECStatus ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize);
 
 int ssl3_GatherAppDataRecord(sslSocket *ss, int flags);
 int ssl3_GatherCompleteHandshake(sslSocket *ss, int flags);
-/*
- * When talking to export clients or using export cipher suites, servers
- * with public RSA keys larger than 512 bits need to use a 512-bit public
- * key, signed by the larger key.  The smaller key is a "step down" key.
- * Generate that key pair and keep it around.
- */
-extern SECStatus ssl3_CreateRSAStepDownKeys(sslSocket *ss);
 
 /* Create a new ref counted key pair object from two keys. */
 extern sslKeyPair *ssl_NewKeyPair(SECKEYPrivateKey *privKey,
                                   SECKEYPublicKey *pubKey);
 
 /* get a new reference (bump ref count) to an ssl3KeyPair. */
 extern sslKeyPair *ssl_GetKeyPairRef(sslKeyPair *keyPair);
 
 /* Decrement keypair's ref count and free if zero. */
 extern void ssl_FreeKeyPair(sslKeyPair *keyPair);
 
 extern sslEphemeralKeyPair *ssl_NewEphemeralKeyPair(
-    const namedGroupDef *group,
+    const sslNamedGroupDef *group,
     SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey);
 extern sslEphemeralKeyPair *ssl_CopyEphemeralKeyPair(
     sslEphemeralKeyPair *keyPair);
 extern void ssl_FreeEphemeralKeyPair(sslEphemeralKeyPair *keyPair);
 extern sslEphemeralKeyPair *ssl_LookupEphemeralKeyPair(
-    sslSocket *ss, const namedGroupDef *groupDef);
+    sslSocket *ss, const sslNamedGroupDef *groupDef);
 extern void ssl_FreeEphemeralKeyPairs(sslSocket *ss);
 
 extern SECStatus ssl_AppendPaddedDHKeyShare(sslSocket *ss,
                                             SECKEYPublicKey *pubKey,
                                             PRBool appendLength);
-extern const ssl3DHParams *ssl_GetDHEParams(const namedGroupDef *groupDef);
+extern const ssl3DHParams *ssl_GetDHEParams(const sslNamedGroupDef *groupDef);
 extern SECStatus ssl_SelectDHEGroup(sslSocket *ss,
-                                    const namedGroupDef **groupDef);
-extern SECStatus ssl_CreateDHEKeyPair(const namedGroupDef *groupDef,
+                                    const sslNamedGroupDef **groupDef);
+extern SECStatus ssl_CreateDHEKeyPair(const sslNamedGroupDef *groupDef,
                                       const ssl3DHParams *params,
                                       sslEphemeralKeyPair **keyPair);
 extern PRBool ssl_IsValidDHEShare(const SECItem *dh_p, const SECItem *dh_Ys);
 extern SECStatus ssl_ValidateDHENamedGroup(sslSocket *ss,
                                            const SECItem *dh_p,
                                            const SECItem *dh_g,
-                                           const namedGroupDef **groupDef,
+                                           const sslNamedGroupDef **groupDef,
                                            const ssl3DHParams **dhParams);
 
 extern PRBool ssl_IsECCEnabled(sslSocket *ss);
 extern PRBool ssl_IsDHEEnabled(sslSocket *ss);
 
 /* Macro for finding a curve equivalent in strength to RSA key's */
-/* clang-format off */
-#define SSL_RSASTRENGTH_TO_ECSTRENGTH(s)                                       \
-        ((s <= 1024) ? 160                                                     \
-                     : ((s <= 2048) ? 224                                      \
-                                    : ((s <= 3072) ? 256                       \
-                                                   : ((s <= 7168) ? 384        \
-                                                                  : 521 ) ) ) )
-/* clang-format on */
+#define SSL_RSASTRENGTH_TO_ECSTRENGTH(s)                            \
+    ((s <= 1024) ? 160                                              \
+                 : ((s <= 2048) ? 224                               \
+                                : ((s <= 3072) ? 256                \
+                                               : ((s <= 7168) ? 384 \
+                                                              : 521))))
 
-extern const namedGroupDef *ssl_LookupNamedGroup(SSLNamedGroup group);
-extern PRBool ssl_NamedGroupEnabled(const sslSocket *ss, const namedGroupDef *group);
+extern const sslNamedGroupDef *ssl_LookupNamedGroup(SSLNamedGroup group);
+extern PRBool ssl_NamedGroupEnabled(const sslSocket *ss, const sslNamedGroupDef *group);
 extern SECStatus ssl_NamedGroup2ECParams(PLArenaPool *arena,
-                                         const namedGroupDef *curve,
+                                         const sslNamedGroupDef *curve,
                                          SECKEYECParams *params);
-extern const namedGroupDef *ssl_ECPubKey2NamedGroup(
+extern const sslNamedGroupDef *ssl_ECPubKey2NamedGroup(
     const SECKEYPublicKey *pubKey);
 
-extern const namedGroupDef *ssl_GetECGroupWithStrength(sslSocket *ss,
-                                                       unsigned int requiredECCbits);
-extern const namedGroupDef *ssl_GetECGroupForServerSocket(sslSocket *ss);
-extern void ssl_DisableNonSuiteBGroups(sslSocket *ss);
+extern const sslNamedGroupDef *ssl_GetECGroupWithStrength(sslSocket *ss,
+                                                          unsigned int requiredECCbits);
+extern const sslNamedGroupDef *ssl_GetECGroupForServerSocket(sslSocket *ss);
+extern void ssl_FilterSupportedGroups(sslSocket *ss);
 
 extern SECStatus ssl3_CipherPrefSetDefault(ssl3CipherSuite which, PRBool on);
 extern SECStatus ssl3_CipherPrefGetDefault(ssl3CipherSuite which, PRBool *on);
 
 extern SECStatus ssl3_CipherPrefSet(sslSocket *ss, ssl3CipherSuite which, PRBool on);
 extern SECStatus ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *on);
 
 extern SECStatus ssl3_SetPolicy(ssl3CipherSuite which, PRInt32 policy);
@@ -1788,19 +1765,19 @@ extern SECStatus ssl_GetPeerInfo(sslSock
 extern SECStatus ssl3_SendECDHClientKeyExchange(sslSocket *ss,
                                                 SECKEYPublicKey *svrPubKey);
 extern SECStatus ssl3_HandleECDHServerKeyExchange(sslSocket *ss,
                                                   SSL3Opaque *b, PRUint32 length);
 extern SECStatus ssl3_HandleECDHClientKeyExchange(sslSocket *ss,
                                                   SSL3Opaque *b, PRUint32 length,
                                                   sslKeyPair *serverKeys);
 extern SECStatus ssl3_SendECDHServerKeyExchange(sslSocket *ss);
-extern SECStatus tls13_ImportECDHKeyShare(
+extern SECStatus ssl_ImportECDHKeyShare(
     sslSocket *ss, SECKEYPublicKey *peerKey,
-    SSL3Opaque *b, PRUint32 length, const namedGroupDef *curve);
+    SSL3Opaque *b, PRUint32 length, const sslNamedGroupDef *curve);
 unsigned int tls13_SizeOfECDHEKeyShareKEX(const SECKEYPublicKey *pubKey);
 SECStatus tls13_EncodeECDHEKeyShareKEX(sslSocket *ss,
                                        const SECKEYPublicKey *pubKey);
 
 extern SECStatus ssl3_ComputeCommonKeyHash(SSLHashType hashAlg,
                                            PRUint8 *hashBuf,
                                            unsigned int bufLen, SSL3Hashes *hashes,
                                            PRBool bypassPKCS11);
@@ -1870,19 +1847,19 @@ extern PRInt32 ssl3_SendServerNameXtn(ss
                                       PRUint32 maxBytes);
 
 extern PRInt32 ssl_SendSupportedGroupsXtn(sslSocket *ss,
                                           PRBool append, PRUint32 maxBytes);
 extern PRInt32 ssl3_SendSupportedPointFormatsXtn(sslSocket *ss,
                                                  PRBool append, PRUint32 maxBytes);
 
 /* call the registered extension handlers. */
-extern SECStatus ssl3_HandleHelloExtensions(sslSocket *ss,
-                                            SSL3Opaque **b, PRUint32 *length,
-                                            SSL3HandshakeType handshakeMessage);
+extern SECStatus ssl3_HandleExtensions(sslSocket *ss,
+                                       SSL3Opaque **b, PRUint32 *length,
+                                       SSL3HandshakeType handshakeMessage);
 
 /* Hello Extension related routines. */
 extern PRBool ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type);
 extern void ssl3_SetSIDSessionTicket(sslSessionID *sid,
                                      /*in/out*/ NewSessionTicket *session_ticket);
 SECStatus ssl3_EncodeSessionTicket(sslSocket *ss,
                                    const NewSessionTicket *ticket_input,
                                    SECItem *ticket_data);
@@ -2000,38 +1977,48 @@ SECStatus ssl3_CompleteHandleCertificate
     unsigned int signatureSchemeCount, CERTDistNames *ca_list);
 SECStatus ssl3_SendServerHello(sslSocket *ss);
 SECStatus ssl3_ComputeHandshakeHashes(sslSocket *ss,
                                       ssl3CipherSpec *spec,
                                       SSL3Hashes *hashes,
                                       PRUint32 sender);
 PRInt32 tls13_ServerSendKeyShareXtn(sslSocket *ss, PRBool append,
                                     PRUint32 maxBytes);
-SECStatus ssl_CreateECDHEphemeralKeyPair(const namedGroupDef *ecGroup,
+SECStatus ssl_CreateECDHEphemeralKeyPair(const sslNamedGroupDef *ecGroup,
                                          sslEphemeralKeyPair **keyPair);
+SECStatus ssl_CreateStaticECDHEKey(sslSocket *ss,
+                                   const sslNamedGroupDef *ecGroup);
 SECStatus ssl3_FlushHandshake(sslSocket *ss, PRInt32 flags);
 PK11SymKey *ssl3_GetWrappingKey(sslSocket *ss,
                                 PK11SlotInfo *masterSecretSlot,
                                 const sslServerCert *serverCert,
                                 CK_MECHANISM_TYPE masterWrapMech,
                                 void *pwArg);
 PRInt32 tls13_ServerSendPreSharedKeyXtn(sslSocket *ss,
                                         PRBool append,
                                         PRUint32 maxBytes);
 PRInt32 tls13_ServerSendEarlyDataXtn(sslSocket *ss,
                                      PRBool append,
                                      PRUint32 maxBytes);
+PRInt32 tls13_ServerSendSigAlgsXtn(sslSocket *ss,
+                                   PRBool append,
+                                   PRUint32 maxBytes);
 PRBool ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type);
 SECStatus ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid);
 const ssl3CipherSuiteDef *ssl_LookupCipherSuiteDef(ssl3CipherSuite suite);
 const ssl3BulkCipherDef *
 ssl_GetBulkCipherDef(const ssl3CipherSuiteDef *cipher_def);
 SECStatus ssl3_SelectServerCert(sslSocket *ss);
+SECStatus ssl_PickSignatureScheme(sslSocket *ss, SECKEYPublicKey *key,
+                                  const SignatureScheme *peerSchemes,
+                                  unsigned int peerSchemeCount,
+                                  PRBool requireSha1);
 SECOidTag ssl3_HashTypeToOID(SSLHashType hashType);
 SSLHashType ssl_SignatureSchemeToHashType(SignatureScheme scheme);
+KeyType ssl_SignatureSchemeToKeyType(SignatureScheme scheme);
 
 SECStatus ssl3_SetCipherSuite(sslSocket *ss, ssl3CipherSuite chosenSuite,
                               PRBool initHashes);
 
 /* Pull in TLS 1.3 functions */
 #include "tls13con.h"
 
 /********************** misc calls *********************/
@@ -2041,20 +2028,16 @@ extern void ssl3_CheckCipherSuiteOrderCo
 #endif
 
 extern int ssl_MapLowLevelError(int hiLevelError);
 
 extern PRUint32 ssl_Time(void);
 
 extern void SSL_AtomicIncrementLong(long *x);
 
-SECStatus SSL_DisableDefaultExportCipherSuites(void);
-SECStatus SSL_DisableExportCipherSuites(PRFileDesc *fd);
-PRBool SSL_IsExportCipherSuite(PRUint16 cipherSuite);
-
 SECStatus ssl3_ApplyNSSPolicy(void);
 
 extern HASH_HashType
 ssl3_GetTls12HashType(sslSocket *ss);
 
 extern SECStatus
 ssl3_TLSPRFWithMasterSecret(ssl3CipherSpec *spec,
                             const char *label, unsigned int labelLen,
--- a/security/nss/lib/ssl/sslinfo.c
+++ b/security/nss/lib/ssl/sslinfo.c
@@ -46,32 +46,44 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLCh
     inf.length = PR_MIN(sizeof inf, len);
 
     if (ss->opt.useSecurity && ss->enoughFirstHsDone) {
         sid = ss->sec.ci.sid;
         inf.protocolVersion = ss->version;
         inf.authKeyBits = ss->sec.authKeyBits;
         inf.keaKeyBits = ss->sec.keaKeyBits;
         if (ss->ssl3.initialized) {
+            SSLCipherSuiteInfo cinfo;
+            SECStatus rv;
+
             ssl_GetSpecReadLock(ss);
             /* XXX  The cipher suite should be in the specs and this
              * function should get it from cwSpec rather than from the "hs".
              * See bug 275744 comment 69 and bug 766137.
              */
-            /* For TLS 1.3, we return the cipher suite of the original
-             * connection if there was one rather than the PSK cipher
-             * suite. This matches the original interface for resumption
-             * and is safe because we only enable the corresponding PSK
-             * cipher suite.
-             */
-            inf.cipherSuite = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 ? ss->ssl3.hs.origCipherSuite : ss->ssl3.hs.cipher_suite;
+            inf.cipherSuite = ss->ssl3.hs.cipher_suite;
             inf.compressionMethod = ss->ssl3.cwSpec->compression_method;
             ssl_ReleaseSpecReadLock(ss);
             inf.compressionMethodName =
                 ssl_GetCompressionMethodName(inf.compressionMethod);
+
+            /* Fill in the cipher details from the cipher suite. */
+            rv = SSL_GetCipherSuiteInfo(inf.cipherSuite,
+                                        &cinfo, sizeof(cinfo));
+            if (rv != SECSuccess) {
+                return SECFailure; /* Error code already set. */
+            }
+            inf.symCipher = cinfo.symCipher;
+            inf.macAlgorithm = cinfo.macAlgorithm;
+            /* Get these fromm |ss->sec| because that is accurate
+             * even with TLS 1.3 disaggregated cipher suites. */
+            inf.keaType = ss->sec.keaType;
+            inf.keaKeyBits = ss->sec.keaKeyBits;
+            inf.authType = ss->sec.authType;
+            inf.authKeyBits = ss->sec.authKeyBits;
         }
         if (sid) {
             unsigned int sidLen;
 
             inf.creationTime = sid->creationTime;
             inf.lastAccessTime = sid->lastAccessTime;
             inf.expirationTime = sid->expirationTime;
             inf.extendedMasterSecretUsed =
@@ -118,60 +130,57 @@ SSL_GetPreliminaryChannelInfo(PRFileDesc
         return SECFailure;
     }
 
     memset(&inf, 0, sizeof(inf));
     inf.length = PR_MIN(sizeof(inf), len);
 
     inf.valuesSet = ss->ssl3.hs.preliminaryInfo;
     inf.protocolVersion = ss->version;
-    /* For TLS 1.3, we return the cipher suite of the original
-     * connection if there was one rather than the PSK cipher
-     * suite. This matches the original interface for resumption
-     * and is safe because we only enable the corresponding PSK
-     * cipher suite.
-     */
-    inf.cipherSuite = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 ? ss->ssl3.hs.origCipherSuite : ss->ssl3.hs.cipher_suite;
+    inf.cipherSuite = ss->ssl3.hs.cipher_suite;
 
     memcpy(info, &inf, inf.length);
     return SECSuccess;
 }
 
 /* name */
 #define CS_(x) x, #x
 #define CS(x) CS_(TLS_##x)
 
 /* legacy values for authAlgorithm */
 #define S_DSA "DSA", ssl_auth_dsa
 /* S_RSA is incorrect for signature-based suites */
 /* ECDH suites incorrectly report S_RSA or S_ECDSA */
 #define S_RSA "RSA", ssl_auth_rsa_decrypt
 #define S_ECDSA "ECDSA", ssl_auth_ecdsa
 #define S_PSK "PSK", ssl_auth_psk
+#define S_ANY "TLS 1.3", ssl_auth_tls13_any
 
 /* real authentication algorithm */
 #define A_DSA ssl_auth_dsa
 #define A_RSAD ssl_auth_rsa_decrypt
 #define A_RSAS ssl_auth_rsa_sign
 #define A_ECDSA ssl_auth_ecdsa
 #define A_ECDH_R ssl_auth_ecdh_rsa
 #define A_ECDH_E ssl_auth_ecdh_ecdsa
 #define A_PSK ssl_auth_psk
 /* Report ssl_auth_null for export suites that can't decide between
  * ssl_auth_rsa_sign and ssl_auth_rsa_decrypt. */
 #define A_EXP ssl_auth_null
+#define A_ANY ssl_auth_tls13_any
 
 /* key exchange */
 #define K_DHE "DHE", ssl_kea_dh
 #define K_RSA "RSA", ssl_kea_rsa
 #define K_KEA "KEA", ssl_kea_kea
 #define K_ECDH "ECDH", ssl_kea_ecdh
 #define K_ECDHE "ECDHE", ssl_kea_ecdh
 #define K_ECDHE_PSK "ECDHE-PSK", ssl_kea_ecdh_psk
 #define K_DHE_PSK "DHE-PSK", ssl_kea_dh_psk
+#define K_ANY "TLS 1.3", ssl_kea_tls13_any
 
 /* record protection cipher */
 #define C_SEED "SEED", calg_seed
 #define C_CAMELLIA "CAMELLIA", calg_camellia
 #define C_AES "AES", calg_aes
 #define C_RC4 "RC4", calg_rc4
 #define C_RC2 "RC2", calg_rc2
 #define C_DES "DES", calg_des
@@ -203,16 +212,20 @@ SSL_GetPreliminaryChannelInfo(PRFileDesc
 #define F_FIPS_STD 1, 0, 0, 0
 #define F_FIPS_NSTD 1, 0, 1, 0
 #define F_NFIPS_STD 0, 0, 0, 0
 #define F_NFIPS_NSTD 0, 0, 1, 0 /* i.e., trash */
 #define F_EXPORT 0, 1, 0, 0     /* i.e., trash */
 
 static const SSLCipherSuiteInfo suiteInfo[] = {
     /* <------ Cipher suite --------------------> <auth> <KEA>  <bulk cipher> <MAC> <FIPS> */
+    { 0, CS_(TLS_AES_128_GCM_SHA256), S_ANY, K_ANY, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_ANY },
+    { 0, CS_(TLS_CHACHA20_POLY1305_SHA256), S_ANY, K_ANY, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_ANY },
+    { 0, CS_(TLS_AES_256_GCM_SHA384), S_ANY, K_ANY, C_AESGCM, B_256, M_AEAD_128, F_NFIPS_STD, A_ANY },
+
     { 0, CS(RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_RSA, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAD },
     { 0, CS(DHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_DHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_RSAS },
 
     { 0, CS(DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_RSAS },
     { 0, CS(DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_DSA },
     { 0, CS(DHE_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_DHE, C_AES, B_256, M_SHA256, F_FIPS_STD, A_RSAS },
     { 0, CS(DHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_DHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAS },
     { 0, CS(DHE_DSS_WITH_AES_256_CBC_SHA), S_DSA, K_DHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_DSA },
@@ -221,42 +234,35 @@ static const SSLCipherSuiteInfo suiteInf
     { 0, CS(RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_RSA, C_AES, B_256, M_SHA256, F_FIPS_STD, A_RSAD },
     { 0, CS(RSA_WITH_AES_256_CBC_SHA), S_RSA, K_RSA, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAD },
 
     { 0, CS(DHE_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_RSAS },
     { 0, CS(DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_DSA },
     { 0, CS(DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_DSA },
     { 0, CS(DHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_DHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAS },
     { 0, CS(DHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAS },
-    { 0, CS(DHE_PSK_WITH_AES_128_GCM_SHA256), S_PSK, K_DHE_PSK, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_PSK },
     { 0, CS(DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAS },
     { 0, CS(DHE_DSS_WITH_AES_128_GCM_SHA256), S_DSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_DSA },
     { 0, CS(DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_DSA },
     { 0, CS(DHE_DSS_WITH_AES_128_CBC_SHA256), S_DSA, K_DHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_DSA },
     { 0, CS(RSA_WITH_SEED_CBC_SHA), S_RSA, K_RSA, C_SEED, B_128, M_SHA, F_FIPS_STD, A_RSAD },
     { 0, CS(RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_RSAD },
     { 0, CS(RSA_WITH_RC4_128_SHA), S_RSA, K_RSA, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_RSAD },
     { 0, CS(RSA_WITH_RC4_128_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, F_NFIPS_STD, A_RSAD },
     { 0, CS(RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_RSA, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAD },
     { 0, CS(RSA_WITH_AES_128_CBC_SHA), S_RSA, K_RSA, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAD },
 
     { 0, CS(DHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_DHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAS },
     { 0, CS(DHE_DSS_WITH_3DES_EDE_CBC_SHA), S_DSA, K_DHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_DSA },
-    { 0, CS_(SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES, B_3DES, M_SHA, F_FIPS_NSTD, A_RSAD },
     { 0, CS(RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAD },
 
     { 0, CS(DHE_RSA_WITH_DES_CBC_SHA), S_RSA, K_DHE, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_RSAS },
     { 0, CS(DHE_DSS_WITH_DES_CBC_SHA), S_DSA, K_DHE, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_DSA },
-    { 0, CS_(SSL_RSA_FIPS_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, F_NFIPS_NSTD, A_RSAD },
     { 0, CS(RSA_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_RSAD },
 
-    { 0, CS(RSA_EXPORT1024_WITH_RC4_56_SHA), S_RSA, K_RSA, C_RC4, B_56, M_SHA, F_EXPORT, A_EXP },
-    { 0, CS(RSA_EXPORT1024_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, F_EXPORT, A_EXP },
-    { 0, CS(RSA_EXPORT_WITH_RC4_40_MD5), S_RSA, K_RSA, C_RC4, B_40, M_MD5, F_EXPORT, A_EXP },
-    { 0, CS(RSA_EXPORT_WITH_RC2_CBC_40_MD5), S_RSA, K_RSA, C_RC2, B_40, M_MD5, F_EXPORT, A_EXP },
     { 0, CS(RSA_WITH_NULL_SHA256), S_RSA, K_RSA, C_NULL, B_0, M_SHA256, F_EXPORT, A_RSAD },
     { 0, CS(RSA_WITH_NULL_SHA), S_RSA, K_RSA, C_NULL, B_0, M_SHA, F_EXPORT, A_RSAD },
     { 0, CS(RSA_WITH_NULL_MD5), S_RSA, K_RSA, C_NULL, B_0, M_MD5, F_EXPORT, A_RSAD },
 
     /* ECC cipher suites */
     { 0, CS(ECDHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAS },
     { 0, CS(ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), S_ECDSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_ECDSA },
     { 0, CS(ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDH_E },
@@ -289,23 +295,16 @@ static const SSLCipherSuiteInfo suiteInf
     { 0, CS(ECDHE_RSA_WITH_AES_256_CBC_SHA384), S_RSA, K_ECDHE, C_AES, B_256, M_SHA384, F_FIPS_STD, A_RSAS },
     { 0, CS(ECDHE_ECDSA_WITH_AES_256_CBC_SHA384), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA384, F_FIPS_STD, A_ECDSA },
     { 0, CS(ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), S_ECDSA, K_ECDHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_ECDSA },
     { 0, CS(ECDHE_RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_ECDHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAS },
 
     { 0, CS(DHE_DSS_WITH_AES_256_GCM_SHA384), S_DSA, K_DHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_DSA },
     { 0, CS(DHE_RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_DHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAS },
     { 0, CS(RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_RSA, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAD },
-
-    { 0, CS(ECDHE_PSK_WITH_AES_128_GCM_SHA256), S_PSK, K_ECDHE_PSK, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_PSK },
-    { 0, CS(ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256), S_PSK, K_ECDHE_PSK, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_PSK },
-    { 0, CS(ECDHE_PSK_WITH_AES_256_GCM_SHA384), S_PSK, K_ECDHE_PSK, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_PSK },
-    { 0, CS(DHE_PSK_WITH_AES_128_GCM_SHA256), S_PSK, K_DHE_PSK, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_PSK },
-    { 0, CS(DHE_PSK_WITH_CHACHA20_POLY1305_SHA256), S_PSK, K_DHE_PSK, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_PSK },
-    { 0, CS(DHE_PSK_WITH_AES_256_GCM_SHA384), S_PSK, K_DHE_PSK, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_PSK },
 };
 
 #define NUM_SUITEINFOS ((sizeof suiteInfo) / (sizeof suiteInfo[0]))
 
 SECStatus
 SSL_GetCipherSuiteInfo(PRUint16 cipherSuite,
                        SSLCipherSuiteInfo *info, PRUintn len)
 {
@@ -322,71 +321,21 @@ SSL_GetCipherSuiteInfo(PRUint16 cipherSu
     len = PR_MIN(len, sizeof suiteInfo[0]);
     for (i = 0; i < NUM_SUITEINFOS; i++) {
         if (suiteInfo[i].cipherSuite == cipherSuite) {
             memcpy(info, &suiteInfo[i], len);
             info->length = len;
             return SECSuccess;
         }
     }
+
     PORT_SetError(SEC_ERROR_INVALID_ARGS);
     return SECFailure;
 }
 
-/* This function might be a candidate to be public.
- * Disables all export ciphers in the default set of enabled ciphers.
- */
-SECStatus
-SSL_DisableDefaultExportCipherSuites(void)
-{
-    const SSLCipherSuiteInfo *pInfo = suiteInfo;
-    unsigned int i;
-
-    for (i = 0; i < NUM_SUITEINFOS; ++i, ++pInfo) {
-        if (pInfo->isExportable) {
-            PORT_CheckSuccess(SSL_CipherPrefSetDefault(pInfo->cipherSuite, PR_FALSE));
-        }
-    }
-    return SECSuccess;
-}
-
-/* This function might be a candidate to be public,
- * except that it takes an sslSocket pointer as an argument.
- * A Public version would take a PRFileDesc pointer.
- * Disables all export ciphers in the default set of enabled ciphers.
- */
-SECStatus
-SSL_DisableExportCipherSuites(PRFileDesc *fd)
-{
-    const SSLCipherSuiteInfo *pInfo = suiteInfo;
-    unsigned int i;
-
-    for (i = 0; i < NUM_SUITEINFOS; ++i, ++pInfo) {
-        if (pInfo->isExportable) {
-            PORT_CheckSuccess(SSL_CipherPrefSet(fd, pInfo->cipherSuite, PR_FALSE));
-        }
-    }
-    return SECSuccess;
-}
-
-/* Tells us if the named suite is exportable
- * returns false for unknown suites.
- */
-PRBool
-SSL_IsExportCipherSuite(PRUint16 cipherSuite)
-{
-    unsigned int i;
-    for (i = 0; i < NUM_SUITEINFOS; i++) {
-        if (suiteInfo[i].cipherSuite == cipherSuite) {
-            return (PRBool)(suiteInfo[i].isExportable);
-        }
-    }
-    return PR_FALSE;
-}
-
 SECItem *
 SSL_GetNegotiatedHostInfo(PRFileDesc *fd)
 {
     SECItem *sniName = NULL;
     sslSocket *ss;
     char *name = NULL;
 
     ss = ssl_FindSocket(fd);
--- a/security/nss/lib/ssl/sslproto.h
+++ b/security/nss/lib/ssl/sslproto.h
@@ -46,84 +46,62 @@
 #define SSL_PE_BAD_CERTIFICATE                  0x0004
 #define SSL_PE_UNSUPPORTED_CERTIFICATE_TYPE     0x0006
 
 /* Deprecated SSL 3.0 & libssl names replaced by IANA-registered TLS names. */
 #ifndef SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES
 #define SSL_NULL_WITH_NULL_NULL                TLS_NULL_WITH_NULL_NULL
 #define SSL_RSA_WITH_NULL_MD5                  TLS_RSA_WITH_NULL_MD5
 #define SSL_RSA_WITH_NULL_SHA                  TLS_RSA_WITH_NULL_SHA
-#define SSL_RSA_EXPORT_WITH_RC4_40_MD5         TLS_RSA_EXPORT_WITH_RC4_40_MD5
 #define SSL_RSA_WITH_RC4_128_MD5               TLS_RSA_WITH_RC4_128_MD5
 #define SSL_RSA_WITH_RC4_128_SHA               TLS_RSA_WITH_RC4_128_SHA
-#define SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5     TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
 #define SSL_RSA_WITH_IDEA_CBC_SHA              TLS_RSA_WITH_IDEA_CBC_SHA
-#define SSL_RSA_EXPORT_WITH_DES40_CBC_SHA      TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
 #define SSL_RSA_WITH_DES_CBC_SHA               TLS_RSA_WITH_DES_CBC_SHA
 #define SSL_RSA_WITH_3DES_EDE_CBC_SHA          TLS_RSA_WITH_3DES_EDE_CBC_SHA
-#define SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA   TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
 #define SSL_DH_DSS_WITH_DES_CBC_SHA            TLS_DH_DSS_WITH_DES_CBC_SHA
 #define SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA       TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA
-#define SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA   TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
 #define SSL_DH_RSA_WITH_DES_CBC_SHA            TLS_DH_RSA_WITH_DES_CBC_SHA
 #define SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA       TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA
-#define SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA  TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
 #define SSL_DHE_DSS_WITH_DES_CBC_SHA           TLS_DHE_DSS_WITH_DES_CBC_SHA
 #define SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA      TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
-#define SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA  TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
 #define SSL_DHE_RSA_WITH_DES_CBC_SHA           TLS_DHE_RSA_WITH_DES_CBC_SHA
 #define SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA      TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
 #define SSL_DH_ANON_WITH_RC4_128_MD5           TLS_DH_anon_WITH_RC4_128_MD5
-#define SSL_DH_ANON_EXPORT_WITH_DES40_CBC_SHA  TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA
 #define SSL_DH_ANON_WITH_DES_CBC_SHA           TLS_DH_anon_WITH_DES_CBC_SHA
 #define SSL_DH_ANON_WITH_3DES_EDE_CBC_SHA      TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
-#define SSL_DH_ANON_EXPORT_WITH_RC4_40_MD5     TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
 #define TLS_DH_ANON_WITH_AES_128_CBC_SHA       TLS_DH_anon_WITH_AES_128_CBC_SHA
 #define TLS_DH_ANON_WITH_AES_256_CBC_SHA       TLS_DH_anon_WITH_AES_256_CBC_SHA
 #define TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA  TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA
 #define TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA  TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA
 #endif
 
 #define TLS_NULL_WITH_NULL_NULL                 0x0000
 
 #define TLS_RSA_WITH_NULL_MD5                   0x0001
 #define TLS_RSA_WITH_NULL_SHA                   0x0002
-#define TLS_RSA_EXPORT_WITH_RC4_40_MD5          0x0003
 #define TLS_RSA_WITH_RC4_128_MD5                0x0004
 #define TLS_RSA_WITH_RC4_128_SHA                0x0005
-#define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5      0x0006
 #define TLS_RSA_WITH_IDEA_CBC_SHA               0x0007
-#define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA       0x0008
 #define TLS_RSA_WITH_DES_CBC_SHA                0x0009
 #define TLS_RSA_WITH_3DES_EDE_CBC_SHA           0x000a
 
-#define TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA    0x000b
 #define TLS_DH_DSS_WITH_DES_CBC_SHA             0x000c
 #define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA        0x000d
-#define TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA    0x000e
 #define TLS_DH_RSA_WITH_DES_CBC_SHA             0x000f
 #define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA        0x0010
 
-#define TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA   0x0011
 #define TLS_DHE_DSS_WITH_DES_CBC_SHA            0x0012
 #define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA       0x0013
-#define TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA   0x0014
 #define TLS_DHE_RSA_WITH_DES_CBC_SHA            0x0015
 #define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA       0x0016
 
-#define TLS_DH_anon_EXPORT_WITH_RC4_40_MD5      0x0017
 #define TLS_DH_anon_WITH_RC4_128_MD5            0x0018
-#define TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA   0x0019
 #define TLS_DH_anon_WITH_DES_CBC_SHA            0x001a
 #define TLS_DH_anon_WITH_3DES_EDE_CBC_SHA       0x001b
 
-#define SSL_FORTEZZA_DMS_WITH_NULL_SHA          0x001c /* deprecated */
-#define SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA  0x001d /* deprecated */
-#define SSL_FORTEZZA_DMS_WITH_RC4_128_SHA       0x001e /* deprecated */
-
 #define TLS_RSA_WITH_AES_128_CBC_SHA            0x002F
 #define TLS_DH_DSS_WITH_AES_128_CBC_SHA         0x0030
 #define TLS_DH_RSA_WITH_AES_128_CBC_SHA         0x0031
 #define TLS_DHE_DSS_WITH_AES_128_CBC_SHA        0x0032
 #define TLS_DHE_RSA_WITH_AES_128_CBC_SHA        0x0033
 #define TLS_DH_anon_WITH_AES_128_CBC_SHA        0x0034
 
 #define TLS_RSA_WITH_AES_256_CBC_SHA            0x0035
@@ -139,21 +117,16 @@
 #define TLS_DHE_DSS_WITH_AES_128_CBC_SHA256     0x0040
 #define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA       0x0041
 #define TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA    0x0042
 #define TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA    0x0043
 #define TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA   0x0044
 #define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA   0x0045
 #define TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA   0x0046
 
-#define TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA     0x0062
-#define TLS_RSA_EXPORT1024_WITH_RC4_56_SHA      0x0064
-
-#define TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA 0x0063
-#define TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA  0x0065
 #define TLS_DHE_DSS_WITH_RC4_128_SHA            0x0066
 #define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256     0x0067
 #define TLS_DHE_DSS_WITH_AES_256_CBC_SHA256     0x006A
 #define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256     0x006B
 
 #define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA       0x0084
 #define TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA    0x0085
 #define TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA    0x0086
@@ -225,33 +198,21 @@
 #define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256   0xC02F
 #define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384   0xC030
 #define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256    0xC031
 
 /* draft-ietf-tls-chacha20-poly1305-04 */
 #define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256   0xCCA8
 #define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9
 #define TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256     0xCCAA
-#define TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256   0xCCAC
-#define TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256     0xCCAD
 
-/* PSK suites are for resumption only */
-/* Experimental PSK support for [draft-mattsson-tls-ecdhe-psk-aead] */
-#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 */
-
-/* Netscape "experimental" cipher suites. */
-#define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA   0xffe0
-#define SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA        0xffe1
-
-/* New non-experimental openly spec'ed versions of those cipher suites. */
-#define SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA      0xfeff
-#define SSL_RSA_FIPS_WITH_DES_CBC_SHA           0xfefe
+/* 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
 
 /* 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
 
@@ -283,12 +244,41 @@
 #define SSL_CK_DES_192_EDE3_CBC_WITH_MD5        0x07
 #define SSL_EN_RC4_128_WITH_MD5                 0xFF01
 #define SSL_EN_RC4_128_EXPORT40_WITH_MD5        0xFF02
 #define SSL_EN_RC2_128_CBC_WITH_MD5             0xFF03
 #define SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5    0xFF04
 #define SSL_EN_IDEA_128_CBC_WITH_MD5            0xFF05
 #define SSL_EN_DES_64_CBC_WITH_MD5              0xFF06
 #define SSL_EN_DES_192_EDE3_CBC_WITH_MD5        0xFF07
+#define TLS_RSA_EXPORT_WITH_RC4_40_MD5          0x0003
+#define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5      0x0006
+#define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA       0x0008
+#define TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA     0x0062
+#define TLS_RSA_EXPORT1024_WITH_RC4_56_SHA      0x0064
+#define TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA   0x0014
+#define TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA    0x000e
+#define TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA 0x0063
+#define TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA  0x0065
+#define TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA    0x000b
+#define TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA   0x0011
+#define TLS_DH_anon_EXPORT_WITH_RC4_40_MD5      0x0017
+#define TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA   0x0019
+#define SSL_FORTEZZA_DMS_WITH_NULL_SHA          0x001c
+#define SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA  0x001d
+#define SSL_FORTEZZA_DMS_WITH_RC4_128_SHA       0x001e
+#define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA   0xffe0
+#define SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA        0xffe1
+#define SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA      0xfeff
+#define SSL_RSA_FIPS_WITH_DES_CBC_SHA           0xfefe
+#define SSL_RSA_EXPORT_WITH_RC4_40_MD5         TLS_RSA_EXPORT_WITH_RC4_40_MD5
+#define SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5     TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
+#define SSL_RSA_EXPORT_WITH_DES40_CBC_SHA      TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
+#define SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA   TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
+#define SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA  TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
+#define SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA   TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
+#define SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA  TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
+#define SSL_DH_ANON_EXPORT_WITH_DES40_CBC_SHA  TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA
+#define SSL_DH_ANON_EXPORT_WITH_RC4_40_MD5     TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
 
 /* clang-format on */
 
 #endif /* __sslproto_h_ */
--- a/security/nss/lib/ssl/sslsecur.c
+++ b/security/nss/lib/ssl/sslsecur.c
@@ -10,21 +10,16 @@
 #include "ssl.h"
 #include "sslimpl.h"
 #include "sslproto.h"
 #include "secoid.h"   /* for SECOID_GetALgorithmTag */
 #include "pk11func.h" /* for PK11_GenerateRandom */
 #include "nss.h"      /* for NSS_RegisterShutdown */
 #include "prinit.h"   /* for PR_CallOnceWithArg */
 
-#define MAX_BLOCK_CYPHER_SIZE 32
-
-#define TEST_FOR_FAILURE /* reminder */
-#define SET_ERROR_CODE   /* reminder */
-
 /* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock.
  *
  * Currently, the list of functions called through ss->handshake is:
  *
  * In sslsocks.c:
  *  SocksGatherRecord
  *  SocksHandleReply
  *  SocksStartGather
@@ -1108,17 +1103,17 @@ SSL_InvalidateSession(PRFileDesc *fd)
 {
     sslSocket *ss = ssl_FindSocket(fd);
     SECStatus rv = SECFailure;
 
     if (ss) {
         ssl_Get1stHandshakeLock(ss);
         ssl_GetSSL3HandshakeLock(ss);
 
-        if (ss->sec.ci.sid && ss->sec.uncache) {
+        if (ss->sec.ci.sid) {
             ss->sec.uncache(ss->sec.ci.sid);
             rv = SECSuccess;
         }
 
         ssl_ReleaseSSL3HandshakeLock(ss);
         ssl_Release1stHandshakeLock(ss);
     }
     return rv;
--- a/security/nss/lib/ssl/sslsnce.c
+++ b/security/nss/lib/ssl/sslsnce.c
@@ -76,18 +76,16 @@
 #ifdef XP_WIN32
 #include <wtypes.h>
 #include "win32err.h"
 #endif
 
 #endif
 #include <sys/types.h>
 
-#define SET_ERROR_CODE /* reminder */
-
 #include "nspr.h"
 #include "sslmutex.h"
 
 /*
 ** Format of a cache entry in the shared memory.
 */
 struct sidCacheEntryStr {
     /* 16 */ PRIPv6Addr addr; /* client's IP address */
@@ -1119,16 +1117,17 @@ InitCache(cacheDesc *cache, int maxCache
         pLock->pid = 0;
     }
     cache->numSIDCacheLocksInitialized = locks_initialized;
 
     return SECSuccess;
 
 loser:
     CloseCache(cache);
+    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
     return SECFailure;
 }
 
 PRUint32
 SSL_GetMaxServerCacheLocks(void)
 {
     return ssl_max_sid_cache_locks + 2;
     /* The extra two are the cert cache lock and the key cache lock. */
@@ -1173,17 +1172,16 @@ ssl_ConfigServerSessionIDCacheInstanceWi
 
     myPid = SSL_GETPID();
     if (!directory) {
         directory = DEFAULT_CACHE_DIRECTORY;
     }
     rv = InitCache(cache, maxCacheEntries, maxCertCacheEntries,
                    maxSrvNameCacheEntries, ssl3_timeout, directory, shared);
     if (rv) {
-        SET_ERROR_CODE
         return SECFailure;
     }
 
     ssl_sid_lookup = ServerSessionIDLookup;
     ssl_sid_cache = ServerSessionIDCache;
     ssl_sid_uncache = ServerSessionIDUncache;
     return SECSuccess;
 }
@@ -1257,39 +1255,39 @@ ssl_ConfigMPServerSIDCacheWithOpt(PRUint
                                                            ssl3_timeout, directory, PR_TRUE,
                                                            maxCacheEntries, maxCacheEntries, maxSrvNameCacheEntries);
     if (result != SECSuccess)
         return result;
 
     prStatus = PR_ExportFileMapAsString(cache->cacheMemMap,
                                         sizeof fmString, fmString);
     if ((prStatus != PR_SUCCESS) || !(fmStrLen = strlen(fmString))) {
-        SET_ERROR_CODE
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
 
     inherit.cacheMemSize = cache->cacheMemSize;
     inherit.fmStrLen = fmStrLen;
 
     inhValue = BTOA_DataToAscii((unsigned char *)&inherit, sizeof inherit);
     if (!inhValue || !strlen(inhValue)) {
-        SET_ERROR_CODE
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
     envValue = PR_smprintf("%s,%s", inhValue, fmString);
     if (!envValue || !strlen(envValue)) {
-        SET_ERROR_CODE
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
     PORT_Free(inhValue);
 
     putEnvFailed = (SECStatus)NSS_PutEnv(envVarName, envValue);
     PR_smprintf_free(envValue);
     if (putEnvFailed) {
-        SET_ERROR_CODE
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         result = SECFailure;
     }
 
 #if defined(XP_UNIX) || defined(XP_BEOS)
     /* Launch thread to poll cache for expired locks on Unix */
     LaunchLockPoller(cache);
 #endif
     return result;
@@ -1368,35 +1366,33 @@ SSL_InheritMPServerSIDCacheInstance(cach
 
     ssl_sid_lookup = ServerSessionIDLookup;
     ssl_sid_cache = ServerSessionIDCache;
     ssl_sid_uncache = ServerSessionIDUncache;
 
     if (!envString) {
         envString = PR_GetEnvSecure(envVarName);
         if (!envString) {
-            SET_ERROR_CODE
+            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
             return SECFailure;
         }
     }
     myEnvString = PORT_Strdup(envString);
     if (!myEnvString)
         return SECFailure;
     fmString = strchr(myEnvString, ',');
     if (!fmString)
         goto loser;
     *fmString++ = 0;
 
     decoString = ATOB_AsciiToData(myEnvString, &decoLen);
     if (!decoString) {
-        SET_ERROR_CODE
         goto loser;
     }
     if (decoLen != sizeof inherit) {
-        SET_ERROR_CODE
         goto loser;
     }
 
     PORT_Memcpy(&inherit, decoString, sizeof inherit);
 
     if (strlen(fmString) != inherit.fmStrLen) {
         goto loser;
     }
@@ -1411,17 +1407,16 @@ SSL_InheritMPServerSIDCacheInstance(cach
     }
     cache->cacheMem = PR_MemMap(cache->cacheMemMap, 0, cache->cacheMemSize);
     if (!cache->cacheMem) {
         goto loser;
     }
     cache->sharedCache = (cacheDesc *)cache->cacheMem;
 
     if (cache->sharedCache->cacheMemSize != cache->cacheMemSize) {
-        SET_ERROR_CODE
         goto loser;
     }
 
     /* We're now going to overwrite the local cache instance with the
     ** shared copy of the cache struct, then update several values in
     ** the local cache using the values for cache->cacheMemMap and
     ** cache->cacheMem computed just above.  So, we copy cache into
     ** the automatic variable "my", to preserve the variables while
@@ -1502,16 +1497,17 @@ SSL_InheritMPServerSIDCacheInstance(cach
 
     return SECSuccess;
 
 loser:
     PORT_Free(myEnvString);
     if (decoString)
         PORT_Free(decoString);
     CloseCache(cache);
+    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
     return SECFailure;
 }
 
 SECStatus
 SSL_InheritMPServerSIDCache(const char *envString)
 {
     return SSL_InheritMPServerSIDCacheInstance(&globalCache, envString);
 }
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -16,18 +16,16 @@
 #include "nspr.h"
 #include "private/pprio.h"
 #ifndef NO_PKCS11_BYPASS
 #include "blapi.h"
 #endif
 #include "nss.h"
 #include "pk11pqg.h"
 
-#define SET_ERROR_CODE /* reminder */
-
 static const sslSocketOps ssl_default_ops = { /* No SSL. */
                                               ssl_DefConnect,
                                               NULL,
                                               ssl_DefBind,
                                               ssl_DefListen,
                                               ssl_DefShutdown,
                                               ssl_DefClose,
                                               ssl_DefRecv,
@@ -62,17 +60,16 @@ static sslOptions ssl_defaults = {
     PR_FALSE,              /* useSocks           */
     PR_FALSE,              /* requestCertificate */
     2,                     /* requireCertificate */
     PR_FALSE,              /* handshakeAsClient  */
     PR_FALSE,              /* handshakeAsServer  */
     PR_FALSE,              /* noCache            */
     PR_FALSE,              /* fdx                */
     PR_TRUE,               /* detectRollBack     */
-    PR_FALSE,              /* noStepDown         */
     PR_FALSE,              /* bypassPKCS11       */
     PR_FALSE,              /* noLocks            */
     PR_FALSE,              /* enableSessionTickets */
     PR_FALSE,              /* enableDeflate      */
     2,                     /* enableRenegotiation (default: requires extension) */
     PR_FALSE,              /* requireSafeNegotiation */
     PR_FALSE,              /* enableFalseStart   */
     PR_TRUE,               /* cbcRandomIV        */
@@ -131,63 +128,70 @@ char lockStatus[] = "Locks are ENABLED. 
 
 /* SRTP_NULL_HMAC_SHA1_80 and SRTP_NULL_HMAC_SHA1_32 are not implemented. */
 static const PRUint16 srtpCiphers[] = {
     SRTP_AES128_CM_HMAC_SHA1_80,
     SRTP_AES128_CM_HMAC_SHA1_32,
     0
 };
 
-/* This list is in rough order of speed.  Note that while some smaller groups
- * appear early in the list, smaller groups are generally ignored when iterating
+/* This list is in preference order.  Note that while some smaller groups appear
+ * early in the list, smaller groups are generally ignored when iterating
  * through this list. ffdhe_custom must not appear in this list. */
-#define ECGROUP(name, size, oid) \
-    ssl_grp_ec_##name, size, group_type_ec, SEC_OID_SECG_EC_##oid
-#define FFGROUP(size, oid) \
-    ssl_grp_ffdhe_##size, size, group_type_ff, SEC_OID_TLS_FFDHE_##oid
-
-/* update SSL_NAMED_GROUP_COUNT when changing the number of entries */
-const namedGroupDef ssl_named_groups[] = {
-    { 0, ECGROUP(secp192r1, 192, SECP192R1), PR_FALSE },
-    { 1, ECGROUP(secp160r2, 160, SECP160R2), PR_FALSE },
-    { 2, ECGROUP(secp160k1, 160, SECP160K1), PR_FALSE },
-    { 3, ECGROUP(secp160r1, 160, SECP160R1), PR_FALSE },
-    { 4, ECGROUP(sect163k1, 163, SECT163K1), PR_FALSE },
-    { 5, ECGROUP(sect163r1, 163, SECT163R1), PR_FALSE },
-    { 6, ECGROUP(sect163r2, 163, SECT163R2), PR_FALSE },
-    { 7, ECGROUP(secp192k1, 192, SECP192K1), PR_FALSE },
-    { 8, ECGROUP(sect193r1, 193, SECT193R1), PR_FALSE },
-    { 9, ECGROUP(sect193r2, 193, SECT193R2), PR_FALSE },
-    { 10, ECGROUP(secp224r1, 224, SECP224R1), PR_FALSE },
-    { 11, ECGROUP(secp224k1, 224, SECP224K1), PR_FALSE },
-    { 12, ECGROUP(sect233k1, 233, SECT233K1), PR_FALSE },
-    { 13, ECGROUP(sect233r1, 233, SECT233R1), PR_FALSE },
-    { 14, ECGROUP(sect239k1, 239, SECT239K1), PR_FALSE },
-    { 15, ECGROUP(secp256r1, 256, SECP256R1), PR_TRUE },
-    { 16, ECGROUP(secp256k1, 256, SECP256K1), PR_FALSE },
-    { 17, ECGROUP(sect283k1, 283, SECT283K1), PR_FALSE },
-    { 18, ECGROUP(sect283r1, 283, SECT283R1), PR_FALSE },
-    { 19, ECGROUP(secp384r1, 384, SECP384R1), PR_TRUE },
-    { 20, ECGROUP(sect409k1, 409, SECT409K1), PR_FALSE },
-    { 21, ECGROUP(sect409r1, 409, SECT409R1), PR_FALSE },
-    { 22, ECGROUP(secp521r1, 521, SECP521R1), PR_TRUE },
-    { 23, ECGROUP(sect571k1, 571, SECT571K1), PR_FALSE },
-    { 24, ECGROUP(sect571r1, 571, SECT571R1), PR_FALSE },
-    { 25, FFGROUP(2048, 2048), PR_FALSE },
-    { 26, FFGROUP(3072, 3072), PR_FALSE },
-    { 27, FFGROUP(4096, 4096), PR_FALSE },
-    { 28, FFGROUP(6144, 6144), PR_FALSE },
-    { 29, FFGROUP(8192, 8192), PR_FALSE }
+#define ECGROUP(name, size, oid, assumeSupported)  \
+    {                                              \
+        ssl_grp_ec_##name, size, ssl_kea_ecdh,     \
+            SEC_OID_SECG_EC_##oid, assumeSupported \
+    }
+#define FFGROUP(size)                           \
+    {                                           \
+        ssl_grp_ffdhe_##size, size, ssl_kea_dh, \
+            SEC_OID_TLS_FFDHE_##size, PR_TRUE   \
+    }
+
+const sslNamedGroupDef ssl_named_groups[] = {
+    /* Note that 256 for 25519 is a lie, but we only use it for checking bit
+     * security and expect 256 bits there (not 255). */
+    { ssl_grp_ec_curve25519, 256, ssl_kea_ecdh, SEC_OID_CURVE25519, PR_TRUE },
+    ECGROUP(secp256r1, 256, SECP256R1, PR_TRUE),
+    ECGROUP(secp384r1, 384, SECP384R1, PR_TRUE),
+    ECGROUP(secp521r1, 521, SECP521R1, PR_TRUE),
+    FFGROUP(2048),
+    FFGROUP(3072),
+    FFGROUP(4096),
+    FFGROUP(6144),
+    FFGROUP(8192),
+    ECGROUP(secp192r1, 192, SECP192R1, PR_FALSE),
+    ECGROUP(secp160r2, 160, SECP160R2, PR_FALSE),
+    ECGROUP(secp160k1, 160, SECP160K1, PR_FALSE),
+    ECGROUP(secp160r1, 160, SECP160R1, PR_FALSE),
+    ECGROUP(sect163k1, 163, SECT163K1, PR_FALSE),
+    ECGROUP(sect163r1, 163, SECT163R1, PR_FALSE),
+    ECGROUP(sect163r2, 163, SECT163R2, PR_FALSE),
+    ECGROUP(secp192k1, 192, SECP192K1, PR_FALSE),
+    ECGROUP(sect193r1, 193, SECT193R1, PR_FALSE),
+    ECGROUP(sect193r2, 193, SECT193R2, PR_FALSE),
+    ECGROUP(secp224r1, 224, SECP224R1, PR_FALSE),
+    ECGROUP(secp224k1, 224, SECP224K1, PR_FALSE),
+    ECGROUP(sect233k1, 233, SECT233K1, PR_FALSE),
+    ECGROUP(sect233r1, 233, SECT233R1, PR_FALSE),
+    ECGROUP(sect239k1, 239, SECT239K1, PR_FALSE),
+    ECGROUP(secp256k1, 256, SECP256K1, PR_FALSE),
+    ECGROUP(sect283k1, 283, SECT283K1, PR_FALSE),
+    ECGROUP(sect283r1, 283, SECT283R1, PR_FALSE),
+    ECGROUP(sect409k1, 409, SECT409K1, PR_FALSE),
+    ECGROUP(sect409r1, 409, SECT409R1, PR_FALSE),
+    ECGROUP(sect571k1, 571, SECT571K1, PR_FALSE),
+    ECGROUP(sect571r1, 571, SECT571R1, PR_FALSE),
 };
+PR_STATIC_ASSERT(SSL_NAMED_GROUP_COUNT == PR_ARRAY_SIZE(ssl_named_groups));
+
 #undef ECGROUP
 #undef FFGROUP
 
-/* Check that the supported groups bits will fit into ss->namedGroups. */
-PR_STATIC_ASSERT(PR_ARRAY_SIZE(ssl_named_groups) < (sizeof(PRUint32) * 8));
-
 /* forward declarations. */
 static sslSocket *ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant variant);
 static SECStatus ssl_MakeLocks(sslSocket *ss);
 static void ssl_SetDefaultsFromEnvironment(void);
 static PRStatus ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack,
                                 PRDescIdentity id);
 
 /************************************************************************/
@@ -300,17 +304,16 @@ ssl_DupSocket(sslSocket *os)
              cursor != &os->serverCerts;
              cursor = PR_NEXT_LINK(cursor)) {
             sslServerCert *sc = ssl_CopyServerCert((sslServerCert *)cursor);
             if (!sc)
                 goto loser;
             PR_APPEND_LINK(&sc->link, &ss->serverCerts);
         }
 
-        ss->stepDownKeyPair = !os->stepDownKeyPair ? NULL : ssl_GetKeyPairRef(os->stepDownKeyPair);
         PR_INIT_CLIST(&ss->ephemeralKeyPairs);
         for (cursor = PR_NEXT_LINK(&os->ephemeralKeyPairs);
              cursor != &os->ephemeralKeyPairs;
              cursor = PR_NEXT_LINK(cursor)) {
             sslEphemeralKeyPair *okp = (sslEphemeralKeyPair *)cursor;
             sslEphemeralKeyPair *skp = ssl_CopyEphemeralKeyPair(okp);
             if (!skp)
                 goto loser;
@@ -409,20 +412,16 @@ ssl_DestroySocketContents(sslSocket *ss)
         PORT_Free((void *)ss->url); /* CONST */
 
     /* Clean up server certificates and sundries. */
     while (!PR_CLIST_IS_EMPTY(&ss->serverCerts)) {
         cursor = PR_LIST_TAIL(&ss->serverCerts);
         PR_REMOVE_LINK(cursor);
         ssl_FreeServerCert((sslServerCert *)cursor);
     }
-    if (ss->stepDownKeyPair) {
-        ssl_FreeKeyPair(ss->stepDownKeyPair);
-        ss->stepDownKeyPair = NULL;
-    }
     ssl_FreeEphemeralKeyPairs(ss);
     SECITEM_FreeItem(&ss->opt.nextProtoNego, PR_FALSE);
     ssl3_FreeSniNameArray(&ss->xtnData);
 }
 
 /*
  * free an sslSocket struct, and all the stuff that hangs off of it
  */
@@ -717,19 +716,16 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 wh
             ss->opt.fdx = on;
             break;
 
         case SSL_ROLLBACK_DETECTION:
             ss->opt.detectRollBack = on;
             break;
 
         case SSL_NO_STEP_DOWN:
-            ss->opt.noStepDown = on;
-            if (on)
-                SSL_DisableExportCipherSuites(fd);
             break;
 
         case SSL_BYPASS_PKCS11:
             if (ss->handshakeBegun) {
                 PORT_SetError(PR_INVALID_STATE_ERROR);
                 rv = SECFailure;
             } else {
                 if (PR_FALSE != on) {
@@ -907,17 +903,17 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 wh
             break;
         case SSL_ENABLE_FDX:
             on = ss->opt.fdx;
             break;
         case SSL_ROLLBACK_DETECTION:
             on = ss->opt.detectRollBack;
             break;
         case SSL_NO_STEP_DOWN:
-            on = ss->opt.noStepDown;
+            on = PR_FALSE;
             break;
         case SSL_BYPASS_PKCS11:
             on = ss->opt.bypassPKCS11;
             break;
         case SSL_NO_LOCKS:
             on = ss->opt.noLocks;
             break;
         case SSL_ENABLE_SESSION_TICKETS:
@@ -1027,17 +1023,17 @@ SSL_OptionGetDefault(PRInt32 which, PRBo
             break;
         case SSL_ENABLE_FDX:
             on = ssl_defaults.fdx;
             break;
         case SSL_ROLLBACK_DETECTION:
             on = ssl_defaults.detectRollBack;
             break;
         case SSL_NO_STEP_DOWN:
-            on = ssl_defaults.noStepDown;
+            on = PR_FALSE;
             break;
         case SSL_BYPASS_PKCS11:
             on = ssl_defaults.bypassPKCS11;
             break;
         case SSL_NO_LOCKS:
             on = ssl_defaults.noLocks;
             break;
         case SSL_ENABLE_SESSION_TICKETS:
@@ -1181,19 +1177,16 @@ SSL_OptionSetDefault(PRInt32 which, PRBo
             ssl_defaults.fdx = on;
             break;
 
         case SSL_ROLLBACK_DETECTION:
             ssl_defaults.detectRollBack = on;
             break;
 
         case SSL_NO_STEP_DOWN:
-            ssl_defaults.noStepDown = on;
-            if (on)
-                SSL_DisableDefaultExportCipherSuites();
             break;
 
         case SSL_BYPASS_PKCS11:
             if (PR_FALSE != on) {
                 if (PR_SUCCESS == SSL_BypassSetup()) {
 #ifdef NO_PKCS11_BYPASS
                     ssl_defaults.bypassPKCS11 = PR_FALSE;
 #else
@@ -1303,23 +1296,16 @@ ssl_IsRemovedCipherSuite(PRInt32 suite)
 
 /* Part of the public NSS API.
  * Since this is a global (not per-socket) setting, we cannot use the
  * HandshakeLock to protect this.  Probably want a global lock.
  */
 SECStatus
 SSL_SetPolicy(long which, int policy)
 {
-    if ((which & 0xfffe) == SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA) {
-        /* one of the two old FIPS ciphers */
-        if (which == SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA)
-            which = SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA;
-        else if (which == SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA)
-            which = SSL_RSA_FIPS_WITH_DES_CBC_SHA;
-    }
     if (ssl_IsRemovedCipherSuite(which))
         return SECSuccess;
     return SSL_CipherPolicySet(which, policy);
 }
 
 SECStatus
 ssl_CipherPolicySet(PRInt32 which, PRInt32 policy)
 {
@@ -1364,37 +1350,26 @@ SSL_CipherPolicyGet(PRInt32 which, PRInt
 /* Part of the public NSS API.
  * Since this is a global (not per-socket) setting, we cannot use the
  * HandshakeLock to protect this.  Probably want a global lock.
  * These changes have no effect on any sslSockets already created.
  */
 SECStatus
 SSL_EnableCipher(long which, PRBool enabled)
 {
-    if ((which & 0xfffe) == SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA) {
-        /* one of the two old FIPS ciphers */
-        if (which == SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA)
-            which = SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA;
-        else if (which == SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA)
-            which = SSL_RSA_FIPS_WITH_DES_CBC_SHA;
-    }
     if (ssl_IsRemovedCipherSuite(which))
         return SECSuccess;
     return SSL_CipherPrefSetDefault(which, enabled);
 }
 
 SECStatus
 ssl_CipherPrefSetDefault(PRInt32 which, PRBool enabled)
 {
     if (ssl_IsRemovedCipherSuite(which))
         return SECSuccess;
-    if (enabled && ssl_defaults.noStepDown && SSL_IsExportCipherSuite(which)) {
-        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
-        return SECFailure;
-    }
     return ssl3_CipherPrefSetDefault((ssl3CipherSuite)which, enabled);
 }
 
 SECStatus
 SSL_CipherPrefSetDefault(PRInt32 which, PRBool enabled)
 {
     SECStatus rv = ssl_Init();
 
@@ -1428,20 +1403,16 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt3
     sslSocket *ss = ssl_FindSocket(fd);
 
     if (!ss) {
         SSL_DBG(("%d: SSL[%d]: bad socket in CipherPrefSet", SSL_GETPID(), fd));
         return SECFailure;
     }
     if (ssl_IsRemovedCipherSuite(which))
         return SECSuccess;
-    if (enabled && ss->opt.noStepDown && SSL_IsExportCipherSuite(which)) {
-        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
-        return SECFailure;
-    }
     return ssl3_CipherPrefSet(ss, (ssl3CipherSuite)which, enabled);
 }
 
 SECStatus
 SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled)
 {
     SECStatus rv;
     sslSocket *ss = ssl_FindSocket(fd);
@@ -1497,62 +1468,55 @@ NSS_SetFrancePolicy(void)
 {
     return NSS_SetDomesticPolicy();
 }
 
 SECStatus
 SSL_NamedGroupConfig(PRFileDesc *fd, const SSLNamedGroup *groups,
                      unsigned int numGroups)
 {
-    unsigned int i, j;
+    unsigned int i;
+    unsigned int j = 0;
     sslSocket *ss = ssl_FindSocket(fd);
+
     if (!ss) {
         PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
         return SECFailure;
     }
 
     if (!groups) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
     if (numGroups > SSL_NAMED_GROUP_COUNT) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
-    for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
-        ss->namedGroupPreferences[i] = NULL;
-    }
-
+    memset((void *)ss->namedGroupPreferences, 0,
+           sizeof(ss->namedGroupPreferences));
     for (i = 0; i < numGroups; ++i) {
-        for (j = 0; j < SSL_NAMED_GROUP_COUNT; ++j) {
-            /* skip duplicate groups */
-            if (ss->namedGroupPreferences[j] &&
-                ss->namedGroupPreferences[j]->name == groups[i]) {
-                break;
-            }
-            if (ssl_named_groups[j].name == groups[i]) {
-                ss->namedGroupPreferences[i] = &ssl_named_groups[j];
-                break;
-            }
+        const sslNamedGroupDef *groupDef = ssl_LookupNamedGroup(groups[i]);
+        if (!ssl_NamedGroupEnabled(ss, groupDef)) {
+            ss->namedGroupPreferences[j++] = groupDef;
         }
     }
 
     return SECSuccess;
 }
 
 SECStatus
 SSL_DHEGroupPrefSet(PRFileDesc *fd, const SSLDHEGroupType *groups,
                     PRUint16 num_groups)
 {
     sslSocket *ss;
     const SSLDHEGroupType *list;
     unsigned int count;
     int i, k;
-    const namedGroupDef *enabled[SSL_NAMED_GROUP_COUNT] = { 0 };
+    const sslNamedGroupDef *enabled[SSL_NAMED_GROUP_COUNT] = { 0 };
     static const SSLDHEGroupType default_dhe_groups[] = {
         ssl_ff_dhe_2048_group
     };
 
     if ((num_groups && !groups) || (!num_groups && groups) ||
         num_groups > SSL_NAMED_GROUP_COUNT) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
@@ -1571,27 +1535,27 @@ SSL_DHEGroupPrefSet(PRFileDesc *fd, cons
         list = default_dhe_groups;
         count = PR_ARRAY_SIZE(default_dhe_groups);
     }
 
     /* save enabled ec groups and clear ss->namedGroupPreferences */
     k = 0;
     for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
         if (ss->namedGroupPreferences[i] &&
-            ss->namedGroupPreferences[i]->type != group_type_ff) {
+            ss->namedGroupPreferences[i]->keaType != ssl_kea_dh) {
             enabled[k++] = ss->namedGroupPreferences[i];
         }
         ss->namedGroupPreferences[i] = NULL;
     }
 
     ss->ssl3.dhePreferredGroup = NULL;
     for (i = 0; i < count; ++i) {
         PRBool duplicate = PR_FALSE;
         SSLNamedGroup name;
-        const namedGroupDef *groupDef;
+        const sslNamedGroupDef *groupDef;
         switch (list[i]) {
             case ssl_ff_dhe_2048_group:
                 name = ssl_grp_ffdhe_2048;
                 break;
             case ssl_ff_dhe_3072_group:
                 name = ssl_grp_ffdhe_3072;
                 break;
             case ssl_ff_dhe_4096_group:
@@ -1736,17 +1700,17 @@ SSL_EnableWeakDHEPrimeGroup(PRFileDesc *
 
     ss->ssl3.dheWeakGroupEnabled = enabled;
     return SECSuccess;
 }
 
 #include "dhe-param.c"
 
 const ssl3DHParams *
-ssl_GetDHEParams(const namedGroupDef *groupDef)
+ssl_GetDHEParams(const sslNamedGroupDef *groupDef)
 {
     switch (groupDef->name) {
         case ssl_grp_ffdhe_2048:
             return &ff_dhe_2048_params;
         case ssl_grp_ffdhe_3072:
             return &ff_dhe_3072_params;
         case ssl_grp_ffdhe_4096:
             return &ff_dhe_4096_params;
@@ -1813,30 +1777,27 @@ ssl_IsValidDHEShare(const SECItem *dh_p,
  * defined in Appendix A of draft-ietf-tls-negotiated-ff-dhe.
  *
  * |groupDef| and |dhParams| are optional outparams that identify the group and
  * its parameters respectively (if this is successful). */
 SECStatus
 ssl_ValidateDHENamedGroup(sslSocket *ss,
                           const SECItem *dh_p,
                           const SECItem *dh_g,
-                          const namedGroupDef **groupDef,
+                          const sslNamedGroupDef **groupDef,
                           const ssl3DHParams **dhParams)
 {
     unsigned int i;
 
     for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
         const ssl3DHParams *params;
         if (!ss->namedGroupPreferences[i]) {
             continue;
         }
-        if (ss->namedGroupPreferences[i]->type != group_type_ff) {
-            continue;
-        }
-        if (!ssl_NamedGroupEnabled(ss, ss->namedGroupPreferences[i])) {
+        if (ss->namedGroupPreferences[i]->keaType != ssl_kea_dh) {
             continue;
         }
 
         params = ssl_GetDHEParams(ss->namedGroupPreferences[i]);
         PORT_Assert(params);
         if (SECITEM_ItemsAreEqual(&params->prime, dh_p)) {
             if (!SECITEM_ItemsAreEqual(&params->base, dh_g)) {
                 return SECFailure;
@@ -1850,22 +1811,22 @@ ssl_ValidateDHENamedGroup(sslSocket *ss,
     }
 
     return SECFailure;
 }
 
 /* Ensure DH parameters have been selected.  This just picks the first enabled
  * FFDHE group in ssl_named_groups, or the weak one if it was enabled. */
 SECStatus
-ssl_SelectDHEGroup(sslSocket *ss, const namedGroupDef **groupDef)
+ssl_SelectDHEGroup(sslSocket *ss, const sslNamedGroupDef **groupDef)
 {
     unsigned int i;
-    static const namedGroupDef weak_group_def = {
-        0, ssl_grp_ffdhe_custom, WEAK_DHE_SIZE, group_type_ff,
-        SEC_OID_TLS_DHE_CUSTOM, PR_FALSE
+    static const sslNamedGroupDef weak_group_def = {
+        ssl_grp_ffdhe_custom, WEAK_DHE_SIZE, ssl_kea_dh,
+        SEC_OID_TLS_DHE_CUSTOM, PR_TRUE
     };
 
     /* Only select weak groups in TLS 1.2 and earlier, but not if the client has
      * indicated that it supports an FFDHE named group. */
     if (ss->ssl3.dheWeakGroupEnabled &&
         ss->version < SSL_LIBRARY_VERSION_TLS_1_3 &&
         !ss->ssl3.hs.peerSupportsFfdheGroups) {
         *groupDef = &weak_group_def;
@@ -1873,18 +1834,17 @@ ssl_SelectDHEGroup(sslSocket *ss, const 
     }
     if (ss->ssl3.dhePreferredGroup &&
         ssl_NamedGroupEnabled(ss, ss->ssl3.dhePreferredGroup)) {
         *groupDef = ss->ssl3.dhePreferredGroup;
         return SECSuccess;
     }
     for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
         if (ss->namedGroupPreferences[i] &&
-            ss->namedGroupPreferences[i]->type == group_type_ff &&
-            ssl_NamedGroupEnabled(ss, ss->namedGroupPreferences[i])) {
+            ss->namedGroupPreferences[i]->keaType == ssl_kea_dh) {
             *groupDef = ss->namedGroupPreferences[i];
             return SECSuccess;
         }
     }
 
     *groupDef = NULL;
     PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
     return SECFailure;
@@ -1916,17 +1876,17 @@ ssl_ImportFD(PRFileDesc *model, PRFileDe
         ns = ssl_DupSocket(ss);
     }
     if (ns == NULL)
         return NULL;
 
     rv = ssl_PushIOLayer(ns, fd, PR_TOP_IO_LAYER);
     if (rv != PR_SUCCESS) {
         ssl_FreeSocket(ns);
-        SET_ERROR_CODE
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return NULL;
     }
 #if defined(DEBUG) || defined(FORCE_PR_ASSERT)
     {
         sslSocket *ss = ssl_FindSocket(fd);
         PORT_Assert(ss == ns);
     }
 #endif
@@ -2205,22 +2165,16 @@ SSL_ReconfigFD(PRFileDesc *model, PRFile
          cursor != &sm->serverCerts;
          cursor = PR_NEXT_LINK(cursor)) {
         sslServerCert *sc = ssl_CopyServerCert((sslServerCert *)cursor);
         if (!sc)
             return NULL;
         PR_APPEND_LINK(&sc->link, &ss->serverCerts);
     }
 
-    if (sm->stepDownKeyPair) {
-        if (ss->stepDownKeyPair) {
-            ssl_FreeKeyPair(ss->stepDownKeyPair);
-        }
-        ss->stepDownKeyPair = ssl_GetKeyPairRef(sm->stepDownKeyPair);
-    }
     ssl_FreeEphemeralKeyPairs(ss);
     for (cursor = PR_NEXT_LINK(&sm->ephemeralKeyPairs);
          cursor != &sm->ephemeralKeyPairs;
          cursor = PR_NEXT_LINK(cursor)) {
         sslEphemeralKeyPair *mkp = (sslEphemeralKeyPair *)cursor;
         sslEphemeralKeyPair *skp = ssl_CopyEphemeralKeyPair(mkp);
         if (!skp)
             return NULL;
@@ -3591,42 +3545,45 @@ ssl_SetDefaultsFromEnvironment(void)
         if (ev && ev[0] == '0') {
             ssl_defaults.cbcRandomIV = PR_FALSE;
             SSL_TRACE(("SSL: cbcRandomIV set to 0"));
         }
     }
 #endif /* NSS_HAVE_GETENV */
 }
 
-const namedGroupDef *
+const sslNamedGroupDef *
 ssl_LookupNamedGroup(SSLNamedGroup group)
 {
     unsigned int i;
 
     for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
         if (ssl_named_groups[i].name == group) {
             return &ssl_named_groups[i];
         }
     }
     return NULL;
 }
 
 PRBool
-ssl_NamedGroupEnabled(const sslSocket *ss, const namedGroupDef *groupDef)
+ssl_NamedGroupEnabled(const sslSocket *ss, const sslNamedGroupDef *groupDef)
 {
-    PRUint32 policy;
+    unsigned int i;
     SECStatus rv;
-    unsigned int i;
-
-    PORT_Assert(groupDef);
+    PRUint32 policy;
+
+    if (!groupDef) {
+        return PR_FALSE;
+    }
 
     rv = NSS_GetAlgorithmPolicy(groupDef->oidTag, &policy);
     if (rv == SECSuccess && !(policy & NSS_USE_ALG_IN_SSL_KX)) {
         return PR_FALSE;
     }
+
     for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
         if (ss->namedGroupPreferences[i] &&
             ss->namedGroupPreferences[i] == groupDef) {
             return PR_TRUE;
         }
     }
     return PR_FALSE;
 }
@@ -3668,17 +3625,17 @@ ssl_FreeKeyPair(sslKeyPair *keyPair)
         SECKEY_DestroyPrivateKey(keyPair->privKey);
         SECKEY_DestroyPublicKey(keyPair->pubKey);
         PORT_Free(keyPair);
     }
 }
 
 /* Ephemeral key handling. */
 sslEphemeralKeyPair *
-ssl_NewEphemeralKeyPair(const namedGroupDef *group,
+ssl_NewEphemeralKeyPair(const sslNamedGroupDef *group,
                         SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey)
 {
     sslKeyPair *keys;
     sslEphemeralKeyPair *pair;
 
     if (!group) {
         PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
         return NULL;
@@ -3723,17 +3680,17 @@ void
 ssl_FreeEphemeralKeyPair(sslEphemeralKeyPair *keyPair)
 {
     ssl_FreeKeyPair(keyPair->keys);
     PR_REMOVE_LINK(&keyPair->link);
     PORT_Free(keyPair);
 }
 
 sslEphemeralKeyPair *
-ssl_LookupEphemeralKeyPair(sslSocket *ss, const namedGroupDef *groupDef)
+ssl_LookupEphemeralKeyPair(sslSocket *ss, const sslNamedGroupDef *groupDef)
 {
     PRCList *cursor;
     for (cursor = PR_NEXT_LINK(&ss->ephemeralKeyPairs);
          cursor != &ss->ephemeralKeyPairs;
          cursor = PR_NEXT_LINK(cursor)) {
         sslEphemeralKeyPair *keyPair = (sslEphemeralKeyPair *)cursor;
         if (keyPair->group == groupDef) {
             return keyPair;
@@ -3755,16 +3712,27 @@ ssl_FreeEphemeralKeyPairs(sslSocket *ss)
 ** Create a newsocket structure for a file descriptor.
 */
 static sslSocket *
 ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
 {
     SECStatus rv;
     sslSocket *ss;
     int i;
+    /* TODO: remove this when 25519 and p256 have equal priority */
+    const SSLNamedGroup preferredGroups[] = {
+        ssl_grp_ec_secp256r1,
+        ssl_grp_ec_secp384r1,
+        ssl_grp_ec_secp521r1,
+        ssl_grp_ffdhe_2048,
+        ssl_grp_ffdhe_3072,
+        ssl_grp_ffdhe_4096,
+        ssl_grp_ffdhe_6144,
+        ssl_grp_ffdhe_8192
+    };
 
     ssl_SetDefaultsFromEnvironment();
 
     if (ssl_force_locks)
         makeLocks = PR_TRUE;
 
     /* Make a new socket and get it ready */
     ss = (sslSocket *)PORT_ZAlloc(sizeof(sslSocket));
@@ -3782,35 +3750,36 @@ ssl_NewSocket(PRBool makeLocks, SSLProto
 
     ss->peerID = NULL;
     ss->rTimeout = PR_INTERVAL_NO_TIMEOUT;
     ss->wTimeout = PR_INTERVAL_NO_TIMEOUT;
     ss->cTimeout = PR_INTERVAL_NO_TIMEOUT;
     ss->url = NULL;
 
     PR_INIT_CLIST(&ss->serverCerts);
-    ss->stepDownKeyPair = NULL;
     PR_INIT_CLIST(&ss->ephemeralKeyPairs);
 
     ss->dbHandle = CERT_GetDefaultCertDB();
 
     /* Provide default implementation of hooks */
     ss->authCertificate = SSL_AuthCertificate;
     ss->authCertificateArg = (void *)ss->dbHandle;
     ss->sniSocketConfig = NULL;
     ss->sniSocketConfigArg = NULL;
     ss->getClientAuthData = NULL;
     ss->handleBadCert = NULL;
     ss->badCertArg = NULL;
     ss->pkcs11PinArg = NULL;
 
     ssl_ChooseOps(ss);
     ssl3_InitSocketPolicy(ss);
-    for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
-        ss->namedGroupPreferences[i] = &ssl_named_groups[i];
+    memset((void *)ss->namedGroupPreferences, 0, sizeof(ss->namedGroupPreferences));
+    PORT_Assert(PR_ARRAY_SIZE(preferredGroups) < SSL_NAMED_GROUP_COUNT);
+    for (i = 0; i < PR_ARRAY_SIZE(preferredGroups); ++i) {
+        ss->namedGroupPreferences[i] = ssl_LookupNamedGroup(preferredGroups[i]);
     }
     PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight);
     PR_INIT_CLIST(&ss->ssl3.hs.remoteKeyShares);
     PR_INIT_CLIST(&ss->ssl3.hs.cipherSpecs);
     PR_INIT_CLIST(&ss->ssl3.hs.bufferedEarlyData);
     if (makeLocks) {
         rv = ssl_MakeLocks(ss);
         if (rv != SECSuccess)
--- a/security/nss/lib/ssl/sslt.h
+++ b/security/nss/lib/ssl/sslt.h
@@ -40,16 +40,17 @@ typedef struct SSL3StatisticsStr {
 typedef enum {
     ssl_kea_null = 0,
     ssl_kea_rsa = 1,
     ssl_kea_dh = 2,
     ssl_kea_fortezza = 3, /* deprecated, now unused */
     ssl_kea_ecdh = 4,
     ssl_kea_ecdh_psk = 5,
     ssl_kea_dh_psk = 6,
+    ssl_kea_tls13_any = 7,
     ssl_kea_size /* number of ssl_kea_ algorithms */
 } SSLKEAType;
 
 /* The following defines are for backwards compatibility.
 ** They will be removed in a forthcoming release to reduce namespace pollution.
 ** programs that use the kt_ symbols should convert to the ssl_kt_ symbols
 ** soon.
 */
@@ -98,16 +99,17 @@ typedef enum {
     ssl_auth_dsa = 2,
     ssl_auth_kea = 3, /* unused */
     ssl_auth_ecdsa = 4,
     ssl_auth_ecdh_rsa = 5,   /* ECDH cert with an RSA signature */
     ssl_auth_ecdh_ecdsa = 6, /* ECDH cert with an ECDSA signature */
     ssl_auth_rsa_sign = 7,   /* RSA PKCS#1.5 signing */
     ssl_auth_rsa_pss = 8,
     ssl_auth_psk = 9,
+    ssl_auth_tls13_any = 10,
     ssl_auth_size /* number of authentication types */
 } SSLAuthType;
 
 /* This is defined for backward compatibility reasons */
 #define ssl_auth_rsa ssl_auth_rsa_decrypt
 
 typedef enum {
     ssl_calg_null = 0,
@@ -152,19 +154,20 @@ typedef struct SSLExtraServerCertDataStr
      * used to generate the OCSP stapling answer provided by the server. */
     const SECItemArray* stapledOCSPResponses;
     /* A serialized sign_certificate_timestamp extension, used to answer
      * requests from clients for this data. */
     const SECItem* signedCertTimestamps;
 } SSLExtraServerCertData;
 
 typedef struct SSLChannelInfoStr {
-    /* |length| is obsolete. On return, SSL_GetChannelInfo sets |length| to the
-     * smaller of the |len| argument and the length of the struct. The caller
-     * may ignore |length|. */
+    /* On return, SSL_GetChannelInfo sets |length| to the smaller of
+     * the |len| argument and the length of the struct used by NSS.
+     * Callers must ensure the application uses a version of NSS that
+     * isn't older than the version used at compile time. */
     PRUint32 length;
     PRUint16 protocolVersion;
     PRUint16 cipherSuite;
 
     /* server authentication info */
     PRUint32 authKeyBits;
 
     /* key exchange algorithm info */
@@ -189,41 +192,56 @@ typedef struct SSLChannelInfoStr {
      */
     PRBool extendedMasterSecretUsed;
 
     /* The following fields were added in NSS 3.25.
      * This field only has meaning in TLS >= 1.3, and indicates on the
      * client side that the server accepted early (0-RTT) data.
      */
     PRBool earlyDataAccepted;
+
+    /* The following fields were added in NSS 3.28. */
+    /* These fields have the same meaning as in SSLCipherSuiteInfo. */
+    SSLKEAType keaType;
+    SSLCipherAlgorithm symCipher;
+    SSLMACAlgorithm macAlgorithm;
+    SSLAuthType authType;
+
+    /* When adding new fields to this structure, please document the
+     * NSS version in which they were added. */
 } SSLChannelInfo;
 
 /* Preliminary channel info */
 #define ssl_preinfo_version (1U << 0)
 #define ssl_preinfo_cipher_suite (1U << 1)
 #define ssl_preinfo_all (ssl_preinfo_version | ssl_preinfo_cipher_suite)
 
 typedef struct SSLPreliminaryChannelInfoStr {
-    /* |length| is obsolete. On return, SSL_GetPreliminaryChannelInfo sets
-     * |length| to the smaller of the |len| argument and the length of the
-     * struct. The caller may ignore |length|. */
+    /* On return, SSL_GetPreliminaryChannelInfo sets |length| to the smaller of
+     * the |len| argument and the length of the struct used by NSS.
+     * Callers must ensure the application uses a version of NSS that
+     * isn't older than the version used at compile time. */
     PRUint32 length;
     /* A bitfield over SSLPreliminaryValueSet that describes which
      * preliminary values are set (see ssl_preinfo_*). */
     PRUint32 valuesSet;
     /* Protocol version: test (valuesSet & ssl_preinfo_version) */
     PRUint16 protocolVersion;
     /* Cipher suite: test (valuesSet & ssl_preinfo_cipher_suite) */
     PRUint16 cipherSuite;
+
+    /* When adding new fields to this structure, please document the
+     * NSS version in which they were added. */
 } SSLPreliminaryChannelInfo;
 
 typedef struct SSLCipherSuiteInfoStr {
-    /* |length| is obsolete. On return, SSL_GetCipherSuitelInfo sets |length|
-     * to the smaller of the |len| argument and the length of the struct. The
-     * caller may ignore |length|. */
+    /* On return, SSL_GetCipherSuitelInfo sets |length| to the smaller of
+     * the |len| argument and the length of the struct used by NSS.
+     * Callers must ensure the application uses a version of NSS that
+     * isn't older than the version used at compile time. */
     PRUint16 length;
     PRUint16 cipherSuite;
 
     /* Cipher Suite Name */
     const char* cipherSuiteName;
 
     /* server authentication info */
     const char* authAlgorithmName;
@@ -244,24 +262,27 @@ typedef struct SSLCipherSuiteInfoStr {
     /* AEAD ciphers don't have a MAC. For an AEAD cipher, macAlgorithmName
      * is "AEAD", macAlgorithm is ssl_mac_aead, and macBits is the length in
      * bits of the authentication tag. */
     const char* macAlgorithmName;
     SSLMACAlgorithm macAlgorithm;
     PRUint16 macBits;
 
     PRUintn isFIPS : 1;
-    PRUintn isExportable : 1;
+    PRUintn isExportable : 1; /* deprecated, don't use */
     PRUintn nonStandard : 1;
     PRUintn reservedBits : 29;
 
+    /* The following fields were added in NSS 3.24. */
     /* This reports the correct authentication type for the cipher suite, use
      * this instead of |authAlgorithm|. */
     SSLAuthType authType;
 
+    /* When adding new fields to this structure, please document the
+     * NSS version in which they were added. */
 } SSLCipherSuiteInfo;
 
 typedef enum {
     ssl_variant_stream = 0,
     ssl_variant_datagram = 1
 } SSLProtocolVariant;
 
 typedef struct SSLVersionRangeStr {
@@ -292,20 +313,25 @@ typedef enum {
     ssl_tls13_key_share_xtn = 40,
     ssl_tls13_pre_shared_key_xtn = 41,
     ssl_tls13_early_data_xtn = 42,
     ssl_next_proto_nego_xtn = 13172,
     ssl_renegotiation_info_xtn = 0xff01,
     ssl_tls13_draft_version_xtn = 0xff02 /* experimental number */
 } SSLExtensionType;
 
+typedef enum {
+    ssl_tls13_ticket_early_data_info_xtn = 1
+} TLS13TicketExtensionType;
+
 /* This is the old name for the supported_groups extensions. */
 #define ssl_elliptic_curves_xtn ssl_supported_groups_xtn
 
-#define SSL_MAX_EXTENSIONS 16 /* doesn't include ssl_padding_xtn. */
+#define SSL_MAX_EXTENSIONS 16 /* doesn't include ssl_padding_xtn or \
+                               * TLS 1.3 NewSessionTicket extensions. */
 
 /* 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,
@@ -334,17 +360,18 @@ typedef enum {
     ssl_grp_ec_secp192k1 = 18,
     ssl_grp_ec_secp192r1 = 19,
     ssl_grp_ec_secp224k1 = 20,
     ssl_grp_ec_secp224r1 = 21,
     ssl_grp_ec_secp256k1 = 22,
     ssl_grp_ec_secp256r1 = 23,
     ssl_grp_ec_secp384r1 = 24,
     ssl_grp_ec_secp521r1 = 25,
-    ssl_grp_ffdhe_2048 = 256, /* RFC7919 */
+    ssl_grp_ec_curve25519 = 29, /* RFC4492 */
+    ssl_grp_ffdhe_2048 = 256,   /* RFC7919 */
     ssl_grp_ffdhe_3072 = 257,
     ssl_grp_ffdhe_4096 = 258,
     ssl_grp_ffdhe_6144 = 259,
     ssl_grp_ffdhe_8192 = 260,
     ssl_grp_ffdhe_custom = 65537 /* special value */
 } SSLNamedGroup;
 
 #endif /* __sslt_h_ */
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -42,17 +42,24 @@ static SECStatus tls13_AESGCM(
     const unsigned char *in, int inlen,
     const unsigned char *additionalData, int additionalDataLen);
 static SECStatus tls13_ChaCha20Poly1305(
     ssl3KeyMaterial *keys,
     PRBool doDecrypt,
     unsigned char *out, int *outlen, int maxout,
     const unsigned char *in, int inlen,
     const unsigned char *additionalData, int additionalDataLen);
+static SECStatus tls13_SendServerHelloSequence(sslSocket *ss);
 static SECStatus tls13_SendEncryptedExtensions(sslSocket *ss);
+static void tls13_SetKeyExchangeType(sslSocket *ss, const sslNamedGroupDef *group);
+static SECStatus tls13_HandleClientKeyShare(sslSocket *ss,
+                                            const sslNamedGroupDef *group,
+                                            PRBool *shouldRetry);
+
+static SECStatus tls13_HandleServerKeyShare(sslSocket *ss);
 static SECStatus tls13_HandleEncryptedExtensions(sslSocket *ss, SSL3Opaque *b,
                                                  PRUint32 length);
 static SECStatus tls13_HandleCertificate(
     sslSocket *ss, SSL3Opaque *b, PRUint32 length);
 static SECStatus tls13_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b,
                                                 PRUint32 length);
 static SECStatus
 tls13_SendCertificateVerify(sslSocket *ss, SECKEYPrivateKey *privKey);
@@ -306,98 +313,103 @@ tls13_GetHmacMechanism(sslSocket *ss)
             return CKM_SHA384_HMAC;
         default:
             PORT_Assert(0);
     }
     return CKM_SHA256_HMAC;
 }
 
 SECStatus
-tls13_CreateKeyShare(sslSocket *ss, const namedGroupDef *groupDef)
+tls13_CreateKeyShare(sslSocket *ss, const sslNamedGroupDef *groupDef)
 {
     SECStatus rv;
     sslEphemeralKeyPair *keyPair = NULL;
     const ssl3DHParams *params;
 
-    switch (groupDef->type) {
-        case group_type_ec:
+    switch (groupDef->keaType) {
+        case ssl_kea_ecdh:
             rv = ssl_CreateECDHEphemeralKeyPair(groupDef, &keyPair);
             if (rv != SECSuccess) {
                 return SECFailure;
             }
             break;
-        case group_type_ff:
+        case ssl_kea_dh:
             params = ssl_GetDHEParams(groupDef);
             PORT_Assert(params->name != ssl_grp_ffdhe_custom);
             rv = ssl_CreateDHEKeyPair(groupDef, params, &keyPair);
             if (rv != SECSuccess) {
                 return SECFailure;
             }
             break;
+        default:
+            PORT_Assert(0);
+            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+            return SECFailure;
     }
 
     PR_APPEND_LINK(&keyPair->link, &ss->ephemeralKeyPairs);
     return rv;
 }
 
 /*
  * Generate shares for ECDHE and FFDHE.  This picks the first enabled group of
  * the requisite type and creates a share for that.
  *
  * Called from ssl3_SendClientHello.
  */
 SECStatus
 tls13_SetupClientHello(sslSocket *ss)
 {
     unsigned int i;
-    PRBool ecNeeded = ssl_IsECCEnabled(ss);
-    /* Only generate an FFDHE share when EC suites are disabled. */
-    PRBool ffNeeded = !ecNeeded;
+    NewSessionTicket *session_ticket = NULL;
+    sslSessionID *sid = ss->sec.ci.sid;
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
     PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
 
+    /* Select the first enabled group.
+     * TODO(ekr@rtfm.com): be smarter about offering the group
+     * that the other side negotiated if we are resuming. */
     for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
         SECStatus rv;
-        const namedGroupDef *groupDef = ss->namedGroupPreferences[i];
+        const sslNamedGroupDef *groupDef = ss->namedGroupPreferences[i];
         if (!groupDef) {
             continue;
         }
 
-        if (!ssl_NamedGroupEnabled(ss, groupDef)) {
-            continue;
-        }
-        switch (groupDef->type) {
-            case group_type_ec:
-                if (!ecNeeded) {
-                    continue;
-                }
-                ecNeeded = PR_FALSE;
-                break;
-            case group_type_ff:
-                if (!ffNeeded) {
-                    continue;
-                }
-                ffNeeded = PR_FALSE;
-                break;
-        }
-
         rv = tls13_CreateKeyShare(ss, groupDef);
         if (rv != SECSuccess) {
             return SECFailure;
         }
-    }
-
-    PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
-    /* We don't permit all groups of a given type to be disabled, so this should
-     * never reach this point wanting for a share of either type. */
-    PORT_Assert(!ecNeeded);
-    PORT_Assert(!ffNeeded);
+        break;
+    }
+
+    if (PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs)) {
+        PORT_SetError(SSL_ERROR_NO_CIPHERS_SUPPORTED);
+        return SECFailure;
+    }
+
+    /* Below here checks if we can do stateless resumption. */
+    if (sid->cached == never_cached ||
+        sid->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+        return SECSuccess;
+    }
+
+    /* The caller must be holding sid->u.ssl3.lock for reading. */
+    session_ticket = &sid->u.ssl3.locked.sessionTicket;
+    PORT_Assert(session_ticket && session_ticket->ticket.data);
+
+    if (session_ticket->ticket_lifetime_hint == 0 ||
+        (session_ticket->ticket_lifetime_hint +
+             session_ticket->received_timestamp >
+         ssl_Time())) {
+        ss->statelessResume = PR_TRUE;
+    }
 
     return SECSuccess;
 }
 
 static SECStatus
 tls13_ImportDHEKeyShare(sslSocket *ss, SECKEYPublicKey *peerKey,
                         SSL3Opaque *b, PRUint32 length,
                         SECKEYPublicKey *pubKey)
@@ -444,25 +456,25 @@ tls13_HandleKeyShare(sslSocket *ss,
     peerKey = PORT_ArenaZNew(&arena.arena, SECKEYPublicKey);
     if (peerKey == NULL) {
         goto loser;
     }
     peerKey->arena = &arena.arena;
     peerKey->pkcs11Slot = NULL;
     peerKey->pkcs11ID = CK_INVALID_HANDLE;
 
-    switch (entry->group->type) {
-        case group_type_ec:
-            rv = tls13_ImportECDHKeyShare(ss, peerKey,
-                                          entry->key_exchange.data,
-                                          entry->key_exchange.len,
-                                          entry->group);
+    switch (entry->group->keaType) {
+        case ssl_kea_ecdh:
+            rv = ssl_ImportECDHKeyShare(ss, peerKey,
+                                        entry->key_exchange.data,
+                                        entry->key_exchange.len,
+                                        entry->group);
             mechanism = CKM_ECDH1_DERIVE;
             break;
-        case group_type_ff:
+        case ssl_kea_dh:
             rv = tls13_ImportDHEKeyShare(ss, peerKey,
                                          entry->key_exchange.data,
                                          entry->key_exchange.len,
                                          keyPair->pubKey);
             mechanism = CKM_DH_PKCS_DERIVE;
             break;
         default:
             PORT_Assert(0);
@@ -878,72 +890,36 @@ static void
 tls13_RestoreCipherInfo(sslSocket *ss, sslSessionID *sid)
 {
     /* Set these to match the cached value.
      * TODO(ekr@rtfm.com): Make a version with the "true" values.
      * Bug 1256137.
      */
     ss->sec.authType = sid->authType;
     ss->sec.authKeyBits = sid->authKeyBits;
-    ss->sec.keaType = sid->keaType;
-    ss->sec.keaKeyBits = sid->keaKeyBits;
-    ss->ssl3.hs.origCipherSuite = sid->u.ssl3.cipherSuite;
-}
-
-PRBool
-tls13_AllowPskCipher(const sslSocket *ss, const ssl3CipherSuiteDef *cipher_def)
-{
-    if (ss->sec.isServer) {
-        if (!ss->statelessResume)
-            return PR_FALSE;
-    } else {
-        sslSessionID *sid = ss->sec.ci.sid;
-        const ssl3CipherSuiteDef *cached_cipher_def;
-
-        /* Verify that this was cached. */
-        PORT_Assert(sid);
-        if (sid->cached == never_cached)
-            return PR_FALSE;
-
-        cached_cipher_def = ssl_LookupCipherSuiteDef(
-            sid->u.ssl3.cipherSuite);
-        PORT_Assert(cached_cipher_def);
-
-        /* Only offer a PSK cipher with the same symmetric parameters
-         * as we negotiated before. */
-        if (cached_cipher_def->bulk_cipher_alg !=
-            cipher_def->bulk_cipher_alg)
-            return PR_FALSE;
-
-        /* PSK cipher must have the same PSK hash as was negotiated before. */
-        if (cipher_def->prf_hash != cached_cipher_def->prf_hash) {
-            return PR_FALSE;
-        }
-    }
-    SSL_TRC(3, ("%d: TLS 1.3[%d]: Enabling cipher suite suite 0x%04x",
-                SSL_GETPID(), ss->fd,
-                cipher_def->cipher_suite));
-
-    return PR_TRUE;
 }
 
 /* Check whether resumption-PSK is allowed. */
 static PRBool
 tls13_CanResume(sslSocket *ss, const sslSessionID *sid)
 {
     const sslServerCert *sc;
 
     if (!sid) {
         return PR_FALSE;
     }
 
     if (sid->version != ss->version) {
         return PR_FALSE;
     }
 
+    if (sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite) {
+        return PR_FALSE;
+    }
+
     /* Server sids don't remember the server cert we previously sent, but they
      * do remember the type of certificate we originally used, so we can locate
      * it again, provided that the current ssl socket has had its server certs
      * configured the same as the previous one. */
     sc = ssl_FindServerCert(ss, &sid->certType);
     if (!sc || !sc->serverCert) {
         return PR_FALSE;
     }
@@ -1015,34 +991,162 @@ tls13_NegotiateZeroRtt(sslSocket *ss, co
     } else {
         SSL_TRC(3, ("%d: TLS13[%d]: ignore 0-RTT",
                     SSL_GETPID(), ss->fd));
         ss->ssl3.hs.zeroRttState = ssl_0rtt_ignored;
         ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_trial;
     }
 }
 
+static SECStatus
+tls13_NegotiateKeyExchange(sslSocket *ss, const sslNamedGroupDef **group)
+{
+    int index;
+
+    /* We insist on DHE. */
+    if (ss->statelessResume) {
+        if (!memchr(ss->xtnData.psk_ke_modes.data, tls13_psk_dh_ke,
+                    ss->xtnData.psk_ke_modes.len)) {
+            SSL_TRC(3, ("%d: TLS13[%d]: client offered PSK without DH",
+                        SSL_GETPID(), ss->fd));
+            ss->statelessResume = PR_FALSE;
+        }
+    }
+
+    /* Now figure out which key share we like the best out of the
+     * mutually supported groups, regardless of what the client offered
+     * for key shares.
+     */
+    if (!ssl3_ExtensionNegotiated(ss, ssl_supported_groups_xtn)) {
+        FATAL_ERROR(ss, SSL_ERROR_MISSING_SUPPORTED_GROUPS_EXTENSION,
+                    missing_extension);
+        return SECFailure;
+    }
+
+    SSL_TRC(3, ("%d: TLS13[%d]: selected KE = %s",
+                SSL_GETPID(), ss->fd, ss->statelessResume ? "PSK + (EC)DHE" : "(EC)DHE"));
+
+    for (index = 0; index < SSL_NAMED_GROUP_COUNT; ++index) {
+        /* Enabled here checks for being mutually supported. */
+        if (ssl_NamedGroupEnabled(ss, ss->namedGroupPreferences[index])) {
+            *group = ss->namedGroupPreferences[index];
+            SSL_TRC(3, ("%d: TLS13[%d]: group = %d", (*group)->name));
+
+            return SECSuccess;
+        }
+    }
+
+    FATAL_ERROR(ss, SSL_ERROR_NO_CYPHER_OVERLAP, handshake_failure);
+    return SECFailure;
+}
+
+SECStatus
+tls13_SelectServerCert(sslSocket *ss)
+{
+    PRCList *cursor;
+    SECStatus rv;
+
+    if (ss->ssl3.hs.numClientSigScheme == 0) {
+        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO,
+                    illegal_parameter);
+        return SECFailure;
+    }
+
+    /* This picks the first certificate that has:
+     * a) the right authentication method, and
+     * b) the right named curve (EC only)
+     *
+     * We might want to do some sort of ranking here later.  For now, it's all
+     * based on what order they are configured in. */
+    for (cursor = PR_NEXT_LINK(&ss->serverCerts);
+         cursor != &ss->serverCerts;
+         cursor = PR_NEXT_LINK(cursor)) {
+        sslServerCert *cert = (sslServerCert *)cursor;
+
+        if (cert->certType.authType == ssl_auth_rsa_pss ||
+            cert->certType.authType == ssl_auth_rsa_decrypt) {
+            continue;
+        }
+
+        rv = ssl_PickSignatureScheme(ss, cert->serverKeyPair->pubKey,
+                                     ss->ssl3.hs.clientSigSchemes,
+                                     ss->ssl3.hs.numClientSigScheme,
+                                     PR_FALSE);
+        if (rv == SECSuccess) {
+            /* Found one. */
+            ss->sec.serverCert = cert;
+            ss->sec.authType = cert->certType.authType;
+            ss->ssl3.hs.kea_def_mutable.authKeyType = cert->certType.authType;
+            ss->sec.authKeyBits = cert->serverKeyBits;
+            return SECSuccess;
+        }
+    }
+
+    FATAL_ERROR(ss, SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM,
+                handshake_failure);
+    return SECFailure;
+}
+
+static SECStatus
+tls13_NegotiateAuthentication(sslSocket *ss)
+{
+    SECStatus rv;
+
+    if (ss->statelessResume) {
+        /* We refuse to sign. */
+        if (memchr(ss->xtnData.psk_auth_modes.data, tls13_psk_auth,
+                   ss->xtnData.psk_auth_modes.len)) {
+            SSL_TRC(3, ("%d: TLS13[%d]: selected PSK authentication",
+                        SSL_GETPID(), ss->fd));
+
+            ss->ssl3.hs.signatureScheme = ssl_sig_none;
+            ss->ssl3.hs.kea_def_mutable.authKeyType = ssl_auth_psk;
+            return SECSuccess;
+        }
+
+        SSL_TRC(3, ("%d: TLS13[%d]: rejected PSK authentication",
+                    SSL_GETPID(), ss->fd));
+
+        ss->statelessResume = PR_FALSE;
+    }
+
+    SSL_TRC(3, ("%d: TLS13[%d]: selected certificate authentication",
+                SSL_GETPID(), ss->fd));
+    rv = ssl3_RegisterServerHelloExtensionSender(
+        ss, ssl_signature_algorithms_xtn,
+        tls13_ServerSendSigAlgsXtn);
+    if (rv != SECSuccess) {
+        return SECFailure; /* Error code set already. */
+    }
+
+    /* We've now established that we need to sign.... */
+    rv = tls13_SelectServerCert(ss);
+    if (rv != SECSuccess) {
+        return SECFailure;
+    }
+    ss->ssl3.hs.kea_def_mutable.authKeyType =
+        ss->sec.serverCert->certType.authType;
+    return SECSuccess;
+}
+
 /* Called from ssl3_HandleClientHello after we have parsed the
  * ClientHello and are sure that we are going to do TLS 1.3
  * or fail. */
 SECStatus
 tls13_HandleClientHelloPart2(sslSocket *ss,
                              const SECItem *suites,
                              sslSessionID *sid)
 {
     SECStatus rv;
     SSL3Statistics *ssl3stats = SSL_GetStatistics();
+    const sslNamedGroupDef *expectedGroup;
     int j;
     PRBool shouldRetry = PR_FALSE;
     ssl3CipherSuite previousCipherSuite;
 
-    if (!tls13_CanResume(ss, sid)) {
-        ss->statelessResume = PR_FALSE;
-    }
-
 #ifndef PARANOID
     /* Look for a matching cipher suite. */
     j = ssl3_config_match_init(ss);
     if (j <= 0) { /* no ciphers are working/supported by PK11 */
         FATAL_ERROR(ss, PORT_GetError(), internal_error);
         goto loser;
     }
 #endif
@@ -1056,23 +1160,64 @@ tls13_HandleClientHelloPart2(sslSocket *
     }
     /* If we are going around again, then we should make sure that the cipher
      * suite selection doesn't change. That's a sign of client shennanigans. */
     if (ss->ssl3.hs.helloRetry &&
         ss->ssl3.hs.cipher_suite != previousCipherSuite) {
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, handshake_failure);
         goto loser;
     }
-    if (ss->ssl3.hs.kea_def->authKeyType != ssl_auth_psk) {
-        ss->statelessResume = PR_FALSE;
+
+    /* Now create a synthetic kea_def that we can tweak. */
+    ss->ssl3.hs.kea_def_mutable = *ss->ssl3.hs.kea_def;
+    ss->ssl3.hs.kea_def = &ss->ssl3.hs.kea_def_mutable;
+
+    /* Note: We call this quite a bit earlier than with TLS 1.2 and
+     * before. */
+    rv = ssl3_ServerCallSNICallback(ss);
+    if (rv != SECSuccess) {
+        goto loser; /* An alert has already been sent. */
+    }
+
+    /* Check if we could in principle resume. */
+    if (ss->statelessResume) {
+        PORT_Assert(sid);
+        if (!sid) {
+            FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+            return SECFailure;
+        }
+        if (!tls13_CanResume(ss, sid)) {
+            ss->statelessResume = PR_FALSE;
+        }
+    }
+
+    /* Select key exchange. */
+    rv = tls13_NegotiateKeyExchange(ss, &expectedGroup);
+    if (rv != SECSuccess) {
+        return SECFailure;
+    }
+
+    /* Select the authentication (this is also handshake shape). */
+    rv = tls13_NegotiateAuthentication(ss);
+    if (rv != SECSuccess) {
+        return SECFailure;
     }
 
     if (ss->statelessResume) {
+        /* We are now committed to trying to resume. */
         PORT_Assert(sid);
 
+        /* Check that the negotiated SNI and the cached SNI match. */
+        if (SECITEM_CompareItem(&sid->u.ssl3.srvName,
+                                &ss->ssl3.hs.srvVirtName) != SECEqual) {
+            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO,
+                        handshake_failure);
+            goto loser;
+        }
+
         rv = tls13_RecoverWrappedSharedSecret(ss, sid);
         if (rv != SECSuccess) {
             FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
             goto loser;
         }
 
         tls13_RestoreCipherInfo(ss, sid);
 
@@ -1082,103 +1227,86 @@ tls13_HandleClientHelloPart2(sslSocket *
         if (sid->peerCert != NULL) {
             ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
         }
         ssl3_RegisterServerHelloExtensionSender(
             ss, ssl_tls13_pre_shared_key_xtn, tls13_ServerSendPreSharedKeyXtn);
 
         tls13_NegotiateZeroRtt(ss, sid);
     } else {
-        ss->ssl3.hs.origCipherSuite = ss->ssl3.hs.cipher_suite;
-
+        if (sid) { /* we had a sid, but it's no longer valid, free it */
+            SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok);
+            if (ss->sec.uncache)
+                ss->sec.uncache(sid);
+            ssl_FreeSID(sid);
+            sid = NULL;
+        }
         tls13_NegotiateZeroRtt(ss, NULL);
     }
 
-    rv = ssl3_ServerCallSNICallback(ss);
-    if (rv != SECSuccess) {
-        goto loser; /* An alert has already been sent. */
-    }
-
-    if (ss->statelessResume) {
-        /* Check that the negotiated SID and the cached SID match. */
-        if (SECITEM_CompareItem(&sid->u.ssl3.srvName,
-                                &ss->ssl3.hs.srvVirtName) != SECEqual) {
-            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO,
-                        handshake_failure);
-            goto loser;
-        }
-    } else {
-        if (ss->ssl3.hs.numClientSigScheme == 0) {
-            /* TODO test what happens when we strip signature_algorithms...
-                    this might not be needed */
-            PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
-            FATAL_ERROR(ss, PORT_GetError(), missing_extension);
-            return SECFailure;
-        }
-
-        rv = ssl3_SelectServerCert(ss);
-        if (rv != SECSuccess) {
-            FATAL_ERROR(ss, PORT_GetError(), handshake_failure);
-            goto loser;
-        }
-    }
-
     /* If this is TLS 1.3 we are expecting a ClientKeyShare
      * extension. Missing/absent extension cause failure
      * below. */
-    rv = tls13_HandleClientKeyShare(ss, &shouldRetry);
+    rv = tls13_HandleClientKeyShare(ss, expectedGroup,
+                                    &shouldRetry);
     if (rv != SECSuccess) {
         goto loser; /* An alert was sent already. */
     }
     if (shouldRetry) {
         /* Unfortunately, there's a bit of cleanup needed here to back out
          * changes from the stateless resumption setup. */
         if (ss->statelessResume) {
             PK11_FreeSymKey(ss->ssl3.hs.resumptionPsk);
             SECITEM_FreeItem(&ss->ssl3.hs.resumptionContext, PR_FALSE);
             CERT_DestroyCertificate(ss->sec.localCert);
             if (ss->sec.peerCert) {
                 CERT_DestroyCertificate(ss->sec.peerCert);
             }
         }
 
         if (sid) { /* Free the sid. */
-            if (ss->sec.uncache)
-                ss->sec.uncache(sid);
+            ss->sec.uncache(sid);
             ssl_FreeSID(sid);
         }
         PORT_Assert(ss->ssl3.hs.helloRetry);
         return SECSuccess;
     }
 
     /* From this point we are either committed to resumption, or not. */
     if (ss->statelessResume) {
         SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_hits);
         SSL_AtomicIncrementLong(&ssl3stats->hch_sid_stateless_resumes);
     } else {
         if (sid) {
             /* We had a sid, but it's no longer valid, free it. */
             SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok);
-            if (ss->sec.uncache)
-                ss->sec.uncache(sid);
+            ss->sec.uncache(sid);
             ssl_FreeSID(sid);
         } else {
             SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_misses);
         }
 
         sid = ssl3_NewSessionID(ss, PR_TRUE);
         if (!sid) {
             FATAL_ERROR(ss, PORT_GetError(), internal_error);
             return SECFailure;
         }
     }
     /* Take ownership of the session. */
     ss->sec.ci.sid = sid;
     sid = NULL;
 
+    tls13_SetKeyExchangeType(ss, expectedGroup);
+    rv = tls13_ComputeEarlySecrets(ss, ss->ssl3.hs.zeroRttState ==
+                                           ssl_0rtt_accepted);
+    if (rv != SECSuccess) {
+        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+        return SECFailure;
+    }
+
     if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) {
         /* Store the handshake hash. We'll want it later. */
         ss->ssl3.hs.clientHelloHash = PK11_CloneContext(ss->ssl3.hs.sha);
         if (!ss->ssl3.hs.clientHelloHash) {
             FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
             return SECFailure;
         }
 
@@ -1201,25 +1329,24 @@ tls13_HandleClientHelloPart2(sslSocket *
             return SECFailure;
         }
     }
 
     return SECSuccess;
 
 loser:
     if (sid) {
-        if (ss->sec.uncache)
-            ss->sec.uncache(sid);
+        ss->sec.uncache(sid);
         ssl_FreeSID(sid);
     }
     return SECFailure;
 }
 
 static SECStatus
-tls13_SendHelloRetryRequest(sslSocket *ss, const namedGroupDef *selectedGroup)
+tls13_SendHelloRetryRequest(sslSocket *ss, const sslNamedGroupDef *selectedGroup)
 {
     SECStatus rv;
 
     SSL_TRC(3, ("%d: TLS13[%d]: send hello retry request handshake",
                 SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
@@ -1290,69 +1417,32 @@ loser:
     ssl_ReleaseXmitBufLock(ss);
     return SECFailure;
 }
 
 /* Called from tls13_HandleClientHello.
  *
  * Caller must hold Handshake and RecvBuf locks.
  */
-SECStatus
-tls13_HandleClientKeyShare(sslSocket *ss, PRBool *shouldRetry)
+
+static SECStatus
+tls13_HandleClientKeyShare(sslSocket *ss, const sslNamedGroupDef *selectedGroup,
+                           PRBool *shouldRetry)
 {
-    const namedGroupDef *selectedGroup;
     SECStatus rv;
     TLS13KeyShareEntry *peerShare = NULL; /* theirs */
     sslEphemeralKeyPair *keyPair;         /* ours */
     PRCList *cur_p;
 
     SSL_TRC(3, ("%d: TLS13[%d]: handle client_key_share handshake",
                 SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
-    /* Verify that the other side sent supported groups as required
-     * by the specification. */
-    if (!ssl3_ExtensionNegotiated(ss, ssl_supported_groups_xtn)) {
-        FATAL_ERROR(ss, SSL_ERROR_MISSING_SUPPORTED_GROUPS_EXTENSION,
-                    missing_extension);
-        return SECFailure;
-    }
-
-    /* Figure out what group we expect */
-    switch (ss->ssl3.hs.kea_def->exchKeyType) {
-        case ssl_kea_ecdh:
-        case ssl_kea_ecdh_psk:
-            selectedGroup = ssl_GetECGroupForServerSocket(ss);
-            if (!selectedGroup) {
-                FATAL_ERROR(ss, SSL_ERROR_NO_CYPHER_OVERLAP,
-                            handshake_failure);
-                return SECFailure;
-            }
-            break;
-
-        case ssl_kea_dh:
-        case ssl_kea_dh_psk:
-            rv = ssl_SelectDHEGroup(ss, &selectedGroup);
-            if (rv != SECSuccess) {
-                FATAL_ERROR(ss, SSL_ERROR_NO_CYPHER_OVERLAP,
-                            handshake_failure);
-                return SECFailure;
-            }
-            PORT_Assert(selectedGroup);
-            break;
-
-        default:
-            /* Got an unknown or unsupported Key Exchange Algorithm.
-             * Can't happen. */
-            FATAL_ERROR(ss, SEC_ERROR_UNSUPPORTED_KEYALG,
-                        internal_error);
-            return SECFailure;
-    }
+    PORT_Assert(selectedGroup);
 
     /* Now walk through the keys until we find one for our group */
     cur_p = PR_NEXT_LINK(&ss->ssl3.hs.remoteKeyShares);
     while (cur_p != &ss->ssl3.hs.remoteKeyShares) {
         TLS13KeyShareEntry *offer = (TLS13KeyShareEntry *)cur_p;
 
         if (offer->group == selectedGroup) {
             peerShare = offer;
@@ -1361,51 +1451,41 @@ tls13_HandleClientKeyShare(sslSocket *ss
         cur_p = PR_NEXT_LINK(cur_p);
     }
 
     if (!peerShare) {
         *shouldRetry = PR_TRUE;
         return tls13_SendHelloRetryRequest(ss, selectedGroup);
     }
 
-    PORT_Assert(ss->ssl3.hs.zeroRttState != ssl_0rtt_sent);
-    rv = tls13_ComputeEarlySecrets(ss, ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        return SECFailure;
-    }
-
     /* Generate our key */
     rv = tls13_CreateKeyShare(ss, selectedGroup);
     if (rv != SECSuccess)
         return rv;
 
     /* We should have exactly one key share. */
     PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
     PORT_Assert(PR_PREV_LINK(&ss->ephemeralKeyPairs) ==
                 PR_NEXT_LINK(&ss->ephemeralKeyPairs));
 
     keyPair = ((sslEphemeralKeyPair *)PR_NEXT_LINK(&ss->ephemeralKeyPairs));
 
-    ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
     ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(keyPair->keys->pubKey);
 
     /* Register the sender */
     rv = ssl3_RegisterServerHelloExtensionSender(ss, ssl_tls13_key_share_xtn,
                                                  tls13_ServerSendKeyShareXtn);
     if (rv != SECSuccess) {
         return SECFailure; /* Error code set already. */
     }
 
     rv = tls13_HandleKeyShare(ss, peerShare, keyPair->keys);
     return rv; /* Error code set already. */
 }
 
-static const unsigned char tls13_certreq_context[] = { 0 };
-
 /*
  *     [draft-ietf-tls-tls13-11] Section 6.3.3.2
  *
  *     opaque DistinguishedName<1..2^16-1>;
  *
  *     struct {
  *         opaque certificate_extension_oid<1..2^8-1>;
  *         opaque certificate_extension_values<0..2^16-1>;
@@ -1437,25 +1517,24 @@ tls13_SendCertificateRequest(sslSocket *
 
     rv = ssl3_EncodeSigAlgs(ss, sigSchemes, sizeof(sigSchemes),
                             &sigSchemesLength);
     if (rv != SECSuccess) {
         return rv;
     }
 
     ssl3_GetCertificateRequestCAs(ss, &calen, &names, &nnames);
-    length = 1 + sizeof(tls13_certreq_context) +
+    length = 1 + 0 /* length byte for empty request context */ +
              2 + sigSchemesLength + 2 + calen + 2;
 
     rv = ssl3_AppendHandshakeHeader(ss, certificate_request, length);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
-    rv = ssl3_AppendHandshakeVariable(ss, tls13_certreq_context,
-                                      sizeof(tls13_certreq_context), 1);
+    rv = ssl3_AppendHandshakeNumber(ss, 0, 1);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
     rv = ssl3_AppendHandshakeVariable(ss, sigSchemes, sigSchemesLength, 2);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
     rv = ssl3_AppendHandshakeNumber(ss, calen, 2);
@@ -1476,17 +1555,17 @@ tls13_SendCertificateRequest(sslSocket *
     return SECSuccess;
 }
 
 static SECStatus
 tls13_HandleHelloRetryRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 {
     SECStatus rv;
     PRInt32 tmp;
-    const namedGroupDef *group;
+    const sslNamedGroupDef *group;
 
     SSL_TRC(3, ("%d: TLS13[%d]: handle hello retry request",
                 SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     /* Client */
@@ -1527,17 +1606,17 @@ tls13_HandleHelloRetryRequest(sslSocket 
         return SECFailure; /* error code already set */
     }
 
     tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
     if (tmp < 0) {
         return SECFailure; /* error code already set */
     }
     group = ssl_LookupNamedGroup((SSLNamedGroup)tmp);
-    if (!group || !ssl_NamedGroupEnabled(ss, group)) {
+    if (!ssl_NamedGroupEnabled(ss, group)) {
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST,
                     illegal_parameter);
         return SECFailure;
     }
 
     tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
     if (tmp < 0) {
         return SECFailure; /* error code already set */
@@ -1606,16 +1685,23 @@ tls13_HandleCertificateRequest(sslSocket
         FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
         return SECFailure;
     }
 
     rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length);
     if (rv != SECSuccess)
         goto loser;
 
+    /* We don't support post-handshake client auth, the certificate request
+     * context must always be null. */
+    if (context.len > 0) {
+        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST, illegal_parameter);
+        goto loser;
+    }
+
     certRequest = PORT_ArenaZNew(arena, TLS13CertificateRequest);
     if (!certRequest)
         goto loser;
     certRequest->arena = arena;
     certRequest->ca_list.arena = arena;
 
     rv = ssl_ParseSignatureSchemes(ss, arena,
                                    &certRequest->signatureSchemes,
@@ -1688,17 +1774,17 @@ tls13_SendEncryptedServerSequence(sslSoc
     }
 
     if (ss->opt.requestCertificate) {
         rv = tls13_SendCertificateRequest(ss);
         if (rv != SECSuccess) {
             return SECFailure; /* error code is set. */
         }
     }
-    if (ss->ssl3.hs.kea_def->authKeyType != ssl_auth_psk) {
+    if (ss->ssl3.hs.signatureScheme != ssl_sig_none) {
         SECKEYPrivateKey *svrPrivKey;
 
         rv = ssl3_SendCertificate(ss);
         if (rv != SECSuccess) {
             return SECFailure; /* error code is set. */
         }
 
         svrPrivKey = ss->sec.serverCert->serverKeyPair->privKey;
@@ -1712,17 +1798,17 @@ tls13_SendEncryptedServerSequence(sslSoc
     if (rv != SECSuccess) {
         return SECFailure; /* error code is set. */
     }
 
     return SECSuccess;
 }
 
 /* Called from:  ssl3_HandleClientHello */
-SECStatus
+static SECStatus
 tls13_SendServerHelloSequence(sslSocket *ss)
 {
     SECStatus rv;
     PRErrorCode err = 0;
 
     SSL_TRC(3, ("%d: TLS13[%d]: begin send server_hello sequence",
                 SSL_GETPID(), ss->fd));
 
@@ -1797,63 +1883,84 @@ tls13_SendServerHelloSequence(sslSocket 
                                                   : wait_finished);
     return SECSuccess;
 }
 
 SECStatus
 tls13_HandleServerHelloPart2(sslSocket *ss)
 {
     SECStatus rv;
-    PRBool isPSK = ssl3_ExtensionNegotiated(ss, ssl_tls13_pre_shared_key_xtn);
     sslSessionID *sid = ss->sec.ci.sid;
     SSL3Statistics *ssl3stats = SSL_GetStatistics();
 
-    if (isPSK) {
+    if (ssl3_ExtensionNegotiated(ss, ssl_tls13_pre_shared_key_xtn)) {
+        PORT_Assert(ss->statelessResume);
+    } else {
+        ss->statelessResume = PR_FALSE;
+    }
+
+    if (ss->statelessResume) {
+        if (ssl3_ExtensionNegotiated(ss, ssl_signature_algorithms_xtn)) {
+            FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_EXTENSION,
+                        unexpected_message);
+            return SECFailure;
+        }
+    } else {
+        if (!ssl3_ExtensionNegotiated(ss, ssl_signature_algorithms_xtn)) {
+            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO,
+                        missing_extension);
+            return SECFailure;
+        }
+    }
+
+    /* Now create a synthetic kea_def that we can tweak. */
+    ss->ssl3.hs.kea_def_mutable = *ss->ssl3.hs.kea_def;
+    ss->ssl3.hs.kea_def = &ss->ssl3.hs.kea_def_mutable;
+
+    if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) {
+        rv = SSL3_SendAlert(ss, alert_warning, end_of_early_data);
+        if (rv != SECSuccess) {
+            FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+            return SECFailure;
+        }
+    }
+
+    if (ss->statelessResume) {
         PRBool cacheOK = PR_FALSE;
         do {
-            if (ss->ssl3.hs.kea_def->authKeyType != ssl_auth_psk) {
-                FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO,
-                            illegal_parameter);
-                break;
-            }
+            ss->ssl3.hs.kea_def_mutable.authKeyType = ssl_auth_psk;
+
             /* If we offered early data, then we already have the shared secret
              * recovered. */
             if (ss->ssl3.hs.zeroRttState == ssl_0rtt_none) {
                 rv = tls13_RecoverWrappedSharedSecret(ss, sid);
                 if (rv != SECSuccess) {
                     FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
                     break;
                 }
             } else {
                 PORT_Assert(ss->ssl3.hs.currentSecret);
             }
             cacheOK = PR_TRUE;
         } while (0);
 
         if (!cacheOK) {
             SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_cache_not_ok);
-            if (ss->sec.uncache)
-                ss->sec.uncache(sid);
+            ss->sec.uncache(sid);
             return SECFailure;
         }
 
         tls13_RestoreCipherInfo(ss, sid);
         if (sid->peerCert) {
             ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
         }
 
         SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_cache_hits);
         SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_stateless_resumes);
     } else {
-        /* No PSK negotiated.*/
-        if (ss->ssl3.hs.kea_def->authKeyType == ssl_auth_psk) {
-            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO,
-                        illegal_parameter);
-            return SECFailure;
-        }
         if (ss->ssl3.hs.zeroRttState != ssl_0rtt_none) {
             PORT_Assert(ss->ssl3.hs.currentSecret);
             /* If we tried 0-RTT and didn't even get PSK, we need to clean
              * stuff up. */
             PK11_FreeSymKey(ss->ssl3.hs.currentSecret);
             ss->ssl3.hs.currentSecret = NULL;
             SECITEM_FreeItem(&ss->ssl3.hs.resumptionContext, PR_FALSE);
         }
@@ -1867,26 +1974,24 @@ tls13_HandleServerHelloPart2(sslSocket *
             if (rv != SECSuccess) {
                 FATAL_ERROR(ss, SEC_ERROR_NO_MEMORY, internal_error);
                 return SECFailure;
             }
             /* Clean up the temporary pointer to the handshake buffer. */
             ss->xtnData.signedCertTimestamps.data = NULL;
             ss->xtnData.signedCertTimestamps.len = 0;
         }
-        ss->ssl3.hs.origCipherSuite = ss->ssl3.hs.cipher_suite;
-
-        if (sid->cached == in_client_cache && (ss->sec.uncache)) {
+        if (sid->cached == in_client_cache) {
             /* If we tried to resume and failed, let's not try again. */
             ss->sec.uncache(sid);
         }
     }
 
     if (!ss->ssl3.hs.currentSecret) {
-        PORT_Assert(!isPSK || ss->ssl3.hs.zeroRttState == ssl_0rtt_none);
+        PORT_Assert(!ss->statelessResume || ss->ssl3.hs.zeroRttState == ssl_0rtt_none);
 
         /* If we don't already have the Early Secret we need to make it
          * now. */
         rv = tls13_ComputeEarlySecrets(ss, PR_FALSE);
         if (rv != SECSuccess) {
             FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
             return SECFailure;
         }
@@ -1896,49 +2001,70 @@ tls13_HandleServerHelloPart2(sslSocket *
      * end up looking a lot like the old one.
      */
     ssl_FreeSID(sid);
     ss->sec.ci.sid = sid = ssl3_NewSessionID(ss, PR_FALSE);
     if (sid == NULL) {
         FATAL_ERROR(ss, PORT_GetError(), internal_error);
         return SECFailure;
     }
-    if (isPSK && ss->sec.peerCert) {
+    if (ss->statelessResume) {
+        PORT_Assert(ss->sec.peerCert);
         sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
     }
     sid->version = ss->version;
-    sid->u.ssl3.cipherSuite = ss->ssl3.hs.origCipherSuite;
 
     rv = tls13_HandleServerKeyShare(ss);
     if (rv != SECSuccess) {
         return SECFailure;
     }
-
     rv = tls13_ComputeHandshakeSecrets(ss);
     if (rv != SECSuccess) {
         return SECFailure; /* error code is set. */
     }
 
     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);
 
     return SECSuccess;
 }
 
+static void
+tls13_SetKeyExchangeType(sslSocket *ss, const sslNamedGroupDef *group)
+{
+    switch (group->keaType) {
+        /* Note: These overwrite on resumption.... so if you start with ECDH
+         * and resume with DH, we report DH. That's fine, since no answer
+         * is really right. */
+        case ssl_kea_ecdh:
+            ss->ssl3.hs.kea_def_mutable.exchKeyType =
+                ss->statelessResume ? ssl_kea_ecdh_psk : ssl_kea_ecdh;
+            ss->sec.keaType = ssl_kea_ecdh;
+            break;
+        case ssl_kea_dh:
+            ss->ssl3.hs.kea_def_mutable.exchKeyType =
+                ss->statelessResume ? ssl_kea_dh_psk : ssl_kea_dh;
+            ss->sec.keaType = ssl_kea_dh;
+            break;
+        default:
+            PORT_Assert(0);
+    }
+}
+
 /*
  * Called from ssl3_HandleServerHello.
  *
  * Caller must hold Handshake and RecvBuf locks.
  */
-SECStatus
+static SECStatus
 tls13_HandleServerKeyShare(sslSocket *ss)
 {
     SECStatus rv;
     TLS13KeyShareEntry *entry;
     sslEphemeralKeyPair *keyPair;
 
     SSL_TRC(3, ("%d: TLS13[%d]: handle server_key_share handshake",
                 SSL_GETPID(), ss->fd));
@@ -1962,17 +2088,17 @@ tls13_HandleServerKeyShare(sslSocket *ss
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_KEY_SHARE, illegal_parameter);
         return SECFailure;
     }
 
     rv = tls13_HandleKeyShare(ss, entry, keyPair->keys);
     if (rv != SECSuccess)
         return SECFailure; /* Error code set by caller. */
 
-    ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
+    tls13_SetKeyExchangeType(ss, entry->group);
     ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(keyPair->keys->pubKey);
 
     return SECSuccess;
 }
 
 /* Called from tls13_CompleteHandleHandshakeMessage() when it has deciphered a complete
  * tls13 Certificate message.
  * Caller must hold Handshake and RecvBuf locks.
@@ -1997,32 +2123,21 @@ tls13_HandleCertificate(sslSocket *ss, S
     }
     if (rv != SECSuccess)
         return SECFailure;
 
     /* Process the context string */
     rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length);
     if (rv != SECSuccess)
         return SECFailure;
-    if (!ss->sec.isServer) {
-        if (context.len) {
-            /* The server's context string MUST be empty */
-            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE,
-                        illegal_parameter);
-            return SECFailure;
-        }
-    } else {
-        if (context.len != sizeof(tls13_certreq_context) ||
-            (NSS_SecureMemcmp(tls13_certreq_context,
-                              context.data, context.len) != 0)) {
-            FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE,
-                        illegal_parameter);
-            return SECFailure;
-        }
-        context.len = 0; /* Belt and suspenders. Zero out the context. */
+
+    if (context.len) {
+        /* The context string MUST be empty */
+        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE, illegal_parameter);
+        return SECFailure;
     }
 
     rv = ssl3_CompleteHandleCertificate(ss, b, length);
     if (rv != SECSuccess)
         return rv;
 
     return SECSuccess;
 }
@@ -2255,16 +2370,39 @@ tls13_DeriveTrafficKeys(sslSocket *ss, s
         *prkp = NULL;
     }
     return SECSuccess;
 
 loser:
     return SECFailure;
 }
 
+static SECStatus
+tls13_SetupPendingCipherSpec(sslSocket *ss)
+{
+    ssl3CipherSpec *pSpec;
+    ssl3CipherSuite suite = ss->ssl3.hs.cipher_suite;
+    const ssl3BulkCipherDef *bulk = ssl_GetBulkCipherDef(
+        ssl_LookupCipherSuiteDef(suite));
+
+    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+    ssl_GetSpecWriteLock(ss); /*******************************/
+
+    pSpec = ss->ssl3.pwSpec;
+    pSpec->version = ss->version;
+
+    SSL_TRC(3, ("%d: TLS13[%d]: Set Pending Cipher Suite to 0x%04x",
+                SSL_GETPID(), ss->fd, suite));
+    pSpec->cipher_def = bulk;
+
+    ssl_ReleaseSpecWriteLock(ss); /*******************************/
+    return SECSuccess;
+}
+
 /* Install a new cipher spec for this direction. */
 static SECStatus
 tls13_SetCipherSpec(sslSocket *ss, TrafficKeyType type,
                     CipherSpecDirection direction, PRBool deleteSecret)
 {
     SECStatus rv;
     ssl3CipherSpec *spec = NULL;
     ssl3CipherSpec **specp = (direction == CipherSpecRead) ? &ss->ssl3.crSpec : &ss->ssl3.cwSpec;
@@ -2281,19 +2419,17 @@ tls13_SetCipherSpec(sslSocket *ss, Traff
     if (!spec) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         return SECFailure;
     }
     spec->refCt = 1;
     PR_APPEND_LINK(&spec->link, &ss->ssl3.hs.cipherSpecs);
     ss->ssl3.pwSpec = ss->ssl3.prSpec = spec;
 
-    /* This is really overkill, because we need about 10% of
-     * what ssl3_SetupPendingCipherSpec does. */
-    rv = ssl3_SetupPendingCipherSpec(ss);
+    rv = tls13_SetupPendingCipherSpec(ss);
     if (rv != SECSuccess)
         return SECFailure;
 
     switch (spec->cipher_def->calg) {
         case calg_aes_gcm:
             spec->aead = tls13_AESGCM;
             break;
         case calg_chacha20:
@@ -2620,17 +2756,17 @@ tls13_HandleEncryptedExtensions(sslSocke
     /* If we are doing 0-RTT, then we already have an NPN value. Stash
      * it for comparison. */
     if (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent &&
         ss->ssl3.nextProtoState == SSL_NEXT_PROTO_EARLY_VALUE) {
         oldNpn = ss->ssl3.nextProto;
         ss->ssl3.nextProto.data = NULL;
         ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_SUPPORT;
     }
-    rv = ssl3_HandleHelloExtensions(ss, &b, &length, encrypted_extensions);
+    rv = ssl3_HandleExtensions(ss, &b, &length, encrypted_extensions);
     if (rv != SECSuccess) {
         return SECFailure; /* Error code set below */
     }
 
     if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) {
         /* Check that the server negotiated the same ALPN (if any). */
         if (SECITEM_CompareItem(&oldNpn, &ss->ssl3.nextProto)) {
             SECITEM_FreeItem(&oldNpn, PR_FALSE);
@@ -2811,17 +2947,17 @@ tls13_HandleCertificateVerify(sslSocket 
     rv = ssl_ConsumeSignatureScheme(ss, &b, &length, &sigScheme);
     if (rv != SECSuccess) {
         PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_VERIFY);
         return SECFailure;
     }
 
     rv = ssl_CheckSignatureSchemeConsistency(ss, sigScheme, ss->sec.peerCert);
     if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_VERIFY, decrypt_error);
+        /* Error set already */
         return SECFailure;
     }
     hashAlg = ssl_SignatureSchemeToHashType(sigScheme);
 
     rv = tls13_AddContextToHashes(ss, hashes, hashAlg, PR_FALSE, &tbsHash);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SSL_ERROR_DIGEST_FAILURE, internal_error);
         return SECFailure;
@@ -2839,16 +2975,30 @@ tls13_HandleCertificateVerify(sslSocket 
     }
 
     rv = ssl3_VerifySignedHashes(ss, sigScheme, &tbsHash, &signed_hash);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, PORT_GetError(), decrypt_error);
         return SECFailure;
     }
 
+    /* Set the auth type. */
+    if (!ss->sec.isServer) {
+        switch (ssl_SignatureSchemeToKeyType(sigScheme)) {
+            case rsaKey:
+                ss->sec.authType = ssl_auth_rsa_sign;
+                break;
+            case ecKey:
+                ss->sec.authType = ssl_auth_ecdsa;
+                break;
+            default:
+                PORT_Assert(PR_FALSE);
+        }
+    }
+
     /* Request a client certificate now if one was requested. */
     if (ss->ssl3.hs.certificateRequest) {
         TLS13CertificateRequest *req = ss->ssl3.hs.certificateRequest;
 
         PORT_Assert(!ss->sec.isServer);
         rv = ssl3_CompleteHandleCertificateRequest(ss, req->signatureSchemes,
                                                    req->signatureSchemeCount,
                                                    &req->ca_list);
@@ -3255,92 +3405,110 @@ tls13_SendClientSecondRound(sslSocket *s
 
 loser:
     ssl_ReleaseXmitBufLock(ss); /*******************************/
     FATAL_ERROR(ss, PORT_GetError(), internal_error);
     return SECFailure;
 }
 
 /*
-    enum { (65535) } TicketExtensionType;
-
-    struct {
-        TicketExtensionType extension_type;
-        opaque extension_data<0..2^16-1>;
-    } TicketExtension;
-
-    struct {
-        uint32 ticket_lifetime;
-        uint32 flags;
-        uint32 ticket_age_add;
-        TicketExtension extensions<2..2^16-2>;
-        opaque ticket<0..2^16-1>;
-    } NewSessionTicket;
-*/
+ *  enum { (65535) } TicketExtensionType;
+ *
+ *  struct {
+ *      TicketExtensionType extension_type;
+ *      opaque extension_data<0..2^16-1>;
+ *  } TicketExtension;
+ *
+ *   struct {
+ *       uint32 ticket_lifetime;
+ *       PskKeMode ke_modes<1..255>;
+ *       PskAuthMode auth_modes<1..255>;
+ *       opaque ticket<1..2^16-1>;
+ *       TicketExtension extensions<0..2^16-2>;
+ *   } NewSessionTicket;
+ */
 static SECStatus
 tls13_SendNewSessionTicket(sslSocket *ss)
 {
     PRUint16 message_length;
     SECItem ticket_data = { 0, NULL, 0 };
-    PRUint32 flags = ticket_allow_dhe_resumption;
     SECStatus rv;
     NewSessionTicket ticket = { 0 };
-
+    PRUint32 ticket_age_add_len = 0;
     ticket.flags = 0;
     if (ss->opt.enable0RttData) {
         ticket.flags |= ticket_allow_early_data;
+
+        /* Generate a random value to add to ticket age. */
+        rv = PK11_GenerateRandom((PRUint8 *)&ticket.ticket_age_add,
+                                 sizeof(ticket.ticket_age_add));
+        if (rv != SECSuccess)
+            goto loser;
+        ticket_age_add_len = 8; /* type + len + value. */
     }
     ticket.ticket_lifetime_hint = TLS_EX_SESS_TICKET_LIFETIME_HINT;
-    /* Generate a random value to add to ticket age. */
-    rv = PK11_GenerateRandom((PRUint8 *)&ticket.ticket_age_add,
-                             sizeof(ticket.ticket_age_add));
-    if (rv != SECSuccess)
-        goto loser;
 
     rv = ssl3_EncodeSessionTicket(ss, &ticket, &ticket_data);
     if (rv != SECSuccess)
         goto loser;
 
     message_length =
-        4 + /* lifetime */
-        4 + /* flags */
-        4 + /* ticket_age_add */
-        2 + /* empty extensions */
-        2 + /* ticket length */
+        4 +                      /* lifetime */
+        1 + 1 +                  /* ke_modes */
+        1 + 1 +                  /* auth_modes */
+        2 + ticket_age_add_len + /* ticket_age_add_len */
+        2 +                      /* ticket length */
         ticket_data.len;
 
     rv = ssl3_AppendHandshakeHeader(ss, new_session_ticket,
                                     message_length);
     if (rv != SECSuccess)
         goto loser;
 
     /* This is a fixed value. */
     rv = ssl3_AppendHandshakeNumber(ss, TLS_EX_SESS_TICKET_LIFETIME_HINT, 4);
     if (rv != SECSuccess)
         goto loser;
 
-    /* Currently we only allow DHE resumption
-     * TODO(ekr@rtfm.com): Update when we add PSK-resumption and 0-RTT.
-     */
-    if (ss->opt.enable0RttData) {
-        flags |= ticket_allow_early_data;
-    }
-    rv = ssl3_AppendHandshakeNumber(ss, flags, sizeof(flags));
+    /* Key exchange modes. */
+    rv = ssl3_AppendHandshakeNumber(ss, 1, 1);
+    if (rv != SECSuccess)
+        goto loser;
+    rv = ssl3_AppendHandshakeNumber(ss, tls13_psk_dh_ke, 1);
+    if (rv != SECSuccess)
+        goto loser;
+
+    /* Authentication modes. */
+    rv = ssl3_AppendHandshakeNumber(ss, 1, 1);
+    if (rv != SECSuccess)
+        goto loser;
+    rv = ssl3_AppendHandshakeNumber(ss, tls13_psk_auth, 1);
     if (rv != SECSuccess)
         goto loser;
 
-    rv = ssl3_AppendHandshakeNumber(ss, ticket.ticket_age_add,
-                                    sizeof(ticket.ticket_age_add));
+    /* Extensions. */
+    rv = ssl3_AppendHandshakeNumber(ss, ticket_age_add_len, 2);
     if (rv != SECSuccess)
         goto loser;
 
-    /* No extensions. */
-    rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
-    if (rv != SECSuccess)
-        goto loser;
+    if (ticket_age_add_len) {
+        rv = ssl3_AppendHandshakeNumber(
+            ss, ssl_tls13_ticket_early_data_info_xtn, 2);
+        if (rv != SECSuccess)
+            goto loser;
+
+        /* Length */
+        rv = ssl3_AppendHandshakeNumber(ss, 4, 2);
+        if (rv != SECSuccess)
+            goto loser;
+
+        rv = ssl3_AppendHandshakeNumber(ss, ticket.ticket_age_add, 4);
+        if (rv != SECSuccess)
+            goto loser;
+    }
 
     /* Encode the ticket. */
     rv = ssl3_AppendHandshakeVariable(
         ss, ticket_data.data, ticket_data.len, 2);
     if (rv != SECSuccess)
         goto loser;
 
     rv = SECSuccess;
@@ -3352,18 +3520,17 @@ loser:
     return rv;
 }
 
 static SECStatus
 tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 {
     SECStatus rv;
     PRInt32 tmp;
-    PRUint32 tmpu;
-    NewSessionTicket ticket;
+    NewSessionTicket ticket = { 0 };
     SECItem data;
 
     SSL_TRC(3, ("%d: TLS13[%d]: handle new session ticket message",
                 SSL_GETPID(), ss->fd));
 
     rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET,
                               idle_handshake);
     if (rv != SECSuccess) {
@@ -3380,62 +3547,84 @@ tls13_HandleNewSessionTicket(sslSocket *
     if (tmp < 0) {
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET,
                     decode_error);
         return SECFailure;
     }
     ticket.ticket_lifetime_hint = (PRUint32)tmp;
     ticket.ticket.type = siBuffer;
 
-    /* Flags. */
-    rv = ssl3_ConsumeHandshake(ss, &tmpu, 4, &b, &length);
+    /* key exchange modes. */
+    rv = ssl3_ConsumeHandshakeVariable(ss, &data, 1, &b, &length);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET,
                     decode_error);
         return SECFailure;
     }
-    ticket.flags = PR_ntohl(tmpu);
-
-    rv = ssl3_ConsumeHandshake(ss, &tmpu, 4, &b, &length);
+    if (memchr(data.data, tls13_psk_dh_ke, data.len)) {
+        ticket.flags |= ticket_allow_psk_dhe_ke;
+    }
+
+    /* auth modes. */
+    rv = ssl3_ConsumeHandshakeVariable(ss, &data, 1, &b, &length);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET,
                     decode_error);
         return SECFailure;
     }
-    ticket.ticket_age_add = (PRUint32)tmpu;
-
-    /* Parse and discard extensions. */
+    if (memchr(data.data, tls13_psk_auth, data.len)) {
+        ticket.flags |= ticket_allow_psk_auth;
+    }
+
+    /* Parse extensions. */
     rv = ssl3_ConsumeHandshakeVariable(ss, &data, 2, &b, &length);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET,
                     decode_error);
         return SECFailure;
     }
-
+    ss->xtnData.ticket_age_add_found = PR_FALSE;
+    rv = ssl3_HandleExtensions(ss, &data.data,
+                               &data.len, new_session_ticket);
+    if (rv != SECSuccess) {
+        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET,
+                    decode_error);
+        return SECFailure;
+    }
+
+    if (ss->xtnData.ticket_age_add_found) {
+        ticket.flags |= ticket_allow_early_data;
+        ticket.ticket_age_add = ss->xtnData.ticket_age_add;
+    }
+
+    /* Get the ticket value. */
     rv = ssl3_ConsumeHandshakeVariable(ss, &data, 2, &b, &length);
     if (rv != SECSuccess || length != 0 || !data.len) {
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET,
                     decode_error);
         return SECFailure;
     }
 
     /* TODO(ekr@rtfm.com): Re-enable new tickets when PSK mode is
      * in use. I believe this works, but I can't test it until the
      * server side supports it. Bug 1257047.
      */
-    if (!ss->opt.noCache && ss->sec.cache &&
-        ss->ssl3.hs.kea_def->authKeyType != ssl_auth_psk) {
+    if (!ss->opt.noCache && ss->ssl3.hs.kea_def->authKeyType != ssl_auth_psk) {
 
         /* Uncache so that we replace. */
-        (*ss->sec.uncache)(ss->sec.ci.sid);
+        ss->sec.uncache(ss->sec.ci.sid);
 
         /* We only support DHE resumption so any ticket which doesn't
          * support it we don't cache, but it can evict previous
          * cache entries. */
-        if (!(ticket.flags & ticket_allow_dhe_resumption)) {
+        if (!(ticket.flags & ticket_allow_psk_dhe_ke)) {
+            return SECSuccess;
+        }
+
+        if (!(ticket.flags & ticket_allow_psk_auth)) {
             return SECSuccess;
         }
 
         rv = SECITEM_CopyItem(NULL, &ticket.ticket, &data);
         if (rv != SECSuccess) {
             FATAL_ERROR(ss, SEC_ERROR_NO_MEMORY, internal_error);
             return SECFailure;
         }
@@ -3447,60 +3636,63 @@ tls13_HandleNewSessionTicket(sslSocket *
         PORT_Assert(!ticket.ticket.data);
 
         rv = ssl3_FillInCachedSID(ss, ss->sec.ci.sid);
         if (rv != SECSuccess)
             return SECFailure;
 
         /* Cache the session. */
         ss->sec.ci.sid->cached = never_cached;
-        (*ss->sec.cache)(ss->sec.ci.sid);
+        ss->sec.cache(ss->sec.ci.sid);
     }
 
     return SECSuccess;
 }
 
 typedef enum {
     ExtensionNotUsed,
     ExtensionClientOnly,
     ExtensionSendClear,
     ExtensionSendEncrypted,
+    ExtensionNewSessionTicket
 } Tls13ExtensionStatus;
 
 static const struct {
-    SSLExtensionType ex_value;
+    PRUint16 ex_value;
     Tls13ExtensionStatus status;
 } KnownExtensions[] = {
     { ssl_server_name_xtn, ExtensionSendEncrypted },
     { ssl_supported_groups_xtn, ExtensionSendEncrypted },
     { ssl_ec_point_formats_xtn, ExtensionNotUsed },
-    { ssl_signature_algorithms_xtn, ExtensionClientOnly },
+    { ssl_signature_algorithms_xtn, ExtensionSendClear },
     { ssl_use_srtp_xtn, ExtensionSendEncrypted },
     { ssl_app_layer_protocol_xtn, ExtensionSendEncrypted },
     { ssl_padding_xtn, ExtensionNotUsed },
     { ssl_extended_master_secret_xtn, ExtensionNotUsed },
     { ssl_session_ticket_xtn, ExtensionClientOnly },
     { ssl_tls13_key_share_xtn, ExtensionSendClear },
     { ssl_tls13_pre_shared_key_xtn, ExtensionSendClear },
     { ssl_tls13_early_data_xtn, ExtensionSendEncrypted },
     { ssl_next_proto_nego_xtn, ExtensionNotUsed },
     { ssl_renegotiation_info_xtn, ExtensionNotUsed },
     { ssl_signed_cert_timestamp_xtn, ExtensionSendEncrypted },
     { ssl_cert_status_xtn, ExtensionSendEncrypted },
-    { ssl_tls13_draft_version_xtn, ExtensionClientOnly }
+    { ssl_tls13_draft_version_xtn, ExtensionClientOnly },
+    { ssl_tls13_ticket_early_data_info_xtn, ExtensionNewSessionTicket }
 };
 
 PRBool
 tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message)
 {
     unsigned int i;
 
     PORT_Assert((message == client_hello) ||
                 (message == server_hello) ||
-                (message == encrypted_extensions));
+                (message == encrypted_extensions) ||
+                (message == new_session_ticket));
 
     for (i = 0; i < PR_ARRAY_SIZE(KnownExtensions); i++) {
         if (KnownExtensions[i].ex_value == extension)
             break;
     }
     if (i == PR_ARRAY_SIZE(KnownExtensions)) {
         /* We have never heard of this extension which is OK on
          * the server but not the client. */
@@ -3513,16 +3705,18 @@ tls13_ExtensionAllowed(PRUint16 extensio
         case ExtensionClientOnly:
             return message == client_hello;
         case ExtensionSendClear:
             return message == client_hello ||
                    message == server_hello;
         case ExtensionSendEncrypted:
             return message == client_hello ||
                    message == encrypted_extensions;
+        case ExtensionNewSessionTicket:
+            return message == new_session_ticket;
     }
 
     PORT_Assert(0);
 
     /* Not reached */
     return PR_TRUE;
 }
 
@@ -3740,18 +3934,17 @@ PRBool
 tls13_ClientAllow0Rtt(sslSocket *ss, const sslSessionID *sid)
 {
     if (sid->version < SSL_LIBRARY_VERSION_TLS_1_3)
         return PR_FALSE;
     if (ss->ssl3.hs.helloRetry)
         return PR_FALSE;
     if (!ss->opt.enable0RttData)
         return PR_FALSE;
-    if (!ss->xtnData.ticketTimestampVerified &&
-        !ssl3_ClientExtensionAdvertised(ss, ssl_tls13_pre_shared_key_xtn))
+    if (!ss->statelessResume)
         return PR_FALSE;
     if ((sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data) == 0)
         return PR_FALSE;
     return tls13_AlpnTagAllowed(ss, &sid->u.ssl3.alpnSelection);
 }
 
 SECStatus
 tls13_MaybeDo0RTTHandshake(sslSocket *ss)
--- a/security/nss/lib/ssl/tls13con.h
+++ b/security/nss/lib/ssl/tls13con.h
@@ -45,19 +45,16 @@ PRBool tls13_AllowPskCipher(const sslSoc
 PRBool tls13_PskSuiteEnabled(sslSocket *ss);
 SECStatus tls13_HandleClientHelloPart2(sslSocket *ss,
                                        const SECItem *suites,
                                        sslSessionID *sid);
 SECStatus tls13_HandleServerHelloPart2(sslSocket *ss);
 SECStatus tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
                                                 PRUint32 length,
                                                 SSL3Hashes *hashesPtr);
-SECStatus tls13_HandleClientKeyShare(sslSocket *ss, PRBool *retry);
-SECStatus tls13_SendServerHelloSequence(sslSocket *ss);
-SECStatus tls13_HandleServerKeyShare(sslSocket *ss);
 void tls13_DestroyKeyShareEntry(TLS13KeyShareEntry *entry);
 void tls13_DestroyKeyShares(PRCList *list);
 void tls13_DestroyEarlyData(PRCList *list);
 void tls13_CipherSpecAddRef(ssl3CipherSpec *spec);
 void tls13_CipherSpecRelease(ssl3CipherSpec *spec);
 void tls13_DestroyCipherSpecs(PRCList *list);
 PRBool tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message);
 SECStatus tls13_ProtectRecord(sslSocket *ss,
--- a/security/nss/lib/util/manifest.mn
+++ b/security/nss/lib/util/manifest.mn
@@ -2,16 +2,17 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 CORE_DEPTH = ../..
 
 EXPORTS = \
 	base64.h \
 	ciferfam.h \
+	eccutil.h \
 	hasht.h \
 	nssb64.h \
 	nssb64t.h \
 	nsslocks.h \
 	nssilock.h \
 	nssilckt.h \
 	nssrwlk.h \
 	nssrwlkt.h \
--- a/security/nss/lib/util/nssutil.h
+++ b/security/nss/lib/util/nssutil.h
@@ -14,19 +14,19 @@
 
 /*
  * NSS utilities's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
  */
-#define NSSUTIL_VERSION "3.27 Beta"
+#define NSSUTIL_VERSION "3.28 Beta"
 #define NSSUTIL_VMAJOR 3
-#define NSSUTIL_VMINOR 27
+#define NSSUTIL_VMINOR 28
 #define NSSUTIL_VPATCH 0
 #define NSSUTIL_VBUILD 0
 #define NSSUTIL_BETA PR_TRUE
 
 SEC_BEGIN_PROTOS
 
 /*
  * Returns a const string of the UTIL library version.
--- a/security/nss/lib/util/pkcs11t.h
+++ b/security/nss/lib/util/pkcs11t.h
@@ -1587,17 +1587,17 @@ typedef struct CK_SSL3_KEY_MAT_OUT {
 } CK_SSL3_KEY_MAT_OUT;
 
 typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
 
 typedef struct CK_SSL3_KEY_MAT_PARAMS {
     CK_ULONG ulMacSizeInBits;
     CK_ULONG ulKeySizeInBits;
     CK_ULONG ulIVSizeInBits;
-    CK_BBOOL bIsExport;
+    CK_BBOOL bIsExport; /* Unused. Must be set to CK_FALSE. */
     CK_SSL3_RANDOM_DATA RandomInfo;
     CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
 } CK_SSL3_KEY_MAT_PARAMS;
 
 typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
 
 /* CK_TLS_PRF_PARAMS is new for version 2.20 */
 typedef struct CK_TLS_PRF_PARAMS {
@@ -1690,17 +1690,17 @@ typedef struct CK_WTLS_KEY_MAT_OUT {
 typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
 
 typedef struct CK_WTLS_KEY_MAT_PARAMS {
     CK_MECHANISM_TYPE DigestMechanism;
     CK_ULONG ulMacSizeInBits;
     CK_ULONG ulKeySizeInBits;
     CK_ULONG ulIVSizeInBits;
     CK_ULONG ulSequenceNumber;
-    CK_BBOOL bIsExport;
+    CK_BBOOL bIsExport; /* Unused. Must be set to CK_FALSE. */
     CK_WTLS_RANDOM_DATA RandomInfo;
     CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
 } CK_WTLS_KEY_MAT_PARAMS;
 
 typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
 
 /* CMS is new for version 2.20 */
 typedef struct CK_CMS_SIG_PARAMS {
--- a/security/nss/lib/util/secoid.c
+++ b/security/nss/lib/util/secoid.c
@@ -579,16 +579,21 @@ CONST_OID secgECsect571k1[] = { SECG_OID
 CONST_OID secgECsect571r1[] = { SECG_OID, 0x27 };
 
 CONST_OID seed_CBC[] = { SEED_OID, 4 };
 
 CONST_OID evIncorporationLocality[] = { EV_NAME_ATTRIBUTE, 1 };
 CONST_OID evIncorporationState[] = { EV_NAME_ATTRIBUTE, 2 };
 CONST_OID evIncorporationCountry[] = { EV_NAME_ATTRIBUTE, 3 };
 
+/* https://tools.ietf.org/html/draft-josefsson-pkix-newcurves-01
+ * 1.3.6.1.4.1.11591.15.1
+ */
+CONST_OID curve25519[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01 };
+
 #define OI(x)                                  \
     {                                          \
         siDEROID, (unsigned char *)x, sizeof x \
     }
 #ifndef SECOID_NO_STRINGS
 #define OD(oid, tag, desc, mech, ext) \
     {                                 \
         OI(oid)                       \
@@ -1738,17 +1743,20 @@ const static SECOidData oids[SEC_OID_TOT
     ODE(SEC_OID_TLS_FFDHE_4096,
         "TLS FFDHE 4096-bit key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
     ODE(SEC_OID_TLS_FFDHE_6144,
         "TLS FFDHE 6144-bit key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
     ODE(SEC_OID_TLS_FFDHE_8192,
         "TLS FFDHE 8192-bit key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
     ODE(SEC_OID_TLS_DHE_CUSTOM,
         "TLS DHE custom group key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
-
+    OD(curve25519, SEC_OID_CURVE25519,
+       "Curve25519", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+    ODE(SEC_OID_TLS13_KEA_ANY,
+        "TLS 1.3 fake key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
 };
 
 /* PRIVATE EXTENDED SECOID Table
  * This table is private. Its structure is opaque to the outside.
  * It is indexed by the same SECOidTag as the oids table above.
  * Every member of this struct must have accessor functions (set, get)
  * and those functions must operate by value, not by reference.
  * The addresses of the contents of this table must not be exposed
--- a/security/nss/lib/util/secoidt.h
+++ b/security/nss/lib/util/secoidt.h
@@ -485,16 +485,20 @@ typedef enum {
 
     SEC_OID_TLS_FFDHE_2048 = 349,
     SEC_OID_TLS_FFDHE_3072 = 350,
     SEC_OID_TLS_FFDHE_4096 = 351,
     SEC_OID_TLS_FFDHE_6144 = 352,
     SEC_OID_TLS_FFDHE_8192 = 353,
     SEC_OID_TLS_DHE_CUSTOM = 354,
 
+    SEC_OID_CURVE25519 = 355,
+
+    SEC_OID_TLS13_KEA_ANY = 356,
+
     SEC_OID_TOTAL
 } SECOidTag;
 
 #define SEC_OID_SECG_EC_SECP192R1 SEC_OID_ANSIX962_EC_PRIME192V1
 #define SEC_OID_SECG_EC_SECP256R1 SEC_OID_ANSIX962_EC_PRIME256V1
 #define SEC_OID_PKCS12_KEY_USAGE SEC_OID_X509_KEY_USAGE
 
 /* fake OID for DSS sign/verify */
--- a/security/nss/tests/all.sh
+++ b/security/nss/tests/all.sh
@@ -32,16 +32,18 @@
 #   merge.sh     - tests merging old and new shareable databases
 #   pkits.sh     - NIST/PKITS tests
 #   chains.sh    - PKIX cert chains tests
 #   dbupgrade.sh - upgrade databases to new shareable version (used
 #                  only in upgrade test cycle)
 #   memleak.sh   - memory leak testing (optional)
 #   ssl_gtests.sh- Gtest based unit tests for ssl
 #   gtests.sh    - Gtest based unit tests for everything else
+#   bogo.sh      - Bogo interop tests (disabled by default)
+#                  https://boringssl.googlesource.com/boringssl/+/master/ssl/test/PORTING.md
 #
 # NSS testing is now devided to 4 cycles:
 # ---------------------------------------
 #   standard     - run test suites with defaults settings
 #   pkix         - run test suites with PKIX enabled
 #   upgradedb    - upgrade existing certificate databases to shareable
 #                  format (creates them if doesn't exist yet) and run
 #                  test suites with those databases
--- a/security/nss/tests/common/init.sh
+++ b/security/nss/tests/common/init.sh
@@ -188,32 +188,28 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOU
     {
         increase_msg_id
         html "<TR><TD>#${MSG_ID}: $1 ${HTML_PASSED}"
         echo "${SCRIPTNAME}: #${MSG_ID}: $* - PASSED"
     }
     html_passed()
     {
         html_detect_core "$@" || return
-        increase_msg_id
-        html "<TR><TD>#${MSG_ID}: $1 ${HTML_PASSED}"
-        echo "${SCRIPTNAME}: #${MSG_ID}: $* - PASSED"
+        html_passed_ignore_core "$@"
     }
     html_failed_ignore_core()
     {
         increase_msg_id
         html "<TR><TD>#${MSG_ID}: $1 ${HTML_FAILED}"
         echo "${SCRIPTNAME}: #${MSG_ID}: $* - FAILED"
     }
     html_failed()
     {
         html_detect_core "$@" || return
-        increase_msg_id
-        html "<TR><TD>#${MSG_ID}: $1 ${HTML_FAILED}"
-        echo "${SCRIPTNAME}: #${MSG_ID}: $* - FAILED"
+        html_failed_ignore_core "$@" || return
     }
     html_unknown_ignore_core()
     {
         increase_msg_id
         html "<TR><TD>#${MSG_ID}: $1 ${HTML_UNKNOWN}"
         echo "${SCRIPTNAME}: #${MSG_ID}: $* - UNKNOWN"
     }
     html_unknown()
--- a/security/nss/tests/ec/ecperf.sh
+++ b/security/nss/tests/ec/ecperf.sh
@@ -36,16 +36,17 @@ ecperf_cleanup()
 {
   html "</TABLE><BR>"
   cd ${QADIR}
   . common/cleanup.sh
 }
 
 ecperf_init
 ECPERF_OUT=$(ecperf 2>&1)
+echo "$ECPERF_OUT"
 ECPERF_OUT=`echo $ECPERF_OUT | grep -i 'failed\|Assertion failure'`
 # TODO: this is a perf test we don't check for performance here but only failed
 if [ -n "$ECPERF_OUT" ] ; then
   html_failed "ec(perf) test"
 else
   html_passed "ec(perf) test"
 fi
 ecperf_cleanup
--- a/security/nss/tests/ec/ectest.sh
+++ b/security/nss/tests/ec/ectest.sh
@@ -34,18 +34,49 @@ ectest_init()
 
 ectest_cleanup()
 {
   html "</TABLE><BR>"
   cd ${QADIR}
   . common/cleanup.sh
 }
 
+ectest_genkeydb_test()
+{
+  certutil -N -d "${HOSTDIR}" -f "${R_PWFILE}" 2>&1
+  if [ $? -ne 0 ]; then
+    return $?
+  fi
+  curves=( \
+    "curve25519" \
+    "secp256r1" \
+    "secp384r1" \
+    "secp521r1" \
+  )
+  for curve in "${curves[@]}"; do
+    echo "Test $curve key generation using certutil ..."
+    certutil -G -d "${HOSTDIR}" -k ec -q $curve -f "${R_PWFILE}" -z ${NOISE_FILE}
+    if [ $? -ne 0 ]; then
+      html_failed "ec test certutil keygen - $curve"
+    else
+      html_passed "ec test certutil keygen - $curve"
+    fi
+  done
+  echo "Test sect571r1 key generation using certutil that should fail because it's not implemented ..."
+  certutil -G -d "${HOSTDIR}" -k ec -q sect571r1 -f "${R_PWFILE}" -z ${NOISE_FILE}
+  if [ $? -eq 0 ]; then
+    html_failed "ec test certutil keygen - $curve"
+  else
+    html_passed "ec test certutil keygen - $curve"
+  fi
+}
+
 ectest_init
-ECTEST_OUT=$(ectest 2>&1)
+ectest_genkeydb_test
+ECTEST_OUT=$(ectest -f -p -n -d 2>&1)
 ECTEST_OUT=`echo $ECTEST_OUT | grep -i 'not okay\|Assertion failure'`
 # TODO: expose individual tests and failures instead of overall
 if [ -n "$ECTEST_OUT" ] ; then
-  html_failed "ec(test) test"
+  html_failed "ec freebl and pk11 test"
 else
-  html_passed "ec(test) test"
+  html_passed "ec freebl and pk11 test"
 fi
 ectest_cleanup
--- a/security/nss/tests/iopr/server_scr/cipher.list
+++ b/security/nss/tests/iopr/server_scr/cipher.list
@@ -4,87 +4,66 @@
 
 nss                                      openssl                    iis 
 
 #
 # SSL v3.0 cipher suites.
 #
 SSL3_RSA_WITH_NULL_MD5                   NULL-MD5                   i
 SSL3_RSA_WITH_NULL_SHA                   NULL-SHA                   z
-SSL3_RSA_EXPORT_WITH_RC4_40_MD5          EXP-RC4-MD5                f
 SSL3_RSA_WITH_RC4_128_MD5                RC4-MD5                    c
 SSL3_RSA_WITH_RC4_128_SHA                RC4-SHA                    n
-SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5      EXP-RC2-CBC-MD5            g
 SSL3_RSA_WITH_IDEA_CBC_SHA               IDEA-CBC-SHA
-SSL3_RSA_EXPORT_WITH_DES40_CBC_SHA       EXP-DES-CBC-SHA            
 SSL3_RSA_WITH_DES_CBC_SHA                DES-CBC-SHA                e
 SSL3_RSA_WITH_3DES_EDE_CBC_SHA           DES-CBC3-SHA               d
 
-SSL3_DH_DSS_EXPORT_WITH_DES40_CBC_SHA    Not_implemented.
 SSL3_DH_DSS_WITH_DES_CBC_SHA             Not_implemented.
 SSL3_DH_DSS_WITH_3DES_EDE_CBC_SHA        Not_implemented.
-SSL3_DH_RSA_EXPORT_WITH_DES40_CBC_SHA    Not_implemented.
 SSL3_DH_RSA_WITH_DES_CBC_SHA             Not_implemented.
 SSL3_DH_RSA_WITH_3DES_EDE_CBC_SHA        Not_implemented.
-SSL3_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA   EXP-EDH-DSS-DES-CBC-SHA
 SSL3_DHE_DSS_WITH_DES_CBC_SHA            EDH-DSS-CBC-SHA            s
 SSL3_DHE_DSS_WITH_3DES_EDE_CBC_SHA       EDH-DSS-DES-CBC3-SHA       q
-SSL3_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA   EXP-EDH-RSA-DES-CBC-SHA
 SSL3_DHE_RSA_WITH_DES_CBC_SHA            EDH-RSA-DES-CBC-SHA
 SSL3_DHE_RSA_WITH_3DES_EDE_CBC_SHA       EDH-RSA-DES-CBC3-SHA
 
-SSL3_DH_anon_EXPORT_WITH_RC4_40_MD5      EXP-ADH-RC4-MD5
 SSL3_DH_anon_WITH_RC4_128_MD5            ADH-RC4-MD5
-SSL3_DH_anon_EXPORT_WITH_DES40_CBC_SHA   EXP-ADH-DES-CBC-SHA
 SSL3_DH_anon_WITH_DES_CBC_SHA            ADH-DES-CBC-SHA
 SSL3_DH_anon_WITH_3DES_EDE_CBC_SHA       ADH-DES-CBC3-SHA
 
 SSL3_FORTEZZA_KEA_WITH_NULL_SHA          Not_implemented.
 SSL3_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA  Not_implemented.
 SSL3_FORTEZZA_KEA_WITH_RC4_128_SHA       Not_implemented.
 
 #
 # Next four added to have ciphers below for SSL3 protocol
 #
 SSL3_RSA_WITH_AES_128_CBC_SHA            AES128-SHA
 SSL3_RSA_WITH_AES_256_CBC_SHA            AES256-SHA
 
-SSL3_RSA_EXPORT_WITH_DES_CBC_SHA         EXP1024-DES-CBC-SHA        l
-SSL3_RSA_EXPORT_WITH_RC4_56_SHA          EXP1024-RC4-SHA            m
-
 #
 #TLS v1.0 cipher suites.
 #
 TLS_RSA_WITH_NULL_MD5                   NULL-MD5
 TLS_RSA_WITH_NULL_SHA                   NULL-SHA
-TLS_RSA_EXPORT_WITH_RC4_40_MD5          EXP-RC4-MD5
 TLS_RSA_WITH_RC4_128_MD5                RC4-MD5
 TLS_RSA_WITH_RC4_128_SHA                RC4-SHA
-TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5      EXP-RC2-CBC-MD5
 TLS_RSA_WITH_IDEA_CBC_SHA               IDEA-CBC-SHA
-TLS_RSA_EXPORT_WITH_DES40_CBC_SHA       EXP-DES-CBC-SHA
 TLS_RSA_WITH_DES_CBC_SHA                DES-CBC-SHA
 TLS_RSA_WITH_3DES_EDE_CBC_SHA           DES-CBC3-SHA
 
-TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA    Not_implemented.
 TLS_DH_DSS_WITH_DES_CBC_SHA             Not_implemented.
 TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA        Not_implemented.
-TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA    Not_implemented.
 TLS_DH_RSA_WITH_DES_CBC_SHA             Not_implemented.
 TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA        Not_implemented.
-TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA   EXP-EDH-DSS-DES-CBC-SHA
 TLS_DHE_DSS_WITH_DES_CBC_SHA            EDH-DSS-CBC-SHA
 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA       EDH-DSS-DES-CBC3-SHA
-TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA   EXP-EDH-RSA-DES-CBC-SHA
 TLS_DHE_RSA_WITH_DES_CBC_SHA            EDH-RSA-DES-CBC-SHA
 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA       EDH-RSA-DES-CBC3-SHA
 
-TLS_DH_anon_EXPORT_WITH_RC4_40_MD5      EXP-ADH-RC4-MD5
 TLS_DH_anon_WITH_RC4_128_MD5            ADH-RC4-MD5
-TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA   EXP-ADH-DES-CBC-SHA
 TLS_DH_anon_WITH_DES_CBC_SHA            ADH-DES-CBC-SHA
 TLS_DH_anon_WITH_3DES_EDE_CBC_SHA       ADH-DES-CBC3-SHA
 
 #
 #AES ciphersuites from RFC3268, extending TLS v1.0
 #
 
 TLS_RSA_WITH_AES_128_CBC_SHA            AES128-SHA
@@ -99,24 +78,20 @@ TLS_DHE_DSS_WITH_AES_128_CBC_SHA        
 TLS_DHE_DSS_WITH_AES_256_CBC_SHA        DHE-DSS-AES256-SHA
 TLS_DHE_RSA_WITH_AES_128_CBC_SHA        DHE-RSA-AES128-SHA
 TLS_DHE_RSA_WITH_AES_256_CBC_SHA        DHE-RSA-AES256-SHA
 
 TLS_DH_anon_WITH_AES_128_CBC_SHA        ADH-AES128-SHA
 TLS_DH_anon_WITH_AES_256_CBC_SHA        ADH-AES256-SHA
 
 #
-#Additional Export 1024 and other cipher suites
+#Additional cipher suites
 #
 #Note: these ciphers can also be used in SSL v3.
 #
-TLS_RSA_EXPORT_WITH_DES_CBC_SHA         EXP1024-DES-CBC-SHA
-TLS_RSA_EXPORT_WITH_RC4_56_SHA          EXP1024-RC4-SHA
-TLS_DHE_DSS_EXPORT_WITH_DES_CBC_SHA     EXP1024-DHE-DSS-DES-CBC-SHA
-TLS_DHE_DSS_EXPORT_WITH_RC4_56_SHA      EXP1024-DHE-DSS-RC4-SHA
 TLS_DHE_DSS_WITH_RC4_128_SHA            DHE-DSS-RC4-SHA
 
 #
 # FIPS cipher list
 #        
 TLS_RSA_FIPS_WITH_3DES_EDE_CBC_SHA      Not_implemented
 TLS_RSA_FIPS_WITH_DES_CBC_SHA           Not_implemented
 SSL3_RSA_FIPS_WITH_3DES_EDE_CBC_SHA     Not_implemented
--- a/security/nss/tests/ssl/ssl.sh
+++ b/security/nss/tests/ssl/ssl.sh
@@ -83,17 +83,17 @@ ssl_init()
   USER_NICKNAME=TestUser
   NORM_EXT=""
 
   EC_SUITES=":C001:C002:C003:C004:C005:C006:C007:C008:C009:C00A:C00B:C00C:C00D"
   EC_SUITES="${EC_SUITES}:C00E:C00F:C010:C011:C012:C013:C014:C023:C024:C027"
   EC_SUITES="${EC_SUITES}:C028:C02B:C02C:C02F:C030:CCA8:CCA9:CCAA"
 
   NON_EC_SUITES=":0016:0032:0033:0038:0039:003B:003C:003D:0040:0041:0067:006A:006B"
-  NON_EC_SUITES="${NON_EC_SUITES}:0084:009C:009D:009E:009F:00A2:00A3:CCAAcdefgijklmnvyz"
+  NON_EC_SUITES="${NON_EC_SUITES}:0084:009C:009D:009E:009F:00A2:00A3:CCAAcdeinvyz"
 
   if [ -z "$NSS_DISABLE_ECC" ] ; then
       ECC_STRING=" - with ECC"
       # List of cipher suites to test, including ECC cipher suites.
       CIPHER_SUITES="-c ${EC_SUITES}${NON_EC_SUITES}"
   else
       ECC_STRING=""
       # List of cipher suites to test, excluding ECC cipher suites.
@@ -281,18 +281,16 @@ ssl_cov()
   exec < ${SSLCOV}
   while read ectype testmax param testname
   do
       echo "${testname}" | grep "EXPORT" > /dev/null
       EXP=$?
 
       if [ "$ectype" = "ECC" -a -n "$NSS_DISABLE_ECC" ] ; then
           echo "$SCRIPTNAME: skipping  $testname (ECC only)"
-      elif [ "$SERVER_MODE" = "fips" -o "$CLIENT_MODE" = "fips" ] && [ "$EXP" -eq 0 ] ; then
-          echo "$SCRIPTNAME: skipping  $testname (non-FIPS only)"
       elif [ "`echo $ectype | cut -b 1`" != "#" ] ; then
           echo "$SCRIPTNAME: running $testname ----------------------------"
           VMAX="ssl3"
           if [ "$testmax" = "TLS10" ]; then
               VMAX="tls1.0"
           fi
           if [ "$testmax" = "TLS11" ]; then
               VMAX="tls1.1"
--- a/security/nss/tests/ssl/sslcov.txt
+++ b/security/nss/tests/ssl/sslcov.txt
@@ -5,77 +5,52 @@
 # This file enables test coverage of the various SSL ciphers
 #
 # Enable Enable Cipher Test Name 
 #  EC     TLS
 #
   noECC  SSL3   c    SSL3_RSA_WITH_RC4_128_MD5
   noECC  SSL3   d    SSL3_RSA_WITH_3DES_EDE_CBC_SHA
   noECC  SSL3   e    SSL3_RSA_WITH_DES_CBC_SHA
-  noECC  SSL3   f    SSL3_RSA_EXPORT_WITH_RC4_40_MD5
-  noECC  SSL3   g    SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5
   noECC  SSL3   i    SSL3_RSA_WITH_NULL_MD5
-  noECC  SSL3   j    SSL3_RSA_FIPS_WITH_3DES_EDE_CBC_SHA
-  noECC  SSL3   k    SSL3_RSA_FIPS_WITH_DES_CBC_SHA
-  noECC  SSL3   l    SSL3_RSA_EXPORT_WITH_DES_CBC_SHA   (new)
-  noECC  SSL3   m    SSL3_RSA_EXPORT_WITH_RC4_56_SHA    (new)
   noECC  SSL3   n    SSL3_RSA_WITH_RC4_128_SHA
   noECC  SSL3   v    SSL3_RSA_WITH_AES_128_CBC_SHA
   noECC  SSL3   y    SSL3_RSA_WITH_AES_256_CBC_SHA
   noECC  SSL3   z    SSL3_RSA_WITH_NULL_SHA
   noECC  TLS12 :009F  TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
   noECC  TLS12 :00A3  TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
   noECC  TLS12 :009D  TLS_RSA_WITH_AES_256_GCM_SHA384
 #  noECC  SSL3  :0041 TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
 #  noECC  SSL3  :0084 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
 #
   noECC  TLS10   c    TLS_RSA_WITH_RC4_128_MD5
   noECC  TLS10   d    TLS_RSA_WITH_3DES_EDE_CBC_SHA
   noECC  TLS10   e    TLS_RSA_WITH_DES_CBC_SHA
-  noECC  TLS10   f    TLS_RSA_EXPORT_WITH_RC4_40_MD5
-  noECC  TLS10   g    TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
   noECC  TLS10   i    TLS_RSA_WITH_NULL_MD5
-  noECC  TLS10   j    TLS_RSA_FIPS_WITH_3DES_EDE_CBC_SHA
-  noECC  TLS10   k    TLS_RSA_FIPS_WITH_DES_CBC_SHA
-  noECC  TLS10   l    TLS_RSA_EXPORT_WITH_DES_CBC_SHA   (new)
-  noECC  TLS10   m    TLS_RSA_EXPORT_WITH_RC4_56_SHA    (new)
   noECC  TLS10   n    TLS_RSA_WITH_RC4_128_SHA
   noECC  TLS10   v    TLS_RSA_WITH_AES_128_CBC_SHA
   noECC  TLS10   y    TLS_RSA_WITH_AES_256_CBC_SHA
   noECC  TLS10   z    TLS_RSA_WITH_NULL_SHA
 #  noECC  TLS10 :0041  TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
 #  noECC  TLS10 :0084  TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
 #
 #
   noECC  TLS11   c    TLS11_RSA_WITH_RC4_128_MD5
   noECC  TLS11   d    TLS11_RSA_WITH_3DES_EDE_CBC_SHA
   noECC  TLS11   e    TLS11_RSA_WITH_DES_CBC_SHA
-# 40 bit ciphers not allowed in tls 1.1
-#  noECC  TLS11   f    TLS11_RSA_EXPORT_WITH_RC4_40_MD5
-#  noECC  TLS11   g    TLS11_RSA_EXPORT_WITH_RC2_CBC_40_MD5
   noECC  TLS11   i    TLS11_RSA_WITH_NULL_MD5
-  noECC  TLS11   j    TLS11_RSA_FIPS_WITH_3DES_EDE_CBC_SHA
-  noECC  TLS11   k    TLS11_RSA_FIPS_WITH_DES_CBC_SHA
-  noECC  TLS11   l    TLS11_RSA_EXPORT_WITH_DES_CBC_SHA   (new)
-  noECC  TLS11   m    TLS11_RSA_EXPORT_WITH_RC4_56_SHA    (new)
   noECC  TLS11   n    TLS11_RSA_WITH_RC4_128_SHA
   noECC  TLS11   v    TLS11_RSA_WITH_AES_128_CBC_SHA
   noECC  TLS11   y    TLS11_RSA_WITH_AES_256_CBC_SHA
   noECC  TLS11   z    TLS11_RSA_WITH_NULL_SHA
 #
   noECC  TLS12   c    TLS12_RSA_WITH_RC4_128_MD5
   noECC  TLS12   d    TLS12_RSA_WITH_3DES_EDE_CBC_SHA
   noECC  TLS12   e    TLS12_RSA_WITH_DES_CBC_SHA
   noECC  TLS12   i    TLS12_RSA_WITH_NULL_MD5
-  noECC  TLS12   j    TLS12_RSA_FIPS_WITH_3DES_EDE_CBC_SHA
-  noECC  TLS12   k    TLS12_RSA_FIPS_WITH_DES_CBC_SHA
-# disabled because of bug 1136095
-#  noECC  TLS12   l    TLS12_RSA_EXPORT_WITH_DES_CBC_SHA   (new)
-# disabled because of bug 1136095
-#  noECC  TLS12   m    TLS12_RSA_EXPORT_WITH_RC4_56_SHA    (new)
   noECC  TLS12   n    TLS12_RSA_WITH_RC4_128_SHA
   noECC  TLS12   v    TLS12_RSA_WITH_AES_128_CBC_SHA
   noECC  TLS12   y    TLS12_RSA_WITH_AES_256_CBC_SHA
   noECC  TLS12   z    TLS12_RSA_WITH_NULL_SHA
   noECC  TLS12 :0016  TLS12_DHE_RSA_WITH_3DES_EDE_CBC_SHA
   noECC  TLS12 :0032  TLS12_DHE_DSS_WITH_AES_128_CBC_SHA
   noECC  TLS12 :0033  TLS12_DHE_RSA_WITH_AES_128_CBC_SHA
   noECC  TLS12 :0038  TLS12_DHE_DSS_WITH_AES_256_CBC_SHA