Bug 1166031 - Update NSS to NSS_3_19_1_RTM. a=2.2+
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 28 May 2015 19:33:45 -0400
changeset 238530 1ad8a7e8dcfb
parent 238529 e7b92037e967
child 238531 76bd11cf59e9
push id663
push userryanvm@gmail.com
push dateSat, 30 May 2015 17:12:11 +0000
treeherdermozilla-b2g37_v2_2@ed2f6aeb1d81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewers2
bugs1166031
milestone37.0
Bug 1166031 - Update NSS to NSS_3_19_1_RTM. a=2.2+
CLOBBER
configure.in
security/nss/TAG-INFO
security/nss/cmd/certutil/certext.c
security/nss/cmd/certutil/certutil.c
security/nss/cmd/checkcert/checkcert.c
security/nss/cmd/crlutil/crlgen.c
security/nss/cmd/lib/secutil.c
security/nss/cmd/lib/secutil.h
security/nss/cmd/modutil/install.c
security/nss/cmd/pk12util/pk12util.c
security/nss/cmd/platlibs.mk
security/nss/cmd/tstclnt/manifest.mn
security/nss/cmd/tstclnt/tstclnt.c
security/nss/coreconf/Darwin.mk
security/nss/coreconf/coreconf.dep
security/nss/coreconf/location.mk
security/nss/doc/certutil.xml
security/nss/doc/html/certutil.html
security/nss/doc/nroff/certutil.1
security/nss/external_tests/README
security/nss/external_tests/ssl_gtest/databuffer.h
security/nss/external_tests/ssl_gtest/gtest_utils.h
security/nss/external_tests/ssl_gtest/manifest.mn
security/nss/external_tests/ssl_gtest/ssl_extension_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_gtest.cc
security/nss/external_tests/ssl_gtest/ssl_loopback_unittest.cc
security/nss/external_tests/ssl_gtest/ssl_skip_unittest.cc
security/nss/external_tests/ssl_gtest/test_io.cc
security/nss/external_tests/ssl_gtest/test_io.h
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_filter.cc
security/nss/external_tests/ssl_gtest/tls_filter.h
security/nss/external_tests/ssl_gtest/tls_parser.cc
security/nss/external_tests/ssl_gtest/tls_parser.h
security/nss/lib/certdb/cert.h
security/nss/lib/certdb/certdb.c
security/nss/lib/certdb/certdb.h
security/nss/lib/certdb/certi.h
security/nss/lib/certdb/certt.h
security/nss/lib/certdb/certv3.c
security/nss/lib/certdb/crl.c
security/nss/lib/certdb/genname.c
security/nss/lib/ckfw/builtins/certdata.txt
security/nss/lib/ckfw/builtins/config.mk
security/nss/lib/ckfw/builtins/nssckbi.h
security/nss/lib/ckfw/capi/config.mk
security/nss/lib/cryptohi/keyhi.h
security/nss/lib/cryptohi/seckey.c
security/nss/lib/freebl/blapit.h
security/nss/lib/freebl/ecl/ecp_jac.c
security/nss/lib/freebl/ecl/ecp_jm.c
security/nss/lib/freebl/mpi/mpmontg.c
security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c
security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c
security/nss/lib/nss/nss.def
security/nss/lib/nss/nss.h
security/nss/lib/pk11wrap/pk11cert.c
security/nss/lib/pk11wrap/pk11pub.h
security/nss/lib/pkcs12/p12.h
security/nss/lib/pkcs12/p12d.c
security/nss/lib/pkcs12/p12local.c
security/nss/lib/pki/tdcache.c
security/nss/lib/smime/cmsmessage.c
security/nss/lib/smime/smime.def
security/nss/lib/smime/smimeutil.c
security/nss/lib/softoken/config.mk
security/nss/lib/softoken/lowpbe.c
security/nss/lib/softoken/sftkpwd.c
security/nss/lib/softoken/softkver.h
security/nss/lib/ssl/SSLerrs.h
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3ecc.c
security/nss/lib/ssl/ssl3ext.c
security/nss/lib/ssl/sslerr.h
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/sslsock.c
security/nss/lib/util/nssutil.h
security/nss/tests/all.sh
security/nss/tests/cert/cert.sh
security/nss/tests/chains/scenarios/realcerts.cfg
security/nss/tests/cipher/cipher.sh
security/nss/tests/common/init.sh
security/nss/tests/dbtests/dbtests.sh
security/nss/tests/libpkix/certs/PayPalEE.cert
security/nss/tests/libpkix/certs/PayPalICA.cert
security/nss/tests/libpkix/certs/PayPalRootCA.cert
security/nss/tests/libpkix/vfychain_test.lst
security/nss/tests/memleak/memleak.sh
security/nss/tests/ssl/sslcov.txt
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Merge day clobber
+Bug 1166031 - NSS update hit needs-clobber bustage.
--- a/configure.in
+++ b/configure.in
@@ -3614,17 +3614,17 @@ dnl = If NSS was not detected in the sys
 dnl = use the one in the source tree (mozilla/security/nss)
 dnl ========================================================
 
 MOZ_ARG_WITH_BOOL(system-nss,
 [  --with-system-nss       Use system installed NSS],
     _USE_SYSTEM_NSS=1 )
 
 if test -n "$_USE_SYSTEM_NSS"; then
-    AM_PATH_NSS(3.17.4, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
+    AM_PATH_NSS(3.19.1, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
 fi
 
 if test -n "$MOZ_NATIVE_NSS"; then
    NSS_LIBS="$NSS_LIBS -lcrmf"
 else
    NSS_CFLAGS='-I$(LIBXUL_DIST)/include/nss'
 
    if test -z "$GNU_CC" -a "$OS_ARCH" = "WINNT"; then
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-NSS_3_17_4_RTM
+NSS_3_19_1_RTM
--- a/security/nss/cmd/certutil/certext.c
+++ b/security/nss/cmd/certutil/certext.c
@@ -982,20 +982,23 @@ AddNameConstraints(void *extHandle)
         }
 
         (void) SEC_ASN1EncodeInteger(arena, &current->min, 0);
 
         if (!GetGeneralName(arena, &current->name, PR_TRUE)) {
             GEN_BREAK(SECFailure);
         }
 
-        PrintChoicesAndGetAnswer("Type of Name Constraint?\n"
+        if (PrintChoicesAndGetAnswer("Type of Name Constraint?\n"
             "\t1 - permitted\n\t2 - excluded\n\tAny"
             "other number to finish\n\tChoice",
-            buffer, sizeof(buffer));
+            buffer, sizeof(buffer)) != SECSuccess) {
+            GEN_BREAK(SECFailure);
+        }
+
         intValue = PORT_Atoi(buffer);
         switch (intValue) {
         case 1:
             if (constraints->permited == NULL) {
                 constraints->permited = last_permited = current;
             }
             last_permited->l.next = &(current->l);
             current->l.prev = &(last_permited->l);
@@ -1821,21 +1824,23 @@ AddInfoAccess(void *extHandle, PRBool ad
                     "Subject Information Access extension:\n");
                 intValue = caRepository;
             } else {
                 puts("Adding \"Time Stamping Services\" access method type for "
                     "Subject Information Access extension:\n");
                 intValue = timeStamping;
             }
         } else {
-            PrintChoicesAndGetAnswer("Enter access method type "
+            if (PrintChoicesAndGetAnswer("Enter access method type "
                 "for Authority Information Access extension:\n"
                 "\t1 - CA Issuers\n\t2 - OCSP\n\tAny"
                 "other number to finish\n\tChoice",
-                buffer, sizeof(buffer));
+                buffer, sizeof(buffer)) != SECSuccess) {
+                GEN_BREAK (SECFailure);
+            }
             intValue = PORT_Atoi(buffer);
         }
         if (addSIAExt) {
             switch (intValue) {
               case caRepository:
                   oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_REPOSITORY);
                   break;
                   
--- a/security/nss/cmd/certutil/certutil.c
+++ b/security/nss/cmd/certutil/certutil.c
@@ -35,17 +35,17 @@
 #include "secoid.h"
 #include "certdb.h"
 #include "nss.h"
 #include "certutil.h"
 
 #define MIN_KEY_BITS		512
 /* MAX_KEY_BITS should agree with MAX_RSA_MODULUS in freebl */
 #define MAX_KEY_BITS		8192
-#define DEFAULT_KEY_BITS	1024
+#define DEFAULT_KEY_BITS	2048
 
 #define GEN_BREAK(e) rv=e; break;
 
 char *progName;
 
 static CERTCertificateRequest *
 GetCertRequest(const SECItem *reqDER)
 {
@@ -175,17 +175,17 @@ AddCert(PK11SlotInfo *slot, CERTCertDBHa
     CERT_DestroyCertificate (cert);
     PORT_Free(trust);
 
     return rv;
 }
 
 static SECStatus
 CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
-        SECOidTag hashAlgTag, CERTName *subject, char *phone, int ascii, 
+        SECOidTag hashAlgTag, CERTName *subject, const char *phone, int ascii,
 	const char *emailAddrs, const char *dnsNames,
         certutilExtnList extnList, const char *extGeneric,
         /*out*/ SECItem *result)
 {
     CERTSubjectPublicKeyInfo *spki;
     CERTCertificateRequest *cr;
     SECItem *encoding;
     SECOidTag signAlgTag;
@@ -265,17 +265,17 @@ CertReq(SECKEYPrivateKey *privk, SECKEYP
 	}
 
 	name = CERT_GetCommonName(subject);
 	if (!name) {
 	    name = PORT_Strdup("(not specified)");
 	}
 
 	if (!phone)
-	    phone = strdup("(not specified)");
+	    phone = "(not specified)";
 
 	email = CERT_GetCertEmailAddress(subject);
 	if (!email)
 	    email = PORT_Strdup("(not specified)");
 
 	org = CERT_GetOrgName(subject);
 	if (!org)
 	    org = PORT_Strdup("(not specified)");
@@ -318,16 +318,17 @@ CertReq(SECKEYPrivateKey *privk, SECKEYP
 		    PORT_Memcpy(result->data + headerLen, obuf, obufLen);
 		    PORT_Memcpy(result->data + headerLen + obufLen,
 				trailer, trailerLen);
 		}
 		PR_smprintf_free(trailer);
 	    }
 	    PR_smprintf_free(header);
 	}
+	PORT_Free(obuf);
     } else {
 	(void) SECITEM_CopyItem(NULL, result, &signedReq);
     }
 
     if (!result->data) {
 oom:    SECU_PrintError(progName, "out of memory");
 	PORT_SetError(SEC_ERROR_NO_MEMORY);
 	rv = SECFailure;
--- a/security/nss/cmd/checkcert/checkcert.c
+++ b/security/nss/cmd/checkcert/checkcert.c
@@ -215,40 +215,39 @@ CERTCertificate *createEmptyCertificate(
     if (c) {
 	c->referenceCount = 1;
 	c->arena = arena;
     } else {
 	PORT_FreeArena(arena,PR_TRUE);
     }
 
     return c;
-}    
-
-
+}
 
 
 int main(int argc, char **argv)
 {
-    int rv, verbose=0, force=0;
+    int verbose=0, force=0;
     int ascii=0, issuerAscii=0;
     char *progName=0;
     PRFileDesc *inFile=0, *issuerCertFile=0;
     SECItem derCert, derIssuerCert;
     PLArenaPool *arena=0;
     CERTSignedData *signedData=0;
     CERTCertificate *cert=0, *issuerCert=0;
     SECKEYPublicKey *rsapubkey=0;
     SECAlgorithmID md5WithRSAEncryption, md2WithRSAEncryption;
     SECAlgorithmID sha1WithRSAEncryption, rsaEncryption;
     SECItem spk;
     int selfSigned=0;
     int invalid=0;
     char *inFileName = NULL, *issuerCertFileName = NULL;
     PLOptState *optstate;
     PLOptStatus status;
+    SECStatus rv;
 
     PORT_Memset(&md5WithRSAEncryption, 0, sizeof(md5WithRSAEncryption));
     PORT_Memset(&md2WithRSAEncryption, 0, sizeof(md2WithRSAEncryption));
     PORT_Memset(&sha1WithRSAEncryption, 0, sizeof(sha1WithRSAEncryption));
     PORT_Memset(&rsaEncryption, 0, sizeof(rsaEncryption));
 
     progName = strrchr(argv[0], '/');
     progName = progName ? progName+1 : argv[0];
@@ -400,27 +399,47 @@ int main(int argc, char **argv)
     }
 
 
     /* Do various checks on the cert */
 
     printf("\n");
 
     /* Check algorithms */
-    SECOID_SetAlgorithmID(arena, &md5WithRSAEncryption,
+    rv = SECOID_SetAlgorithmID(arena, &md5WithRSAEncryption,
 		       SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, NULL);
+    if (rv) {
+	fprintf(stderr, "%s: failed to set algorithm ID for SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION.\n",
+                progName);
+	exit(1);
+    }
 
-    SECOID_SetAlgorithmID(arena, &md2WithRSAEncryption,
+    rv = SECOID_SetAlgorithmID(arena, &md2WithRSAEncryption,
 		       SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION, NULL);
+    if (rv) {
+	fprintf(stderr, "%s: failed to set algorithm ID for SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION.\n",
+                progName);
+	exit(1);
+    }
 
-    SECOID_SetAlgorithmID(arena, &sha1WithRSAEncryption,
+    rv = SECOID_SetAlgorithmID(arena, &sha1WithRSAEncryption,
 		       SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, NULL);
+    if (rv) {
+	fprintf(stderr, "%s: failed to set algorithm ID for SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION.\n",
+                progName);
+	exit(1);
+    }
 
-    SECOID_SetAlgorithmID(arena, &rsaEncryption,
+    rv = SECOID_SetAlgorithmID(arena, &rsaEncryption,
 		       SEC_OID_PKCS1_RSA_ENCRYPTION, NULL);
+    if (rv) {
+	fprintf(stderr, "%s: failed to set algorithm ID for SEC_OID_PKCS1_RSA_ENCRYPTION.\n",
+                progName);
+	exit(1);
+    }
 
     {
 	int isMD5RSA = (SECOID_CompareAlgorithmID(&cert->signature,
 					       &md5WithRSAEncryption) == 0);
 	int isMD2RSA = (SECOID_CompareAlgorithmID(&cert->signature,
 					       &md2WithRSAEncryption) == 0);
 	int isSHA1RSA = (SECOID_CompareAlgorithmID(&cert->signature,
 					       &sha1WithRSAEncryption) == 0);
--- a/security/nss/cmd/crlutil/crlgen.c
+++ b/security/nss/cmd/crlutil/crlgen.c
@@ -1164,17 +1164,17 @@ crlgen_setNextDataFn_field(CRLGENGenerat
     PORT_Assert(crlGenData);
     if (!crlGenData) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
     switch (crlGenData->contextId) {
       case CRLGEN_CHANGE_RANGE_CONTEXT:
-          if (dtype != CRLGEN_TYPE_DIGIT || dtype != CRLGEN_TYPE_DIGIT_RANGE) {
+          if (dtype != CRLGEN_TYPE_DIGIT && dtype != CRLGEN_TYPE_DIGIT_RANGE) {
               crlgen_PrintError(crlGenData->parsedLineNum,
                                 "range value should have "
                                 "numeric or numeric range values.\n");
               return SECFailure;
           }
           break;
       case CRLGEN_NEXT_UPDATE_CONTEXT:
       case CRLGEN_UPDATE_CONTEXT:
--- a/security/nss/cmd/lib/secutil.c
+++ b/security/nss/cmd/lib/secutil.c
@@ -2407,16 +2407,56 @@ SECU_PrintCertificate(FILE *out, const S
 	secu_PrintDecodedBitString(out, &c->subjectID, "Subject Unique ID", level+1);
     SECU_PrintExtensions(out, c->extensions, "Signed Extensions", level+1);
 loser:
     PORT_FreeArena(arena, PR_FALSE);
     return rv;
 }
 
 int
+SECU_PrintCertificateBasicInfo(FILE *out, const SECItem *der, const char *m, int level)
+{
+    PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+    CERTCertificate *c;
+    int rv = SEC_ERROR_NO_MEMORY;
+    int iv;
+    
+    if (!arena)
+	return rv;
+
+    /* Decode certificate */
+    c = PORT_ArenaZNew(arena, CERTCertificate);
+    if (!c)
+	goto loser;
+    c->arena = arena;
+    rv = SEC_ASN1DecodeItem(arena, c, 
+                            SEC_ASN1_GET(CERT_CertificateTemplate), der);
+    if (rv) {
+        SECU_Indent(out, level); 
+	SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+	SECU_PrintAny(out, der, "Raw", level);
+	goto loser;
+    }
+    /* Pretty print it out */
+    SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+    SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level+1);
+    SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level+1);
+    SECU_PrintName(out, &c->issuer, "Issuer", level+1);
+    if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+	SECU_Newline(out);
+    secu_PrintValidity(out, &c->validity, "Validity", level+1);
+    SECU_PrintName(out, &c->subject, "Subject", level+1);
+    if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+	SECU_Newline(out);
+loser:
+    PORT_FreeArena(arena, PR_FALSE);
+    return rv;
+}
+
+int
 SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m, int level)
 {
     PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     int          rv    = SEC_ERROR_NO_MEMORY;
     CERTSubjectPublicKeyInfo spki;
 
     if (!arena)
 	return rv;
--- a/security/nss/cmd/lib/secutil.h
+++ b/security/nss/cmd/lib/secutil.h
@@ -216,16 +216,19 @@ int SECU_CheckCertNameExists(CERTCertDBH
 /* Dump contents of cert req */
 extern int SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m,
 	int level);
 
 /* Dump contents of certificate */
 extern int SECU_PrintCertificate(FILE *out, const SECItem *der, const char *m,
                                  int level);
 
+extern int SECU_PrintCertificateBasicInfo(FILE *out, const SECItem *der, const char *m,
+                                 int level);
+
 extern int SECU_PrintDumpDerIssuerAndSerial(FILE *out, SECItem *der, char *m,
                                  int level);
 
 /* Dump contents of a DER certificate name (issuer or subject) */
 extern int SECU_PrintDERName(FILE *out, SECItem *der, const char *m, int level);
 
 /* print trust flags on a cert */
 extern void SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, 
--- a/security/nss/cmd/modutil/install.c
+++ b/security/nss/cmd/modutil/install.c
@@ -115,19 +115,20 @@ static char *msgStrings[] = {
 typedef struct StringNode_str {
     char *str;
     struct StringNode_str* next;
 } StringNode;
 
 StringNode* StringNode_new()
 {
 	StringNode* new_this;
-	new_this = (StringNode*)malloc(sizeof(StringNode));
-  new_this->str=NULL;
-  new_this->next=NULL;
+	new_this = (StringNode*)PR_Malloc(sizeof(StringNode));
+	PORT_Assert(new_this != NULL);
+	new_this->str = NULL;
+	new_this->next = NULL;
 	return new_this;
 }
 
 void StringNode_delete(StringNode* s) 
 {
 	if(s->str) {
 		PR_Free(s->str);
 		s->str=NULL;
--- a/security/nss/cmd/pk12util/pk12util.c
+++ b/security/nss/cmd/pk12util/pk12util.c
@@ -40,17 +40,17 @@ Usage(char *progName)
     FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n");
     FPS "\t\t [-v]\n");
 
     FPS "Usage:	 %s -o exportfile -n certname [-d certdir] [-P dbprefix]\n",
 		progName);
     FPS "\t\t [-c key_cipher] [-C cert_cipher]\n"
         "\t\t [-m | --key_len keyLen] [--cert_key_len certKeyLen] [-v]\n");
     FPS "\t\t [-k slotpwfile | -K slotpw]\n"
-		"\t\t [-w p12filepwfile | -W p12filefilepw]\n");
+        "\t\t [-w p12filepwfile | -W p12filepw]\n");
 
     exit(PK12UERR_USAGE);
 }
 
 static PRBool
 p12u_OpenFile(p12uContext *p12cxt, PRBool fileRead)
 {
     if(!p12cxt || !p12cxt->filename) {
@@ -96,19 +96,16 @@ p12u_DestroyContext(p12uContext **ppCtx,
     PR_Free(*ppCtx);
     *ppCtx = NULL;
 }
 
 static p12uContext *
 p12u_InitContext(PRBool fileImport, char *filename)
 {
     p12uContext *p12cxt;
-    PRBool fileExist;
-
-    fileExist = fileImport;
 
     p12cxt = PORT_ZNew(p12uContext);
     if(!p12cxt) {
 	return NULL;
     }
 
     p12cxt->error = PR_FALSE;
     p12cxt->errorValue = 0;
--- a/security/nss/cmd/platlibs.mk
+++ b/security/nss/cmd/platlibs.mk
@@ -82,18 +82,18 @@ EXTRA_LIBS += \
 	$(DIST)/lib/$(LIB_PREFIX)certdb.$(LIB_SUFFIX) \
 	$(SOFTOKENLIB) \
 	$(CRYPTOLIB) \
 	$(DIST)/lib/$(LIB_PREFIX)nsspki.$(LIB_SUFFIX) \
 	$(DIST)/lib/$(LIB_PREFIX)nssdev.$(LIB_SUFFIX) \
 	$(DIST)/lib/$(LIB_PREFIX)nssb.$(LIB_SUFFIX) \
 	$(PKIXLIB) \
 	$(DBMLIB) \
-	$(DIST)/lib/$(LIB_PREFIX)$(SQLITE_LIB_NAME).$(LIB_SUFFIX) \
-	$(DIST)/lib/$(LIB_PREFIX)nssutil3.$(LIB_SUFFIX) \
+	$(SQLITE_LIB_DIR)/$(LIB_PREFIX)$(SQLITE_LIB_NAME).$(LIB_SUFFIX) \
+	$(NSSUTIL_LIB_DIR)/$(LIB_PREFIX)nssutil3.$(LIB_SUFFIX) \
 	$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.$(LIB_SUFFIX) \
 	$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.$(LIB_SUFFIX) \
 	$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.$(LIB_SUFFIX) \
 	$(NULL)
 
 # $(PROGRAM) has NO explicit dependencies on $(OS_LIBS)
 #OS_LIBS += \
 	wsock32.lib \
@@ -130,17 +130,17 @@ EXTRA_LIBS += \
 
 ifeq ($(OS_ARCH), AIX) 
 EXTRA_SHARED_LIBS += -brtl 
 endif
 
 # $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
 # $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
 EXTRA_SHARED_LIBS += \
-	-L$(DIST)/lib \
+	-L$(SQLITE_LIB_DIR) \
 	-l$(SQLITE_LIB_NAME) \
 	-L$(NSSUTIL_LIB_DIR) \
 	-lnssutil3 \
 	-L$(NSPR_LIB_DIR) \
 	-lplc4 \
 	-lplds4 \
 	-lnspr4 \
 	$(NULL)
@@ -148,17 +148,17 @@ endif
 
 else # USE_STATIC_LIBS
 # can't do this in manifest.mn because OS_ARCH isn't defined there.
 ifeq ($(OS_ARCH), WINNT)
 
 # $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
 EXTRA_LIBS += \
 	$(DIST)/lib/$(LIB_PREFIX)sectool.$(LIB_SUFFIX) \
-	$(DIST)/lib/$(IMPORT_LIB_PREFIX)nssutil3$(IMPORT_LIB_SUFFIX) \
+	$(NSSUTIL_LIB_DIR)/$(IMPORT_LIB_PREFIX)nssutil3$(IMPORT_LIB_SUFFIX) \
 	$(DIST)/lib/$(IMPORT_LIB_PREFIX)smime3$(IMPORT_LIB_SUFFIX) \
 	$(DIST)/lib/$(IMPORT_LIB_PREFIX)ssl3$(IMPORT_LIB_SUFFIX) \
 	$(DIST)/lib/$(IMPORT_LIB_PREFIX)nss3$(IMPORT_LIB_SUFFIX) \
 	$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4$(IMPORT_LIB_SUFFIX) \
 	$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4$(IMPORT_LIB_SUFFIX) \
 	$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4$(IMPORT_LIB_SUFFIX) \
 	$(NULL)
 
--- a/security/nss/cmd/tstclnt/manifest.mn
+++ b/security/nss/cmd/tstclnt/manifest.mn
@@ -12,11 +12,12 @@ MODULE = nss
 # and gets translated into $LINCS in manifest.mnw
 # The MODULE is always implicitly required.
 # Listing it here in REQUIRES makes it appear twice in the cc command line.
 REQUIRES = seccmd dbm 
 
 # DIRS = 
 
 CSRCS	= tstclnt.c  
+DEFINES += -DDLL_PREFIX=\"$(DLL_PREFIX)\" -DDLL_SUFFIX=\"$(DLL_SUFFIX)\"
 
 PROGRAM	= tstclnt
 
--- a/security/nss/cmd/tstclnt/tstclnt.c
+++ b/security/nss/cmd/tstclnt/tstclnt.c
@@ -27,16 +27,17 @@
 #include "nspr.h"
 #include "prio.h"
 #include "prnetdb.h"
 #include "nss.h"
 #include "ocsp.h"
 #include "ssl.h"
 #include "sslproto.h"
 #include "pk11func.h"
+#include "secmod.h"
 #include "plgetopt.h"
 #include "plstr.h"
 
 #if defined(WIN32)
 #include <fcntl.h>
 #include <io.h>
 #endif
 
@@ -92,16 +93,17 @@ int ssl3CipherSuites[] = {
     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;
 
 static char *progName;
 
 secuPWData  pwdata          = { PW_NONE, 0 };
 
 void printSecurityInfo(PRFileDesc *fd)
@@ -174,33 +176,40 @@ handshakeCallback(PRFileDesc *fd, void *
 	++renegotiationsDone;
     }
 }
 
 static void PrintUsageHeader(const char *progName)
 {
     fprintf(stderr, 
 "Usage:  %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n"
-                    "[-d certdir] [-n nickname] [-Bafosvx] [-c ciphers] [-Y]\n"
+                    "[-D | -d certdir] [-C] [-b | -R root-module] \n"
+		    "[-n nickname] [-Bafosvx] [-c ciphers] [-Y]\n"
                     "[-V [min-version]:[max-version]] [-K] [-T]\n"
                     "[-r N] [-w passwd] [-W pwfile] [-q [-t seconds]]\n", 
             progName);
 }
 
 static void PrintParameterUsage(void)
 {
     fprintf(stderr, "%-20s Send different SNI name. 1st_hs_name - at first\n"
                     "%-20s handshake, 2nd_hs_name - at second handshake.\n"
                     "%-20s Default is host from the -h argument.\n", "-a name",
                     "", "");
     fprintf(stderr, "%-20s Hostname to connect with\n", "-h host");
     fprintf(stderr, "%-20s Port number for SSL server\n", "-p port");
     fprintf(stderr, 
             "%-20s Directory with cert database (default is ~/.netscape)\n",
 	    "-d certdir");
+    fprintf(stderr, "%-20s Run without a cert database\n", "-D");
+    fprintf(stderr, "%-20s Load the default \"builtins\" root CA module\n", "-b");
+    fprintf(stderr, "%-20s Load the given root CA module\n", "-R");
+    fprintf(stderr, "%-20s Print certificate chain information\n", "-C");
+    fprintf(stderr, "%-20s (use -C twice to print more certificate details)\n", "");
+    fprintf(stderr, "%-20s (use -C three times to include PEM format certificate dumps)\n", "");
     fprintf(stderr, "%-20s Nickname of key and cert for client auth\n", 
                     "-n nickname");
     fprintf(stderr, 
             "%-20s Bypass PKCS11 layer for SSL encryption and MACing.\n", "-B");
     fprintf(stderr, 
             "%-20s Restricts the set of enabled SSL/TLS protocols versions.\n"
             "%-20s All versions are enabled by default.\n"
             "%-20s Possible values for min/max: ssl2 ssl3 tls1.0 tls1.1 tls1.2\n"
@@ -495,22 +504,124 @@ verifyFromSideChannel(CERTCertificate *c
             EXIT_CODE_SIDECHANNELTEST_NODATA;
         return;
     }
     
     sca->sideChannelRevocationTestResultCode = 
         EXIT_CODE_SIDECHANNELTEST_REVOKED;
 }
 
+
+static void
+dumpCertificatePEM(CERTCertificate *cert)
+{
+    SECItem data;
+    data.data = cert->derCert.data;
+    data.len = cert->derCert.len;
+    fprintf(stderr, "%s\n%s\n%s\n", NS_CERT_HEADER, 
+	    BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER);
+}
+
+static void
+dumpServerCertificateChain(PRFileDesc *fd)
+{
+    CERTCertList *peerCertChain = NULL;
+    CERTCertListNode *node = NULL;
+    CERTCertificate *peerCert = NULL;
+    CERTCertificateList *foundChain = NULL;
+    SECU_PPFunc dumpFunction = NULL;
+    PRBool dumpCertPEM = PR_FALSE;
+
+    if (!dumpServerChain) {
+	return;
+    }
+    else if (dumpServerChain == 1) {
+	dumpFunction = SECU_PrintCertificateBasicInfo;
+    } else {
+	dumpFunction = SECU_PrintCertificate;
+	if (dumpServerChain > 2) {
+	    dumpCertPEM = PR_TRUE;
+	}
+    }
+
+    SECU_EnableWrap(PR_FALSE);
+
+    fprintf(stderr, "==== certificate(s) sent by server: ====\n");
+    peerCertChain = SSL_PeerCertificateChain(fd);
+    if (peerCertChain) {
+        node = CERT_LIST_HEAD(peerCertChain);
+        while ( ! CERT_LIST_END(node, peerCertChain) ) {
+            CERTCertificate *cert = node->cert;
+            SECU_PrintSignedContent(stderr, &cert->derCert, "Certificate", 0,
+                                    dumpFunction);
+	    if (dumpCertPEM) {
+		dumpCertificatePEM(cert);
+	    }
+            node = CERT_LIST_NEXT(node);   
+        }
+    }
+
+    if (peerCertChain) {
+	peerCert = SSL_RevealCert(fd);
+	if (peerCert) {
+	    foundChain = CERT_CertChainFromCert(peerCert, certificateUsageSSLServer,
+						PR_TRUE);
+	}
+	if (foundChain) {
+	    int count = 0;
+	    fprintf(stderr, "==== locally found issuer certificate(s): ====\n");
+	    for(count = 0; count < (unsigned int)foundChain->len; count++) {
+		CERTCertificate *c;
+		PRBool wasSentByServer = PR_FALSE;
+		c = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &foundChain->certs[count]);
+
+		node = CERT_LIST_HEAD(peerCertChain);
+		while ( ! CERT_LIST_END(node, peerCertChain) ) {
+		    CERTCertificate *cert = node->cert;
+		    if (CERT_CompareCerts(cert, c)) {
+			wasSentByServer = PR_TRUE;
+			break;
+		    }
+		    node = CERT_LIST_NEXT(node);   
+		}
+		
+		if (!wasSentByServer) {
+		    SECU_PrintSignedContent(stderr, &c->derCert, "Certificate", 0,
+					    dumpFunction);
+		    if (dumpCertPEM) {
+			dumpCertificatePEM(c);
+		    }
+		}
+		CERT_DestroyCertificate(c);
+	    }
+	    CERT_DestroyCertificateList(foundChain);
+	}
+	if (peerCert) {
+	    CERT_DestroyCertificate(peerCert);
+	}
+
+	CERT_DestroyCertList(peerCertChain);
+	peerCertChain = NULL;
+    }
+
+    fprintf(stderr, "==== end of certificate chain information ====\n");
+    fflush(stderr);
+}
+
 static SECStatus 
 ownAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
                        PRBool isServer)
 {
     ServerCertAuth * serverCertAuth = (ServerCertAuth *) arg;
 
+    if (dumpServerChain) {
+	dumpServerCertificateChain(fd);
+    }
+
+
     if (!serverCertAuth->shouldPause) {
         CERTCertificate *cert;
         int i;
         const SECItemArray *csa;
 
         if (!serverCertAuth->testFreshStatusFromSideChannel) {
             return SSL_AuthCertificate(serverCertAuth->dbHandle, 
                                        fd, checkSig, isServer);
@@ -823,16 +934,19 @@ int main(int argc, char **argv)
     int                headerSeparatorPtrnId = 0;
     int                error = 0;
     PRUint16           portno = 443;
     char *             hs1SniHostName = NULL;
     char *             hs2SniHostName = NULL;
     PLOptState *optstate;
     PLOptStatus optstatus;
     PRStatus prStatus;
+    PRBool openDB = PR_TRUE;
+    PRBool loadDefaultRootCAs = PR_FALSE;
+    char *rootModule = NULL;
 
     serverCertAuth.shouldPause = PR_TRUE;
     serverCertAuth.isPaused = PR_FALSE;
     serverCertAuth.dbHandle = NULL;
     serverCertAuth.testFreshStatusFromSideChannel = PR_FALSE;
     serverCertAuth.sideChannelRevocationTestResultCode = EXIT_CODE_HANDSHAKE_FAILED;
     serverCertAuth.requireDataForIntermediates = PR_FALSE;
     serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
@@ -849,27 +963,31 @@ int main(int argc, char **argv)
        if (sec > 0) {
            maxInterval = PR_SecondsToInterval(sec);
        }
     }
 
     SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions);
 
     optstate = PL_CreateOptState(argc, argv,
-                                 "46BFKM:OSTV:W:Ya:c:d:fgh:m:n:op:qr:st:uvw:xz");
+                                 "46BCDFKM:OR:STV:W:Ya:bc:d:fgh:m:n:op:qr:st:uvw:xz");
     while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
 	switch (optstate->option) {
 	  case '?':
 	  default : Usage(progName); 			break;
 
           case '4': allowIPv6 = PR_FALSE; if (!allowIPv4) Usage(progName); break;
           case '6': allowIPv4 = PR_FALSE; if (!allowIPv6) Usage(progName); break;
 
           case 'B': bypassPKCS11 = 1; 			break;
 
+          case 'C': ++dumpServerChain; 			break;
+
+          case 'D': openDB = PR_FALSE; 			break;
+
           case 'F': if (serverCertAuth.testFreshStatusFromSideChannel) {
                         /* parameter given twice or more */
                         serverCertAuth.requireDataForIntermediates = PR_TRUE;
                     }
                     serverCertAuth.testFreshStatusFromSideChannel = PR_TRUE;
                     break;
 
 	  case 'I': /* reserved for OCSP multi-stapling */ break;
@@ -890,16 +1008,18 @@ int main(int argc, char **argv)
                       case 0:
                       default:
                           serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
                           serverCertAuth.allowCRLSideChannelData = PR_TRUE;
                           break;
                     };
                     break;
 
+          case 'R': rootModule = PORT_Strdup(optstate->value); break;
+
           case 'S': skipProtoHeader = PR_TRUE;                 break;
 
           case 'T': enableCertStatus = 1;               break;
 
           case 'V': if (SECU_ParseSSLVersionRangeString(optstate->value,
                             enabledVersions, enableSSL2,
                             &enabledVersions, &enableSSL2) != SECSuccess) {
                         Usage(progName);
@@ -912,16 +1032,18 @@ int main(int argc, char **argv)
                         hs1SniHostName = PORT_Strdup(optstate->value);
                     } else if (!hs2SniHostName) {
                         hs2SniHostName =  PORT_Strdup(optstate->value);
                     } else {
                         Usage(progName);
                     }
                     break;
 
+          case 'b': loadDefaultRootCAs = PR_TRUE;                 break;
+
           case 'c': cipherString = PORT_Strdup(optstate->value); break;
 
           case 'g': enableFalseStart = 1; 		break;
 
           case 'd': certDir = PORT_Strdup(optstate->value);   break;
 
           case 'f': clientSpeaksFirst = PR_TRUE;        break;
 
@@ -967,25 +1089,37 @@ int main(int argc, char **argv)
 	}
     }
 
     PL_DestroyOptState(optstate);
 
     if (optstatus == PL_OPT_BAD)
 	Usage(progName);
 
-    if (!host || !portno) 
+    if (!host || !portno) {
+        fprintf(stderr, "%s: parameters -h and -p are mandatory\n", progName);
     	Usage(progName);
+    }
 
     if (serverCertAuth.testFreshStatusFromSideChannel
         && serverCertAuth.shouldPause) {
         fprintf(stderr, "%s: -F requires the use of -O\n", progName);
         exit(1);
     }
 
+    if (certDir && !openDB) {
+        fprintf(stderr, "%s: Cannot combine parameters -D and -d\n", progName);
+        exit(1);
+    }
+
+    if (rootModule && loadDefaultRootCAs) {
+        fprintf(stderr, "%s: Cannot combine parameters -b and -R\n", progName);
+        exit(1);
+    }
+
     PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
 
     PK11_SetPasswordFunc(SECU_GetModulePassword);
 
     status = PR_StringToNetAddr(host, &addr);
     if (status == PR_SUCCESS) {
     	addr.inet.port = PR_htons(portno);
     } else {
@@ -1068,20 +1202,36 @@ int main(int argc, char **argv)
     if (!certDir) {
         certDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
         certDir = SECU_ConfigDirectory(certDir);
     } else {
         char *certDirTmp = certDir;
         certDir = SECU_ConfigDirectory(certDirTmp);
         PORT_Free(certDirTmp);
     }
-    rv = NSS_Init(certDir);
-    if (rv != SECSuccess) {
-        SECU_PrintError(progName, "unable to open cert database");
-        return 1;
+
+    if (openDB) {
+	rv = NSS_Init(certDir);
+	if (rv != SECSuccess) {
+	    SECU_PrintError(progName, "unable to open cert database");
+	    return 1;
+	}
+    } else {
+	rv = NSS_NoDB_Init(NULL);
+	if (rv != SECSuccess) {
+	    SECU_PrintError(progName, "failed to initialize NSS");
+	    return 1;
+	}
+    }
+
+    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();
 
--- a/security/nss/coreconf/Darwin.mk
+++ b/security/nss/coreconf/Darwin.mk
@@ -111,8 +111,27 @@ 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,^,_,' > $@
 
 USE_SYSTEM_ZLIB = 1
 ZLIB_LIBS	= -lz
+
+# The system sqlite library in the latest version of Mac OS X often becomes
+# newer than the sqlite library in NSS. This may result in certain Mac OS X
+# system libraries having unresolved sqlite symbols during the shlibsign step
+# of the NSS build when we set DYLD_LIBRARY_PATH to the NSS lib directory and
+# the NSS libsqlite3.dylib is used instead of the system one. So just use the
+# system sqlite library on Mac, if it's sufficiently new.
+
+SYS_SQLITE3_VERSION_FULL := $(shell /usr/bin/sqlite3 -version | awk '{print $$1}')
+SYS_SQLITE3_VERSION_MAJOR := $(shell echo $(SYS_SQLITE3_VERSION_FULL) | awk -F. '{ print $$1 }')
+SYS_SQLITE3_VERSION_MINOR := $(shell echo $(SYS_SQLITE3_VERSION_FULL) | awk -F. '{ print $$2 }')
+
+ifeq (3,$(SYS_SQLITE3_VERSION_MAJOR))
+    ifeq (,$(filter-out 0 1 2 3 4,$(SYS_SQLITE3_VERSION_MINOR)))
+        # sqlite <= 3.4.x is too old, it doesn't provide sqlite3_file_control
+    else
+        NSS_USE_SYSTEM_SQLITE = 1
+    endif
+endif
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,8 +5,9 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
+
--- a/security/nss/coreconf/location.mk
+++ b/security/nss/coreconf/location.mk
@@ -62,13 +62,17 @@ endif
 ifdef SOFTOKEN_INCLUDE_DIR
     INCLUDES += -I$(SOFTOKEN_INCLUDE_DIR)
 endif
 
 ifndef SOFTOKEN_LIB_DIR
     SOFTOKEN_LIB_DIR = $(DIST)/lib
 endif
 
+ifndef SQLITE_LIB_DIR
+    SQLITE_LIB_DIR = $(DIST)/lib
+endif
+
 ifndef SQLITE_LIB_NAME
     SQLITE_LIB_NAME = sqlite3
 endif
 
 MK_LOCATION = included
--- a/security/nss/doc/certutil.xml
+++ b/security/nss/doc/certutil.xml
@@ -242,17 +242,17 @@ Add one or multiple extensions that cert
         <term>-f password-file</term>
         <listitem><para>Specify a file that will automatically supply the password to include in a certificate 
  or to access a certificate database. This is a plain-text file containing one password. Be sure to prevent 
  unauthorized access to this file.</para></listitem>
       </varlistentry>
 
       <varlistentry>
         <term>-g keysize</term>
-        <listitem><para>Set a key size to use when generating new public and private key pairs. The minimum is 512 bits and the maximum is 16384 bits. The default is 1024 bits. Any size between the minimum and maximum is allowed.</para></listitem>
+        <listitem><para>Set a key size to use when generating new public and private key pairs. The minimum is 512 bits and the maximum is 16384 bits. The default is 2048 bits. Any size between the minimum and maximum is allowed.</para></listitem>
       </varlistentry>
 
 
       <varlistentry>
         <term>-h tokenname</term>
         <listitem><para>Specify the name of a token to use or act on. If not specified the default token is the internal database slot.</para></listitem>
       </varlistentry>
 
--- a/security/nss/doc/html/certutil.html
+++ b/security/nss/doc/html/certutil.html
@@ -1,25 +1,25 @@
-<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>CERTUTIL</title><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="index.html" title="CERTUTIL"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">CERTUTIL</th></tr></table><hr></div><div class="refentry"><a name="certutil"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>certutil — Manage keys and certificate in both NSS databases and other NSS tokens</p></div><div class="refsynopsisdiv"><h2>Synopsis</h2><div class="cmdsynopsis"><p><code class="command">certutil</code>  [<em class="replaceable"><code>options</code></em>] [[<em class="replaceable"><code>arguments</code></em>]]</p></div></div><div class="refsection"><a name="idp47645360"></a><h2>STATUS</h2><p>This documentation is still work in progress. Please contribute to the initial review in <a class="ulink" href="https://bugzilla.mozilla.org/show_bug.cgi?id=836477" target="_top">Mozilla NSS bug 836477</a>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>CERTUTIL</title><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="index.html" title="CERTUTIL"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">CERTUTIL</th></tr></table><hr></div><div class="refentry"><a name="certutil"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>certutil — Manage keys and certificate in both NSS databases and other NSS tokens</p></div><div class="refsynopsisdiv"><h2>Synopsis</h2><div class="cmdsynopsis"><p><code class="command">certutil</code>  [<em class="replaceable"><code>options</code></em>] [[<em class="replaceable"><code>arguments</code></em>]]</p></div></div><div class="refsection"><a name="idm139713586320592"></a><h2>STATUS</h2><p>This documentation is still work in progress. Please contribute to the initial review in <a class="ulink" href="https://bugzilla.mozilla.org/show_bug.cgi?id=836477" target="_top">Mozilla NSS bug 836477</a>
     </p></div><div class="refsection"><a name="description"></a><h2>Description</h2><p>The Certificate Database Tool, <span class="command"><strong>certutil</strong></span>, is a command-line utility that can create and modify certificate and key databases. It can specifically list, generate, modify, or delete certificates, create or change the password, generate new public and private key pairs, display the contents of the key database, or delete key pairs within the key database.</p><p>Certificate issuance, part of the key and certificate management process, requires that keys and certificates be created in the key database. This document discusses certificate and key database management. For information on the security module database management, see the <span class="command"><strong>modutil</strong></span> manpage.</p></div><div class="refsection"><a name="options"></a><h2>Command Options and Arguments</h2><p>Running <span class="command"><strong>certutil</strong></span> always requires one and only one command option to specify the type of certificate operation. Each command option may take zero or more arguments. The command option <code class="option">-H</code> will list all the command options and their relevant arguments.</p><p><span class="command"><strong>Command Options</strong></span></p><div class="variablelist"><dl class="variablelist"><dt><span class="term">-A </span></dt><dd><p>Add an existing certificate to a certificate database. The certificate database should already exist; if one is not present, this command option will initialize one by default.</p></dd><dt><span class="term">-B</span></dt><dd><p>Run a series of commands from the specified batch file. This requires the <code class="option">-i</code> argument.</p></dd><dt><span class="term">-C </span></dt><dd><p>Create a new binary certificate file from a binary certificate request file. Use the <code class="option">-i</code> argument to specify the certificate request file. If this argument is not used, <span class="command"><strong>certutil</strong></span> prompts for a filename. </p></dd><dt><span class="term">-D </span></dt><dd><p>Delete a certificate from the certificate database.</p></dd><dt><span class="term">-E </span></dt><dd><p>Add an email certificate to the certificate database.</p></dd><dt><span class="term">-F</span></dt><dd><p>Delete a private key from a key database. Specify the key to delete with the -n argument. Specify the database from which to delete the key with the 
 <code class="option">-d</code> argument. Use the <code class="option">-k</code> argument to specify explicitly whether to delete a DSA, RSA, or ECC key. If you don't use the <code class="option">-k</code> argument, the option looks for an RSA key matching the specified nickname. 
 </p><p>
 When you delete keys, be sure to also remove any certificates associated with those keys from the certificate database, by using -D. Some smart cards do not let you remove a public key you have generated. In such a case, only the private key is deleted from the key pair. You can display the public key with the command certutil -K -h tokenname. </p></dd><dt><span class="term">-G </span></dt><dd><p>Generate a new public and private key pair within a key database. The key database should already exist; if one is not present, this command option will initialize one by default. Some smart cards can store only one key pair. If you create a new key pair for such a card, the previous pair is overwritten.</p></dd><dt><span class="term">-H </span></dt><dd><p>Display a list of the command options and arguments.</p></dd><dt><span class="term">-K </span></dt><dd><p>List the key ID of keys in the key database. A key ID is the modulus of the RSA key or the publicValue of the DSA key. IDs are displayed in hexadecimal ("0x" is not shown).</p></dd><dt><span class="term">-L </span></dt><dd><p>List all the certificates, or display information about a named certificate, in a certificate database.
 Use the -h tokenname argument to specify the certificate database on a particular hardware or software token.</p></dd><dt><span class="term">-M </span></dt><dd><p>Modify a certificate's trust attributes using the values of the -t argument.</p></dd><dt><span class="term">-N</span></dt><dd><p>Create new certificate and key databases.</p></dd><dt><span class="term">-O </span></dt><dd><p>Print the certificate chain.</p></dd><dt><span class="term">-R</span></dt><dd><p>Create a certificate request file that can be submitted to a Certificate Authority (CA) for processing into a finished certificate. Output defaults to standard out unless you use -o output-file argument.
 
 Use the -a argument to specify ASCII output.</p></dd><dt><span class="term">-S </span></dt><dd><p>Create an individual certificate and add it to a certificate database.</p></dd><dt><span class="term">-T </span></dt><dd><p>Reset the key database or token.</p></dd><dt><span class="term">-U </span></dt><dd><p>List all available modules or print a single named module.</p></dd><dt><span class="term">-V </span></dt><dd><p>Check the validity of a certificate and its attributes.</p></dd><dt><span class="term">-W </span></dt><dd><p>Change the password to a key database.</p></dd><dt><span class="term">--merge</span></dt><dd><p>Merge two databases into one.</p></dd><dt><span class="term">--upgrade-merge</span></dt><dd><p>Upgrade an old database and merge it into a new database. This is used to migrate legacy NSS databases (<code class="filename">cert8.db</code> and <code class="filename">key3.db</code>) into the newer SQLite databases (<code class="filename">cert9.db</code> and <code class="filename">key4.db</code>).</p></dd></dl></div><p><span class="command"><strong>Arguments</strong></span></p><p>Arguments modify a command option and are usually lower case, numbers, or symbols.</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">-a</span></dt><dd><p>Use ASCII format or allow the use of ASCII format for input or output. This formatting follows RFC 1113. 
 For certificate requests, ASCII output defaults to standard output unless redirected.</p></dd><dt><span class="term">-b validity-time</span></dt><dd><p>Specify a time at which a certificate is required to be valid. Use when checking certificate validity with the <code class="option">-V</code> option. The format of the <span class="emphasis"><em>validity-time</em></span> argument is <span class="emphasis"><em>YYMMDDHHMMSS[+HHMM|-HHMM|Z]</em></span>, which allows offsets to be set relative to the validity end time. Specifying seconds (<span class="emphasis"><em>SS</em></span>) is optional. When specifying an explicit time, use a Z at the end of the term, <span class="emphasis"><em>YYMMDDHHMMSSZ</em></span>, to close it. When specifying an offset time, use <span class="emphasis"><em>YYMMDDHHMMSS+HHMM</em></span> or <span class="emphasis"><em>YYMMDDHHMMSS-HHMM</em></span> for adding or subtracting time, respectively.
 </p><p>
 If this option is not used, the validity check defaults to the current system time.</p></dd><dt><span class="term">-c issuer</span></dt><dd><p>Identify the certificate of the CA from which a new certificate will derive its authenticity. 
  Use the exact nickname or alias of the CA certificate, or use the CA's email address. Bracket the issuer string 
  with quotation marks if it contains spaces. </p></dd><dt><span class="term">-d [prefix]directory</span></dt><dd><p>Specify the database directory containing the certificate and key database files.</p><p><span class="command"><strong>certutil</strong></span> supports two types of databases: the legacy security databases (<code class="filename">cert8.db</code>, <code class="filename">key3.db</code>, and <code class="filename">secmod.db</code>) and new SQLite databases (<code class="filename">cert9.db</code>, <code class="filename">key4.db</code>, and <code class="filename">pkcs11.txt</code>). </p><p>NSS recognizes the following prefixes:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p><span class="command"><strong>sql:</strong></span> requests the newer database</p></li><li class="listitem"><p><span class="command"><strong>dbm:</strong></span> requests the legacy database</p></li></ul></div><p>If no prefix is specified the default type is retrieved from NSS_DEFAULT_DB_TYPE. If NSS_DEFAULT_DB_TYPE is not set then <span class="command"><strong>dbm:</strong></span> is the default.</p></dd><dt><span class="term">--dump-ext-val OID </span></dt><dd><p>For single cert, print binary DER encoding of extension OID.</p></dd><dt><span class="term">-e </span></dt><dd><p>Check a certificate's signature during the process of validating a certificate.</p></dd><dt><span class="term">--email email-address</span></dt><dd><p>Specify the email address of a certificate to list. Used with the -L command option.</p></dd><dt><span class="term">--extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]... </span></dt><dd><p>
 Add one or multiple extensions that certutil cannot encode yet, by loading their encodings from external files.
            </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>OID (example): 1.2.3.4</p></li><li class="listitem"><p>critical-flag: critical or not-critical</p></li><li class="listitem"><p>filename: full path to a file containing an encoded extension</p></li></ul></div></dd><dt><span class="term">-f password-file</span></dt><dd><p>Specify a file that will automatically supply the password to include in a certificate 
  or to access a certificate database. This is a plain-text file containing one password. Be sure to prevent 
- unauthorized access to this file.</p></dd><dt><span class="term">-g keysize</span></dt><dd><p>Set a key size to use when generating new public and private key pairs. The minimum is 512 bits and the maximum is 16384 bits. The default is 1024 bits. Any size between the minimum and maximum is allowed.</p></dd><dt><span class="term">-h tokenname</span></dt><dd><p>Specify the name of a token to use or act on. If not specified the default token is the internal database slot.</p></dd><dt><span class="term">-i input_file</span></dt><dd><p>Pass an input file to the command. Depending on the command option, an input file can be a specific certificate, a certificate request file, or a batch file of commands.</p></dd><dt><span class="term">-k key-type-or-id</span></dt><dd><p>Specify the type or specific ID of a key.</p><p>
+ unauthorized access to this file.</p></dd><dt><span class="term">-g keysize</span></dt><dd><p>Set a key size to use when generating new public and private key pairs. The minimum is 512 bits and the maximum is 16384 bits. The default is 2048 bits. Any size between the minimum and maximum is allowed.</p></dd><dt><span class="term">-h tokenname</span></dt><dd><p>Specify the name of a token to use or act on. If not specified the default token is the internal database slot.</p></dd><dt><span class="term">-i input_file</span></dt><dd><p>Pass an input file to the command. Depending on the command option, an input file can be a specific certificate, a certificate request file, or a batch file of commands.</p></dd><dt><span class="term">-k key-type-or-id</span></dt><dd><p>Specify the type or specific ID of a key.</p><p>
            The valid key type options are rsa, dsa, ec, or all. The default 
            value is rsa. Specifying the type of key can avoid mistakes caused by
            duplicate nicknames. Giving a key type generates a new key pair; 
            giving the ID of an existing key reuses that key pair (which is 
            required to renew certificates).
           </p></dd><dt><span class="term">-l </span></dt><dd><p>Display detailed information when validating a certificate with the -V option.</p></dd><dt><span class="term">-m serial-number</span></dt><dd><p>Assign a unique serial number to a certificate being created. This operation should be performed by a CA. If no serial number is provided a default serial number is made from the current time. Serial numbers are limited to integers </p></dd><dt><span class="term">-n nickname</span></dt><dd><p>Specify the nickname of a certificate or key to list, create, add to a database, modify, or validate. Bracket the nickname string with quotation marks if it contains spaces.</p></dd><dt><span class="term">-o output-file</span></dt><dd><p>Specify the output file name for new certificates or binary certificate requests. Bracket the output-file string with quotation marks if it contains spaces. If this argument is not used the output destination defaults to standard output.</p></dd><dt><span class="term">-P dbPrefix</span></dt><dd><p>Specify the prefix used on the certificate and key database file. This argument is provided to support legacy servers. Most applications do not use a database prefix.</p></dd><dt><span class="term">-p phone</span></dt><dd><p>Specify a contact telephone number to include in new certificates or certificate requests. Bracket this string with quotation marks if it contains spaces.</p></dd><dt><span class="term">-q pqgfile or curve-name</span></dt><dd><p>Read an alternate PQG value from the specified file when generating DSA key pairs. If this argument is not used, <span class="command"><strong>certutil</strong></span> generates its own PQG value. PQG files are created with a separate DSA utility.</p><p>Elliptic curve name is one of the ones from SUITE B: nistp256, nistp384, nistp521</p><p>
            If NSS has been compiled with support curves outside of SUITE B:
               sect163k1, nistk163, sect163r1, sect163r2,            
--- a/security/nss/doc/nroff/certutil.1
+++ b/security/nss/doc/nroff/certutil.1
@@ -1,18 +1,18 @@
 '\" t
 .\"     Title: CERTUTIL
 .\"    Author: [see the "Authors" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date:  7 January 2015
+.\"      Date: 23 February 2015
 .\"    Manual: NSS Security Tools
 .\"    Source: nss-tools
 .\"  Language: English
 .\"
-.TH "CERTUTIL" "1" "7 January 2015" "nss-tools" "NSS Security Tools"
+.TH "CERTUTIL" "1" "23 February 2015" "nss-tools" "NSS Security Tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
 .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 .\" http://bugs.debian.org/507673
 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
 .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 .ie \n(.g .ds Aq \(aq
@@ -305,17 +305,17 @@ filename: full path to a file containing
 .PP
 \-f password\-file
 .RS 4
 Specify a file that will automatically supply the password to include in a certificate or to access a certificate database\&. This is a plain\-text file containing one password\&. Be sure to prevent unauthorized access to this file\&.
 .RE
 .PP
 \-g keysize
 .RS 4
-Set a key size to use when generating new public and private key pairs\&. The minimum is 512 bits and the maximum is 16384 bits\&. The default is 1024 bits\&. Any size between the minimum and maximum is allowed\&.
+Set a key size to use when generating new public and private key pairs\&. The minimum is 512 bits and the maximum is 16384 bits\&. The default is 2048 bits\&. Any size between the minimum and maximum is allowed\&.
 .RE
 .PP
 \-h tokenname
 .RS 4
 Specify the name of a token to use or act on\&. If not specified the default token is the internal database slot\&.
 .RE
 .PP
 \-i input_file
--- a/security/nss/external_tests/README
+++ b/security/nss/external_tests/README
@@ -16,16 +16,16 @@ work do:
 
 This will run the certutil tests (generating a test db) and
 will finalize with a call to the ssl_gtest
 
 You should be able to run the unit tests manually as:
 
   ssl_gtest -d ${SSLGTESTDIR}
 
-Where $SSLGTESTDIR the directory created by ./all.sh or a manually
-created directory with a database containing a certificate called
-server (with its private keys)
+Where $SSLGTESTDIR is a directory with a database containing:
+ - an RSA certificate called server (with its private key)
+ - an ECDSA certificate called ecdsa (with its private key)
 
+A directory like this is created by ./all.sh and can be found
+in a directory named something like
 
-There is a very trivial set of tests that demonstrate some
-of the features.
-
+  tests_results/security/${hostname}.${NUMBER}/ssl_gtests
--- a/security/nss/external_tests/ssl_gtest/databuffer.h
+++ b/security/nss/external_tests/ssl_gtest/databuffer.h
@@ -2,38 +2,147 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef databuffer_h__
 #define databuffer_h__
 
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <iomanip>
+#include <iostream>
+
+namespace nss_test {
+
 class DataBuffer {
  public:
   DataBuffer() : data_(nullptr), len_(0) {}
   DataBuffer(const uint8_t *data, size_t len) : data_(nullptr), len_(0) {
     Assign(data, len);
   }
+  explicit DataBuffer(const DataBuffer& other) : data_(nullptr), len_(0) {
+    Assign(other.data(), other.len());
+  }
   ~DataBuffer() { delete[] data_; }
 
-  void Assign(const uint8_t *data, size_t len) {
-    Allocate(len);
-    memcpy(static_cast<void *>(data_), static_cast<const void *>(data), len);
+  DataBuffer& operator=(const DataBuffer& other) {
+    if (&other != this) {
+      Assign(other.data(), other.len());
+    }
+    return *this;
   }
 
   void Allocate(size_t len) {
     delete[] data_;
-    data_ = new unsigned char[len ? len : 1];  // Don't depend on new [0].
+    data_ = new uint8_t[len ? len : 1];  // Don't depend on new [0].
     len_ = len;
   }
 
+  void Truncate(size_t len) {
+    len_ = std::min(len_, len);
+  }
+
+  void Assign(const uint8_t* data, size_t len) {
+    Allocate(len);
+    memcpy(static_cast<void *>(data_), static_cast<const void *>(data), len);
+  }
+
+  // Write will do a new allocation and expand the size of the buffer if needed.
+  void Write(size_t index, const uint8_t* val, size_t count) {
+    if (index + count > len_) {
+      size_t newlen = index + count;
+      uint8_t* tmp = new uint8_t[newlen]; // Always > 0.
+      memcpy(static_cast<void*>(tmp),
+             static_cast<const void*>(data_), len_);
+      if (index > len_) {
+        memset(static_cast<void*>(tmp + len_), 0, index - len_);
+      }
+      delete[] data_;
+      data_ = tmp;
+      len_ = newlen;
+    }
+    memcpy(static_cast<void*>(data_ + index),
+           static_cast<const void*>(val), count);
+  }
+
+  void Write(size_t index, const DataBuffer& buf) {
+    Write(index, buf.data(), buf.len());
+  }
+
+  // Write an integer, also performing host-to-network order conversion.
+  void Write(size_t index, uint32_t val, size_t count) {
+    assert(count <= sizeof(uint32_t));
+    uint32_t nvalue = htonl(val);
+    auto* addr = reinterpret_cast<const uint8_t*>(&nvalue);
+    Write(index, addr + sizeof(uint32_t) - count, count);
+  }
+
+  // Starting at |index|, remove |remove| bytes and replace them with the
+  // contents of |buf|.
+  void Splice(const DataBuffer& buf, size_t index, size_t remove = 0) {
+    Splice(buf.data(), buf.len(), index, remove);
+  }
+
+  void Splice(const uint8_t* ins, size_t ins_len, size_t index, size_t remove = 0) {
+    uint8_t* old_value = data_;
+    size_t old_len = len_;
+
+    // The amount of stuff remaining from the tail of the old.
+    size_t tail_len = old_len - std::min(old_len, index + remove);
+    // The new length: the head of the old, the new, and the tail of the old.
+    len_ = index + ins_len + tail_len;
+    data_ = new uint8_t[len_ ? len_ : 1];
+
+    // The head of the old.
+    Write(0, old_value, std::min(old_len, index));
+    // Maybe a gap.
+    if (index > old_len) {
+      memset(old_value + index, 0, index - old_len);
+    }
+    // The new.
+    Write(index, ins, ins_len);
+    // The tail of the old.
+    if (tail_len > 0) {
+      Write(index + ins_len,
+            old_value + index + remove, tail_len);
+    }
+
+    delete[] old_value;
+  }
+
+  void Append(const DataBuffer& buf) { Splice(buf, len_); }
+
   const uint8_t *data() const { return data_; }
-  uint8_t *data() { return data_; }
+  uint8_t* data() { return data_; }
   size_t len() const { return len_; }
-  const bool empty() const { return len_ != 0; }
+  bool empty() const { return len_ == 0; }
 
  private:
-  uint8_t *data_;
+  uint8_t* data_;
   size_t len_;
 };
 
+#ifdef DEBUG
+static const size_t kMaxBufferPrint = 10000;
+#else
+static const size_t kMaxBufferPrint = 32;
 #endif
+
+inline std::ostream& operator<<(std::ostream& stream, const DataBuffer& buf) {
+  stream << "[" << buf.len() << "] ";
+  for (size_t i = 0; i < buf.len(); ++i) {
+    if (i >= kMaxBufferPrint) {
+      stream << "...";
+      break;
+    }
+    stream << std::hex << std::setfill('0') << std::setw(2)
+           << static_cast<unsigned>(buf.data()[i]);
+  }
+  stream << std::dec;
+  return stream;
+}
+
+} // namespace nss_test
+
+#endif
--- a/security/nss/external_tests/ssl_gtest/gtest_utils.h
+++ b/security/nss/external_tests/ssl_gtest/gtest_utils.h
@@ -2,25 +2,32 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef gtest_utils_h__
 #define gtest_utils_h__
 
+#define GTEST_HAS_RTTI 0
+#include "gtest/gtest.h"
+#include "test_io.h"
+
 namespace nss_test {
 
 // Gtest utilities
 class Timeout : public PollTarget {
  public:
   Timeout(int32_t timer_ms) : handle_(nullptr), timed_out_(false) {
     Poller::Instance()->SetTimer(timer_ms, this, &Timeout::ExpiredCallback,
                                  &handle_);
   }
+  ~Timeout() {
+    Cancel();
+  }
 
   static void ExpiredCallback(PollTarget* target, Event event) {
     Timeout* timeout = static_cast<Timeout*>(target);
     timeout->timed_out_ = true;
   }
 
   void Cancel() { handle_->Cancel(); }
 
--- a/security/nss/external_tests/ssl_gtest/manifest.mn
+++ b/security/nss/external_tests/ssl_gtest/manifest.mn
@@ -1,20 +1,25 @@
-# 
+#
 # 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 = ../..
 DEPTH      = ../..
 MODULE = nss
 
 CPPSRCS = \
       ssl_loopback_unittest.cc \
+      ssl_extension_unittest.cc \
+      ssl_skip_unittest.cc \
       ssl_gtest.cc \
       test_io.cc \
+      tls_agent.cc \
+      tls_connect.cc \
+      tls_filter.cc \
       tls_parser.cc \
       $(NULL)
 
 INCLUDES += -I$(CORE_DEPTH)/external_tests/google_test/gtest/include
 
 REQUIRES = nspr nss libdbm gtest
 
 PROGRAM = ssl_gtest
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/ssl_extension_unittest.cc
@@ -0,0 +1,578 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ssl.h"
+#include "sslproto.h"
+
+#include <memory>
+
+#include "tls_parser.h"
+#include "tls_filter.h"
+#include "tls_connect.h"
+
+namespace nss_test {
+
+class TlsExtensionFilter : public TlsHandshakeFilter {
+ protected:
+  virtual bool FilterHandshake(uint16_t version, uint8_t handshake_type,
+                               const DataBuffer& input, DataBuffer* output) {
+    if (handshake_type == kTlsHandshakeClientHello) {
+      TlsParser parser(input);
+      if (!FindClientHelloExtensions(parser, version)) {
+        return false;
+      }
+      return FilterExtensions(parser, input, output);
+    }
+    if (handshake_type == kTlsHandshakeServerHello) {
+      TlsParser parser(input);
+      if (!FindServerHelloExtensions(parser, version)) {
+        return false;
+      }
+      return FilterExtensions(parser, input, output);
+    }
+    return false;
+  }
+
+  virtual bool FilterExtension(uint16_t extension_type,
+                               const DataBuffer& input, DataBuffer* output) = 0;
+
+ public:
+  static bool FindClientHelloExtensions(TlsParser& parser, uint16_t version) {
+    if (!parser.Skip(2 + 32)) { // version + random
+      return false;
+    }
+    if (!parser.SkipVariable(1)) { // session ID
+      return false;
+    }
+    if (IsDtls(version) && !parser.SkipVariable(1)) { // DTLS cookie
+      return false;
+    }
+    if (!parser.SkipVariable(2)) { // cipher suites
+      return false;
+    }
+    if (!parser.SkipVariable(1)) { // compression methods
+      return false;
+    }
+    return true;
+  }
+
+  static bool FindServerHelloExtensions(TlsParser& parser, uint16_t version) {
+    if (!parser.Skip(2 + 32)) { // version + random
+      return false;
+    }
+    if (!parser.SkipVariable(1)) { // session ID
+      return false;
+    }
+    if (!parser.Skip(2)) { // cipher suite
+      return false;
+    }
+    if (NormalizeTlsVersion(version) <= SSL_LIBRARY_VERSION_TLS_1_2) {
+      if (!parser.Skip(1)) { // compression method
+        return false;
+      }
+    }
+    return true;
+  }
+
+ private:
+  bool FilterExtensions(TlsParser& parser,
+                        const DataBuffer& input, DataBuffer* output) {
+    size_t length_offset = parser.consumed();
+    uint32_t all_extensions;
+    if (!parser.Read(&all_extensions, 2)) {
+      return false; // no extensions, odd but OK
+    }
+    if (all_extensions != parser.remaining()) {
+      return false; // malformed
+    }
+
+    bool changed = false;
+
+    // Write out the start of the message.
+    output->Allocate(input.len());
+    output->Write(0, input.data(), parser.consumed());
+    size_t output_offset = parser.consumed();
+
+    while (parser.remaining()) {
+      uint32_t extension_type;
+      if (!parser.Read(&extension_type, 2)) {
+        return false; // malformed
+      }
+
+      // Copy extension type.
+      output->Write(output_offset, extension_type, 2);
+
+      DataBuffer extension;
+      if (!parser.ReadVariable(&extension, 2)) {
+        return false; // malformed
+      }
+      output_offset = ApplyFilter(static_cast<uint16_t>(extension_type), extension,
+                                  output, output_offset + 2, &changed);
+    }
+    output->Truncate(output_offset);
+
+    if (changed) {
+      size_t newlen = output->len() - length_offset - 2;
+      if (newlen >= 0x10000) {
+        return false; // bad: size increased too much
+      }
+      output->Write(length_offset, newlen, 2);
+    }
+    return changed;
+  }
+
+  size_t ApplyFilter(uint16_t extension_type, const DataBuffer& extension,
+                     DataBuffer* output, size_t offset, bool* changed) {
+    const DataBuffer* source = &extension;
+    DataBuffer filtered;
+    if (FilterExtension(extension_type, extension, &filtered) &&
+        filtered.len() < 0x10000) {
+      *changed = true;
+      std::cerr << "extension old: " << extension << std::endl;
+      std::cerr << "extension new: " << filtered << std::endl;
+      source = &filtered;
+    }
+
+    output->Write(offset, source->len(), 2);
+    output->Write(offset + 2, *source);
+    return offset + 2 + source->len();
+  }
+};
+
+class TlsExtensionTruncator : public TlsExtensionFilter {
+ public:
+  TlsExtensionTruncator(uint16_t extension, size_t length)
+      : extension_(extension), length_(length) {}
+  virtual bool FilterExtension(uint16_t extension_type,
+                               const DataBuffer& input, DataBuffer* output) {
+    if (extension_type != extension_) {
+      return false;
+    }
+    if (input.len() <= length_) {
+      return false;
+    }
+
+    output->Assign(input.data(), length_);
+    return true;
+  }
+ private:
+    uint16_t extension_;
+    size_t length_;
+};
+
+class TlsExtensionDamager : public TlsExtensionFilter {
+ public:
+  TlsExtensionDamager(uint16_t extension, size_t index)
+      : extension_(extension), index_(index) {}
+  virtual bool FilterExtension(uint16_t extension_type,
+                               const DataBuffer& input, DataBuffer* output) {
+    if (extension_type != extension_) {
+      return false;
+    }
+
+    *output = input;
+    output->data()[index_] += 73; // Increment selected for maximum damage
+    return true;
+  }
+ private:
+  uint16_t extension_;
+  size_t index_;
+};
+
+class TlsExtensionReplacer : public TlsExtensionFilter {
+ public:
+  TlsExtensionReplacer(uint16_t extension, const DataBuffer& data)
+      : extension_(extension), data_(data) {}
+  virtual bool FilterExtension(uint16_t extension_type,
+                               const DataBuffer& input, DataBuffer* output) {
+    if (extension_type != extension_) {
+      return false;
+    }
+
+    *output = data_;
+    return true;
+  }
+ private:
+  uint16_t extension_;
+  DataBuffer data_;
+};
+
+class TlsExtensionInjector : public TlsHandshakeFilter {
+ public:
+  TlsExtensionInjector(uint16_t ext, DataBuffer& data)
+      : extension_(ext), data_(data) {}
+
+  virtual bool FilterHandshake(uint16_t version, uint8_t handshake_type,
+                               const DataBuffer& input, DataBuffer* output) {
+    size_t offset;
+    if (handshake_type == kTlsHandshakeClientHello) {
+      TlsParser parser(input);
+      if (!TlsExtensionFilter::FindClientHelloExtensions(parser, version)) {
+        return false;
+      }
+      offset = parser.consumed();
+    } else if (handshake_type == kTlsHandshakeServerHello) {
+      TlsParser parser(input);
+      if (!TlsExtensionFilter::FindServerHelloExtensions(parser, version)) {
+        return false;
+      }
+      offset = parser.consumed();
+    } else {
+      return false;
+    }
+
+    *output = input;
+
+    std::cerr << "Pre:" << input << std::endl;
+    std::cerr << "Lof:" << offset << std::endl;
+
+    // Increase the size of the extensions.
+    uint16_t* len_addr = reinterpret_cast<uint16_t*>(output->data() + offset);
+    std::cerr << "L-p:" << ntohs(*len_addr) << std::endl;
+    *len_addr = htons(ntohs(*len_addr) + data_.len() + 4);
+    std::cerr << "L-i:" << ntohs(*len_addr) << std::endl;
+
+
+    // Insert the extension type and length.
+    DataBuffer type_length;
+    type_length.Allocate(4);
+    type_length.Write(0, extension_, 2);
+    type_length.Write(2, data_.len(), 2);
+    output->Splice(type_length, offset + 2);
+
+    // Insert the payload.
+    output->Splice(data_, offset + 6);
+
+    std::cerr << "Aft:" << *output << std::endl;
+    return true;
+  }
+
+ private:
+  uint16_t extension_;
+  DataBuffer data_;
+};
+
+class TlsExtensionTestBase : public TlsConnectTestBase {
+ protected:
+  TlsExtensionTestBase(Mode mode, uint16_t version)
+    : TlsConnectTestBase(mode, version) {}
+
+  void ClientHelloErrorTest(PacketFilter* filter,
+                            uint8_t alert = kTlsAlertDecodeError) {
+    auto alert_recorder = new TlsAlertRecorder();
+    server_->SetPacketFilter(alert_recorder);
+    if (filter) {
+      client_->SetPacketFilter(filter);
+    }
+    ConnectExpectFail();
+    EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
+    EXPECT_EQ(alert, alert_recorder->description());
+  }
+
+  void ServerHelloErrorTest(PacketFilter* filter,
+                            uint8_t alert = kTlsAlertDecodeError) {
+    auto alert_recorder = new TlsAlertRecorder();
+    client_->SetPacketFilter(alert_recorder);
+    if (filter) {
+      server_->SetPacketFilter(filter);
+    }
+    ConnectExpectFail();
+    EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
+    EXPECT_EQ(alert, alert_recorder->description());
+  }
+
+  static void InitSimpleSni(DataBuffer* extension) {
+    const char* name = "host.name";
+    const size_t namelen = PL_strlen(name);
+    extension->Allocate(namelen + 5);
+    extension->Write(0, namelen + 3, 2);
+    extension->Write(2, static_cast<uint32_t>(0), 1); // 0 == hostname
+    extension->Write(3, namelen, 2);
+    extension->Write(5, reinterpret_cast<const uint8_t*>(name), namelen);
+  }
+};
+
+class TlsExtensionTestDtls
+  : public TlsExtensionTestBase,
+    public ::testing::WithParamInterface<uint16_t> {
+ public:
+  TlsExtensionTestDtls() : TlsExtensionTestBase(DGRAM, GetParam()) {}
+};
+
+class TlsExtensionTest12Plus
+  : public TlsExtensionTestBase,
+    public ::testing::WithParamInterface<std::string> {
+ public:
+  TlsExtensionTest12Plus()
+    : TlsExtensionTestBase(TlsConnectTestBase::ToMode(GetParam()),
+                           SSL_LIBRARY_VERSION_TLS_1_2) {}
+};
+
+class TlsExtensionTestGeneric
+  : public TlsExtensionTestBase,
+    public ::testing::WithParamInterface<std::tuple<std::string, uint16_t>> {
+ public:
+  TlsExtensionTestGeneric()
+    : TlsExtensionTestBase(TlsConnectTestBase::ToMode((std::get<0>(GetParam()))),
+                           std::get<1>(GetParam())) {}
+};
+
+TEST_P(TlsExtensionTestGeneric, DamageSniLength) {
+  ClientHelloErrorTest(new TlsExtensionDamager(ssl_server_name_xtn, 1));
+}
+
+TEST_P(TlsExtensionTestGeneric, DamageSniHostLength) {
+  ClientHelloErrorTest(new TlsExtensionDamager(ssl_server_name_xtn, 4));
+}
+
+TEST_P(TlsExtensionTestGeneric, TruncateSni) {
+  ClientHelloErrorTest(new TlsExtensionTruncator(ssl_server_name_xtn, 7));
+}
+
+// A valid extension that appears twice will be reported as unsupported.
+TEST_P(TlsExtensionTestGeneric, RepeatSni) {
+  DataBuffer extension;
+  InitSimpleSni(&extension);
+  ClientHelloErrorTest(new TlsExtensionInjector(ssl_server_name_xtn, extension),
+                       kTlsAlertIllegalParameter);
+}
+
+// An SNI entry with zero length is considered invalid (strangely, not if it is
+// the last entry, which is probably a bug).
+TEST_P(TlsExtensionTestGeneric, BadSni) {
+  DataBuffer simple;
+  InitSimpleSni(&simple);
+  DataBuffer extension;
+  extension.Allocate(simple.len() + 3);
+  extension.Write(0, static_cast<uint32_t>(0), 3);
+  extension.Write(3, simple);
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_server_name_xtn, extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, EmptyAlpnExtension) {
+  EnableAlpn();
+  DataBuffer extension;
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_app_layer_protocol_xtn, extension),
+                       kTlsAlertIllegalParameter);
+}
+
+// An empty ALPN isn't considered bad, though it does lead to there being no
+// protocol for the server to select.
+TEST_P(TlsExtensionTestGeneric, EmptyAlpnList) {
+  EnableAlpn();
+  const uint8_t val[] = { 0x00, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_app_layer_protocol_xtn, extension),
+                       kTlsAlertNoApplicationProtocol);
+}
+
+TEST_P(TlsExtensionTestGeneric, OneByteAlpn) {
+  EnableAlpn();
+  ClientHelloErrorTest(new TlsExtensionTruncator(ssl_app_layer_protocol_xtn, 1));
+}
+
+TEST_P(TlsExtensionTestGeneric, AlpnMissingValue) {
+  EnableAlpn();
+  // This will leave the length of the second entry, but no value.
+  ClientHelloErrorTest(new TlsExtensionTruncator(ssl_app_layer_protocol_xtn, 5));
+}
+
+TEST_P(TlsExtensionTestGeneric, AlpnZeroLength) {
+  EnableAlpn();
+  const uint8_t val[] = { 0x01, 0x61, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_app_layer_protocol_xtn, extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, AlpnMismatch) {
+  const uint8_t client_alpn[] = { 0x01, 0x61 };
+  client_->EnableAlpn(client_alpn, sizeof(client_alpn));
+  const uint8_t server_alpn[] = { 0x02, 0x61, 0x62 };
+  server_->EnableAlpn(server_alpn, sizeof(server_alpn));
+
+  ClientHelloErrorTest(nullptr, kTlsAlertNoApplicationProtocol);
+}
+
+TEST_P(TlsExtensionTestGeneric, AlpnReturnedEmptyList) {
+  EnableAlpn();
+  const uint8_t val[] = { 0x00, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ServerHelloErrorTest(new TlsExtensionReplacer(ssl_app_layer_protocol_xtn, extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, AlpnReturnedEmptyName) {
+  EnableAlpn();
+  const uint8_t val[] = { 0x00, 0x01, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ServerHelloErrorTest(new TlsExtensionReplacer(ssl_app_layer_protocol_xtn, extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, AlpnReturnedListTrailingData) {
+  EnableAlpn();
+  const uint8_t val[] = { 0x00, 0x02, 0x01, 0x61, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ServerHelloErrorTest(new TlsExtensionReplacer(ssl_app_layer_protocol_xtn, extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, AlpnReturnedExtraEntry) {
+  EnableAlpn();
+  const uint8_t val[] = { 0x00, 0x04, 0x01, 0x61, 0x01, 0x62 };
+  DataBuffer extension(val, sizeof(val));
+  ServerHelloErrorTest(new TlsExtensionReplacer(ssl_app_layer_protocol_xtn, extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, AlpnReturnedBadListLength) {
+  EnableAlpn();
+  const uint8_t val[] = { 0x00, 0x99, 0x01, 0x61, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ServerHelloErrorTest(new TlsExtensionReplacer(ssl_app_layer_protocol_xtn, extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, AlpnReturnedBadNameLength) {
+  EnableAlpn();
+  const uint8_t val[] = { 0x00, 0x02, 0x99, 0x61 };
+  DataBuffer extension(val, sizeof(val));
+  ServerHelloErrorTest(new TlsExtensionReplacer(ssl_app_layer_protocol_xtn, extension));
+}
+
+TEST_P(TlsExtensionTestDtls, SrtpShort) {
+  EnableSrtp();
+  ClientHelloErrorTest(new TlsExtensionTruncator(ssl_use_srtp_xtn, 3));
+}
+
+TEST_P(TlsExtensionTestDtls, SrtpOdd) {
+  EnableSrtp();
+  const uint8_t val[] = { 0x00, 0x01, 0xff, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_use_srtp_xtn, extension));
+}
+
+TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsBadLength) {
+  const uint8_t val[] = { 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_signature_algorithms_xtn,
+                                                extension));
+}
+
+TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsTrailingData) {
+  const uint8_t val[] = { 0x00, 0x02, 0x04, 0x01, 0x00 }; // sha-256, rsa
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_signature_algorithms_xtn,
+                                                extension));
+}
+
+TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsEmpty) {
+  const uint8_t val[] = { 0x00, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_signature_algorithms_xtn,
+                                                extension));
+}
+
+TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsOddLength) {
+  const uint8_t val[] = { 0x00, 0x01, 0x04 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_signature_algorithms_xtn,
+                                                extension));
+}
+
+// The extension handling ignores unsupported hashes, so breaking that has no
+// effect on success rates.  However, ssl3_SendServerKeyExchange catches an
+// unsupported signature algorithm.
+
+// This actually fails with a decryption error (fatal alert 51).  That's a bad
+// to fail, since any tampering with the handshake will trigger that alert when
+// verifying the Finished message.  Thus, this test is disabled until this error
+// is turned into an alert.
+TEST_P(TlsExtensionTest12Plus, DISABLED_SignatureAlgorithmsSigUnsupported) {
+  const uint8_t val[] = { 0x00, 0x02, 0x04, 0x99 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_signature_algorithms_xtn,
+                                                extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, SupportedCurvesShort) {
+  EnableSomeEcdheCiphers();
+  const uint8_t val[] = { 0x00, 0x01, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_elliptic_curves_xtn,
+                                                extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, SupportedCurvesBadLength) {
+  EnableSomeEcdheCiphers();
+  const uint8_t val[] = { 0x09, 0x99, 0x00, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_elliptic_curves_xtn,
+                                                extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, SupportedCurvesTrailingData) {
+  EnableSomeEcdheCiphers();
+  const uint8_t val[] = { 0x00, 0x02, 0x00, 0x00, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_elliptic_curves_xtn,
+                                                extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, SupportedPointsEmpty) {
+  EnableSomeEcdheCiphers();
+  const uint8_t val[] = { 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_ec_point_formats_xtn,
+                                                extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, SupportedPointsBadLength) {
+  EnableSomeEcdheCiphers();
+  const uint8_t val[] = { 0x99, 0x00, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_ec_point_formats_xtn,
+                                                extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, SupportedPointsTrailingData) {
+  EnableSomeEcdheCiphers();
+  const uint8_t val[] = { 0x01, 0x00, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_ec_point_formats_xtn,
+                                                extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, RenegotiationInfoBadLength) {
+  const uint8_t val[] = { 0x99 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_renegotiation_info_xtn,
+                                                extension));
+}
+
+TEST_P(TlsExtensionTestGeneric, RenegotiationInfoMismatch) {
+  const uint8_t val[] = { 0x01, 0x00 };
+  DataBuffer extension(val, sizeof(val));
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_renegotiation_info_xtn,
+                                                extension));
+}
+
+// The extension has to contain a length.
+TEST_P(TlsExtensionTestGeneric, RenegotiationInfoExtensionEmpty) {
+  DataBuffer extension;
+  ClientHelloErrorTest(new TlsExtensionReplacer(ssl_renegotiation_info_xtn,
+                                                extension));
+}
+
+INSTANTIATE_TEST_CASE_P(ExtensionTls10, TlsExtensionTestGeneric,
+                        ::testing::Combine(
+                          TlsConnectTestBase::kTlsModesStream,
+                          TlsConnectTestBase::kTlsV10));
+INSTANTIATE_TEST_CASE_P(ExtensionVariants, TlsExtensionTestGeneric,
+                        ::testing::Combine(
+                          TlsConnectTestBase::kTlsModesAll,
+                          TlsConnectTestBase::kTlsV11V12));
+INSTANTIATE_TEST_CASE_P(ExtensionTls12Plus, TlsExtensionTest12Plus,
+                        TlsConnectTestBase::kTlsModesAll);
+INSTANTIATE_TEST_CASE_P(ExtensionDgram, TlsExtensionTestDtls,
+                        TlsConnectTestBase::kTlsV11V12);
+
+}  // namespace nspr_test
--- a/security/nss/external_tests/ssl_gtest/ssl_gtest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_gtest.cc
@@ -1,24 +1,30 @@
 #include "nspr.h"
 #include "nss.h"
 #include "ssl.h"
 
+#include <cstdlib>
+
 #include "test_io.h"
 
 #define GTEST_HAS_RTTI 0
 #include "gtest/gtest.h"
 
 std::string g_working_dir_path;
 
 int main(int argc, char **argv) {
   // Start the tests
   ::testing::InitGoogleTest(&argc, argv);
   g_working_dir_path = ".";
 
+  char* workdir = getenv("NSS_GTEST_WORKDIR");
+  if (workdir)
+    g_working_dir_path = workdir;
+
   for (int i = 0; i < argc; i++) {
     if (!strcmp(argv[i], "-d")) {
       g_working_dir_path = argv[i + 1];
       ++i;
     }
   }
 
   NSS_Initialize(g_working_dir_path.c_str(), "", "", SECMOD_DB, NSS_INIT_READONLY);
--- a/security/nss/external_tests/ssl_gtest/ssl_loopback_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_loopback_unittest.cc
@@ -1,685 +1,272 @@
-#include "prio.h"
-#include "prerror.h"
-#include "prlog.h"
-#include "pk11func.h"
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 #include "ssl.h"
-#include "sslerr.h"
 #include "sslproto.h"
-#include "keyhi.h"
 
 #include <memory>
 
-#include "test_io.h"
 #include "tls_parser.h"
-
-#define GTEST_HAS_RTTI 0
-#include "gtest/gtest.h"
-#include "gtest_utils.h"
-
-extern std::string g_working_dir_path;
+#include "tls_filter.h"
+#include "tls_connect.h"
 
 namespace nss_test {
 
-#define LOG(a) std::cerr << name_ << ": " << a << std::endl;
-
-// Inspector that parses out DTLS records and passes
-// them on.
-class TlsRecordInspector : public Inspector {
- public:
-  virtual void Inspect(DummyPrSocket* adapter, const void* data, size_t len) {
-    TlsRecordParser parser(static_cast<const unsigned char*>(data), len);
-
-    uint8_t content_type;
-    std::auto_ptr<DataBuffer> buf;
-    while (parser.NextRecord(&content_type, &buf)) {
-      OnRecord(adapter, content_type, buf->data(), buf->len());
-    }
-  }
-
-  virtual void OnRecord(DummyPrSocket* adapter, uint8_t content_type,
-                        const unsigned char* record, size_t len) = 0;
-};
-
-// Inspector that injects arbitrary packets based on
-// DTLS records of various types.
-class TlsInspectorInjector : public TlsRecordInspector {
- public:
-  TlsInspectorInjector(uint8_t packet_type, uint8_t handshake_type,
-                       const unsigned char* data, size_t len)
-      : packet_type_(packet_type),
-        handshake_type_(handshake_type),
-        injected_(false),
-        data_(data, len) {}
-
-  virtual void OnRecord(DummyPrSocket* adapter, uint8_t content_type,
-                        const unsigned char* data, size_t len) {
-    // Only inject once.
-    if (injected_) {
-      return;
-    }
-
-    // Check that the first byte is as requested.
-    if (content_type != packet_type_) {
-      return;
-    }
-
-    if (handshake_type_ != 0xff) {
-      // Check that the packet is plausibly long enough.
-      if (len < 1) {
-        return;
-      }
-
-      // Check that the handshake type is as requested.
-      if (data[0] != handshake_type_) {
-        return;
-      }
-    }
-
-    adapter->WriteDirect(data_.data(), data_.len());
-  }
-
- private:
-  uint8_t packet_type_;
-  uint8_t handshake_type_;
-  bool injected_;
-  DataBuffer data_;
-};
-
-// Make a copy of the first instance of a message.
-class TlsInspectorRecordHandshakeMessage : public TlsRecordInspector {
+class TlsServerKeyExchangeEcdhe {
  public:
-  TlsInspectorRecordHandshakeMessage(uint8_t handshake_type)
-      : handshake_type_(handshake_type), buffer_() {}
-
-  virtual void OnRecord(DummyPrSocket* adapter, uint8_t content_type,
-                        const unsigned char* data, size_t len) {
-    // Only do this once.
-    if (buffer_.len()) {
-      return;
-    }
-
-    // Check that the first byte is as requested.
-    if (content_type != kTlsHandshakeType) {
-      return;
-    }
-
-    TlsParser parser(data, len);
-    while (parser.remaining()) {
-      unsigned char message_type;
-      // Read the content type.
-      if (!parser.Read(&message_type)) {
-        // Malformed.
-        return;
-      }
-
-      // Read the record length.
-      uint32_t length;
-      if (!parser.Read(&length, 3)) {
-        // Malformed.
-        return;
-      }
-
-      if (adapter->mode() == DGRAM) {
-        // DTLS
-        uint32_t message_seq;
-        if (!parser.Read(&message_seq, 2)) {
-          return;
-        }
-
-        uint32_t fragment_offset;
-        if (!parser.Read(&fragment_offset, 3)) {
-          return;
-        }
-
-        uint32_t fragment_length;
-        if (!parser.Read(&fragment_length, 3)) {
-          return;
-        }
-
-        if ((fragment_offset != 0) || (fragment_length != length)) {
-          // This shouldn't happen because all current tests where we
-          // are using this code don't fragment.
-          return;
-        }
-      }
-
-      unsigned char* dest = nullptr;
-
-      if (message_type == handshake_type_) {
-        buffer_.Allocate(length);
-        dest = buffer_.data();
-      }
-
-      if (!parser.Read(dest, length)) {
-        // Malformed
-        return;
-      }
-
-      if (dest) return;
-    }
-  }
-
-  const DataBuffer& buffer() { return buffer_; }
-
- private:
-  uint8_t handshake_type_;
-  DataBuffer buffer_;
-};
-
-class TlsServerKeyExchangeECDHE {
- public:
-  bool Parse(const unsigned char* data, size_t len) {
-    TlsParser parser(data, len);
+  bool Parse(const DataBuffer& buffer) {
+    TlsParser parser(buffer);
 
     uint8_t curve_type;
     if (!parser.Read(&curve_type)) {
       return false;
     }
 
     if (curve_type != 3) {  // named_curve
       return false;
     }
 
     uint32_t named_curve;
     if (!parser.Read(&named_curve, 2)) {
       return false;
     }
 
-    uint32_t point_length;
-    if (!parser.Read(&point_length, 1)) {
-      return false;
-    }
-
-    public_key_.Allocate(point_length);
-    if (!parser.Read(public_key_.data(), point_length)) {
-      return false;
-    }
-
-    return true;
+    return parser.ReadVariable(&public_key_, 1);
   }
 
   DataBuffer public_key_;
 };
 
-class TlsAgent : public PollTarget {
- public:
-  enum Role { CLIENT, SERVER };
-  enum State { INIT, CONNECTING, CONNECTED, ERROR };
-
-  TlsAgent(const std::string& name, Role role, Mode mode)
-      : name_(name),
-        mode_(mode),
-        pr_fd_(nullptr),
-        adapter_(nullptr),
-        ssl_fd_(nullptr),
-        role_(role),
-        state_(INIT) {
-      memset(&info_, 0, sizeof(info_));
-      memset(&csinfo_, 0, sizeof(csinfo_));
-  }
-
-  ~TlsAgent() {
-    if (pr_fd_) {
-      PR_Close(pr_fd_);
-    }
-
-    if (ssl_fd_) {
-      PR_Close(ssl_fd_);
-    }
-  }
-
-  bool Init() {
-    pr_fd_ = DummyPrSocket::CreateFD(name_, mode_);
-    if (!pr_fd_) return false;
-
-    adapter_ = DummyPrSocket::GetAdapter(pr_fd_);
-    if (!adapter_) return false;
-
-    return true;
-  }
-
-  void SetPeer(TlsAgent* peer) { adapter_->SetPeer(peer->adapter_); }
-
-  void SetInspector(Inspector* inspector) { adapter_->SetInspector(inspector); }
-
-  void StartConnect() {
-    ASSERT_TRUE(EnsureTlsSetup());
-
-    SECStatus rv;
-    rv = SSL_ResetHandshake(ssl_fd_, role_ == SERVER ? PR_TRUE : PR_FALSE);
-    ASSERT_EQ(SECSuccess, rv);
-    SetState(CONNECTING);
-  }
-
-  void EnableSomeECDHECiphers() {
-    ASSERT_TRUE(EnsureTlsSetup());
-
-    const uint32_t EnabledCiphers[] = {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-                                       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA};
-
-    for (size_t i = 0; i < PR_ARRAY_SIZE(EnabledCiphers); ++i) {
-      SECStatus rv = SSL_CipherPrefSet(ssl_fd_, EnabledCiphers[i], PR_TRUE);
-      ASSERT_EQ(SECSuccess, rv);
-    }
-  }
-
-  bool EnsureTlsSetup() {
-    // Don't set up twice
-    if (ssl_fd_) return true;
-
-    if (adapter_->mode() == STREAM) {
-      ssl_fd_ = SSL_ImportFD(nullptr, pr_fd_);
-    } else {
-      ssl_fd_ = DTLS_ImportFD(nullptr, pr_fd_);
-    }
-
-    EXPECT_NE(nullptr, ssl_fd_);
-    if (!ssl_fd_) return false;
-    pr_fd_ = nullptr;
-
-    if (role_ == SERVER) {
-      CERTCertificate* cert = PK11_FindCertFromNickname(name_.c_str(), nullptr);
-      EXPECT_NE(nullptr, cert);
-      if (!cert) return false;
-
-      SECKEYPrivateKey* priv = PK11_FindKeyByAnyCert(cert, nullptr);
-      EXPECT_NE(nullptr, priv);
-      if (!priv) return false;  // Leak cert.
-
-      SECStatus rv = SSL_ConfigSecureServer(ssl_fd_, cert, priv, kt_rsa);
-      EXPECT_EQ(SECSuccess, rv);
-      if (rv != SECSuccess) return false;  // Leak cert and key.
-
-      SECKEY_DestroyPrivateKey(priv);
-      CERT_DestroyCertificate(cert);
-    } else {
-      SECStatus rv = SSL_SetURL(ssl_fd_, "server");
-      EXPECT_EQ(SECSuccess, rv);
-      if (rv != SECSuccess) return false;
-    }
-
-    SECStatus rv = SSL_AuthCertificateHook(ssl_fd_, AuthCertificateHook,
-                                           reinterpret_cast<void*>(this));
-    EXPECT_EQ(SECSuccess, rv);
-    if (rv != SECSuccess) return false;
-
-    return true;
-  }
-
-  void SetSessionTicketsEnabled(bool en) {
-    ASSERT_TRUE(EnsureTlsSetup());
-
-    SECStatus rv = SSL_OptionSet(ssl_fd_, SSL_ENABLE_SESSION_TICKETS,
-                                  en ? PR_TRUE : PR_FALSE);
-    ASSERT_EQ(SECSuccess, rv);
-  }
-
-  void SetSessionCacheEnabled(bool en) {
-    ASSERT_TRUE(EnsureTlsSetup());
-
-    SECStatus rv = SSL_OptionSet(ssl_fd_, SSL_NO_CACHE,
-                                  en ? PR_FALSE : PR_TRUE);
-    ASSERT_EQ(SECSuccess, rv);
-  }
-
-  void SetVersionRange(uint16_t minver, uint16_t maxver) {
-    SSLVersionRange range = {minver, maxver};
-    ASSERT_EQ(SECSuccess, SSL_VersionRangeSet(ssl_fd_, &range));
-  }
-
-  State state() const { return state_; }
-
-  const char* state_str() const { return state_str(state()); }
-
-  const char* state_str(State state) const { return states[state]; }
-
-  PRFileDesc* ssl_fd() { return ssl_fd_; }
-
-  bool version(uint16_t* version) const {
-    if (state_ != CONNECTED) return false;
-
-    *version = info_.protocolVersion;
-
-    return true;
-  }
-
-  bool cipher_suite(int16_t* cipher_suite) const {
-    if (state_ != CONNECTED) return false;
-
-    *cipher_suite = info_.cipherSuite;
-    return true;
-  }
-
-  std::string cipher_suite_name() const {
-    if (state_ != CONNECTED) return "UNKNOWN";
-
-    return csinfo_.cipherSuiteName;
-  }
-
-  void CheckKEAType(SSLKEAType type) const {
-    ASSERT_EQ(CONNECTED, state_);
-    ASSERT_EQ(type, csinfo_.keaType);
-  }
-
-  void CheckVersion(uint16_t version) const {
-    ASSERT_EQ(CONNECTED, state_);
-    ASSERT_EQ(version, info_.protocolVersion);
-  }
-
-  void Handshake() {
-    SECStatus rv = SSL_ForceHandshake(ssl_fd_);
-    if (rv == SECSuccess) {
-      LOG("Handshake success");
-      SECStatus rv = SSL_GetChannelInfo(ssl_fd_, &info_, sizeof(info_));
-      ASSERT_EQ(SECSuccess, rv);
-
-      rv = SSL_GetCipherSuiteInfo(info_.cipherSuite, &csinfo_, sizeof(csinfo_));
-      ASSERT_EQ(SECSuccess, rv);
-
-      SetState(CONNECTED);
-      return;
-    }
-
-    int32_t err = PR_GetError();
-    switch (err) {
-      case PR_WOULD_BLOCK_ERROR:
-        LOG("Would have blocked");
-        // TODO(ekr@rtfm.com): set DTLS timeouts
-        Poller::Instance()->Wait(READABLE_EVENT, adapter_, this,
-                                 &TlsAgent::ReadableCallback);
-        return;
-        break;
-
-      // TODO(ekr@rtfm.com): needs special case for DTLS
-      case SSL_ERROR_RX_MALFORMED_HANDSHAKE:
-      default:
-        LOG("Handshake failed with error " << err);
-        SetState(ERROR);
-        return;
-    }
-  }
-
-  std::vector<uint8_t> GetSessionId() {
-    return std::vector<uint8_t>(info_.sessionID,
-                                info_.sessionID + info_.sessionIDLength);
-  }
-
- private:
-  const static char* states[];
-
-  void SetState(State state) {
-    if (state_ == state) return;
-
-    LOG("Changing state from " << state_str(state_) << " to "
-                               << state_str(state));
-    state_ = state;
-  }
-
-  // Dummy auth certificate hook.
-  static SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd,
-                                       PRBool checksig, PRBool isServer) {
-    return SECSuccess;
-  }
-
-  static void ReadableCallback(PollTarget* self, Event event) {
-    TlsAgent* agent = static_cast<TlsAgent*>(self);
-    agent->ReadableCallback_int(event);
-  }
-
-  void ReadableCallback_int(Event event) {
-    LOG("Readable");
-    Handshake();
-  }
-
-  const std::string name_;
-  Mode mode_;
-  PRFileDesc* pr_fd_;
-  DummyPrSocket* adapter_;
-  PRFileDesc* ssl_fd_;
-  Role role_;
-  State state_;
-  SSLChannelInfo info_;
-  SSLCipherSuiteInfo csinfo_;
-};
-
-const char* TlsAgent::states[] = {"INIT", "CONNECTING", "CONNECTED", "ERROR"};
-
-class TlsConnectTestBase : public ::testing::Test {
- public:
-  TlsConnectTestBase(Mode mode)
-      : mode_(mode),
-        client_(new TlsAgent("client", TlsAgent::CLIENT, mode_)),
-        server_(new TlsAgent("server", TlsAgent::SERVER, mode_)) {}
-
-  ~TlsConnectTestBase() {
-    delete client_;
-    delete server_;
-  }
-
-  void SetUp() {
-    // Configure a fresh session cache.
-    SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str());
-
-    Init();
-  }
-
-  void TearDown() {
-    client_ = nullptr;
-    server_ = nullptr;
-
-    SSL_ShutdownServerSessionIDCache();
-  }
-
-  void Init() {
-    ASSERT_TRUE(client_->Init());
-    ASSERT_TRUE(server_->Init());
-
-    client_->SetPeer(server_);
-    server_->SetPeer(client_);
-  }
-
-  void Reset() {
-    delete client_;
-    delete server_;
-
-    client_ = new TlsAgent("client", TlsAgent::CLIENT, mode_);
-    server_ = new TlsAgent("server", TlsAgent::SERVER, mode_);
-
-    Init();
-  }
-
-  void EnsureTlsSetup() {
-    ASSERT_TRUE(client_->EnsureTlsSetup());
-    ASSERT_TRUE(server_->EnsureTlsSetup());
-  }
-
-  void Connect() {
-    server_->StartConnect();  // Server
-    client_->StartConnect();  // Client
-    client_->Handshake();
-    server_->Handshake();
-
-    ASSERT_TRUE_WAIT(client_->state() != TlsAgent::CONNECTING &&
-                         server_->state() != TlsAgent::CONNECTING,
-                     5000);
-    ASSERT_EQ(TlsAgent::CONNECTED, server_->state());
-
-    int16_t cipher_suite1, cipher_suite2;
-    bool ret = client_->cipher_suite(&cipher_suite1);
-    ASSERT_TRUE(ret);
-    ret = server_->cipher_suite(&cipher_suite2);
-    ASSERT_TRUE(ret);
-    ASSERT_EQ(cipher_suite1, cipher_suite2);
-
-    std::cerr << "Connected with cipher suite " << client_->cipher_suite_name()
-              << std::endl;
-
-    // Check and store session ids.
-    std::vector<uint8_t> sid_c1 = client_->GetSessionId();
-    ASSERT_EQ(32, sid_c1.size());
-    std::vector<uint8_t> sid_s1 = server_->GetSessionId();
-    ASSERT_EQ(32, sid_s1.size());
-    ASSERT_EQ(sid_c1, sid_s1);
-    session_id_ = sid_c1;
-  }
-
-  void EnableSomeECDHECiphers() {
-    client_->EnableSomeECDHECiphers();
-    server_->EnableSomeECDHECiphers();
-  }
-
- protected:
-  Mode mode_;
-  TlsAgent* client_;
-  TlsAgent* server_;
-  std::vector<uint8_t> session_id_;
-};
-
-class TlsConnectTest : public TlsConnectTestBase {
- public:
-  TlsConnectTest() : TlsConnectTestBase(STREAM) {}
-};
-
-class DtlsConnectTest : public TlsConnectTestBase {
- public:
-  DtlsConnectTest() : TlsConnectTestBase(DGRAM) {}
-};
-
-class TlsConnectGeneric : public TlsConnectTestBase,
-                          public ::testing::WithParamInterface<std::string> {
- public:
-  TlsConnectGeneric()
-      : TlsConnectTestBase((GetParam() == "TLS") ? STREAM : DGRAM) {
-    std::cerr << "Variant: " << GetParam() << std::endl;
-  }
-};
-
 TEST_P(TlsConnectGeneric, SetupOnly) {}
 
 TEST_P(TlsConnectGeneric, Connect) {
   Connect();
-
-  // Check that we negotiated the expected version.
-  if (mode_ == STREAM) {
-    client_->CheckVersion(SSL_LIBRARY_VERSION_TLS_1_0);
-  } else {
-    client_->CheckVersion(SSL_LIBRARY_VERSION_TLS_1_1);
-  }
+  client_->CheckVersion(std::get<1>(GetParam()));
+  client_->CheckAuthType(ssl_auth_rsa);
 }
 
 TEST_P(TlsConnectGeneric, ConnectResumed) {
+  ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
   Connect();
-  std::vector<uint8_t> old_sid = session_id_;
+
+  ResetRsa();
+  Connect();
+  CheckResumption(RESUME_SESSIONID);
+}
 
-  Reset();
+TEST_P(TlsConnectGeneric, ConnectClientCacheDisabled) {
+  ConfigureSessionCache(RESUME_NONE, RESUME_SESSIONID);
+  Connect();
+  ResetRsa();
   Connect();
-  ASSERT_EQ(old_sid, session_id_) << "Session was not resumed when it should have been";
+  CheckResumption(RESUME_NONE);
+}
+
+TEST_P(TlsConnectGeneric, ConnectServerCacheDisabled) {
+  ConfigureSessionCache(RESUME_SESSIONID, RESUME_NONE);
+  Connect();
+  ResetRsa();
+  Connect();
+  CheckResumption(RESUME_NONE);
 }
 
-TEST_P(TlsConnectGeneric, ConnectNotResumed) {
+TEST_P(TlsConnectGeneric, ConnectSessionCacheDisabled) {
+  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
+  Connect();
+  ResetRsa();
   Connect();
-  std::vector<uint8_t> old_sid = session_id_;
+  CheckResumption(RESUME_NONE);
+}
 
-  Reset();
-  client_->SetSessionCacheEnabled(false);
+TEST_P(TlsConnectGeneric, ConnectResumeSupportBoth) {
+  // This prefers tickets.
+  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
   Connect();
 
-  ASSERT_NE(old_sid, session_id_) << "Session was resumed when it should not have been";
+  ResetRsa();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+  Connect();
+  CheckResumption(RESUME_TICKET);
+}
+
+TEST_P(TlsConnectGeneric, ConnectResumeClientTicketServerBoth) {
+  // This causes no resumption because the client needs the
+  // session cache to resume even with tickets.
+  ConfigureSessionCache(RESUME_TICKET, RESUME_BOTH);
+  Connect();
+
+  ResetRsa();
+  ConfigureSessionCache(RESUME_TICKET, RESUME_BOTH);
+  Connect();
+  CheckResumption(RESUME_NONE);
 }
 
-TEST_P(TlsConnectGeneric, ConnectTLS_1_1_Only) {
-  EnsureTlsSetup();
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_1);
+TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicket) {
+  // This causes a ticket resumption.
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  Connect();
+
+  ResetRsa();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  Connect();
+  CheckResumption(RESUME_TICKET);
+}
 
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_1);
+TEST_P(TlsConnectGeneric, ConnectClientServerTicketOnly) {
+  // This causes no resumption because the client needs the
+  // session cache to resume even with tickets.
+  ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
+  Connect();
 
+  ResetRsa();
+  ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
+  Connect();
+  CheckResumption(RESUME_NONE);
+}
+
+TEST_P(TlsConnectGeneric, ConnectClientBothServerNone) {
+  ConfigureSessionCache(RESUME_BOTH, RESUME_NONE);
   Connect();
 
-  client_->CheckVersion(SSL_LIBRARY_VERSION_TLS_1_1);
+  ResetRsa();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_NONE);
+  Connect();
+  CheckResumption(RESUME_NONE);
+}
+
+TEST_P(TlsConnectGeneric, ConnectClientNoneServerBoth) {
+  ConfigureSessionCache(RESUME_NONE, RESUME_BOTH);
+  Connect();
+
+  ResetRsa();
+  ConfigureSessionCache(RESUME_NONE, RESUME_BOTH);
+  Connect();
+  CheckResumption(RESUME_NONE);
 }
 
-TEST_P(TlsConnectGeneric, ConnectTLS_1_2_Only) {
+TEST_P(TlsConnectGeneric, ResumeWithHigherVersion) {
   EnsureTlsSetup();
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+  ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_1);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_1);
+  Connect();
+
+  ResetRsa();
+  EnsureTlsSetup();
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_2);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_2);
   Connect();
+  CheckResumption(RESUME_NONE);
   client_->CheckVersion(SSL_LIBRARY_VERSION_TLS_1_2);
 }
 
-TEST_F(TlsConnectTest, ConnectECDHE) {
-  EnableSomeECDHECiphers();
+TEST_P(TlsConnectGeneric, ConnectAlpn) {
+  EnableAlpn();
+  Connect();
+  client_->CheckAlpn(SSL_NEXT_PROTO_SELECTED, "a");
+  server_->CheckAlpn(SSL_NEXT_PROTO_NEGOTIATED, "a");
+}
+
+TEST_P(TlsConnectGeneric, ConnectEcdsa) {
+  ResetEcdsa();
+  Connect();
+  client_->CheckVersion(std::get<1>(GetParam()));
+  client_->CheckAuthType(ssl_auth_ecdsa);
+}
+
+TEST_P(TlsConnectDatagram, ConnectSrtp) {
+  EnableSrtp();
+  Connect();
+  CheckSrtp();
+}
+
+TEST_P(TlsConnectStream, ConnectEcdhe) {
+  EnableSomeEcdheCiphers();
   Connect();
   client_->CheckKEAType(ssl_kea_ecdh);
 }
 
-TEST_F(TlsConnectTest, ConnectECDHETwiceReuseKey) {
-  EnableSomeECDHECiphers();
+TEST_P(TlsConnectStream, ConnectEcdheTwiceReuseKey) {
+  EnableSomeEcdheCiphers();
   TlsInspectorRecordHandshakeMessage* i1 =
       new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange);
-  server_->SetInspector(i1);
+  server_->SetPacketFilter(i1);
   Connect();
   client_->CheckKEAType(ssl_kea_ecdh);
-  TlsServerKeyExchangeECDHE dhe1;
-  ASSERT_TRUE(dhe1.Parse(i1->buffer().data(), i1->buffer().len()));
+  TlsServerKeyExchangeEcdhe dhe1;
+  EXPECT_TRUE(dhe1.Parse(i1->buffer()));
 
   // Restart
-  Reset();
+  ResetRsa();
   TlsInspectorRecordHandshakeMessage* i2 =
       new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange);
-  server_->SetInspector(i2);
-  EnableSomeECDHECiphers();
-  client_->SetSessionCacheEnabled(false);
+  server_->SetPacketFilter(i2);
+  EnableSomeEcdheCiphers();
+  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
   Connect();
   client_->CheckKEAType(ssl_kea_ecdh);
 
-  TlsServerKeyExchangeECDHE dhe2;
-  ASSERT_TRUE(dhe2.Parse(i2->buffer().data(), i2->buffer().len()));
+  TlsServerKeyExchangeEcdhe dhe2;
+  EXPECT_TRUE(dhe2.Parse(i2->buffer()));
 
   // Make sure they are the same.
-  ASSERT_EQ(dhe1.public_key_.len(), dhe2.public_key_.len());
-  ASSERT_TRUE(!memcmp(dhe1.public_key_.data(), dhe2.public_key_.data(),
+  EXPECT_EQ(dhe1.public_key_.len(), dhe2.public_key_.len());
+  EXPECT_TRUE(!memcmp(dhe1.public_key_.data(), dhe2.public_key_.data(),
                       dhe1.public_key_.len()));
 }
 
-TEST_F(TlsConnectTest, ConnectECDHETwiceNewKey) {
-  EnableSomeECDHECiphers();
+TEST_P(TlsConnectStream, ConnectEcdheTwiceNewKey) {
+  EnableSomeEcdheCiphers();
   SECStatus rv =
       SSL_OptionSet(server_->ssl_fd(), SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE);
-  ASSERT_EQ(SECSuccess, rv);
+  EXPECT_EQ(SECSuccess, rv);
   TlsInspectorRecordHandshakeMessage* i1 =
       new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange);
-  server_->SetInspector(i1);
+  server_->SetPacketFilter(i1);
   Connect();
   client_->CheckKEAType(ssl_kea_ecdh);
-  TlsServerKeyExchangeECDHE dhe1;
-  ASSERT_TRUE(dhe1.Parse(i1->buffer().data(), i1->buffer().len()));
+  TlsServerKeyExchangeEcdhe dhe1;
+  EXPECT_TRUE(dhe1.Parse(i1->buffer()));
 
   // Restart
-  Reset();
-  EnableSomeECDHECiphers();
+  ResetRsa();
+  EnableSomeEcdheCiphers();
   rv = SSL_OptionSet(server_->ssl_fd(), SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE);
-  ASSERT_EQ(SECSuccess, rv);
+  EXPECT_EQ(SECSuccess, rv);
   TlsInspectorRecordHandshakeMessage* i2 =
       new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange);
-  server_->SetInspector(i2);
-  client_->SetSessionCacheEnabled(false);
+  server_->SetPacketFilter(i2);
+  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
   Connect();
   client_->CheckKEAType(ssl_kea_ecdh);
 
-  TlsServerKeyExchangeECDHE dhe2;
-  ASSERT_TRUE(dhe2.Parse(i2->buffer().data(), i2->buffer().len()));
+  TlsServerKeyExchangeEcdhe dhe2;
+  EXPECT_TRUE(dhe2.Parse(i2->buffer()));
 
   // Make sure they are different.
-  ASSERT_FALSE((dhe1.public_key_.len() == dhe2.public_key_.len()) &&
+  EXPECT_FALSE((dhe1.public_key_.len() == dhe2.public_key_.len()) &&
                (!memcmp(dhe1.public_key_.data(), dhe2.public_key_.data(),
                         dhe1.public_key_.len())));
 }
 
-INSTANTIATE_TEST_CASE_P(Variants, TlsConnectGeneric,
-                        ::testing::Values("TLS", "DTLS"));
+INSTANTIATE_TEST_CASE_P(VariantsStream10, TlsConnectGeneric,
+                        ::testing::Combine(
+                          TlsConnectTestBase::kTlsModesStream,
+                          TlsConnectTestBase::kTlsV10));
+INSTANTIATE_TEST_CASE_P(VariantsAll, TlsConnectGeneric,
+                        ::testing::Combine(
+                          TlsConnectTestBase::kTlsModesAll,
+                          TlsConnectTestBase::kTlsV11V12));
+INSTANTIATE_TEST_CASE_P(VersionsDatagram, TlsConnectDatagram,
+                        TlsConnectTestBase::kTlsV11V12);
+INSTANTIATE_TEST_CASE_P(VersionsDatagram, TlsConnectStream,
+                        TlsConnectTestBase::kTlsV11V12);
 
 }  // namespace nspr_test
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/ssl_skip_unittest.cc
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "sslerr.h"
+
+#include "tls_parser.h"
+#include "tls_filter.h"
+#include "tls_connect.h"
+
+/*
+ * The tests in this file test that the TLS state machine is robust against
+ * attacks that alter the order of handshake messages.
+ *
+ * See <https://www.smacktls.com/smack.pdf> for a description of the problems
+ * that this sort of attack can enable.
+ */
+namespace nss_test {
+
+class TlsHandshakeSkipFilter : public TlsRecordFilter {
+ public:
+  // A TLS record filter that skips handshake messages of the identified type.
+  TlsHandshakeSkipFilter(uint8_t handshake_type)
+      : handshake_type_(handshake_type),
+        skipped_(false) {}
+
+ protected:
+  // Takes a record; if it is a handshake record, it removes the first handshake
+  // message that is of handshake_type_ type.
+  virtual bool FilterRecord(uint8_t content_type, uint16_t version,
+                            const DataBuffer& input, DataBuffer* output) {
+    if (content_type != kTlsHandshakeType) {
+      return false;
+    }
+
+    size_t output_offset = 0U;
+    output->Allocate(input.len());
+
+    TlsParser parser(input);
+    while (parser.remaining()) {
+      size_t start = parser.consumed();
+      uint8_t handshake_type;
+      if (!parser.Read(&handshake_type)) {
+        return false;
+      }
+      uint32_t length;
+      if (!TlsHandshakeFilter::ReadLength(&parser, version, &length)) {
+        return false;
+      }
+
+      if (!parser.Skip(length)) {
+        return false;
+      }
+
+      if (skipped_ || handshake_type != handshake_type_) {
+        size_t entire_length = parser.consumed() - start;
+        output->Write(output_offset, input.data() + start,
+                      entire_length);
+        // DTLS sequence numbers need to be rewritten
+        if (skipped_ && IsDtls(version)) {
+          output->data()[start + 5] -= 1;
+        }
+        output_offset += entire_length;
+      } else {
+        std::cerr << "Dropping handshake: "
+                  << static_cast<unsigned>(handshake_type_) << std::endl;
+        // We only need to report that the output contains changed data if we
+        // drop a handshake message.  But once we've skipped one message, we
+        // have to modify all subsequent handshake messages so that they include
+        // the correct DTLS sequence numbers.
+        skipped_ = true;
+      }
+    }
+    output->Truncate(output_offset);
+    return skipped_;
+  }
+
+ private:
+  // The type of handshake message to drop.
+  uint8_t handshake_type_;
+  // Whether this filter has ever skipped a handshake message.  Track this so
+  // that sequence numbers on DTLS handshake messages can be rewritten in
+  // subsequent calls.
+  bool skipped_;
+};
+
+class TlsSkipTest
+  : public TlsConnectTestBase,
+    public ::testing::WithParamInterface<std::tuple<std::string, uint16_t>> {
+
+ protected:
+  TlsSkipTest()
+    : TlsConnectTestBase(TlsConnectTestBase::ToMode(std::get<0>(GetParam())),
+                         std::get<1>(GetParam())) {}
+
+  void ServerSkipTest(PacketFilter* filter,
+                      uint8_t alert = kTlsAlertUnexpectedMessage) {
+    auto alert_recorder = new TlsAlertRecorder();
+    client_->SetPacketFilter(alert_recorder);
+    if (filter) {
+      server_->SetPacketFilter(filter);
+    }
+    ConnectExpectFail();
+    EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
+    EXPECT_EQ(alert, alert_recorder->description());
+  }
+};
+
+TEST_P(TlsSkipTest, SkipCertificate) {
+  ServerSkipTest(new TlsHandshakeSkipFilter(kTlsHandshakeCertificate));
+  client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
+}
+
+TEST_P(TlsSkipTest, SkipCertificateEcdhe) {
+  EnableSomeEcdheCiphers();
+  ServerSkipTest(new TlsHandshakeSkipFilter(kTlsHandshakeCertificate));
+  client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH);
+}
+
+TEST_P(TlsSkipTest, SkipCertificateEcdsa) {
+  ResetEcdsa();
+  ServerSkipTest(new TlsHandshakeSkipFilter(kTlsHandshakeCertificate));
+  client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH);
+}
+
+TEST_P(TlsSkipTest, SkipServerKeyExchange) {
+  // Have to enable some ephemeral suites, or ServerKeyExchange doesn't appear.
+  EnableSomeEcdheCiphers();
+  ServerSkipTest(new TlsHandshakeSkipFilter(kTlsHandshakeServerKeyExchange));
+  client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
+}
+
+TEST_P(TlsSkipTest, SkipServerKeyExchangeEcdsa) {
+  ResetEcdsa();
+  ServerSkipTest(new TlsHandshakeSkipFilter(kTlsHandshakeServerKeyExchange));
+  client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
+}
+
+TEST_P(TlsSkipTest, SkipCertAndKeyExch) {
+  auto chain = new ChainedPacketFilter();
+  chain->Add(new TlsHandshakeSkipFilter(kTlsHandshakeCertificate));
+  chain->Add(new TlsHandshakeSkipFilter(kTlsHandshakeServerKeyExchange));
+  ServerSkipTest(chain);
+  client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
+}
+
+TEST_P(TlsSkipTest, SkipCertAndKeyExchEcdsa) {
+  ResetEcdsa();
+  auto chain = new ChainedPacketFilter();
+  chain->Add(new TlsHandshakeSkipFilter(kTlsHandshakeCertificate));
+  chain->Add(new TlsHandshakeSkipFilter(kTlsHandshakeServerKeyExchange));
+  ServerSkipTest(chain);
+  client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
+}
+
+INSTANTIATE_TEST_CASE_P(SkipTls10, TlsSkipTest,
+                        ::testing::Combine(
+                          TlsConnectTestBase::kTlsModesStream,
+                          TlsConnectTestBase::kTlsV10));
+INSTANTIATE_TEST_CASE_P(SkipVariants, TlsSkipTest,
+                        ::testing::Combine(
+                          TlsConnectTestBase::kTlsModesAll,
+                          TlsConnectTestBase::kTlsV11V12));
+
+}  // namespace nss_test
--- a/security/nss/external_tests/ssl_gtest/test_io.cc
+++ b/security/nss/external_tests/ssl_gtest/test_io.cc
@@ -1,50 +1,53 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include <assert.h>
+#include "test_io.h"
 
+#include <algorithm>
+#include <cassert>
 #include <iostream>
 #include <memory>
 
 #include "prerror.h"
-#include "prio.h"
 #include "prlog.h"
 #include "prthread.h"
 
-#include "test_io.h"
+#include "databuffer.h"
 
 namespace nss_test {
 
 static PRDescIdentity test_fd_identity = PR_INVALID_IO_LAYER;
 
-#define UNIMPLEMENTED()                                                 \
-  fprintf(stderr, "Call to unimplemented function %s\n", __FUNCTION__); \
-  PR_ASSERT(PR_FALSE);                                                  \
+#define UNIMPLEMENTED()                          \
+  std::cerr << "Call to unimplemented function " \
+            << __FUNCTION__ << std::endl;        \
+  PR_ASSERT(PR_FALSE);                           \
   PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0)
 
 #define LOG(a) std::cerr << name_ << ": " << a << std::endl;
 
-struct Packet {
-  Packet() : data_(nullptr), len_(0), offset_(0) {}
+class Packet : public DataBuffer {
+ public:
+  Packet(const DataBuffer& buf) : DataBuffer(buf), offset_(0) {}
 
-  void Assign(const void *data, int32_t len) {
-    data_ = new uint8_t[len];
-    memcpy(data_, data, len);
-    len_ = len;
+  void Advance(size_t delta) {
+    PR_ASSERT(offset_ + delta <= len());
+    offset_ = std::min(len(), offset_ + delta);
   }
 
-  ~Packet() { delete data_; }
-  uint8_t *data_;
-  int32_t len_;
-  int32_t offset_;
+  size_t offset() const { return offset_; }
+  size_t remaining() const { return len() - offset_; }
+
+ private:
+  size_t offset_;
 };
 
 // Implementation of NSPR methods
 static PRStatus DummyClose(PRFileDesc *f) {
   f->secret = nullptr;
   return PR_SUCCESS;
 }
 
@@ -241,16 +244,26 @@ static PRStatus DummyConnectContinue(PRF
   return PR_FAILURE;
 }
 
 static int32_t DummyReserved(PRFileDesc *f) {
   UNIMPLEMENTED();
   return -1;
 }
 
+DummyPrSocket::~DummyPrSocket() {
+  delete filter_;
+  while (!input_.empty())
+  {
+    Packet* front = input_.front();
+    input_.pop();
+    delete front;
+  }
+}
+
 static const struct PRIOMethods DummyMethods = {
     PR_DESC_LAYERED,  DummyClose,           DummyRead,
     DummyWrite,       DummyAvailable,       DummyAvailable64,
     DummySync,        DummySeek,            DummySeek64,
     DummyFileInfo,    DummyFileInfo64,      DummyWritev,
     DummyConnect,     DummyAccept,          DummyBind,
     DummyListen,      DummyShutdown,        DummyRecv,
     DummySend,        DummyRecvfrom,        DummySendto,
@@ -270,19 +283,18 @@ PRFileDesc *DummyPrSocket::CreateFD(cons
 
   return fd;
 }
 
 DummyPrSocket *DummyPrSocket::GetAdapter(PRFileDesc *fd) {
   return reinterpret_cast<DummyPrSocket *>(fd->secret);
 }
 
-void DummyPrSocket::PacketReceived(const void *data, int32_t len) {
-  input_.push(new Packet());
-  input_.back()->Assign(data, len);
+void DummyPrSocket::PacketReceived(const DataBuffer& packet) {
+  input_.push(new Packet(packet));
 }
 
 int32_t DummyPrSocket::Read(void *data, int32_t len) {
   PR_ASSERT(mode_ == STREAM);
 
   if (mode_ != STREAM) {
     PR_SetError(PR_INVALID_METHOD_ERROR, 0);
     return -1;
@@ -290,68 +302,70 @@ int32_t DummyPrSocket::Read(void *data, 
 
   if (input_.empty()) {
     LOG("Read --> wouldblock " << len);
     PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
     return -1;
   }
 
   Packet *front = input_.front();
-  int32_t to_read = std::min(len, front->len_ - front->offset_);
-  memcpy(data, front->data_ + front->offset_, to_read);
-  front->offset_ += to_read;
+  size_t to_read = std::min(static_cast<size_t>(len),
+                            front->len() - front->offset());
+  memcpy(data, static_cast<const void*>(front->data() + front->offset()),
+         to_read);
+  front->Advance(to_read);
 
-  if (front->offset_ == front->len_) {
+  if (!front->remaining()) {
     input_.pop();
     delete front;
   }
 
-  return to_read;
+  return static_cast<int32_t>(to_read);
 }
 
 int32_t DummyPrSocket::Recv(void *buf, int32_t buflen) {
   if (input_.empty()) {
     PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
     return -1;
   }
 
   Packet *front = input_.front();
-  if (buflen < front->len_) {
+  if (static_cast<size_t>(buflen) < front->len()) {
     PR_ASSERT(false);
     PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
     return -1;
   }
 
-  int32_t count = front->len_;
-  memcpy(buf, front->data_, count);
+  size_t count = front->len();
+  memcpy(buf, front->data(), count);
 
   input_.pop();
   delete front;
 
-  return count;
+  return static_cast<int32_t>(count);
 }
 
 int32_t DummyPrSocket::Write(const void *buf, int32_t length) {
-  if (inspector_) {
-    inspector_->Inspect(this, buf, length);
-  }
-
-  return WriteDirect(buf, length);
-}
-
-int32_t DummyPrSocket::WriteDirect(const void *buf, int32_t length) {
   if (!peer_) {
     PR_SetError(PR_IO_ERROR, 0);
     return -1;
   }
 
-  LOG("Wrote " << length);
-
-  peer_->PacketReceived(buf, length);
-  return length;
+  DataBuffer packet(static_cast<const uint8_t*>(buf),
+                    static_cast<size_t>(length));
+  DataBuffer filtered;
+  if (filter_ && filter_->Filter(packet, &filtered)) {
+    LOG("Filtered packet: " << filtered);
+    peer_->PacketReceived(filtered);
+  } else {
+    peer_->PacketReceived(packet);
+  }
+  // libssl can't handle it if this reports something other than the length
+  // of what was passed in (or less, but we're not doing partial writes).
+  return static_cast<int32_t>(packet.len());
 }
 
 Poller *Poller::instance;
 
 Poller *Poller::Instance() {
   if (!instance) instance = new Poller();
 
   return instance;
@@ -433,16 +447,18 @@ bool Poller::Poll() {
 
   // Now process anything that timed out.
   now = PR_Now();
   while (!timers_.empty()) {
     if (now < timers_.top()->deadline_) break;
 
     Timer *timer = timers_.top();
     timers_.pop();
-    timer->callback_(timer->target_, TIMER_EVENT);
+    if (timer->callback_) {
+      timer->callback_(timer->target_, TIMER_EVENT);
+    }
     delete timer;
   }
 
   return true;
 }
 
 }  // namespace nss_test
--- a/security/nss/external_tests/ssl_gtest/test_io.h
+++ b/security/nss/external_tests/ssl_gtest/test_io.h
@@ -7,68 +7,79 @@
 #ifndef test_io_h_
 #define test_io_h_
 
 #include <string.h>
 #include <map>
 #include <memory>
 #include <queue>
 #include <string>
+#include <ostream>
+
+#include "prio.h"
 
 namespace nss_test {
 
-struct Packet;
+class DataBuffer;
+class Packet;
 class DummyPrSocket;  // Fwd decl.
 
 // Allow us to inspect a packet before it is written.
-class Inspector {
+class PacketFilter {
  public:
-  virtual ~Inspector() {}
+  virtual ~PacketFilter() {}
 
-  virtual void Inspect(DummyPrSocket* adapter, const void* data,
-                       size_t len) = 0;
+  // The packet filter takes input and has the option of mutating it.
+  //
+  // A filter that modifies the data places the modified data in *output and
+  // returns true.  A filter that does not modify data returns false, in which
+  // case the value in *output is ignored.
+  virtual bool Filter(const DataBuffer& input, DataBuffer* output) = 0;
 };
 
 enum Mode { STREAM, DGRAM };
 
+inline std::ostream& operator<<(std::ostream& os, Mode m) {
+  return os << ((m == STREAM) ? "TLS" : "DTLS");
+}
+
 class DummyPrSocket {
  public:
-  ~DummyPrSocket() { delete inspector_; }
+  ~DummyPrSocket();
 
   static PRFileDesc* CreateFD(const std::string& name,
                               Mode mode);  // Returns an FD.
   static DummyPrSocket* GetAdapter(PRFileDesc* fd);
 
   void SetPeer(DummyPrSocket* peer) { peer_ = peer; }
 
-  void SetInspector(Inspector* inspector) { inspector_ = inspector; }
+  void SetPacketFilter(PacketFilter* filter) { filter_ = filter; }
 
-  void PacketReceived(const void* data, int32_t len);
+  void PacketReceived(const DataBuffer& data);
   int32_t Read(void* data, int32_t len);
   int32_t Recv(void* buf, int32_t buflen);
   int32_t Write(const void* buf, int32_t length);
-  int32_t WriteDirect(const void* buf, int32_t length);
 
   Mode mode() const { return mode_; }
-  bool readable() { return !input_.empty(); }
+  bool readable() const { return !input_.empty(); }
   bool writable() { return true; }
 
  private:
   DummyPrSocket(const std::string& name, Mode mode)
       : name_(name),
         mode_(mode),
         peer_(nullptr),
         input_(),
-        inspector_(nullptr) {}
+        filter_(nullptr) {}
 
   const std::string name_;
   Mode mode_;
   DummyPrSocket* peer_;
   std::queue<Packet*> input_;
-  Inspector* inspector_;
+  PacketFilter* filter_;
 };
 
 // Marker interface.
 class PollTarget {};
 
 enum Event { READABLE_EVENT, TIMER_EVENT /* Must be last */ };
 
 typedef void (*PollCallback)(PollTarget*, Event);
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/tls_agent.cc
@@ -0,0 +1,229 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "tls_agent.h"
+
+#include "pk11func.h"
+#include "ssl.h"
+#include "sslerr.h"
+#include "sslproto.h"
+#include "keyhi.h"
+
+#define GTEST_HAS_RTTI 0
+#include "gtest/gtest.h"
+
+namespace nss_test {
+
+const char* TlsAgent::states[] = {"INIT", "CONNECTING", "CONNECTED", "ERROR"};
+
+bool TlsAgent::EnsureTlsSetup() {
+  // Don't set up twice
+  if (ssl_fd_) return true;
+
+  if (adapter_->mode() == STREAM) {
+    ssl_fd_ = SSL_ImportFD(nullptr, pr_fd_);
+  } else {
+    ssl_fd_ = DTLS_ImportFD(nullptr, pr_fd_);
+  }
+
+  EXPECT_NE(nullptr, ssl_fd_);
+  if (!ssl_fd_) return false;
+  pr_fd_ = nullptr;
+
+  if (role_ == SERVER) {
+    CERTCertificate* cert = PK11_FindCertFromNickname(name_.c_str(), nullptr);
+    EXPECT_NE(nullptr, cert);
+    if (!cert) return false;
+
+    SECKEYPrivateKey* priv = PK11_FindKeyByAnyCert(cert, nullptr);
+    EXPECT_NE(nullptr, priv);
+    if (!priv) return false;  // Leak cert.
+
+    SECStatus rv = SSL_ConfigSecureServer(ssl_fd_, cert, priv, kea_);
+    EXPECT_EQ(SECSuccess, rv);
+    if (rv != SECSuccess) return false;  // Leak cert and key.
+
+    SECKEY_DestroyPrivateKey(priv);
+    CERT_DestroyCertificate(cert);
+
+    rv = SSL_SNISocketConfigHook(ssl_fd_, SniHook,
+                                 reinterpret_cast<void*>(this));
+    EXPECT_EQ(SECSuccess, rv);  // don't abort, just fail
+  } else {
+    SECStatus rv = SSL_SetURL(ssl_fd_, "server");
+    EXPECT_EQ(SECSuccess, rv);
+    if (rv != SECSuccess) return false;
+  }
+
+  SECStatus rv = SSL_VersionRangeSet(ssl_fd_, &vrange_);
+  EXPECT_EQ(SECSuccess, rv);
+  if (rv != SECSuccess) return false;
+
+  rv = SSL_AuthCertificateHook(ssl_fd_, AuthCertificateHook,
+                               reinterpret_cast<void*>(this));
+  EXPECT_EQ(SECSuccess, rv);
+  if (rv != SECSuccess) return false;
+
+  return true;
+}
+
+void TlsAgent::StartConnect() {
+  EXPECT_TRUE(EnsureTlsSetup());
+
+  SECStatus rv;
+  rv = SSL_ResetHandshake(ssl_fd_, role_ == SERVER ? PR_TRUE : PR_FALSE);
+  EXPECT_EQ(SECSuccess, rv);
+  SetState(CONNECTING);
+}
+
+void TlsAgent::EnableSomeEcdheCiphers() {
+  EXPECT_TRUE(EnsureTlsSetup());
+
+  const uint32_t EcdheCiphers[] = {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+                                   TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+                                   TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                                   TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA};
+
+  for (size_t i = 0; i < PR_ARRAY_SIZE(EcdheCiphers); ++i) {
+    SECStatus rv = SSL_CipherPrefSet(ssl_fd_, EcdheCiphers[i], PR_TRUE);
+    EXPECT_EQ(SECSuccess, rv);
+  }
+}
+
+void TlsAgent::SetSessionTicketsEnabled(bool en) {
+  EXPECT_TRUE(EnsureTlsSetup());
+
+  SECStatus rv = SSL_OptionSet(ssl_fd_, SSL_ENABLE_SESSION_TICKETS,
+                               en ? PR_TRUE : PR_FALSE);
+  EXPECT_EQ(SECSuccess, rv);
+}
+
+void TlsAgent::SetSessionCacheEnabled(bool en) {
+  EXPECT_TRUE(EnsureTlsSetup());
+
+  SECStatus rv = SSL_OptionSet(ssl_fd_, SSL_NO_CACHE,
+                               en ? PR_FALSE : PR_TRUE);
+  EXPECT_EQ(SECSuccess, rv);
+}
+
+void TlsAgent::SetVersionRange(uint16_t minver, uint16_t maxver) {
+   vrange_.min = minver;
+   vrange_.max = maxver;
+
+   if (ssl_fd_) {
+     SECStatus rv = SSL_VersionRangeSet(ssl_fd_, &vrange_);
+     EXPECT_EQ(SECSuccess, rv);
+   }
+}
+
+void TlsAgent::CheckKEAType(SSLKEAType type) const {
+  EXPECT_EQ(CONNECTED, state_);
+  EXPECT_EQ(type, csinfo_.keaType);
+}
+
+void TlsAgent::CheckAuthType(SSLAuthType type) const {
+  EXPECT_EQ(CONNECTED, state_);
+  EXPECT_EQ(type, csinfo_.authAlgorithm);
+}
+
+void TlsAgent::CheckVersion(uint16_t version) const {
+  EXPECT_EQ(CONNECTED, state_);
+  EXPECT_EQ(version, info_.protocolVersion);
+}
+
+void TlsAgent::EnableAlpn(const uint8_t* val, size_t len) {
+  EXPECT_TRUE(EnsureTlsSetup());
+
+  EXPECT_EQ(SECSuccess, SSL_OptionSet(ssl_fd_, SSL_ENABLE_ALPN, PR_TRUE));
+  EXPECT_EQ(SECSuccess, SSL_SetNextProtoNego(ssl_fd_, val, len));
+}
+
+void TlsAgent::CheckAlpn(SSLNextProtoState expected_state,
+                         const std::string& expected) {
+  SSLNextProtoState state;
+  char chosen[10];
+  unsigned int chosen_len;
+  SECStatus rv = SSL_GetNextProto(ssl_fd_, &state,
+                                  reinterpret_cast<unsigned char*>(chosen),
+                                  &chosen_len, sizeof(chosen));
+  EXPECT_EQ(SECSuccess, rv);
+  EXPECT_EQ(expected_state, state);
+  EXPECT_EQ(expected, std::string(chosen, chosen_len));
+}
+
+void TlsAgent::EnableSrtp() {
+  EXPECT_TRUE(EnsureTlsSetup());
+  const uint16_t ciphers[] = {
+    SRTP_AES128_CM_HMAC_SHA1_80, SRTP_AES128_CM_HMAC_SHA1_32
+  };
+  EXPECT_EQ(SECSuccess, SSL_SetSRTPCiphers(ssl_fd_, ciphers,
+                                           PR_ARRAY_SIZE(ciphers)));
+
+}
+
+void TlsAgent::CheckSrtp() {
+  uint16_t actual;
+  EXPECT_EQ(SECSuccess, SSL_GetSRTPCipher(ssl_fd_, &actual));
+  EXPECT_EQ(SRTP_AES128_CM_HMAC_SHA1_80, actual);
+}
+
+void TlsAgent::CheckErrorCode(int32_t expected) const {
+  EXPECT_EQ(ERROR, state_);
+  EXPECT_EQ(expected, error_code_);
+}
+
+void TlsAgent::Handshake() {
+  SECStatus rv = SSL_ForceHandshake(ssl_fd_);
+  if (rv == SECSuccess) {
+    LOG("Handshake success");
+    SECStatus rv = SSL_GetChannelInfo(ssl_fd_, &info_, sizeof(info_));
+    EXPECT_EQ(SECSuccess, rv);
+
+    rv = SSL_GetCipherSuiteInfo(info_.cipherSuite, &csinfo_, sizeof(csinfo_));
+    EXPECT_EQ(SECSuccess, rv);
+
+    SetState(CONNECTED);
+    return;
+  }
+
+  int32_t err = PR_GetError();
+  switch (err) {
+    case PR_WOULD_BLOCK_ERROR:
+      LOG("Would have blocked");
+      // TODO(ekr@rtfm.com): set DTLS timeouts
+      Poller::Instance()->Wait(READABLE_EVENT, adapter_, this,
+                               &TlsAgent::ReadableCallback);
+      return;
+      break;
+
+      // TODO(ekr@rtfm.com): needs special case for DTLS
+    case SSL_ERROR_RX_MALFORMED_HANDSHAKE:
+    default:
+      LOG("Handshake failed with error " << err);
+      error_code_ = err;
+      SetState(ERROR);
+      return;
+  }
+}
+
+void TlsAgent::ConfigureSessionCache(SessionResumptionMode mode) {
+  EXPECT_TRUE(EnsureTlsSetup());
+
+  SECStatus rv = SSL_OptionSet(ssl_fd_,
+                               SSL_NO_CACHE,
+                               mode & RESUME_SESSIONID ?
+                               PR_FALSE : PR_TRUE);
+  EXPECT_EQ(SECSuccess, rv);
+
+  rv = SSL_OptionSet(ssl_fd_,
+                     SSL_ENABLE_SESSION_TICKETS,
+                     mode & RESUME_TICKET ?
+                     PR_TRUE : PR_FALSE);
+  EXPECT_EQ(SECSuccess, rv);
+}
+
+
+} // namespace nss_test
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/tls_agent.h
@@ -0,0 +1,193 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef tls_agent_h_
+#define tls_agent_h_
+
+#include "prio.h"
+#include "ssl.h"
+
+#include <iostream>
+
+#include "test_io.h"
+
+#define GTEST_HAS_RTTI 0
+#include "gtest/gtest.h"
+
+namespace nss_test {
+
+#define LOG(msg) std::cerr << name_ << ": " << msg << std::endl
+
+enum SessionResumptionMode {
+  RESUME_NONE = 0,
+  RESUME_SESSIONID = 1,
+  RESUME_TICKET = 2,
+  RESUME_BOTH = RESUME_SESSIONID | RESUME_TICKET
+};
+
+class TlsAgent : public PollTarget {
+ public:
+  enum Role { CLIENT, SERVER };
+  enum State { INIT, CONNECTING, CONNECTED, ERROR };
+
+  TlsAgent(const std::string& name, Role role, Mode mode, SSLKEAType kea)
+      : name_(name),
+        mode_(mode),
+        kea_(kea),
+        pr_fd_(nullptr),
+        adapter_(nullptr),
+        ssl_fd_(nullptr),
+        role_(role),
+        state_(INIT),
+        error_code_(0) {
+      memset(&info_, 0, sizeof(info_));
+      memset(&csinfo_, 0, sizeof(csinfo_));
+      SECStatus rv = SSL_VersionRangeGetDefault(mode_ == STREAM ?
+                                                ssl_variant_stream : ssl_variant_datagram,
+                                                &vrange_);
+      EXPECT_EQ(SECSuccess, rv);
+  }
+
+  ~TlsAgent() {
+    if (pr_fd_) {
+      PR_Close(pr_fd_);
+    }
+
+    if (ssl_fd_) {
+      PR_Close(ssl_fd_);
+    }
+  }
+
+  bool Init() {
+    pr_fd_ = DummyPrSocket::CreateFD(name_, mode_);
+    if (!pr_fd_) return false;
+
+    adapter_ = DummyPrSocket::GetAdapter(pr_fd_);
+    if (!adapter_) return false;
+
+    return true;
+  }
+
+  void SetPeer(TlsAgent* peer) { adapter_->SetPeer(peer->adapter_); }
+
+  void SetPacketFilter(PacketFilter* filter) {
+    adapter_->SetPacketFilter(filter);
+  }
+
+
+  void StartConnect();
+  void CheckKEAType(SSLKEAType type) const;
+  void CheckAuthType(SSLAuthType type) const;
+  void CheckVersion(uint16_t version) const;
+
+  void Handshake();
+  void EnableSomeEcdheCiphers();
+  bool EnsureTlsSetup();
+
+  void ConfigureSessionCache(SessionResumptionMode mode);
+  void SetSessionTicketsEnabled(bool en);
+  void SetSessionCacheEnabled(bool en);
+  void SetVersionRange(uint16_t minver, uint16_t maxver);
+  void EnableAlpn(const uint8_t* val, size_t len);
+  void CheckAlpn(SSLNextProtoState expected_state,
+                 const std::string& expected);
+  void EnableSrtp();
+  void CheckSrtp();
+  void CheckErrorCode(int32_t expected) const;
+
+  State state() const { return state_; }
+
+  const char* state_str() const { return state_str(state()); }
+
+  const char* state_str(State state) const { return states[state]; }
+
+  PRFileDesc* ssl_fd() { return ssl_fd_; }
+
+  uint16_t min_version() const { return vrange_.min; }
+  uint16_t max_version() const { return vrange_.max; }
+
+  bool version(uint16_t* version) const {
+    if (state_ != CONNECTED) return false;
+
+    *version = info_.protocolVersion;
+
+    return true;
+  }
+
+  uint16_t version() const {
+    EXPECT_EQ(CONNECTED, state_);
+
+    return info_.protocolVersion;
+  }
+
+  bool cipher_suite(int16_t* cipher_suite) const {
+    if (state_ != CONNECTED) return false;
+
+    *cipher_suite = info_.cipherSuite;
+    return true;
+  }
+
+  std::string cipher_suite_name() const {
+    if (state_ != CONNECTED) return "UNKNOWN";
+
+    return csinfo_.cipherSuiteName;
+  }
+
+  std::vector<uint8_t> session_id() const {
+    return std::vector<uint8_t>(info_.sessionID,
+                                info_.sessionID + info_.sessionIDLength);
+  }
+
+ private:
+  const static char* states[];
+
+  void SetState(State state) {
+    if (state_ == state) return;
+
+    LOG("Changing state from " << state_str(state_) << " to "
+                               << state_str(state));
+    state_ = state;
+  }
+
+  // Dummy auth certificate hook.
+  static SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd,
+                                       PRBool checksig, PRBool isServer) {
+    return SECSuccess;
+  }
+
+  static void ReadableCallback(PollTarget* self, Event event) {
+    TlsAgent* agent = static_cast<TlsAgent*>(self);
+    agent->ReadableCallback_int();
+  }
+
+  void ReadableCallback_int() {
+    LOG("Readable");
+    Handshake();
+  }
+
+  static PRInt32 SniHook(PRFileDesc *fd, const SECItem *srvNameArr,
+                         PRUint32 srvNameArrSize,
+                         void *arg) {
+    return SSL_SNI_CURRENT_CONFIG_IS_USED;
+  }
+
+  const std::string name_;
+  Mode mode_;
+  SSLKEAType kea_;
+  PRFileDesc* pr_fd_;
+  DummyPrSocket* adapter_;
+  PRFileDesc* ssl_fd_;
+  Role role_;
+  State state_;
+  SSLChannelInfo info_;
+  SSLCipherSuiteInfo csinfo_;
+  SSLVersionRange vrange_;
+  int32_t error_code_;
+};
+
+}  // namespace nss_test
+
+#endif
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/tls_connect.cc
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "tls_connect.h"
+
+#include <iostream>
+
+#include "sslproto.h"
+#include "gtest_utils.h"
+
+extern std::string g_working_dir_path;
+
+namespace nss_test {
+
+static const std::string kTlsModesStreamArr[] = {"TLS"};
+::testing::internal::ParamGenerator<std::string>
+  TlsConnectTestBase::kTlsModesStream = ::testing::ValuesIn(kTlsModesStreamArr);
+static const std::string kTlsModesAllArr[] = {"TLS", "DTLS"};
+::testing::internal::ParamGenerator<std::string>
+  TlsConnectTestBase::kTlsModesAll = ::testing::ValuesIn(kTlsModesAllArr);
+static const uint16_t kTlsV10Arr[] = {SSL_LIBRARY_VERSION_TLS_1_0};
+::testing::internal::ParamGenerator<uint16_t>
+  TlsConnectTestBase::kTlsV10 = ::testing::ValuesIn(kTlsV10Arr);
+static const uint16_t kTlsV11V12Arr[] = {SSL_LIBRARY_VERSION_TLS_1_1,
+                                         SSL_LIBRARY_VERSION_TLS_1_2};
+::testing::internal::ParamGenerator<uint16_t>
+  TlsConnectTestBase::kTlsV11V12 = ::testing::ValuesIn(kTlsV11V12Arr);
+// TODO: add TLS 1.3
+static const uint16_t kTlsV12PlusArr[] = {SSL_LIBRARY_VERSION_TLS_1_2};
+::testing::internal::ParamGenerator<uint16_t>
+  TlsConnectTestBase::kTlsV12Plus = ::testing::ValuesIn(kTlsV12PlusArr);
+
+static std::string VersionString(uint16_t version) {
+  switch(version) {
+  case 0:
+    return "(no version)";
+  case SSL_LIBRARY_VERSION_TLS_1_0:
+    return "1.0";
+  case SSL_LIBRARY_VERSION_TLS_1_1:
+    return "1.1";
+  case SSL_LIBRARY_VERSION_TLS_1_2:
+    return "1.2";
+  default:
+    std::cerr << "Invalid version: " << version << std::endl;
+    EXPECT_TRUE(false);
+    return "";
+  }
+}
+
+TlsConnectTestBase::TlsConnectTestBase(Mode mode, uint16_t version)
+      : mode_(mode),
+        client_(new TlsAgent("client", TlsAgent::CLIENT, mode_, ssl_kea_rsa)),
+        server_(new TlsAgent("server", TlsAgent::SERVER, mode_, ssl_kea_rsa)),
+        version_(version),
+        session_ids_() {
+  std::cerr << "Version: " << mode_ << " " << VersionString(version_) << std::endl;
+}
+
+TlsConnectTestBase::~TlsConnectTestBase() {
+  delete client_;
+  delete server_;
+}
+
+void TlsConnectTestBase::SetUp() {
+  // Configure a fresh session cache.
+  SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str());
+
+  // Clear statistics.
+  SSL3Statistics* stats = SSL_GetStatistics();
+  memset(stats, 0, sizeof(*stats));
+
+  Init();
+}
+
+void TlsConnectTestBase::TearDown() {
+  client_ = nullptr;
+  server_ = nullptr;
+
+  SSL_ClearSessionCache();
+  SSL_ShutdownServerSessionIDCache();
+}
+
+void TlsConnectTestBase::Init() {
+  EXPECT_TRUE(client_->Init());
+  EXPECT_TRUE(server_->Init());
+
+  client_->SetPeer(server_);
+  server_->SetPeer(client_);
+
+  if (version_) {
+    client_->SetVersionRange(version_, version_);
+    server_->SetVersionRange(version_, version_);
+  }
+}
+
+void TlsConnectTestBase::Reset(const std::string& server_name, SSLKEAType kea) {
+  delete client_;
+  delete server_;
+
+  client_ = new TlsAgent("client", TlsAgent::CLIENT, mode_, kea);
+  server_ = new TlsAgent(server_name, TlsAgent::SERVER, mode_, kea);
+
+  Init();
+}
+
+void TlsConnectTestBase::ResetRsa() {
+  Reset("server", ssl_kea_rsa);
+}
+
+void TlsConnectTestBase::ResetEcdsa() {
+  Reset("ecdsa", ssl_kea_ecdh);
+  EnableSomeEcdheCiphers();
+}
+
+void TlsConnectTestBase::EnsureTlsSetup() {
+  EXPECT_TRUE(client_->EnsureTlsSetup());
+  EXPECT_TRUE(server_->EnsureTlsSetup());
+}
+
+void TlsConnectTestBase::Handshake() {
+  server_->StartConnect();
+  client_->StartConnect();
+  client_->Handshake();
+  server_->Handshake();
+
+  ASSERT_TRUE_WAIT((client_->state() != TlsAgent::CONNECTING) &&
+                   (server_->state() != TlsAgent::CONNECTING),
+                   5000);
+
+}
+
+void TlsConnectTestBase::Connect() {
+  Handshake();
+
+  // Check the version is as expected
+  EXPECT_EQ(client_->version(), server_->version());
+  EXPECT_EQ(std::min(client_->max_version(),
+                     server_->max_version()),
+            client_->version());
+
+  EXPECT_EQ(TlsAgent::CONNECTED, client_->state());
+  EXPECT_EQ(TlsAgent::CONNECTED, server_->state());
+
+  int16_t cipher_suite1, cipher_suite2;
+  bool ret = client_->cipher_suite(&cipher_suite1);
+  EXPECT_TRUE(ret);
+  ret = server_->cipher_suite(&cipher_suite2);
+  EXPECT_TRUE(ret);
+  EXPECT_EQ(cipher_suite1, cipher_suite2);
+
+  std::cerr << "Connected with version " << client_->version()
+            << " cipher suite " << client_->cipher_suite_name()
+            << std::endl;
+
+  // Check and store session ids.
+  std::vector<uint8_t> sid_c1 = client_->session_id();
+  EXPECT_EQ(32U, sid_c1.size());
+  std::vector<uint8_t> sid_s1 = server_->session_id();
+  EXPECT_EQ(32U, sid_s1.size());
+  EXPECT_EQ(sid_c1, sid_s1);
+  session_ids_.push_back(sid_c1);
+}
+
+void TlsConnectTestBase::ConnectExpectFail() {
+  Handshake();
+
+  ASSERT_EQ(TlsAgent::ERROR, client_->state());
+  ASSERT_EQ(TlsAgent::ERROR, server_->state());
+}
+
+void TlsConnectTestBase::EnableSomeEcdheCiphers() {
+  client_->EnableSomeEcdheCiphers();
+  server_->EnableSomeEcdheCiphers();
+}
+
+
+void TlsConnectTestBase::ConfigureSessionCache(SessionResumptionMode client,
+                                               SessionResumptionMode server) {
+  client_->ConfigureSessionCache(client);
+  server_->ConfigureSessionCache(server);
+}
+
+void TlsConnectTestBase::CheckResumption(SessionResumptionMode expected) {
+  EXPECT_NE(RESUME_BOTH, expected);
+
+  int resume_ct = expected ? 1 : 0;
+  int stateless_ct = (expected & RESUME_TICKET) ? 1 : 0;
+
+  SSL3Statistics* stats = SSL_GetStatistics();
+  EXPECT_EQ(resume_ct, stats->hch_sid_cache_hits);
+  EXPECT_EQ(resume_ct, stats->hsh_sid_cache_hits);
+
+  EXPECT_EQ(stateless_ct, stats->hch_sid_stateless_resumes);
+  EXPECT_EQ(stateless_ct, stats->hsh_sid_stateless_resumes);
+
+  if (resume_ct) {
+    // Check that the last two session ids match.
+    EXPECT_GE(2U, session_ids_.size());
+    EXPECT_EQ(session_ids_[session_ids_.size()-1],
+              session_ids_[session_ids_.size()-2]);
+  }
+}
+
+void TlsConnectTestBase::EnableAlpn() {
+  // A simple value of "a", "b".  Note that the preferred value of "a" is placed
+  // at the end, because the NSS API follows the now defunct NPN specification,
+  // which places the preferred (and default) entry at the end of the list.
+  // NSS will move this final entry to the front when used with ALPN.
+  static const uint8_t val[] = { 0x01, 0x62, 0x01, 0x61 };
+  client_->EnableAlpn(val, sizeof(val));
+  server_->EnableAlpn(val, sizeof(val));
+}
+
+void TlsConnectTestBase::EnableSrtp() {
+  client_->EnableSrtp();
+  server_->EnableSrtp();
+}
+
+void TlsConnectTestBase::CheckSrtp() {
+  client_->CheckSrtp();
+  server_->CheckSrtp();
+}
+
+TlsConnectGeneric::TlsConnectGeneric()
+  : TlsConnectTestBase(TlsConnectTestBase::ToMode(std::get<0>(GetParam())),
+                       std::get<1>(GetParam())) {}
+
+} // namespace nss_test
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/tls_connect.h
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef tls_connect_h_
+#define tls_connect_h_
+
+#include <tuple>
+
+#include "sslt.h"
+
+#include "tls_agent.h"
+
+#define GTEST_HAS_RTTI 0
+#include "gtest/gtest.h"
+
+namespace nss_test {
+
+// A generic TLS connection test base.
+class TlsConnectTestBase : public ::testing::Test {
+ public:
+  static ::testing::internal::ParamGenerator<std::string> kTlsModesStream;
+  static ::testing::internal::ParamGenerator<std::string> kTlsModesAll;
+  static ::testing::internal::ParamGenerator<uint16_t> kTlsV10;
+  static ::testing::internal::ParamGenerator<uint16_t> kTlsV11V12;
+  static ::testing::internal::ParamGenerator<uint16_t> kTlsV12Plus;
+
+  static inline Mode ToMode(const std::string& str) {
+    return str == "TLS" ? STREAM : DGRAM;
+  }
+
+  TlsConnectTestBase(Mode mode, uint16_t version);
+  virtual ~TlsConnectTestBase();
+
+  void SetUp();
+  void TearDown();
+
+  // Initialize client and server.
+  void Init();
+  // Re-initialize client and server with the default RSA cert.
+  void ResetRsa();
+  // Re-initialize client and server with an ECDSA cert on the server
+  // and some ECDHE suites.
+  void ResetEcdsa();
+  // Make sure TLS is configured for a connection.
+  void EnsureTlsSetup();
+
+  // Run the handshake.
+  void Handshake();
+  // Connect and check that it works.
+  void Connect();
+  // Connect and expect it to fail.
+  void ConnectExpectFail();
+
+  void EnableSomeEcdheCiphers();
+  void ConfigureSessionCache(SessionResumptionMode client,
+                             SessionResumptionMode server);
+  void CheckResumption(SessionResumptionMode expected);
+  void EnableAlpn();
+  void EnableSrtp();
+  void CheckSrtp();
+ protected:
+
+  Mode mode_;
+  TlsAgent* client_;
+  TlsAgent* server_;
+  uint16_t version_;
+  std::vector<std::vector<uint8_t>> session_ids_;
+
+ private:
+  void Reset(const std::string& server_name, SSLKEAType kea);
+};
+
+// A TLS-only test base.
+class TlsConnectStream : public TlsConnectTestBase,
+                         public ::testing::WithParamInterface<uint16_t> {
+ public:
+  TlsConnectStream() : TlsConnectTestBase(STREAM, GetParam()) {}
+};
+
+// A DTLS-only test base.
+class TlsConnectDatagram : public TlsConnectTestBase,
+                           public ::testing::WithParamInterface<uint16_t> {
+ public:
+  TlsConnectDatagram() : TlsConnectTestBase(DGRAM, GetParam()) {}
+};
+
+// A generic test class that can be either STREAM or DGRAM and a single version
+// of TLS.  This is configured in ssl_loopback_unittest.cc.  All uses of this
+// should use TEST_P().
+class TlsConnectGeneric
+  : public TlsConnectTestBase,
+    public ::testing::WithParamInterface<std::tuple<std::string, uint16_t>> {
+ public:
+  TlsConnectGeneric();
+};
+
+} // namespace nss_test
+
+#endif
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/tls_filter.cc
@@ -0,0 +1,232 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "tls_filter.h"
+
+#include <iostream>
+
+namespace nss_test {
+
+bool TlsRecordFilter::Filter(const DataBuffer& input, DataBuffer* output) {
+  bool changed = false;
+  size_t output_offset = 0U;
+  output->Allocate(input.len());
+
+  TlsParser parser(input);
+  while (parser.remaining()) {
+    size_t start = parser.consumed();
+    uint8_t content_type;
+    if (!parser.Read(&content_type)) {
+      return false;
+    }
+    uint32_t version;
+    if (!parser.Read(&version, 2)) {
+      return false;
+    }
+
+    if (IsDtls(version)) {
+      if (!parser.Skip(8)) {
+        return false;
+      }
+    }
+    size_t header_len = parser.consumed() - start;
+    output->Write(output_offset, input.data() + start, header_len);
+
+    DataBuffer record;
+    if (!parser.ReadVariable(&record, 2)) {
+      return false;
+    }
+
+    // Move the offset in the output forward.  ApplyFilter() returns the index
+    // of the end of the record it wrote to the output, so we need to skip
+    // over the content type and version for the value passed to it.
+    output_offset = ApplyFilter(content_type, version, record, output,
+                                output_offset + header_len,
+                                &changed);
+  }
+  output->Truncate(output_offset);
+
+  // Record how many packets we actually touched.
+  if (changed) {
+    ++count_;
+  }
+
+  return changed;
+}
+
+size_t TlsRecordFilter::ApplyFilter(uint8_t content_type, uint16_t version,
+                                    const DataBuffer& record,
+                                    DataBuffer* output,
+                                    size_t offset, bool* changed) {
+  const DataBuffer* source = &record;
+  DataBuffer filtered;
+  if (FilterRecord(content_type, version, record, &filtered) &&
+      filtered.len() < 0x10000) {
+    *changed = true;
+    std::cerr << "record old: " << record << std::endl;
+    std::cerr << "record new: " << filtered << std::endl;
+    source = &filtered;
+  }
+
+  output->Write(offset, source->len(), 2);
+  output->Write(offset + 2, *source);
+  return offset + 2 + source->len();
+}
+
+bool TlsHandshakeFilter::FilterRecord(uint8_t content_type, uint16_t version,
+                                      const DataBuffer& input,
+                                      DataBuffer* output) {
+  // Check that the first byte is as requested.
+  if (content_type != kTlsHandshakeType) {
+    return false;
+  }
+
+  bool changed = false;
+  size_t output_offset = 0U;
+  output->Allocate(input.len()); // Preallocate a little.
+
+  TlsParser parser(input);
+  while (parser.remaining()) {
+    size_t start = parser.consumed();
+    uint8_t handshake_type;
+    if (!parser.Read(&handshake_type)) {
+      return false; // malformed
+    }
+    uint32_t length;
+    if (!ReadLength(&parser, version, &length)) {
+      return false;
+    }
+
+    size_t header_len = parser.consumed() - start;
+    output->Write(output_offset, input.data() + start, header_len);
+
+    DataBuffer handshake;
+    if (!parser.Read(&handshake, length)) {
+      return false;
+    }
+
+    // Move the offset in the output forward.  ApplyFilter() returns the index
+    // of the end of the message it wrote to the output, so we need to identify
+    // offsets from the start of the message for length and the handshake
+    // message.
+    output_offset = ApplyFilter(version, handshake_type, handshake,
+                                output, output_offset + 1,
+                                output_offset + header_len,
+                                &changed);
+  }
+  output->Truncate(output_offset);
+  return changed;
+}
+
+bool TlsHandshakeFilter::ReadLength(TlsParser* parser, uint16_t version, uint32_t *length) {
+  if (!parser->Read(length, 3)) {
+    return false; // malformed
+  }
+
+  if (!IsDtls(version)) {
+    return true; // nothing left to do
+  }
+
+  // Read and check DTLS parameters
+  if (!parser->Skip(2)) { // sequence number
+    return false;
+  }
+
+  uint32_t fragment_offset;
+  if (!parser->Read(&fragment_offset, 3)) {
+    return false;
+  }
+
+  uint32_t fragment_length;
+  if (!parser->Read(&fragment_length, 3)) {
+    return false;
+  }
+
+  // All current tests where we are using this code don't fragment.
+  return (fragment_offset == 0 && fragment_length == *length);
+}
+
+size_t TlsHandshakeFilter::ApplyFilter(
+    uint16_t version, uint8_t handshake_type, const DataBuffer& handshake,
+    DataBuffer* output, size_t length_offset, size_t value_offset,
+    bool* changed) {
+  const DataBuffer* source = &handshake;
+  DataBuffer filtered;
+  if (FilterHandshake(version, handshake_type, handshake, &filtered) &&
+      filtered.len() < 0x1000000) {
+    *changed = true;
+    std::cerr << "handshake old: " << handshake << std::endl;
+    std::cerr << "handshake new: " << filtered << std::endl;
+    source = &filtered;
+  }
+
+  // Back up and overwrite the (two) length field(s): the handshake message
+  // length and the DTLS fragment length.
+  output->Write(length_offset, source->len(), 3);
+  if (IsDtls(version)) {
+    output->Write(length_offset + 8, source->len(), 3);
+  }
+  output->Write(value_offset, *source);
+  return value_offset + source->len();
+}
+
+bool TlsInspectorRecordHandshakeMessage::FilterHandshake(
+    uint16_t version, uint8_t handshake_type,
+    const DataBuffer& input, DataBuffer* output) {
+  // Only do this once.
+  if (buffer_.len()) {
+    return false;
+  }
+
+  if (handshake_type == handshake_type_) {
+    buffer_ = input;
+  }
+  return false;
+}
+
+bool TlsAlertRecorder::FilterRecord(uint8_t content_type, uint16_t version,
+                                    const DataBuffer& input, DataBuffer* output) {
+  if (level_ == kTlsAlertFatal) { // already fatal
+    return false;
+  }
+  if (content_type != kTlsAlertType) {
+    return false;
+  }
+
+  std::cerr << "Alert: " << input << std::endl;
+
+  TlsParser parser(input);
+  uint8_t lvl;
+  if (!parser.Read(&lvl)) {
+    return false;
+  }
+  if (lvl == kTlsAlertWarning) { // not strong enough
+    return false;
+  }
+  level_ = lvl;
+  (void)parser.Read(&description_);
+  return false;
+}
+
+ChainedPacketFilter::~ChainedPacketFilter() {
+  for (auto it = filters_.begin(); it != filters_.end(); ++it) {
+    delete *it;
+  }
+}
+
+bool ChainedPacketFilter::Filter(const DataBuffer& input, DataBuffer* output) {
+  DataBuffer in(input);
+  bool changed = false;
+  for (auto it = filters_.begin(); it != filters_.end(); ++it) {
+    if ((*it)->Filter(in, output)) {
+      in = *output;
+      changed = true;
+    }
+  }
+  return changed;
+}
+
+}  // namespace nss_test
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/tls_filter.h
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef tls_filter_h_
+#define tls_filter_h_
+
+#include <memory>
+#include <vector>
+
+#include "test_io.h"
+#include "tls_parser.h"
+
+namespace nss_test {
+
+// Abstract filter that operates on entire (D)TLS records.
+class TlsRecordFilter : public PacketFilter {
+ public:
+  TlsRecordFilter() : count_(0) {}
+
+  virtual bool Filter(const DataBuffer& input, DataBuffer* output);
+
+  // Report how many packets were altered by the filter.
+  size_t filtered_packets() const { return count_; }
+
+ protected:
+  virtual bool FilterRecord(uint8_t content_type, uint16_t version,
+                            const DataBuffer& data, DataBuffer* changed) = 0;
+ private:
+  size_t ApplyFilter(uint8_t content_type, uint16_t version,
+                     const DataBuffer& record, DataBuffer* output,
+                     size_t offset, bool* changed);
+
+  size_t count_;
+};
+
+// Abstract filter that operates on handshake messages rather than records.
+// This assumes that the handshake messages are written in a block as entire
+// records and that they don't span records or anything crazy like that.
+class TlsHandshakeFilter : public TlsRecordFilter {
+ public:
+  TlsHandshakeFilter() {}
+
+  // Reads the length from the record header.
+  // This also reads the DTLS fragment information and checks it.
+  static bool ReadLength(TlsParser* parser, uint16_t version, uint32_t *length);
+
+ protected:
+  virtual bool FilterRecord(uint8_t content_type, uint16_t version,
+                            const DataBuffer& input, DataBuffer* output);
+  virtual bool FilterHandshake(uint16_t version, uint8_t handshake_type,
+                               const DataBuffer& input, DataBuffer* output) = 0;
+
+ private:
+  size_t ApplyFilter(uint16_t version, uint8_t handshake_type,
+                     const DataBuffer& record, DataBuffer* output,
+                     size_t length_offset, size_t value_offset, bool* changed);
+};
+
+// Make a copy of the first instance of a handshake message.
+class TlsInspectorRecordHandshakeMessage : public TlsHandshakeFilter {
+ public:
+  TlsInspectorRecordHandshakeMessage(uint8_t handshake_type)
+      : handshake_type_(handshake_type), buffer_() {}
+
+  virtual bool FilterHandshake(uint16_t version, uint8_t handshake_type,
+                               const DataBuffer& input, DataBuffer* output);
+
+  const DataBuffer& buffer() const { return buffer_; }
+
+ private:
+  uint8_t handshake_type_;
+  DataBuffer buffer_;
+};
+
+// Records an alert.  If an alert has already been recorded, it won't save the
+// new alert unless the old alert is a warning and the new one is fatal.
+class TlsAlertRecorder : public TlsRecordFilter {
+ public:
+  TlsAlertRecorder() : level_(255), description_(255) {}
+
+  virtual bool FilterRecord(uint8_t content_type, uint16_t version,
+                            const DataBuffer& input, DataBuffer* output);
+
+  uint8_t level() const { return level_; }
+  uint8_t description() const { return description_; }
+
+ private:
+  uint8_t level_;
+  uint8_t description_;
+};
+
+// Runs multiple packet filters in series.
+class ChainedPacketFilter : public PacketFilter {
+ public:
+  ChainedPacketFilter() {}
+  ChainedPacketFilter(const std::vector<PacketFilter*> filters)
+      : filters_(filters.begin(), filters.end()) {}
+  virtual ~ChainedPacketFilter();
+
+  virtual bool Filter(const DataBuffer& input, DataBuffer* output);
+
+  // Takes ownership of the filter.
+  void Add(PacketFilter* filter) {
+    filters_.push_back(filter);
+  }
+
+ private:
+  std::vector<PacketFilter*> filters_;
+};
+
+}  // namespace nss_test
+
+#endif
--- a/security/nss/external_tests/ssl_gtest/tls_parser.cc
+++ b/security/nss/external_tests/ssl_gtest/tls_parser.cc
@@ -1,57 +1,71 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "tls_parser.h"
 
-// Process DTLS Records
-#define CHECK_LENGTH(expected)                \
-  do {                                        \
-    if (remaining() < expected) return false; \
-  } while (0)
+namespace nss_test {
 
-bool TlsParser::Read(unsigned char* val) {
+bool TlsParser::Read(uint8_t* val) {
   if (remaining() < 1) {
     return false;
   }
   *val = *ptr();
   consume(1);
   return true;
 }
 
-bool TlsParser::Read(unsigned char* val, size_t len) {
+bool TlsParser::Read(uint32_t* val, size_t size) {
+  if (size > sizeof(uint32_t)) {
+    return false;
+  }
+
+  uint32_t v = 0;
+  for (size_t i = 0; i < size; ++i) {
+    uint8_t tmp;
+    if (!Read(&tmp)) {
+      return false;
+    }
+
+    v = (v << 8) | tmp;
+  }
+
+  *val = v;
+  return true;
+}
+
+bool TlsParser::Read(DataBuffer* val, size_t len) {
   if (remaining() < len) {
     return false;
   }
 
-  if (val) {
-    memcpy(val, ptr(), len);
-  }
+  val->Assign(ptr(), len);
   consume(len);
-
   return true;
 }
 
-bool TlsRecordParser::NextRecord(uint8_t* ct,
-                                 std::auto_ptr<DataBuffer>* buffer) {
-  if (!remaining()) return false;
-
-  CHECK_LENGTH(5U);
-  const uint8_t* ctp = reinterpret_cast<const uint8_t*>(ptr());
-  consume(3);  // ct + version
+bool TlsParser::ReadVariable(DataBuffer* val, size_t len_size) {
+  uint32_t len;
+  if (!Read(&len, len_size)) {
+    return false;
+  }
+  return Read(val, len);
+}
 
-  const uint16_t* tmp = reinterpret_cast<const uint16_t*>(ptr());
-  size_t length = ntohs(*tmp);
-  consume(2);
-
-  CHECK_LENGTH(length);
-  DataBuffer* db = new DataBuffer(ptr(), length);
-  consume(length);
-
-  *ct = *ctp;
-  buffer->reset(db);
-
+bool TlsParser::Skip(size_t len) {
+  if (len > remaining()) { return false; }
+  consume(len);
   return true;
 }
+
+bool TlsParser::SkipVariable(size_t len_size) {
+  uint32_t len;
+  if (!Read(&len, len_size)) {
+    return false;
+  }
+  return Skip(len);
+}
+
+} // namespace nss_test
--- a/security/nss/external_tests/ssl_gtest/tls_parser.h
+++ b/security/nss/external_tests/ssl_gtest/tls_parser.h
@@ -3,81 +3,96 @@
 /* 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 tls_parser_h_
 #define tls_parser_h_
 
 #include <memory>
-#include <stdint.h>
-#include <string.h>
+#include <cstdint>
+#include <cstring>
 #include <arpa/inet.h>
 #include "databuffer.h"
 
-const uint8_t kTlsChangeCipherSpecType = 0x14;
-const uint8_t kTlsHandshakeType = 0x16;
+namespace nss_test {
+
+const uint8_t kTlsChangeCipherSpecType = 20;
+const uint8_t kTlsAlertType = 21;
+const uint8_t kTlsHandshakeType = 22;
 
-const uint8_t kTlsHandshakeCertificate = 0x0b;
-const uint8_t kTlsHandshakeServerKeyExchange = 0x0c;
+const uint8_t kTlsHandshakeClientHello = 1;
+const uint8_t kTlsHandshakeServerHello = 2;
+const uint8_t kTlsHandshakeCertificate = 11;
+const uint8_t kTlsHandshakeServerKeyExchange = 12;
+
+const uint8_t kTlsAlertWarning = 1;
+const uint8_t kTlsAlertFatal = 2;
+
+const uint8_t kTlsAlertUnexpectedMessage = 10;
+const uint8_t kTlsAlertHandshakeFailure = 40;
+const uint8_t kTlsAlertIllegalParameter = 47;
+const uint8_t kTlsAlertDecodeError = 50;
+const uint8_t kTlsAlertUnsupportedExtension = 110;
+const uint8_t kTlsAlertNoApplicationProtocol = 120;
 
 const uint8_t kTlsFakeChangeCipherSpec[] = {
     kTlsChangeCipherSpecType,        // Type
     0xfe,                     0xff,  // Version
     0x00,                     0x00, 0x00, 0x00,
     0x00,                     0x00, 0x00, 0x10,  // Fictitious sequence #
     0x00,                     0x01,              // Length
     0x01                                         // Value
 };
 
+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;
+  }
+  return version;
+}
+
+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());
+}
+
 class TlsParser {
  public:
-  TlsParser(const unsigned char *data, size_t len)
+  TlsParser(const uint8_t* data, size_t len)
       : buffer_(data, len), offset_(0) {}
-
-  bool Read(unsigned char *val);
-
-  // Read an integral type of specified width.
-  bool Read(uint32_t *val, size_t len) {
-    if (len > sizeof(uint32_t)) return false;
-
-    *val = 0;
+  explicit TlsParser(const DataBuffer& buf)
+      : buffer_(buf), offset_(0) {}
 
-    for (size_t i = 0; i < len; ++i) {
-      unsigned char tmp;
-
-      (*val) <<= 8;
-      if (!Read(&tmp)) return false;
+  bool Read(uint8_t* val);
+  // Read an integral type of specified width.
+  bool Read(uint32_t* val, size_t size);
+  // Reads len bytes into dest buffer, overwriting it.
+  bool Read(DataBuffer* dest, size_t len);
+  // Reads bytes into dest buffer, overwriting it.  The number of bytes is
+  // determined by reading from len_size bytes from the stream first.
+  bool ReadVariable(DataBuffer* dest, size_t len_size);
 
-      *val += tmp;
-    }
+  bool Skip(size_t len);
+  bool SkipVariable(size_t len_size);
 
-    return true;
-  }
-
-  bool Read(unsigned char *val, size_t len);
+  size_t consumed() const { return offset_; }
   size_t remaining() const { return buffer_.len() - offset_; }
 
  private:
   void consume(size_t len) { offset_ += len; }
-  const uint8_t *ptr() const { return buffer_.data() + offset_; }
+  const uint8_t* ptr() const { return buffer_.data() + offset_; }
 
   DataBuffer buffer_;
   size_t offset_;
 };
 
-class TlsRecordParser {
- public:
-  TlsRecordParser(const unsigned char *data, size_t len)
-      : buffer_(data, len), offset_(0) {}
-
-  bool NextRecord(uint8_t *ct, std::auto_ptr<DataBuffer> *buffer);
-
- private:
-  size_t remaining() const { return buffer_.len() - offset_; }
-  const uint8_t *ptr() const { return buffer_.data() + offset_; }
-  void consume(size_t len) { offset_ += len; }
-
-  DataBuffer buffer_;
-  size_t offset_;
-};
+} // namespace nss_test
 
 #endif
--- a/security/nss/lib/certdb/cert.h
+++ b/security/nss/lib/certdb/cert.h
@@ -924,25 +924,19 @@ CERT_DecodeOidSequence(const SECItem *se
 extern SECStatus CERT_FindCertExtension
    (const CERTCertificate *cert, int tag, SECItem *value);
 
 extern SECStatus CERT_FindNSCertTypeExtension
    (CERTCertificate *cert, SECItem *value);
 
 extern char * CERT_FindNSStringExtension (CERTCertificate *cert, int oidtag);
 
-extern SECStatus CERT_FindIssuerCertExtension
-   (CERTCertificate *cert, int tag, SECItem *value);
-
 extern SECStatus CERT_FindCertExtensionByOID
    (CERTCertificate *cert, SECItem *oid, SECItem *value);
 
-extern char *CERT_FindCertURLExtension (CERTCertificate *cert, int tag, 
-								int catag);
-
 /* Returns the decoded value of the authKeyID extension.
 **   Note that this uses passed in the arena to allocate storage for the result
 */
 extern CERTAuthKeyID * CERT_FindAuthKeyIDExten (PLArenaPool *arena,CERTCertificate *cert);
 
 /* Returns the decoded value of the basicConstraint extension.
  */
 extern SECStatus CERT_FindBasicConstraintExten
@@ -1173,16 +1167,30 @@ extern CERTPrivKeyUsagePeriod *
 CERT_DecodePrivKeyUsagePeriodExtension(PLArenaPool *arena, SECItem *extnValue);
 
 extern CERTGeneralName *
 CERT_GetNextGeneralName(CERTGeneralName *current);
 
 extern CERTGeneralName *
 CERT_GetPrevGeneralName(CERTGeneralName *current);
 
+/*
+ * Look up name constraints for some certs that do not include name constraints
+ * (Most importantly, root certificates)
+ *
+ * If a matching subject is found, |extensions| will be populated with a copy of the
+ * DER-encoded name constraints extension. The data in |extensions| will point to
+ * memory that the caller owns.
+ *
+ * There is no mechanism to configure imposed name constraints right now.  All
+ * imposed name constraints are built into NSS.
+ */
+SECStatus
+CERT_GetImposedNameConstraints(const SECItem *derSubject, SECItem *extensions);
+
 CERTNameConstraint *
 CERT_GetNextNameConstraint(CERTNameConstraint *current);
 
 CERTNameConstraint *
 CERT_GetPrevNameConstraint(CERTNameConstraint *current);
 
 void
 CERT_DestroyUserNotice(CERTUserNotice *userNotice);
@@ -1544,16 +1552,19 @@ CERT_CopyNameConstraint(PLArenaPool     
  */
 extern SECStatus
 CERT_CheckNameSpace(PLArenaPool          *arena,
 		    const CERTNameConstraints *constraints,
 		    const CERTGeneralName *currentName);
 
 /*
  * Extract and allocate the name constraints extension from the CA cert.
+ * If the certificate contains no name constraints extension, but
+ * CERT_GetImposedNameConstraints returns a name constraints extension
+ * for the subject of the certificate, then that extension will be returned.
  */
 extern SECStatus
 CERT_FindNameConstraintsExten(PLArenaPool      *arena,
 			      CERTCertificate  *cert,
 			      CERTNameConstraints **constraints);
 
 /*
  * Initialize a new GERTGeneralName fields (link)
--- a/security/nss/lib/certdb/certdb.c
+++ b/security/nss/lib/certdb/certdb.c
@@ -1046,39 +1046,46 @@ SEC_GetCrlTimes(CERTCrl *date, PRTime *n
 /* These routines should probably be combined with the cert
  * routines using an common extraction routine.
  */
 SECCertTimeValidity
 SEC_CheckCrlTimes(CERTCrl *crl, PRTime t) {
     PRTime notBefore, notAfter, llPendingSlop, tmp1;
     SECStatus rv;
 
+    if (!crl) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return(secCertTimeUndetermined);
+    }
+
     rv = SEC_GetCrlTimes(crl, &notBefore, &notAfter);
     
     if (rv) {
 	return(secCertTimeExpired); 
     }
 
     LL_I2L(llPendingSlop, pendingSlop);
     /* convert to micro seconds */
     LL_I2L(tmp1, PR_USEC_PER_SEC);
     LL_MUL(llPendingSlop, llPendingSlop, tmp1);
     LL_SUB(notBefore, notBefore, llPendingSlop);
     if ( LL_CMP( t, <, notBefore ) ) {
+	PORT_SetError(SEC_ERROR_CRL_EXPIRED);
 	return(secCertTimeNotValidYet);
     }
 
     /* If next update is omitted and the test for notBefore passes, then
        we assume that the crl is up to date.
      */
     if ( LL_IS_ZERO(notAfter) ) {
 	return(secCertTimeValid);
     }
 
     if ( LL_CMP( t, >, notAfter) ) {
+	PORT_SetError(SEC_ERROR_CRL_EXPIRED);
 	return(secCertTimeExpired);
     }
 
     return(secCertTimeValid);
 }
 
 PRBool
 SEC_CrlIsNewer(CERTCrl *inNew, CERTCrl *old) {
@@ -1420,27 +1427,25 @@ cert_TestHostName(char * cn, const char 
 SECStatus
 cert_VerifySubjectAltName(const CERTCertificate *cert, const char *hn)
 {
     PLArenaPool *     arena          = NULL;
     CERTGeneralName * nameList       = NULL;
     CERTGeneralName * current;
     char *            cn;
     int               cnBufLen;
-    unsigned int      hnLen;
     int               DNSextCount    = 0;
     int               IPextCount     = 0;
     PRBool            isIPaddr       = PR_FALSE;
     SECStatus         rv             = SECFailure;
     SECItem           subAltName;
     PRNetAddr         netAddr;
     char              cnbuf[128];
 
     subAltName.data = NULL;
-    hnLen    = strlen(hn);
     cn       = cnbuf;
     cnBufLen = sizeof cnbuf;
 
     rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME, 
 				&subAltName);
     if (rv != SECSuccess) {
 	goto fail;
     }
@@ -2306,31 +2311,31 @@ CERT_FixupEmailAddr(const char *emailAdd
 /*
  * NOTE - don't allow encode of govt-approved or invisible bits
  */
 SECStatus
 CERT_DecodeTrustString(CERTCertTrust *trust, const char *trusts)
 {
     unsigned int i;
     unsigned int *pflags;
-    
+
     if (!trust) {
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	return SECFailure;
     }
     trust->sslFlags = 0;
     trust->emailFlags = 0;
     trust->objectSigningFlags = 0;
     if (!trusts) {
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	return SECFailure;
     }
 
     pflags = &trust->sslFlags;
-    
+
     for (i=0; i < PORT_Strlen(trusts); i++) {
 	switch (trusts[i]) {
 	  case 'p':
 	      *pflags = *pflags | CERTDB_TERMINAL_RECORD;
 	      break;
 
 	  case 'P':
 	      *pflags = *pflags | CERTDB_TRUSTED | CERTDB_TERMINAL_RECORD;
@@ -2366,16 +2371,17 @@ CERT_DecodeTrustString(CERTCertTrust *tr
 	  case ',':
 	      if ( pflags == &trust->sslFlags ) {
 		  pflags = &trust->emailFlags;
 	      } else {
 		  pflags = &trust->objectSigningFlags;
 	      }
 	      break;
 	  default:
+              PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	      return SECFailure;
 	}
     }
 
     return SECSuccess;
 }
 
 static void
--- a/security/nss/lib/certdb/certdb.h
+++ b/security/nss/lib/certdb/certdb.h
@@ -70,14 +70,29 @@ SECStatus
 CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname,
 		       CERTCertTrust *trust);
 
 SECStatus SEC_DeletePermCertificate(CERTCertificate *cert);
 
 PRBool
 SEC_CrlIsNewer(CERTCrl *inNew, CERTCrl *old);
 
+/*
+** Extract the validity times from a CRL
+**	"crl" is the CRL
+**	"notBefore" is the start of the validity period (last update)
+**	"notAfter" is the end of the validity period (next update)
+*/
+SECStatus
+SEC_GetCrlTimes(CERTCrl *crl, PRTime *notBefore, PRTime *notAfter);
+
+/*
+** Check the validity times of a crl vs. time 't', allowing
+** some slop for broken clocks and stuff.
+**	"crl" is the certificate to be checked
+**	"t" is the time to check against
+*/
 SECCertTimeValidity
 SEC_CheckCrlTimes(CERTCrl *crl, PRTime t);
 
 SEC_END_PROTOS
 
 #endif /* _CERTDB_H_ */
--- a/security/nss/lib/certdb/certi.h
+++ b/security/nss/lib/certdb/certi.h
@@ -111,21 +111,26 @@ struct CachedCrlStr {
 */
 
 struct CRLDPCacheStr {
 #ifdef DPC_RWLOCK
     NSSRWLock* lock;
 #else
     PRLock* lock;
 #endif
-    CERTCertificate* issuer;    /* issuer cert
-                                   XXX there may be multiple issuer certs,
-                                       with different validity dates. Also
-                                       need to deal with SKID/AKID . See
-                                       bugzilla 217387, 233118 */
+    SECItem *issuerDERCert;    /* issuer DER cert. Don't hold a reference
+				  to the actual cert so the trust can be
+				  updated on the cert automatically.
+				  XXX there may be multiple issuer certs,
+				  with different validity dates. Also
+				  need to deal with SKID/AKID . See
+				  bugzilla 217387, 233118 */
+
+    CERTCertDBHandle *dbHandle;
+
     SECItem* subject;           /* DER of issuer subject */
     SECItem* distributionPoint; /* DER of distribution point. This may be
                                    NULL when distribution points aren't
                                    in use (ie. the CA has a single CRL).
                                    Currently not used. */
 
     /* array of full CRLs matching this distribution point */
     PRUint32 ncrls;              /* total number of CRLs in crls */
@@ -160,25 +165,16 @@ struct CRLDPCacheStr {
     XCRL once we support multiple issuing distribution points, this object
     will be a hash table. For now, it just holds the single CRL distribution
     point cache structure.
 */
 
 struct CRLIssuerCacheStr {
     SECItem* subject;           /* DER of issuer subject */
     CRLDPCache* dpp;
-#if 0
-    /* XCRL for future use.
-       We don't need to lock at the moment because we only have one DP,
-       which gets created at the same time as this object */
-    NSSRWLock* lock;
-    CRLDPCache** dps;
-    PLHashTable* distributionpoints;
-    CERTCertificate* issuer;
-#endif
 };
 
 /*  CRL revocation cache object
     This object tracks all the issuer caches
 */
 
 struct CRLCacheStr {
 #ifdef GLOBAL_RWLOCK
--- a/security/nss/lib/certdb/certt.h
+++ b/security/nss/lib/certdb/certt.h
@@ -181,17 +181,17 @@ struct CERTSubjectListStr {
 };
 
 /*
 ** An X.509 certificate object (the unsigned form)
 */
 struct CERTCertificateStr {
     /* the arena is used to allocate any data structures that have the same
      * lifetime as the cert.  This is all stuff that hangs off of the cert
-     * structure, and is all freed at the same time.  I is used when the
+     * structure, and is all freed at the same time.  It is used when the
      * cert is decoded, destroyed, and at some times when it changes
      * state
      */
     PLArenaPool *arena;
 
     /* The following fields are static after the cert has been decoded */
     char *subjectName;
     char *issuerName;
--- a/security/nss/lib/certdb/certv3.c
+++ b/security/nss/lib/certdb/certv3.c
@@ -38,152 +38,16 @@ SetExts(void *object, CERTCertExtension 
 }
 
 void *
 CERT_StartCertExtensions(CERTCertificate *cert)
 {
     return (cert_StartExtensions ((void *)cert, cert->arena, SetExts));
 }
 
-/* find the given extension in the certificate of the Issuer of 'cert' */
-SECStatus
-CERT_FindIssuerCertExtension(CERTCertificate *cert, int tag, SECItem *value)
-{
-    CERTCertificate *issuercert;
-    SECStatus rv;
-
-    issuercert = CERT_FindCertByName(cert->dbhandle, &cert->derIssuer);
-    if ( issuercert ) {
-	rv = cert_FindExtension(issuercert->extensions, tag, value);
-	CERT_DestroyCertificate(issuercert);
-    } else {
-	rv = SECFailure;
-    }
-    
-    return(rv);
-}
-
-/* find a URL extension in the cert or its CA
- * apply the base URL string if it exists
- */
-char *
-CERT_FindCertURLExtension(CERTCertificate *cert, int tag, int catag)
-{
-    SECStatus rv;
-    SECItem urlitem = {siBuffer,0};
-    SECItem baseitem = {siBuffer,0};
-    SECItem urlstringitem = {siBuffer,0};
-    SECItem basestringitem = {siBuffer,0};
-    PLArenaPool *arena = NULL;
-    PRBool hasbase;
-    char *urlstring;
-    char *str;
-    int len;
-    unsigned int i;
-    
-    urlstring = NULL;
-
-    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if ( ! arena ) {
-	goto loser;
-    }
-    
-    hasbase = PR_FALSE;
-    
-    rv = cert_FindExtension(cert->extensions, tag, &urlitem);
-    if ( rv == SECSuccess ) {
-	rv = cert_FindExtension(cert->extensions, SEC_OID_NS_CERT_EXT_BASE_URL,
-				   &baseitem);
-	if ( rv == SECSuccess ) {
-	    hasbase = PR_TRUE;
-	}
-	
-    } else if ( catag ) {
-	/* if the cert doesn't have the extensions, see if the issuer does */
-	rv = CERT_FindIssuerCertExtension(cert, catag, &urlitem);
-	if ( rv != SECSuccess ) {
-	    goto loser;
-	}	    
-	rv = CERT_FindIssuerCertExtension(cert, SEC_OID_NS_CERT_EXT_BASE_URL,
-					 &baseitem);
-	if ( rv == SECSuccess ) {
-	    hasbase = PR_TRUE;
-	}
-    } else {
-	goto loser;
-    }
-
-    rv = SEC_QuickDERDecodeItem(arena, &urlstringitem,
-                                SEC_ASN1_GET(SEC_IA5StringTemplate), &urlitem);
-
-    if ( rv != SECSuccess ) {
-	goto loser;
-    }
-    if ( hasbase ) {
-	rv = SEC_QuickDERDecodeItem(arena, &basestringitem,
-                                    SEC_ASN1_GET(SEC_IA5StringTemplate),
-                                    &baseitem);
-
-	if ( rv != SECSuccess ) {
-	    goto loser;
-	}
-    }
-    
-    len = urlstringitem.len + ( hasbase ? basestringitem.len : 0 ) + 1;
-    
-    str = urlstring = (char *)PORT_Alloc(len);
-    if ( urlstring == NULL ) {
-	goto loser;
-    }
-    
-    /* copy the URL base first */
-    if ( hasbase ) {
-
-	/* if the urlstring has a : in it, then we assume it is an absolute
-	 * URL, and will not get the base string pre-pended
-	 */
-	for ( i = 0; i < urlstringitem.len; i++ ) {
-	    if ( urlstringitem.data[i] == ':' ) {
-		goto nobase;
-	    }
-	}
-	
-	PORT_Memcpy(str, basestringitem.data, basestringitem.len);
-	str += basestringitem.len;
-	
-    }
-
-nobase:
-    /* copy the rest (or all) of the URL */
-    PORT_Memcpy(str, urlstringitem.data, urlstringitem.len);
-    str += urlstringitem.len;
-    
-    *str = '\0';
-    goto done;
-    
-loser:
-    if ( urlstring ) {
-	PORT_Free(urlstring);
-    }
-    
-    urlstring = NULL;
-done:
-    if ( arena ) {
-	PORT_FreeArena(arena, PR_FALSE);
-    }
-    if ( baseitem.data ) {
-	PORT_Free(baseitem.data);
-    }
-    if ( urlitem.data ) {
-	PORT_Free(urlitem.data);
-    }
-
-    return(urlstring);
-}
-
 /*
  * get the value of the Netscape Certificate Type Extension
  */
 SECStatus
 CERT_FindNSCertTypeExtension(CERTCertificate *cert, SECItem *retItem)
 {
 
     return (CERT_FindBitStringExtension
--- a/security/nss/lib/certdb/crl.c
+++ b/security/nss/lib/certdb/crl.c
@@ -1118,19 +1118,19 @@ static SECStatus DPCache_Destroy(CRLDPCa
         }
     }
     /* free the array of CRLs */
     if (cache->crls)
     {
 	PORT_Free(cache->crls);
     }
     /* destroy the cert */
-    if (cache->issuer)
+    if (cache->issuerDERCert)
     {
-        CERT_DestroyCertificate(cache->issuer);
+        SECITEM_FreeItem(cache->issuerDERCert, PR_TRUE);
     }
     /* free the subject */
     if (cache->subject)
     {
         SECITEM_FreeItem(cache->subject, PR_TRUE);
     }
     /* free the distribution points */
     if (cache->distributionPoint)
@@ -1566,24 +1566,30 @@ static SECStatus CachedCrl_Verify(CRLDPC
         crlobject->sigChecked = PR_TRUE; /* we can never verify a CRL
             with bogus DER. Mark it checked so we won't try again */
         PORT_SetError(SEC_ERROR_BAD_DER);
         return SECSuccess;
     }
     else
     {
         SECStatus signstatus = SECFailure;
-        if (cache->issuer)
+        if (cache->issuerDERCert)
         {
-            signstatus = CERT_VerifyCRL(crlobject->crl, cache->issuer, vfdate,
+	    CERTCertificate *issuer = CERT_NewTempCertificate(cache->dbHandle,
+		cache->issuerDERCert, NULL, PR_FALSE, PR_TRUE);
+
+	    if (issuer) {
+                signstatus = CERT_VerifyCRL(crlobject->crl, issuer, vfdate,
                                         wincx);
+		CERT_DestroyCertificate(issuer);
+	    }
         }
         if (SECSuccess != signstatus)
         {
-            if (!cache->issuer)
+            if (!cache->issuerDERCert)
             {
                 /* we tried to verify without an issuer cert . This is
                    because this CRL came through a call to SEC_FindCrlByName.
                    So, we don't cache this verification failure. We'll try
                    to verify the CRL again when a certificate from that issuer
                    becomes available */
             } else
             {
@@ -1920,36 +1926,37 @@ static SECStatus DPCache_GetUpToDate(CRL
         {
             cache->lastcheck = PR_Now();
             DPCache_UnlockWrite();
             mustunlock = PR_FALSE;
         }
     }
 
     /* add issuer certificate if it was previously unavailable */
-    if (issuer && (NULL == cache->issuer) &&
+    if (issuer && (NULL == cache->issuerDERCert) &&
         (SECSuccess == CERT_CheckCertUsage(issuer, KU_CRL_SIGN)))
     {
         /* if we didn't have a valid issuer cert yet, but we do now. add it */
         DPCache_LockWrite();
-        if (!cache->issuer)
+        if (!cache->issuerDERCert)
         {
             dirty = PR_TRUE;
-            cache->issuer = CERT_DupCertificate(issuer);    
+	    cache->dbHandle = issuer->dbhandle;
+    	    cache->issuerDERCert = SECITEM_DupItem(&issuer->derCert);
         }
         DPCache_UnlockWrite();
     }
 
     /* verify CRLs that couldn't be checked when inserted into the cache
        because the issuer cert or a verification date was unavailable.
        These are CRLs that were inserted into the cache through
        SEC_FindCrlByName, or through manual insertion, rather than through a
        certificate verification (CERT_CheckCRL) */
 
-    if (cache->issuer && vfdate )
+    if (cache->issuerDERCert && vfdate )
     {
 	mustunlock = PR_FALSE;
         /* re-process all unverified CRLs */
         for (i = 0; i < cache->ncrls ; i++)
         {
             CachedCrl* savcrl = cache->crls[i];
             if (!savcrl)
             {
@@ -2196,17 +2203,18 @@ static SECStatus DPCache_Create(CRLDPCac
 #endif
     if (!cache->lock)
     {
 	PORT_Free(cache);
         return SECFailure;
     }
     if (issuer)
     {
-        cache->issuer = CERT_DupCertificate(issuer);
+	cache->dbHandle = issuer->dbhandle;
+    	cache->issuerDERCert = SECITEM_DupItem(&issuer->derCert);
     }
     cache->distributionPoint = SECITEM_DupItem(dp);
     cache->subject = SECITEM_DupItem(subject);
     cache->lastfetch = 0;
     cache->lastcheck = 0;
     *returned = cache;
     return SECSuccess;
 }
--- a/security/nss/lib/certdb/genname.c
+++ b/security/nss/lib/certdb/genname.c
@@ -1551,86 +1551,108 @@ done:
     if (rv == SECFailure) {
         PORT_ArenaRelease(arena, mark);
     } else {
         PORT_ArenaUnmark(arena, mark);
     }
     return rv;
 }
 
-/* Add name constraints to certain certs that do not include name constraints
- * This is the core of the implementation for bug 952572.
+/*
+ * Here we define a list of name constraints to be imposed on
+ * certain certificates, most importantly root certificates.
+ *
+ * Each entry in the name constraints list is constructed with this
+ * macro.  An entry contains two SECItems, which have names in
+ * specific forms to make the macro work:
+ *
+ *  * ${CA}_SUBJECT_DN - The subject DN for which the constraints
+ *                       should be applied
+ *  * ${CA}_NAME_CONSTRAINTS - The name constraints extension
+ *
+ * Entities subject to name constraints are identified by subject name
+ * so that we can cover all certificates for that entity, including, e.g.,
+ * cross-certificates.  We use subject rather than public key because
+ * calling methods often have easy access to that field (vs., say, a key ID),
+ * and in practice, subject names and public keys are usually in one-to-one
+ * correspondence anyway.
+ *
  */
 
-static SECStatus
-getNameExtensionsBuiltIn(CERTCertificate  *cert,
-                         SECItem *extensions)
+#define STRING_TO_SECITEM(str) \
+{ siBuffer, (unsigned char*) str, sizeof(str) - 1 }
+
+#define NAME_CONSTRAINTS_ENTRY(CA)  \
+    { \
+        STRING_TO_SECITEM(CA ## _SUBJECT_DN), \
+        STRING_TO_SECITEM(CA ## _NAME_CONSTRAINTS) \
+    }
+
+/* Agence Nationale de la Securite des Systemes d'Information (ANSSI) */
+
+#define ANSSI_SUBJECT_DN \
+    "\x30\x81\x85"                                                     \
+    "\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02" "FR"       /* C */  \
+    "\x31\x0F\x30\x0D\x06\x03\x55\x04\x08\x13\x06" "France"   /* ST */ \
+    "\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05" "Paris"    /* L */  \
+    "\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07" "PM/SGDN"  /* O */  \
+    "\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13\x05" "DCSSI"    /* OU */ \
+    "\x31\x0E\x30\x0C\x06\x03\x55\x04\x03\x13\x05" "IGC/A"    /* CN */ \
+    "\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01"     \
+    "\x16\x14" "igca@sgdn.pm.gouv.fr" /* emailAddress */ \
+
+#define ANSSI_NAME_CONSTRAINTS \
+    "\x30\x5D\xA0\x5B"       \
+    "\x30\x05\x82\x03" ".fr" \
+    "\x30\x05\x82\x03" ".gp" \
+    "\x30\x05\x82\x03" ".gf" \
+    "\x30\x05\x82\x03" ".mq" \
+    "\x30\x05\x82\x03" ".re" \
+    "\x30\x05\x82\x03" ".yt" \
+    "\x30\x05\x82\x03" ".pm" \
+    "\x30\x05\x82\x03" ".bl" \
+    "\x30\x05\x82\x03" ".mf" \
+    "\x30\x05\x82\x03" ".wf" \
+    "\x30\x05\x82\x03" ".pf" \
+    "\x30\x05\x82\x03" ".nc" \
+    "\x30\x05\x82\x03" ".tf" \
+
+static const SECItem builtInNameConstraints[][2] = {
+    NAME_CONSTRAINTS_ENTRY(ANSSI)
+};
+
+SECStatus
+CERT_GetImposedNameConstraints(const SECItem *derSubject,
+                               SECItem *extensions)
 {
-  const char constraintFranceGov[] = "\x30\x5D" /* sequence len = 93*/
-                                     "\xA0\x5B" /* element len =91 */
-                                     "\x30\x05" /* sequence len 5 */
-                                     "\x82\x03" /* entry len 3 */
-                                     ".fr"
-                                     "\x30\x05\x82\x03" /* sequence len5, entry len 3 */
-                                     ".gp"
-                                     "\x30\x05\x82\x03"
-                                     ".gf"
-                                     "\x30\x05\x82\x03"
-                                     ".mq"
-                                     "\x30\x05\x82\x03"
-                                     ".re"
-                                     "\x30\x05\x82\x03"
-                                     ".yt"
-                                     "\x30\x05\x82\x03"
-                                     ".pm"
-                                     "\x30\x05\x82\x03"
-                                     ".bl"
-                                     "\x30\x05\x82\x03"
-                                     ".mf"
-                                     "\x30\x05\x82\x03"
-                                     ".wf"
-                                     "\x30\x05\x82\x03"
-                                     ".pf"
-                                     "\x30\x05\x82\x03"
-                                     ".nc"
-                                     "\x30\x05\x82\x03"
-                                     ".tf";
+    size_t i;
+
+    if (!extensions) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
 
-  /* The stringified value for the subject is:
-     E=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR
-   */
-  const char rawANSSISubject[] = "\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04"
-                                 "\x06\x13\x02\x46\x52\x31\x0F\x30\x0D\x06\x03"
-                                 "\x55\x04\x08\x13\x06\x46\x72\x61\x6E\x63\x65"
-                                 "\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05"
-                                 "\x50\x61\x72\x69\x73\x31\x10\x30\x0E\x06\x03"
-                                 "\x55\x04\x0A\x13\x07\x50\x4D\x2F\x53\x47\x44"
-                                 "\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13"
-                                 "\x05\x44\x43\x53\x53\x49\x31\x0E\x30\x0C\x06"
-                                 "\x03\x55\x04\x03\x13\x05\x49\x47\x43\x2F\x41"
-                                 "\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7"
-                                 "\x0D\x01\x09\x01\x16\x14\x69\x67\x63\x61\x40"
-                                 "\x73\x67\x64\x6E\x2E\x70\x6D\x2E\x67\x6F\x75"
-                                 "\x76\x2E\x66\x72";
+    for (i = 0; i < PR_ARRAY_SIZE(builtInNameConstraints); ++i) {
+        if (SECITEM_ItemsAreEqual(derSubject, &builtInNameConstraints[i][0])) {
+            return SECITEM_CopyItem(NULL,
+                                    extensions, 
+                                    &builtInNameConstraints[i][1]);
+        }
+    }
 
-  const SECItem anssi_subject = {0, (unsigned char *) rawANSSISubject,
-                                 sizeof(rawANSSISubject)-1};
-  const SECItem permitFranceGovNC = {0, (unsigned char *) constraintFranceGov,
-                                     sizeof(constraintFranceGov)-1};
-
-  if (SECITEM_ItemsAreEqual(&cert->derSubject, &anssi_subject)) {
-    SECStatus rv;
-    rv = SECITEM_CopyItem(NULL, extensions, &permitFranceGovNC);
-    return rv;
-  }
-  PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
-  return SECFailure;
+    PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
+    return SECFailure;
 }
 
-/* Extract the name constraints extension from the CA cert. */
+/* 
+ * Extract the name constraints extension from the CA cert.
+ * If the certificate contains no name constraints extension, but
+ * CERT_GetImposedNameConstraints returns a name constraints extension
+ * for the subject of the certificate, then that extension will be returned.
+ */
 SECStatus
 CERT_FindNameConstraintsExten(PLArenaPool      *arena,
                               CERTCertificate  *cert,
                               CERTNameConstraints **constraints)
 {
     SECStatus            rv = SECSuccess;
     SECItem              constraintsExtension;
     void                *mark = NULL;
@@ -1638,17 +1660,18 @@ CERT_FindNameConstraintsExten(PLArenaPoo
     *constraints = NULL;
 
     rv = CERT_FindCertExtension(cert, SEC_OID_X509_NAME_CONSTRAINTS, 
                                 &constraintsExtension);
     if (rv != SECSuccess) {
         if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
             return rv;
         }
-        rv = getNameExtensionsBuiltIn(cert, &constraintsExtension);
+        rv = CERT_GetImposedNameConstraints(&cert->derSubject,
+                                            &constraintsExtension);
         if (rv != SECSuccess) {
           if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
             return SECSuccess;
           }
           return rv;
         }
     }
 
--- a/security/nss/lib/ckfw/builtins/certdata.txt
+++ b/security/nss/lib/ckfw/builtins/certdata.txt
@@ -2452,19 +2452,19 @@ CKA_ISSUER MULTILINE_OCTAL
 \170\040\123\145\143\165\162\145\040\111\156\143\056\061\055\060
 \053\006\003\125\004\003\023\044\105\161\165\151\146\141\170\040
 \123\145\143\165\162\145\040\107\154\157\142\141\154\040\145\102
 \165\163\151\156\145\163\163\040\103\101\055\061
 END
 CKA_SERIAL_NUMBER MULTILINE_OCTAL
 \002\001\001
 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_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
+CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
+CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
 CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
 
 #
 # Certificate "Equifax Secure eBusiness CA 1"
 #
 # Issuer: CN=Equifax Secure eBusiness CA-1,O=Equifax Secure Inc.,C=US
 # Serial Number: 4 (0x4)
 # Subject: CN=Equifax Secure eBusiness CA-1,O=Equifax Secure Inc.,C=US
@@ -13169,19 +13169,19 @@ CKA_ISSUER MULTILINE_OCTAL
 \103\145\156\164\145\162\040\103\154\141\163\163\040\063\040\103
 \101\061\045\060\043\006\003\125\004\003\023\034\124\103\040\124
 \162\165\163\164\103\145\156\164\145\162\040\103\154\141\163\163
 \040\063\040\103\101\040\111\111
 END
 CKA_SERIAL_NUMBER MULTILINE_OCTAL
 \002\016\112\107\000\001\000\002\345\240\135\326\077\000\121\277
 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_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
+CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
+CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
 CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
 
 #
 # Certificate "TC TrustCenter Universal CA I"
 #
 # Issuer: CN=TC TrustCenter Universal CA I,OU=TC TrustCenter Universal CA,O=TC TrustCenter GmbH,C=DE
 # Serial Number:1d:a2:00:01:00:02:ec:b7:60:80:78:8d:b6:06
 # Subject: CN=TC TrustCenter Universal CA I,OU=TC TrustCenter Universal CA,O=TC TrustCenter GmbH,C=DE
@@ -17336,159 +17336,16 @@ CKA_SERIAL_NUMBER MULTILINE_OCTAL
 \002\011\000\302\176\103\004\116\107\077\031
 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
 
 #
-# Certificate "E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi"
-#
-# Issuer: CN=e-Guven Kok Elektronik Sertifika Hizmet Saglayicisi,O=Elektronik Bilgi Guvenligi A.S.,C=TR
-# Serial Number:44:99:8d:3c:c0:03:27:bd:9c:76:95:b9:ea:db:ac:b5
-# Subject: CN=e-Guven Kok Elektronik Sertifika Hizmet Saglayicisi,O=Elektronik Bilgi Guvenligi A.S.,C=TR
-# Not Valid Before: Thu Jan 04 11:32:48 2007
-# Not Valid After : Wed Jan 04 11:32:48 2017
-# Fingerprint (MD5): 3D:41:29:CB:1E:AA:11:74:CD:5D:B0:62:AF:B0:43:5B
-# Fingerprint (SHA1): DD:E1:D2:A9:01:80:2E:1D:87:5E:84:B3:80:7E:4B:B1:FD:99:41:34
-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 "E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi"
-CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
-CKA_SUBJECT MULTILINE_OCTAL
-\060\165\061\013\060\011\006\003\125\004\006\023\002\124\122\061
-\050\060\046\006\003\125\004\012\023\037\105\154\145\153\164\162
-\157\156\151\153\040\102\151\154\147\151\040\107\165\166\145\156
-\154\151\147\151\040\101\056\123\056\061\074\060\072\006\003\125
-\004\003\023\063\145\055\107\165\166\145\156\040\113\157\153\040
-\105\154\145\153\164\162\157\156\151\153\040\123\145\162\164\151
-\146\151\153\141\040\110\151\172\155\145\164\040\123\141\147\154
-\141\171\151\143\151\163\151
-END
-CKA_ID UTF8 "0"
-CKA_ISSUER MULTILINE_OCTAL
-\060\165\061\013\060\011\006\003\125\004\006\023\002\124\122\061
-\050\060\046\006\003\125\004\012\023\037\105\154\145\153\164\162
-\157\156\151\153\040\102\151\154\147\151\040\107\165\166\145\156
-\154\151\147\151\040\101\056\123\056\061\074\060\072\006\003\125
-\004\003\023\063\145\055\107\165\166\145\156\040\113\157\153\040
-\105\154\145\153\164\162\157\156\151\153\040\123\145\162\164\151
-\146\151\153\141\040\110\151\172\155\145\164\040\123\141\147\154
-\141\171\151\143\151\163\151
-END
-CKA_SERIAL_NUMBER MULTILINE_OCTAL
-\002\020\104\231\215\074\300\003\047\275\234\166\225\271\352\333
-\254\265
-END
-CKA_VALUE MULTILINE_OCTAL
-\060\202\003\266\060\202\002\236\240\003\002\001\002\002\020\104
-\231\215\074\300\003\047\275\234\166\225\271\352\333\254\265\060
-\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060\165
-\061\013\060\011\006\003\125\004\006\023\002\124\122\061\050\060
-\046\006\003\125\004\012\023\037\105\154\145\153\164\162\157\156
-\151\153\040\102\151\154\147\151\040\107\165\166\145\156\154\151
-\147\151\040\101\056\123\056\061\074\060\072\006\003\125\004\003
-\023\063\145\055\107\165\166\145\156\040\113\157\153\040\105\154
-\145\153\164\162\157\156\151\153\040\123\145\162\164\151\146\151
-\153\141\040\110\151\172\155\145\164\040\123\141\147\154\141\171
-\151\143\151\163\151\060\036\027\015\060\067\060\061\060\064\061
-\061\063\062\064\070\132\027\015\061\067\060\061\060\064\061\061
-\063\062\064\070\132\060\165\061\013\060\011\006\003\125\004\006
-\023\002\124\122\061\050\060\046\006\003\125\004\012\023\037\105
-\154\145\153\164\162\157\156\151\153\040\102\151\154\147\151\040
-\107\165\166\145\156\154\151\147\151\040\101\056\123\056\061\074
-\060\072\006\003\125\004\003\023\063\145\055\107\165\166\145\156
-\040\113\157\153\040\105\154\145\153\164\162\157\156\151\153\040
-\123\145\162\164\151\146\151\153\141\040\110\151\172\155\145\164
-\040\123\141\147\154\141\171\151\143\151\163\151\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\303\022\040
-\236\260\136\000\145\215\116\106\273\200\134\351\054\006\227\325
-\363\162\311\160\271\347\113\145\200\301\113\276\176\074\327\124
-\061\224\336\325\022\272\123\026\002\352\130\143\357\133\330\363
-\355\052\032\252\161\110\243\334\020\055\137\137\353\134\113\234
-\226\010\102\045\050\021\314\212\132\142\001\120\325\353\011\123
-\057\370\303\217\376\263\374\375\235\242\343\137\175\276\355\013
-\340\140\353\151\354\063\355\330\215\373\022\111\203\000\311\213
-\227\214\073\163\052\062\263\022\367\271\115\362\364\115\155\307
-\346\326\046\067\010\362\331\375\153\134\243\345\110\134\130\274
-\102\276\003\132\201\272\034\065\014\000\323\365\043\176\161\060
-\010\046\070\334\045\021\107\055\363\272\043\020\245\277\274\002
-\367\103\136\307\376\260\067\120\231\173\017\223\316\346\103\054
-\303\176\015\362\034\103\146\140\313\141\061\107\207\243\117\256
-\275\126\154\114\274\274\370\005\312\144\364\351\064\241\054\265
-\163\341\302\076\350\310\311\064\045\010\134\363\355\246\307\224
-\237\255\210\103\045\327\341\071\140\376\254\071\131\002\003\001
-\000\001\243\102\060\100\060\016\006\003\125\035\017\001\001\377
-\004\004\003\002\001\006\060\017\006\003\125\035\023\001\001\377
-\004\005\060\003\001\001\377\060\035\006\003\125\035\016\004\026
-\004\024\237\356\104\263\224\325\372\221\117\056\331\125\232\004
-\126\333\055\304\333\245\060\015\006\011\052\206\110\206\367\015
-\001\001\005\005\000\003\202\001\001\000\177\137\271\123\133\143
-\075\165\062\347\372\304\164\032\313\106\337\106\151\034\122\317
-\252\117\302\150\353\377\200\251\121\350\075\142\167\211\075\012
-\165\071\361\156\135\027\207\157\150\005\301\224\154\331\135\337
-\332\262\131\313\245\020\212\312\314\071\315\237\353\116\336\122
-\377\014\360\364\222\251\362\154\123\253\233\322\107\240\037\164
-\367\233\232\361\057\025\237\172\144\060\030\007\074\052\017\147
-\312\374\017\211\141\235\145\245\074\345\274\023\133\010\333\343
-\377\355\273\006\273\152\006\261\172\117\145\306\202\375\036\234
-\213\265\015\356\110\273\270\275\252\010\264\373\243\174\313\237
-\315\220\166\134\206\226\170\127\012\146\371\130\032\235\375\227
-\051\140\336\021\246\220\034\031\034\356\001\226\042\064\064\056
-\221\371\267\304\047\321\173\346\277\373\200\104\132\026\345\353
-\340\324\012\070\274\344\221\343\325\353\134\301\254\337\033\152
-\174\236\345\165\322\266\227\207\333\314\207\053\103\072\204\010
-\257\253\074\333\367\074\146\061\206\260\235\123\171\355\370\043
-\336\102\343\055\202\361\017\345\372\227
-END
-
-# Trust for Certificate "E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi"
-# Issuer: CN=e-Guven Kok Elektronik Sertifika Hizmet Saglayicisi,O=Elektronik Bilgi Guvenligi A.S.,C=TR
-# Serial Number:44:99:8d:3c:c0:03:27:bd:9c:76:95:b9:ea:db:ac:b5
-# Subject: CN=e-Guven Kok Elektronik Sertifika Hizmet Saglayicisi,O=Elektronik Bilgi Guvenligi A.S.,C=TR
-# Not Valid Before: Thu Jan 04 11:32:48 2007
-# Not Valid After : Wed Jan 04 11:32:48 2017
-# Fingerprint (MD5): 3D:41:29:CB:1E:AA:11:74:CD:5D:B0:62:AF:B0:43:5B
-# Fingerprint (SHA1): DD:E1:D2:A9:01:80:2E:1D:87:5E:84:B3:80:7E:4B:B1:FD:99:41:34
-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 "E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi"
-CKA_CERT_SHA1_HASH MULTILINE_OCTAL
-\335\341\322\251\001\200\056\035\207\136\204\263\200\176\113\261
-\375\231\101\064
-END
-CKA_CERT_MD5_HASH MULTILINE_OCTAL
-\075\101\051\313\036\252\021\164\315\135\260\142\257\260\103\133
-END
-CKA_ISSUER MULTILINE_OCTAL
-\060\165\061\013\060\011\006\003\125\004\006\023\002\124\122\061
-\050\060\046\006\003\125\004\012\023\037\105\154\145\153\164\162
-\157\156\151\153\040\102\151\154\147\151\040\107\165\166\145\156
-\154\151\147\151\040\101\056\123\056\061\074\060\072\006\003\125
-\004\003\023\063\145\055\107\165\166\145\156\040\113\157\153\040
-\105\154\145\153\164\162\157\156\151\153\040\123\145\162\164\151
-\146\151\153\141\040\110\151\172\155\145\164\040\123\141\147\154
-\141\171\151\143\151\163\151
-END
-CKA_SERIAL_NUMBER MULTILINE_OCTAL
-\002\020\104\231\215\074\300\003\047\275\234\166\225\271\352\333
-\254\265
-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_MUST_VERIFY_TRUST
-CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
-
-#
 # Certificate "GlobalSign Root CA - R3"
 #
 # Issuer: CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R3
 # Serial Number:04:00:00:00:00:01:21:58:53:08:a2
 # Subject: CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R3
 # Not Valid Before: Wed Mar 18 10:00:00 2009
 # Not Valid After : Sun Mar 18 10:00:00 2029
 # Fingerprint (MD5): C5:DF:B8:49:CA:05:13:55:EE:2D:BA:1A:C3:3E:B0:28
@@ -30315,8 +30172,1421 @@ END
 CKA_SERIAL_NUMBER MULTILINE_OCTAL
 \002\020\057\000\156\315\027\160\146\347\137\243\202\012\171\037
 \005\256
 END
 CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
 CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
 CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
 CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
+
+#
+# Certificate "Staat der Nederlanden Root CA - G3"
+#
+# Issuer: CN=Staat der Nederlanden Root CA - G3,O=Staat der Nederlanden,C=NL
+# Serial Number: 10003001 (0x98a239)
+# Subject: CN=Staat der Nederlanden Root CA - G3,O=Staat der Nederlanden,C=NL
+# Not Valid Before: Thu Nov 14 11:28:42 2013
+# Not Valid After : Mon Nov 13 23:00:00 2028
+# Fingerprint (SHA-256): 3C:4F:B0:B9:5A:B8:B3:00:32:F4:32:B8:6F:53:5F:E1:72:C1:85:D0:FD:39:86:58:37:CF:36:18:7F:A6:F4:28
+# Fingerprint (SHA1): D8:EB:6B:41:51:92:59:E0:F3:E7:85:00:C0:3D:B6:88:97:C9:EE:FC
+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 "Staat der Nederlanden Root CA - G3"
+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
+CKA_SUBJECT MULTILINE_OCTAL
+\060\132\061\013\060\011\006\003\125\004\006\023\002\116\114\061
+\036\060\034\006\003\125\004\012\014\025\123\164\141\141\164\040
+\144\145\162\040\116\145\144\145\162\154\141\156\144\145\156\061
+\053\060\051\006\003\125\004\003\014\042\123\164\141\141\164\040
+\144\145\162\040\116\145\144\145\162\154\141\156\144\145\156\040
+\122\157\157\164\040\103\101\040\055\040\107\063
+END
+CKA_ID UTF8 "0"
+CKA_ISSUER MULTILINE_OCTAL
+\060\132\061\013\060\011\006\003\125\004\006\023\002\116\114\061
+\036\060\034\006\003\125\004\012\014\025\123\164\141\141\164\040
+\144\145\162\040\116\145\144\145\162\154\141\156\144\145\156\061
+\053\060\051\006\003\125\004\003\014\042\123\164\141\141\164\040
+\144\145\162\040\116\145\144\145\162\154\141\156\144\145\156\040
+\122\157\157\164\040\103\101\040\055\040\107\063
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\004\000\230\242\071
+END
+CKA_VALUE MULTILINE_OCTAL
+\060\202\005\164\060\202\003\134\240\003\002\001\002\002\004\000
+\230\242\071\060\015\006\011\052\206\110\206\367\015\001\001\013
+\005\000\060\132\061\013\060\011\006\003\125\004\006\023\002\116
+\114\061\036\060\034\006\003\125\004\012\014\025\123\164\141\141
+\164\040\144\145\162\040\116\145\144\145\162\154\141\156\144\145
+\156\061\053\060\051\006\003\125\004\003\014\042\123\164\141\141
+\164\040\144\145\162\040\116\145\144\145\162\154\141\156\144\145
+\156\040\122\157\157\164\040\103\101\040\055\040\107\063\060\036
+\027\015\061\063\061\061\061\064\061\061\062\070\064\062\132\027
+\015\062\070\061\061\061\063\062\063\060\060\060\060\132\060\132
+\061\013\060\011\006\003\125\004\006\023\002\116\114\061\036\060
+\034\006\003\125\004\012\014\025\123\164\141\141\164\040\144\145
+\162\040\116\145\144\145\162\154\141\156\144\145\156\061\053\060
+\051\006\003\125\004\003\014\042\123\164\141\141\164\040\144\145
+\162\040\116\145\144\145\162\154\141\156\144\145\156\040\122\157
+\157\164\040\103\101\040\055\040\107\063\060\202\002\042\060\015
+\006\011\052\206\110\206\367\015\001\001\001\005\000\003\202\002
+\017\000\060\202\002\012\002\202\002\001\000\276\062\242\124\017
+\160\373\054\134\131\353\154\304\244\121\350\205\052\263\314\112
+\064\362\260\137\363\016\307\034\075\123\036\210\010\150\330\157
+\075\255\302\236\314\202\147\007\047\207\150\161\072\237\165\226
+\042\106\005\260\355\255\307\133\236\052\336\234\374\072\306\225
+\247\365\027\147\030\347\057\111\010\014\134\317\346\314\064\355
+\170\373\120\261\334\153\062\360\242\376\266\074\344\354\132\227
+\307\077\036\160\010\060\240\334\305\263\155\157\320\202\162\021
+\253\322\201\150\131\202\027\267\170\222\140\372\314\336\077\204
+\353\215\070\063\220\012\162\043\372\065\314\046\161\061\321\162
+\050\222\331\133\043\155\146\265\155\007\102\353\246\063\316\222
+\333\300\366\154\143\170\315\312\116\075\265\345\122\233\361\276
+\073\346\124\140\260\146\036\011\253\007\376\124\211\021\102\321
+\367\044\272\140\170\032\230\367\311\021\375\026\301\065\032\124
+\165\357\103\323\345\256\116\316\347\173\303\306\116\141\121\113
+\253\232\105\113\241\037\101\275\110\123\025\161\144\013\206\263
+\345\056\276\316\244\033\301\051\204\242\265\313\010\043\166\103
+\042\044\037\027\004\324\156\234\306\374\177\053\146\032\354\212
+\345\326\317\115\365\143\011\267\025\071\326\173\254\353\343\174
+\351\116\374\165\102\310\355\130\225\014\006\102\242\234\367\344
+\160\263\337\162\157\132\067\100\211\330\205\244\327\361\013\336
+\103\031\324\112\130\054\214\212\071\236\277\204\207\361\026\073
+\066\014\351\323\264\312\154\031\101\122\011\241\035\260\152\277
+\202\357\160\121\041\062\334\005\166\214\313\367\144\344\003\120
+\257\214\221\147\253\305\362\356\130\330\336\276\367\347\061\317
+\154\311\073\161\301\325\210\265\145\274\300\350\027\027\007\022
+\265\134\322\253\040\223\264\346\202\203\160\066\305\315\243\215
+\255\213\354\243\301\103\207\346\103\342\064\276\225\213\065\355
+\007\071\332\250\035\172\237\066\236\022\260\014\145\022\220\025
+\140\331\046\100\104\343\126\140\245\020\324\152\074\375\101\334
+\016\132\107\266\357\227\141\165\117\331\376\307\262\035\324\355
+\135\111\263\251\152\313\146\204\023\325\134\240\334\337\156\167
+\006\321\161\165\310\127\157\257\017\167\133\002\003\001\000\001
+\243\102\060\100\060\017\006\003\125\035\023\001\001\377\004\005
+\060\003\001\001\377\060\016\006\003\125\035\017\001\001\377\004
+\004\003\002\001\006\060\035\006\003\125\035\016\004\026\004\024
+\124\255\372\307\222\127\256\312\065\234\056\022\373\344\272\135
+\040\334\224\127\060\015\006\011\052\206\110\206\367\015\001\001
+\013\005\000\003\202\002\001\000\060\231\235\005\062\310\136\016
+\073\230\001\072\212\244\347\007\367\172\370\347\232\337\120\103
+\123\227\052\075\312\074\107\230\056\341\025\173\361\222\363\141
+\332\220\045\026\145\300\237\124\135\016\003\073\133\167\002\234
+\204\266\015\230\137\064\335\073\143\302\303\050\201\302\234\051
+\056\051\342\310\303\001\362\063\352\052\252\314\011\010\367\145
+\147\306\315\337\323\266\053\247\275\314\321\016\160\137\270\043
+\321\313\221\116\012\364\310\172\345\331\143\066\301\324\337\374
+\042\227\367\140\135\352\051\057\130\262\275\130\275\215\226\117
+\020\165\277\110\173\075\121\207\241\074\164\042\302\374\007\177
+\200\334\304\254\376\152\301\160\060\260\351\216\151\342\054\151
+\201\224\011\272\335\376\115\300\203\214\224\130\300\106\040\257
+\234\037\002\370\065\125\111\057\106\324\300\360\240\226\002\017
+\063\305\161\363\236\043\175\224\267\375\072\323\011\203\006\041
+\375\140\075\256\062\300\322\356\215\246\360\347\264\202\174\012
+\314\160\311\171\200\370\376\114\367\065\204\031\212\061\373\012
+\331\327\177\233\360\242\232\153\303\005\112\355\101\140\024\060
+\321\252\021\102\156\323\043\002\004\013\306\145\335\335\122\167
+\332\201\153\262\250\372\001\070\271\226\352\052\154\147\227\211
+\224\236\274\341\124\325\344\152\170\357\112\275\053\232\075\100
+\176\306\300\165\322\156\373\150\060\354\354\213\235\371\111\065
+\232\032\054\331\263\225\071\325\036\222\367\246\271\145\057\345
+\075\155\072\110\114\010\334\344\050\022\050\276\175\065\134\352
+\340\026\176\023\033\152\327\076\327\236\374\055\165\262\301\024
+\325\043\003\333\133\157\013\076\170\057\015\336\063\215\026\267
+\110\347\203\232\201\017\173\301\103\115\125\004\027\070\112\121
+\325\131\242\211\164\323\237\276\036\113\327\306\155\267\210\044
+\157\140\221\244\202\205\133\126\101\274\320\104\253\152\023\276
+\321\054\130\267\022\063\130\262\067\143\334\023\365\224\035\077
+\100\121\365\117\365\072\355\310\305\353\302\036\035\026\225\172
+\307\176\102\161\223\156\113\025\267\060\337\252\355\127\205\110
+\254\035\152\335\071\151\344\341\171\170\276\316\005\277\241\014
+\367\200\173\041\147\047\060\131
+END
+
+# Trust for "Staat der Nederlanden Root CA - G3"
+# Issuer: CN=Staat der Nederlanden Root CA - G3,O=Staat der Nederlanden,C=NL
+# Serial Number: 10003001 (0x98a239)
+# Subject: CN=Staat der Nederlanden Root CA - G3,O=Staat der Nederlanden,C=NL
+# Not Valid Before: Thu Nov 14 11:28:42 2013
+# Not Valid After : Mon Nov 13 23:00:00 2028
+# Fingerprint (SHA-256): 3C:4F:B0:B9:5A:B8:B3:00:32:F4:32:B8:6F:53:5F:E1:72:C1:85:D0:FD:39:86:58:37:CF:36:18:7F:A6:F4:28
+# Fingerprint (SHA1): D8:EB:6B:41:51:92:59:E0:F3:E7:85:00:C0:3D:B6:88:97:C9:EE:FC
+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 "Staat der Nederlanden Root CA - G3"
+CKA_CERT_SHA1_HASH MULTILINE_OCTAL
+\330\353\153\101\121\222\131\340\363\347\205\000\300\075\266\210
+\227\311\356\374
+END
+CKA_CERT_MD5_HASH MULTILINE_OCTAL
+\013\106\147\007\333\020\057\031\214\065\120\140\321\013\364\067
+END
+CKA_ISSUER MULTILINE_OCTAL
+\060\132\061\013\060\011\006\003\125\004\006\023\002\116\114\061
+\036\060\034\006\003\125\004\012\014\025\123\164\141\141\164\040
+\144\145\162\040\116\145\144\145\162\154\141\156\144\145\156\061
+\053\060\051\006\003\125\004\003\014\042\123\164\141\141\164\040
+\144\145\162\040\116\145\144\145\162\154\141\156\144\145\156\040
+\122\157\157\164\040\103\101\040\055\040\107\063
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\004\000\230\242\071
+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_MUST_VERIFY_TRUST
+CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
+
+#
+# Certificate "Staat der Nederlanden EV Root CA"
+#
+# Issuer: CN=Staat der Nederlanden EV Root CA,O=Staat der Nederlanden,C=NL
+# Serial Number: 10000013 (0x98968d)
+# Subject: CN=Staat der Nederlanden EV Root CA,O=Staat der Nederlanden,C=NL
+# Not Valid Before: Wed Dec 08 11:19:29 2010
+# Not Valid After : Thu Dec 08 11:10:28 2022
+# Fingerprint (SHA-256): 4D:24:91:41:4C:FE:95:67:46:EC:4C:EF:A6:CF:6F:72:E2:8A:13:29:43:2F:9D:8A:90:7A:C4:CB:5D:AD:C1:5A
+# Fingerprint (SHA1): 76:E2:7E:C1:4F:DB:82:C1:C0:A6:75:B5:05:BE:3D:29:B4:ED:DB:BB
+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 "Staat der Nederlanden EV Root CA"
+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
+CKA_SUBJECT MULTILINE_OCTAL
+\060\130\061\013\060\011\006\003\125\004\006\023\002\116\114\061
+\036\060\034\006\003\125\004\012\014\025\123\164\141\141\164\040
+\144\145\162\040\116\145\144\145\162\154\141\156\144\145\156\061
+\051\060\047\006\003\125\004\003\014\040\123\164\141\141\164\040
+\144\145\162\040\116\145\144\145\162\154\141\156\144\145\156\040
+\105\126\040\122\157\157\164\040\103\101
+END
+CKA_ID UTF8 "0"
+CKA_ISSUER MULTILINE_OCTAL
+\060\130\061\013\060\011\006\003\125\004\006\023\002\116\114\061
+\036\060\034\006\003\125\004\012\014\025\123\164\141\141\164\040
+\144\145\162\040\116\145\144\145\162\154\141\156\144\145\156\061
+\051\060\047\006\003\125\004\003\014\040\123\164\141\141\164\040
+\144\145\162\040\116\145\144\145\162\154\141\156\144\145\156\040
+\105\126\040\122\157\157\164\040\103\101
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\004\000\230\226\215
+END
+CKA_VALUE MULTILINE_OCTAL
+\060\202\005\160\060\202\003\130\240\003\002\001\002\002\004\000
+\230\226\215\060\015\006\011\052\206\110\206\367\015\001\001\013
+\005\000\060\130\061\013\060\011\006\003\125\004\006\023\002\116
+\114\061\036\060\034\006\003\125\004\012\014\025\123\164\141\141
+\164\040\144\145\162\040\116\145\144\145\162\154\141\156\144\145
+\156\061\051\060\047\006\003\125\004\003\014\040\123\164\141\141
+\164\040\144\145\162\040\116\145\144\145\162\154\141\156\144\145
+\156\040\105\126\040\122\157\157\164\040\103\101\060\036\027\015
+\061\060\061\062\060\070\061\061\061\071\062\071\132\027\015\062
+\062\061\062\060\070\061\061\061\060\062\070\132\060\130\061\013
+\060\011\006\003\125\004\006\023\002\116\114\061\036\060\034\006
+\003\125\004\012\014\025\123\164\141\141\164\040\144\145\162\040
+\116\145\144\145\162\154\141\156\144\145\156\061\051\060\047\006
+\003\125\004\003\014\040\123\164\141\141\164\040\144\145\162\040
+\116\145\144\145\162\154\141\156\144\145\156\040\105\126\040\122
+\157\157\164\040\103\101\060\202\002\042\060\015\006\011\052\206
+\110\206\367\015\001\001\001\005\000\003\202\002\017\000\060\202
+\002\012\002\202\002\001\000\343\307\176\211\371\044\113\072\322
+\063\203\065\054\151\354\334\011\244\343\121\250\045\053\171\270
+\010\075\340\221\272\204\205\306\205\244\312\346\311\056\123\244
+\311\044\036\375\125\146\161\135\054\305\140\150\004\267\331\302
+\122\046\070\210\244\326\073\100\246\302\315\077\315\230\223\263
+\124\024\130\226\125\325\120\376\206\255\244\143\177\134\207\366
+\216\346\047\222\147\027\222\002\003\054\334\326\146\164\355\335
+\147\377\301\141\215\143\117\017\233\155\027\060\046\357\253\322
+\037\020\240\371\305\177\026\151\201\003\107\355\036\150\215\162
+\241\115\262\046\306\272\154\137\155\326\257\321\261\023\216\251
+\255\363\136\151\165\046\030\076\101\053\041\177\356\213\135\007
+\006\235\103\304\051\012\053\374\052\076\206\313\074\203\072\371
+\311\015\332\305\231\342\274\170\101\063\166\341\277\057\135\345
+\244\230\120\014\025\335\340\372\234\177\070\150\320\262\246\172
+\247\321\061\275\176\212\130\047\103\263\272\063\221\323\247\230
+\025\134\232\346\323\017\165\331\374\101\230\227\076\252\045\333
+\217\222\056\260\173\014\137\361\143\251\067\371\233\165\151\114
+\050\046\045\332\325\362\022\160\105\125\343\337\163\136\067\365
+\041\154\220\216\065\132\311\323\043\353\323\300\276\170\254\102
+\050\130\146\245\106\155\160\002\327\020\371\113\124\374\135\206
+\112\207\317\177\312\105\254\021\132\265\040\121\215\057\210\107
+\227\071\300\317\272\300\102\001\100\231\110\041\013\153\247\322
+\375\226\325\321\276\106\235\111\340\013\246\240\042\116\070\320
+\301\074\060\274\160\217\054\165\314\320\305\214\121\073\075\224
+\010\144\046\141\175\271\303\145\217\024\234\041\320\252\375\027
+\162\003\217\275\233\214\346\136\123\236\271\235\357\202\273\341
+\274\342\162\101\133\041\224\323\105\067\224\321\337\011\071\135
+\347\043\252\232\035\312\155\250\012\206\205\212\202\276\102\007
+\326\362\070\202\163\332\207\133\345\074\323\236\076\247\073\236
+\364\003\263\371\361\175\023\164\002\377\273\241\345\372\000\171
+\034\246\146\101\210\134\140\127\246\056\011\304\272\375\232\317
+\247\037\100\303\273\314\132\012\125\113\073\070\166\121\270\143
+\213\204\224\026\346\126\363\002\003\001\000\001\243\102\060\100
+\060\017\006\003\125\035\023\001\001\377\004\005\060\003\001\001
+\377\060\016\006\003\125\035\017\001\001\377\004\004\003\002\001
+\006\060\035\006\003\125\035\016\004\026\004\024\376\253\000\220
+\230\236\044\374\251\314\032\212\373\047\270\277\060\156\250\073
+\060\015\006\011\052\206\110\206\367\015\001\001\013\005\000\003
+\202\002\001\000\317\167\054\156\126\276\116\263\266\204\000\224
+\253\107\311\015\322\166\307\206\237\035\007\323\266\264\273\010
+\170\257\151\322\013\111\336\063\305\254\255\302\210\002\175\006
+\267\065\002\301\140\311\277\304\350\224\336\324\323\251\023\045
+\132\376\156\242\256\175\005\334\175\363\154\360\176\246\215\356
+\331\327\316\130\027\350\251\051\256\163\110\207\347\233\312\156
+\051\241\144\137\031\023\367\256\006\020\377\121\306\233\115\125
+\045\117\223\231\020\001\123\165\361\023\316\307\246\101\101\322
+\277\210\245\177\105\374\254\270\245\265\063\014\202\304\373\007
+\366\152\345\045\204\137\006\312\301\206\071\021\333\130\315\167
+\073\054\302\114\017\136\232\343\360\253\076\141\033\120\044\302
+\300\364\361\031\360\021\051\266\245\030\002\233\327\143\114\160
+\214\107\243\003\103\134\271\135\106\240\015\157\377\131\216\276
+\335\237\162\303\133\053\337\214\133\316\345\014\106\154\222\262
+\012\243\114\124\102\030\025\022\030\275\332\374\272\164\156\377
+\301\266\240\144\330\251\137\125\256\237\134\152\166\226\330\163
+\147\207\373\115\177\134\356\151\312\163\020\373\212\251\375\236
+\275\066\070\111\111\207\364\016\024\360\351\207\270\077\247\117
+\172\132\216\171\324\223\344\273\150\122\204\254\154\351\363\230
+\160\125\162\062\371\064\253\053\111\265\315\040\142\344\072\172
+\147\143\253\226\334\155\256\227\354\374\237\166\126\210\056\146
+\317\133\266\311\244\260\327\005\272\341\047\057\223\273\046\052
+\242\223\260\033\363\216\276\035\100\243\271\066\217\076\202\032
+\032\136\210\352\120\370\131\342\203\106\051\013\343\104\134\341
+\225\266\151\220\232\024\157\227\256\201\317\150\357\231\232\276
+\265\347\341\177\370\372\023\107\026\114\314\155\010\100\347\213
+\170\157\120\202\104\120\077\146\006\212\253\103\204\126\112\017
+\040\055\206\016\365\322\333\322\172\212\113\315\245\350\116\361
+\136\046\045\001\131\043\240\176\322\366\176\041\127\327\047\274
+\025\127\114\244\106\301\340\203\036\014\114\115\037\117\006\031
+\342\371\250\364\072\202\241\262\171\103\171\326\255\157\172\047
+\220\003\244\352\044\207\077\331\275\331\351\362\137\120\111\034
+\356\354\327\056
+END
+
+# Trust for "Staat der Nederlanden EV Root CA"
+# Issuer: CN=Staat der Nederlanden EV Root CA,O=Staat der Nederlanden,C=NL
+# Serial Number: 10000013 (0x98968d)
+# Subject: CN=Staat der Nederlanden EV Root CA,O=Staat der Nederlanden,C=NL
+# Not Valid Before: Wed Dec 08 11:19:29 2010
+# Not Valid After : Thu Dec 08 11:10:28 2022
+# Fingerprint (SHA-256): 4D:24:91:41:4C:FE:95:67:46:EC:4C:EF:A6:CF:6F:72:E2:8A:13:29:43:2F:9D:8A:90:7A:C4:CB:5D:AD:C1:5A
+# Fingerprint (SHA1): 76:E2:7E:C1:4F:DB:82:C1:C0:A6:75:B5:05:BE:3D:29:B4:ED:DB:BB
+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 "Staat der Nederlanden EV Root CA"
+CKA_CERT_SHA1_HASH MULTILINE_OCTAL
+\166\342\176\301\117\333\202\301\300\246\165\265\005\276\075\051
+\264\355\333\273
+END
+CKA_CERT_MD5_HASH MULTILINE_OCTAL
+\374\006\257\173\350\032\361\232\264\350\322\160\037\300\365\272
+END
+CKA_ISSUER MULTILINE_OCTAL
+\060\130\061\013\060\011\006\003\125\004\006\023\002\116\114\061
+\036\060\034\006\003\125\004\012\014\025\123\164\141\141\164\040
+\144\145\162\040\116\145\144\145\162\154\141\156\144\145\156\061
+\051\060\047\006\003\125\004\003\014\040\123\164\141\141\164\040
+\144\145\162\040\116\145\144\145\162\154\141\156\144\145\156\040
+\105\126\040\122\157\157\164\040\103\101
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\004\000\230\226\215
+END
+CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
+CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
+CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
+CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
+
+#
+# Certificate "IdenTrust Commercial Root CA 1"
+#
+# Issuer: CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US
+# Serial Number:0a:01:42:80:00:00:01:45:23:c8:44:b5:00:00:00:02
+# Subject: CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US
+# Not Valid Before: Thu Jan 16 18:12:23 2014
+# Not Valid After : Mon Jan 16 18:12:23 2034
+# Fingerprint (SHA-256): 5D:56:49:9B:E4:D2:E0:8B:CF:CA:D0:8A:3E:38:72:3D:50:50:3B:DE:70:69:48:E4:2F:55:60:30:19:E5:28:AE
+# Fingerprint (SHA1): DF:71:7E:AA:4A:D9:4E:C9:55:84:99:60:2D:48:DE:5F:BC:F0:3A:25
+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 "IdenTrust Commercial Root CA 1"
+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
+CKA_SUBJECT MULTILINE_OCTAL
+\060\112\061\013\060\011\006\003\125\004\006\023\002\125\123\061
+\022\060\020\006\003\125\004\012\023\011\111\144\145\156\124\162
+\165\163\164\061\047\060\045\006\003\125\004\003\023\036\111\144
+\145\156\124\162\165\163\164\040\103\157\155\155\145\162\143\151
+\141\154\040\122\157\157\164\040\103\101\040\061
+END
+CKA_ID UTF8 "0"
+CKA_ISSUER MULTILINE_OCTAL
+\060\112\061\013\060\011\006\003\125\004\006\023\002\125\123\061
+\022\060\020\006\003\125\004\012\023\011\111\144\145\156\124\162
+\165\163\164\061\047\060\045\006\003\125\004\003\023\036\111\144
+\145\156\124\162\165\163\164\040\103\157\155\155\145\162\143\151
+\141\154\040\122\157\157\164\040\103\101\040\061
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\020\012\001\102\200\000\000\001\105\043\310\104\265\000\000
+\000\002
+END
+CKA_VALUE MULTILINE_OCTAL
+\060\202\005\140\060\202\003\110\240\003\002\001\002\002\020\012
+\001\102\200\000\000\001\105\043\310\104\265\000\000\000\002\060
+\015\006\011\052\206\110\206\367\015\001\001\013\005\000\060\112
+\061\013\060\011\006\003\125\004\006\023\002\125\123\061\022\060
+\020\006\003\125\004\012\023\011\111\144\145\156\124\162\165\163
+\164\061\047\060\045\006\003\125\004\003\023\036\111\144\145\156
+\124\162\165\163\164\040\103\157\155\155\145\162\143\151\141\154
+\040\122\157\157\164\040\103\101\040\061\060\036\027\015\061\064
+\060\061\061\066\061\070\061\062\062\063\132\027\015\063\064\060
+\061\061\066\061\070\061\062\062\063\132\060\112\061\013\060\011
+\006\003\125\004\006\023\002\125\123\061\022\060\020\006\003\125
+\004\012\023\011\111\144\145\156\124\162\165\163\164\061\047\060
+\045\006\003\125\004\003\023\036\111\144\145\156\124\162\165\163
+\164\040\103\157\155\155\145\162\143\151\141\154\040\122\157\157
+\164\040\103\101\040\061\060\202\002\042\060\015\006\011\052\206
+\110\206\367\015\001\001\001\005\000\003\202\002\017\000\060\202
+\002\012\002\202\002\001\000\247\120\031\336\077\231\075\324\063
+\106\361\157\121\141\202\262\251\117\217\147\211\135\204\331\123
+\335\014\050\331\327\360\377\256\225\103\162\231\371\265\135\174
+\212\301\102\341\061\120\164\321\201\015\174\315\233\041\253\103
+\342\254\255\136\206\156\363\011\212\037\132\062\275\242\353\224
+\371\350\134\012\354\377\230\322\257\161\263\264\123\237\116\207
+\357\222\274\275\354\117\062\060\210\113\027\136\127\304\123\302
+\366\002\227\215\331\142\053\277\044\037\142\215\337\303\270\051
+\113\111\170\074\223\140\210\042\374\231\332\066\310\302\242\324
+\054\124\000\147\065\156\163\277\002\130\360\244\335\345\260\242
+\046\172\312\340\066\245\031\026\365\375\267\357\256\077\100\365
+\155\132\004\375\316\064\312\044\334\164\043\033\135\063\023\022
+\135\304\001\045\366\060\335\002\135\237\340\325\107\275\264\353
+\033\241\273\111\111\330\237\133\002\363\212\344\044\220\344\142
+\117\117\301\257\213\016\164\027\250\321\162\210\152\172\001\111
+\314\264\106\171\306\027\261\332\230\036\007\131\372\165\041\205
+\145\335\220\126\316\373\253\245\140\235\304\235\371\122\260\213
+\275\207\371\217\053\043\012\043\166\073\367\063\341\311\000\363
+\151\371\113\242\340\116\274\176\223\071\204\007\367\104\160\176
+\376\007\132\345\261\254\321\030\314\362\065\345\111\111\010\312
+\126\311\075\373\017\030\175\213\073\301\023\302\115\217\311\117
+\016\067\351\037\241\016\152\337\142\056\313\065\006\121\171\054
+\310\045\070\364\372\113\247\211\134\234\322\343\015\071\206\112
+\164\174\325\131\207\302\077\116\014\134\122\364\075\367\122\202
+\361\352\243\254\375\111\064\032\050\363\101\210\072\023\356\350
+\336\377\231\035\137\272\313\350\036\362\271\120\140\300\061\323
+\163\345\357\276\240\355\063\013\164\276\040\040\304\147\154\360
+\010\003\172\125\200\177\106\116\226\247\364\036\076\341\366\330
+\011\341\063\144\053\143\327\062\136\237\371\300\173\017\170\157
+\227\274\223\232\371\234\022\220\170\172\200\207\025\327\162\164
+\234\125\164\170\261\272\341\156\160\004\272\117\240\272\150\303
+\173\377\061\360\163\075\075\224\052\261\013\101\016\240\376\115
+\210\145\153\171\063\264\327\002\003\001\000\001\243\102\060\100
+\060\016\006\003\125\035\017\001\001\377\004\004\003\002\001\006
+\060\017\006\003\125\035\023\001\001\377\004\005\060\003\001\001
+\377\060\035\006\003\125\035\016\004\026\004\024\355\104\031\300
+\323\360\006\213\356\244\173\276\102\347\046\124\310\216\066\166
+\060\015\006\011\052\206\110\206\367\015\001\001\013\005\000\003
+\202\002\001\000\015\256\220\062\366\246\113\174\104\166\031\141
+\036\047\050\315\136\124\357\045\274\343\010\220\371\051\327\256
+\150\010\341\224\000\130\357\056\056\176\123\122\214\266\134\007
+\352\210\272\231\213\120\224\327\202\200\337\141\011\000\223\255
+\015\024\346\316\301\362\067\224\170\260\137\234\263\242\163\270
+\217\005\223\070\315\215\076\260\270\373\300\317\261\362\354\055
+\055\033\314\354\252\232\263\252\140\202\033\055\073\303\204\075
+\127\212\226\036\234\165\270\323\060\315\140\010\203\220\323\216
+\124\361\115\146\300\135\164\003\100\243\356\205\176\302\037\167
+\234\006\350\301\247\030\135\122\225\355\311\335\045\236\155\372
+\251\355\243\072\064\320\131\173\332\355\120\363\065\277\355\353
+\024\115\061\307\140\364\332\361\207\234\342\110\342\306\305\067
+\373\006\020\372\165\131\146\061\107\051\332\166\232\034\351\202
+\256\357\232\271\121\367\210\043\232\151\225\142\074\345\125\200
+\066\327\124\002\377\361\271\135\316\324\043\157\330\105\204\112
+\133\145\357\211\014\335\024\247\040\313\030\245\045\264\015\371
+\001\360\242\322\364\000\310\164\216\241\052\110\216\145\333\023
+\304\342\045\027\175\353\276\207\133\027\040\124\121\223\112\123
+\003\013\354\135\312\063\355\142\375\105\307\057\133\334\130\240
+\200\071\346\372\327\376\023\024\246\355\075\224\112\102\164\324
+\303\167\131\163\315\217\106\276\125\070\357\372\350\221\062\352
+\227\130\004\042\336\070\303\314\274\155\311\063\072\152\012\151
+\077\240\310\352\162\217\214\143\206\043\275\155\074\226\236\225
+\340\111\114\252\242\271\052\033\234\066\201\170\355\303\350\106
+\342\046\131\104\165\036\331\165\211\121\315\020\204\235\141\140
+\313\135\371\227\042\115\216\230\346\343\177\366\133\273\256\315
+\312\112\201\153\136\013\363\121\341\164\053\351\176\047\247\331
+\231\111\116\370\245\200\333\045\017\034\143\142\212\311\063\147
+\153\074\020\203\306\255\336\250\315\026\216\215\360\007\067\161
+\237\362\253\374\101\365\301\213\354\000\067\135\011\345\116\200
+\357\372\261\134\070\006\245\033\112\341\334\070\055\074\334\253
+\037\220\032\325\112\234\356\321\160\154\314\356\364\127\370\030
+\272\204\156\207
+END
+
+# Trust for "IdenTrust Commercial Root CA 1"
+# Issuer: CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US
+# Serial Number:0a:01:42:80:00:00:01:45:23:c8:44:b5:00:00:00:02
+# Subject: CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US
+# Not Valid Before: Thu Jan 16 18:12:23 2014
+# Not Valid After : Mon Jan 16 18:12:23 2034
+# Fingerprint (SHA-256): 5D:56:49:9B:E4:D2:E0:8B:CF:CA:D0:8A:3E:38:72:3D:50:50:3B:DE:70:69:48:E4:2F:55:60:30:19:E5:28:AE
+# Fingerprint (SHA1): DF:71:7E:AA:4A:D9:4E:C9:55:84:99:60:2D:48:DE:5F:BC:F0:3A:25
+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 "IdenTrust Commercial Root CA 1"
+CKA_CERT_SHA1_HASH MULTILINE_OCTAL
+\337\161\176\252\112\331\116\311\125\204\231\140\055\110\336\137
+\274\360\072\045
+END
+CKA_CERT_MD5_HASH MULTILINE_OCTAL
+\263\076\167\163\165\356\240\323\343\176\111\143\111\131\273\307
+END
+CKA_ISSUER MULTILINE_OCTAL
+\060\112\061\013\060\011\006\003\125\004\006\023\002\125\123\061
+\022\060\020\006\003\125\004\012\023\011\111\144\145\156\124\162
+\165\163\164\061\047\060\045\006\003\125\004\003\023\036\111\144
+\145\156\124\162\165\163\164\040\103\157\155\155\145\162\143\151
+\141\154\040\122\157\157\164\040\103\101\040\061
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\020\012\001\102\200\000\000\001\105\043\310\104\265\000\000
+\000\002
+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_MUST_VERIFY_TRUST
+CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
+
+#
+# Certificate "IdenTrust Public Sector Root CA 1"
+#
+# Issuer: CN=IdenTrust Public Sector Root CA 1,O=IdenTrust,C=US
+# Serial Number:0a:01:42:80:00:00:01:45:23:cf:46:7c:00:00:00:02
+# Subject: CN=IdenTrust Public Sector Root CA 1,O=IdenTrust,C=US
+# Not Valid Before: Thu Jan 16 17:53:32 2014
+# Not Valid After : Mon Jan 16 17:53:32 2034
+# Fingerprint (SHA-256): 30:D0:89:5A:9A:44:8A:26:20:91:63:55:22:D1:F5:20:10:B5:86:7A:CA:E1:2C:78:EF:95:8F:D4:F4:38:9F:2F
+# Fingerprint (SHA1): BA:29:41:60:77:98:3F:F4:F3:EF:F2:31:05:3B:2E:EA:6D:4D:45:FD
+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 "IdenTrust Public Sector Root CA 1"
+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
+CKA_SUBJECT MULTILINE_OCTAL
+\060\115\061\013\060\011\006\003\125\004\006\023\002\125\123\061
+\022\060\020\006\003\125\004\012\023\011\111\144\145\156\124\162
+\165\163\164\061\052\060\050\006\003\125\004\003\023\041\111\144
+\145\156\124\162\165\163\164\040\120\165\142\154\151\143\040\123
+\145\143\164\157\162\040\122\157\157\164\040\103\101\040\061
+END
+CKA_ID UTF8 "0"
+CKA_ISSUER MULTILINE_OCTAL
+\060\115\061\013\060\011\006\003\125\004\006\023\002\125\123\061
+\022\060\020\006\003\125\004\012\023\011\111\144\145\156\124\162
+\165\163\164\061\052\060\050\006\003\125\004\003\023\041\111\144
+\145\156\124\162\165\163\164\040\120\165\142\154\151\143\040\123
+\145\143\164\157\162\040\122\157\157\164\040\103\101\040\061
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\020\012\001\102\200\000\000\001\105\043\317\106\174\000\000
+\000\002
+END
+CKA_VALUE MULTILINE_OCTAL
+\060\202\005\146\060\202\003\116\240\003\002\001\002\002\020\012
+\001\102\200\000\000\001\105\043\317\106\174\000\000\000\002\060
+\015\006\011\052\206\110\206\367\015\001\001\013\005\000\060\115
+\061\013\060\011\006\003\125\004\006\023\002\125\123\061\022\060
+\020\006\003\125\004\012\023\011\111\144\145\156\124\162\165\163
+\164\061\052\060\050\006\003\125\004\003\023\041\111\144\145\156
+\124\162\165\163\164\040\120\165\142\154\151\143\040\123\145\143
+\164\157\162\040\122\157\157\164\040\103\101\040\061\060\036\027
+\015\061\064\060\061\061\066\061\067\065\063\063\062\132\027\015
+\063\064\060\061\061\066\061\067\065\063\063\062\132\060\115\061
+\013\060\011\006\003\125\004\006\023\002\125\123\061\022\060\020
+\006\003\125\004\012\023\011\111\144\145\156\124\162\165\163\164
+\061\052\060\050\006\003\125\004\003\023\041\111\144\145\156\124
+\162\165\163\164\040\120\165\142\154\151\143\040\123\145\143\164
+\157\162\040\122\157\157\164\040\103\101\040\061\060\202\002\042
+\060\015\006\011\052\206\110\206\367\015\001\001\001\005\000\003
+\202\002\017\000\060\202\002\012\002\202\002\001\000\266\042\224
+\374\244\110\257\350\107\153\012\373\047\166\344\362\077\212\073
+\172\112\054\061\052\214\215\260\251\303\061\153\250\167\166\204
+\046\266\254\201\102\015\010\353\125\130\273\172\370\274\145\175
+\362\240\155\213\250\107\351\142\166\036\021\356\010\024\321\262
+\104\026\364\352\320\372\036\057\136\333\313\163\101\256\274\000
+\260\112\053\100\262\254\341\073\113\302\055\235\344\241\233\354
+\032\072\036\360\010\263\320\344\044\065\007\237\234\264\311\122
+\155\333\007\312\217\265\133\360\203\363\117\307\055\245\310\255
+\313\225\040\244\061\050\127\130\132\344\215\033\232\253\236\015
+\014\362\012\063\071\042\071\012\227\056\363\123\167\271\104\105
+\375\204\313\066\040\201\131\055\232\157\155\110\110\141\312\114
+\337\123\321\257\122\274\104\237\253\057\153\203\162\357\165\200
+\332\006\063\033\135\310\332\143\306\115\315\254\146\061\315\321
+\336\076\207\020\066\341\271\244\172\357\140\120\262\313\312\246
+\126\340\067\257\253\064\023\071\045\350\071\146\344\230\172\252
+\022\230\234\131\146\206\076\255\361\260\312\076\006\017\173\360
+\021\113\067\240\104\155\173\313\250\214\161\364\325\265\221\066
+\314\360\025\306\053\336\121\027\261\227\114\120\075\261\225\131
+\174\005\175\055\041\325\000\277\001\147\242\136\173\246\134\362
+\367\042\361\220\015\223\333\252\104\121\146\314\175\166\003\353
+\152\250\052\070\031\227\166\015\153\212\141\371\274\366\356\166
+\375\160\053\335\051\074\370\012\036\133\102\034\213\126\057\125
+\033\034\241\056\265\307\026\346\370\252\074\222\216\151\266\001
+\301\265\206\235\211\017\013\070\224\124\350\352\334\236\075\045
+\274\123\046\355\325\253\071\252\305\100\114\124\253\262\264\331
+\331\370\327\162\333\034\274\155\275\145\137\357\210\065\052\146
+\057\356\366\263\145\360\063\215\174\230\101\151\106\017\103\034
+\151\372\233\265\320\141\152\315\312\113\331\114\220\106\253\025
+\131\241\107\124\051\056\203\050\137\034\302\242\253\162\027\000
+\006\216\105\354\213\342\063\075\177\332\031\104\344\142\162\303
+\337\042\306\362\126\324\335\137\225\162\355\155\137\367\110\003
+\133\375\305\052\240\366\163\043\204\020\033\001\347\002\003\001
+\000\001\243\102\060\100\060\016\006\003\125\035\017\001\001\377
+\004\004\003\002\001\006\060\017\006\003\125\035\023\001\001\377
+\004\005\060\003\001\001\377\060\035\006\003\125\035\016\004\026
+\004\024\343\161\340\236\330\247\102\331\333\161\221\153\224\223
+\353\303\243\321\024\243\060\015\006\011\052\206\110\206\367\015
+\001\001\013\005\000\003\202\002\001\000\107\372\335\012\260\021
+\221\070\255\115\135\367\345\016\227\124\031\202\110\207\124\214
+\252\144\231\330\132\376\210\001\305\130\245\231\261\043\124\043
+\267\152\035\040\127\345\001\142\101\027\323\011\333\165\313\156
+\124\220\165\376\032\237\201\012\302\335\327\367\011\320\133\162
+\025\344\036\011\152\075\063\363\041\232\346\025\176\255\121\325
+\015\020\355\175\102\300\217\356\300\232\010\325\101\326\134\016
+\041\151\156\200\141\016\025\300\270\317\305\111\022\122\314\276
+\072\314\324\056\070\005\336\065\375\037\157\270\200\150\230\075
+\115\240\312\100\145\322\163\174\365\213\331\012\225\077\330\077
+\043\155\032\321\052\044\031\331\205\263\027\357\170\156\251\130
+\321\043\323\307\023\355\162\045\177\135\261\163\160\320\177\006
+\227\011\204\051\200\141\035\372\136\377\163\254\240\343\211\270
+\034\161\025\306\336\061\177\022\334\341\155\233\257\347\350\237
+\165\170\114\253\106\073\232\316\277\005\030\135\115\025\074\026
+\232\031\120\004\232\262\232\157\145\213\122\137\074\130\004\050
+\045\300\146\141\061\176\271\340\165\271\032\250\201\326\162\027
+\263\305\003\061\065\021\170\170\242\340\351\060\214\177\200\337
+\130\337\074\272\047\226\342\200\064\155\343\230\323\144\047\254
+\110\176\050\167\134\306\045\141\045\370\205\014\145\372\304\062
+\057\245\230\005\344\370\013\147\026\026\306\202\270\062\031\371
+\371\271\171\334\037\315\353\257\253\016\335\033\333\105\344\172
+\347\002\342\225\135\374\151\360\123\151\141\225\165\171\013\136
+\125\346\070\034\224\251\131\063\236\310\161\164\171\177\121\211
+\266\310\152\270\060\310\152\070\303\156\236\341\067\026\352\005
+\142\114\133\022\107\355\247\264\263\130\126\307\111\363\177\022
+\150\011\061\161\360\155\370\116\107\373\326\205\356\305\130\100
+\031\244\035\247\371\113\103\067\334\150\132\117\317\353\302\144
+\164\336\264\025\331\364\124\124\032\057\034\327\227\161\124\220
+\216\331\040\235\123\053\177\253\217\342\352\060\274\120\067\357
+\361\107\265\175\174\054\004\354\150\235\264\111\104\020\364\162
+\113\034\144\347\374\346\153\220\335\151\175\151\375\000\126\245
+\267\254\266\255\267\312\076\001\357\234
+END
+
+# Trust for "IdenTrust Public Sector Root CA 1"
+# Issuer: CN=IdenTrust Public Sector Root CA 1,O=IdenTrust,C=US
+# Serial Number:0a:01:42:80:00:00:01:45:23:cf:46:7c:00:00:00:02
+# Subject: CN=IdenTrust Public Sector Root CA 1,O=IdenTrust,C=US
+# Not Valid Before: Thu Jan 16 17:53:32 2014
+# Not Valid After : Mon Jan 16 17:53:32 2034
+# Fingerprint (SHA-256): 30:D0:89:5A:9A:44:8A:26:20:91:63:55:22:D1:F5:20:10:B5:86:7A:CA:E1:2C:78:EF:95:8F:D4:F4:38:9F:2F
+# Fingerprint (SHA1): BA:29:41:60:77:98:3F:F4:F3:EF:F2:31:05:3B:2E:EA:6D:4D:45:FD
+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 "IdenTrust Public Sector Root CA 1"
+CKA_CERT_SHA1_HASH MULTILINE_OCTAL
+\272\051\101\140\167\230\077\364\363\357\362\061\005\073\056\352
+\155\115\105\375
+END
+CKA_CERT_MD5_HASH MULTILINE_OCTAL
+\067\006\245\260\374\211\235\272\364\153\214\032\144\315\325\272
+END
+CKA_ISSUER MULTILINE_OCTAL
+\060\115\061\013\060\011\006\003\125\004\006\023\002\125\123\061
+\022\060\020\006\003\125\004\012\023\011\111\144\145\156\124\162
+\165\163\164\061\052\060\050\006\003\125\004\003\023\041\111\144
+\145\156\124\162\165\163\164\040\120\165\142\154\151\143\040\123
+\145\143\164\157\162\040\122\157\157\164\040\103\101\040\061
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\020\012\001\102\200\000\000\001\105\043\317\106\174\000\000
+\000\002
+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_MUST_VERIFY_TRUST
+CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
+
+#
+# Certificate "S-TRUST Universal Root CA"
+#
+# Issuer: CN=S-TRUST Universal Root CA,OU=S-TRUST Certification Services,O=Deutscher Sparkassen Verlag GmbH,C=DE
+# Serial Number:60:56:c5:4b:23:40:5b:64:d4:ed:25:da:d9:d6:1e:1e
+# Subject: CN=S-TRUST Universal Root CA,OU=S-TRUST Certification Services,O=Deutscher Sparkassen Verlag GmbH,C=DE
+# Not Valid Before: Tue Oct 22 00:00:00 2013
+# Not Valid After : Thu Oct 21 23:59:59 2038
+# Fingerprint (SHA-256): D8:0F:EF:91:0A:E3:F1:04:72:3B:04:5C:EC:2D:01:9F:44:1C:E6:21:3A:DF:15:67:91:E7:0C:17:90:11:0A:31
+# Fingerprint (SHA1): 1B:3D:11:14:EA:7A:0F:95:58:54:41:95:BF:6B:25:82:AB:40:CE:9A
+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 "S-TRUST Universal Root CA"
+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\104\105
+\061\051\060\047\006\003\125\004\012\023\040\104\145\165\164\163
+\143\150\145\162\040\123\160\141\162\153\141\163\163\145\156\040
+\126\145\162\154\141\147\040\107\155\142\110\061\047\060\045\006
+\003\125\004\013\023\036\123\055\124\122\125\123\124\040\103\145
+\162\164\151\146\151\143\141\164\151\157\156\040\123\145\162\166
+\151\143\145\163\061\042\060\040\006\003\125\004\003\023\031\123
+\055\124\122\125\123\124\040\125\156\151\166\145\162\163\141\154
+\040\122\157\157\164\040\103\101
+END
+CKA_ID UTF8 "0"
+CKA_ISSUER MULTILINE_OCTAL
+\060\201\205\061\013\060\011\006\003\125\004\006\023\002\104\105
+\061\051\060\047\006\003\125\004\012\023\040\104\145\165\164\163
+\143\150\145\162\040\123\160\141\162\153\141\163\163\145\156\040
+\126\145\162\154\141\147\040\107\155\142\110\061\047\060\045\006
+\003\125\004\013\023\036\123\055\124\122\125\123\124\040\103\145
+\162\164\151\146\151\143\141\164\151\157\156\040\123\145\162\166
+\151\143\145\163\061\042\060\040\006\003\125\004\003\023\031\123
+\055\124\122\125\123\124\040\125\156\151\166\145\162\163\141\154
+\040\122\157\157\164\040\103\101
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\020\140\126\305\113\043\100\133\144\324\355\045\332\331\326
+\036\036
+END
+CKA_VALUE MULTILINE_OCTAL
+\060\202\003\330\060\202\002\300\240\003\002\001\002\002\020\140
+\126\305\113\043\100\133\144\324\355\045\332\331\326\036\036\060
+\015\006\011\052\206\110\206\367\015\001\001\013\005\000\060\201
+\205\061\013\060\011\006\003\125\004\006\023\002\104\105\061\051
+\060\047\006\003\125\004\012\023\040\104\145\165\164\163\143\150
+\145\162\040\123\160\141\162\153\141\163\163\145\156\040\126\145
+\162\154\141\147\040\107\155\142\110\061\047\060\045\006\003\125
+\004\013\023\036\123\055\124\122\125\123\124\040\103\145\162\164
+\151\146\151\143\141\164\151\157\156\040\123\145\162\166\151\143
+\145\163\061\042\060\040\006\003\125\004\003\023\031\123\055\124
+\122\125\123\124\040\125\156\151\166\145\162\163\141\154\040\122
+\157\157\164\040\103\101\060\036\027\015\061\063\061\060\062\062
+\060\060\060\060\060\060\132\027\015\063\070\061\060\062\061\062
+\063\065\071\065\071\132\060\201\205\061\013\060\011\006\003\125
+\004\006\023\002\104\105\061\051\060\047\006\003\125\004\012\023
+\040\104\145\165\164\163\143\150\145\162\040\123\160\141\162\153
+\141\163\163\145\156\040\126\145\162\154\141\147\040\107\155\142
+\110\061\047\060\045\006\003\125\004\013\023\036\123\055\124\122
+\125\123\124\040\103\145\162\164\151\146\151\143\141\164\151\157
+\156\040\123\145\162\166\151\143\145\163\061\042\060\040\006\003
+\125\004\003\023\031\123\055\124\122\125\123\124\040\125\156\151
+\166\145\162\163\141\154\040\122\157\157\164\040\103\101\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\250
+\343\013\337\021\067\205\202\232\265\154\146\174\141\077\300\107
+\032\035\106\343\260\125\144\345\270\202\071\050\007\176\027\377
+\364\233\212\360\221\201\352\070\077\041\170\154\110\354\153\057
+\242\323\212\162\262\247\327\331\352\177\264\300\111\153\060\045
+\211\214\353\267\325\100\141\230\342\334\074\040\222\315\145\112
+\162\237\032\216\214\372\045\025\277\363\041\203\050\015\213\257
+\131\021\202\103\134\233\115\045\121\177\130\030\143\140\073\263
+\265\212\213\130\143\067\110\110\220\104\302\100\335\135\367\103
+\151\051\230\134\022\145\136\253\220\222\113\146\337\325\165\022
+\123\124\030\246\336\212\326\273\127\003\071\131\231\030\005\014
+\371\375\025\306\220\144\106\027\202\327\302\112\101\075\375\000
+\276\127\162\030\224\167\033\123\132\211\001\366\063\162\016\223
+\072\334\350\036\375\005\005\326\274\163\340\210\334\253\117\354
+\265\030\206\117\171\204\016\110\052\146\052\335\062\310\170\145
+\310\013\235\130\001\005\161\355\201\365\150\027\156\313\015\264
+\113\330\241\354\256\070\353\034\130\057\241\145\003\064\057\002
+\003\001\000\001\243\102\060\100\060\017\006\003\125\035\023\001
+\001\377\004\005\060\003\001\001\377\060\016\006\003\125\035\017
+\001\001\377\004\004\003\002\001\006\060\035\006\003\125\035\016
+\004\026\004\024\232\175\327\353\353\177\124\230\105\051\264\040
+\253\155\013\226\043\031\244\302\060\015\006\011\052\206\110\206
+\367\015\001\001\013\005\000\003\202\001\001\000\116\226\022\333
+\176\167\136\222\047\236\041\027\030\202\166\330\077\274\245\011
+\004\146\210\211\255\333\125\263\063\152\306\145\304\217\115\363
+\062\066\334\171\004\226\251\167\062\321\227\365\030\153\214\272
+\355\316\021\320\104\307\222\361\264\104\216\355\210\122\110\236
+\325\375\131\370\243\036\121\373\001\122\345\137\345\172\335\252
+\044\117\042\213\335\166\106\366\245\240\017\065\330\312\017\230
+\271\060\135\040\157\302\201\036\275\275\300\376\025\323\070\052
+\011\223\230\047\033\223\173\320\053\064\136\150\245\025\117\321
+\122\303\240\312\240\203\105\035\365\365\267\131\163\135\131\001
+\217\252\302\107\057\024\161\325\051\343\020\265\107\223\045\314
+\043\051\332\267\162\330\221\324\354\033\110\212\042\344\301\052
+\367\072\150\223\237\105\031\156\103\267\314\376\270\221\232\141
+\032\066\151\143\144\222\050\363\157\141\222\205\023\237\311\007
+\054\213\127\334\353\236\171\325\302\336\010\325\124\262\127\116
+\052\062\215\241\342\072\321\020\040\042\071\175\064\105\157\161
+\073\303\035\374\377\262\117\250\342\366\060\036
+END
+
+# Trust for "S-TRUST Universal Root CA"
+# Issuer: CN=S-TRUST Universal Root CA,OU=S-TRUST Certification Services,O=Deutscher Sparkassen Verlag GmbH,C=DE
+# Serial Number:60:56:c5:4b:23:40:5b:64:d4:ed:25:da:d9:d6:1e:1e
+# Subject: CN=S-TRUST Universal Root CA,OU=S-TRUST Certification Services,O=Deutscher Sparkassen Verlag GmbH,C=DE
+# Not Valid Before: Tue Oct 22 00:00:00 2013
+# Not Valid After : Thu Oct 21 23:59:59 2038
+# Fingerprint (SHA-256): D8:0F:EF:91:0A:E3:F1:04:72:3B:04:5C:EC:2D:01:9F:44:1C:E6:21:3A:DF:15:67:91:E7:0C:17:90:11:0A:31
+# Fingerprint (SHA1): 1B:3D:11:14:EA:7A:0F:95:58:54:41:95:BF:6B:25:82:AB:40:CE:9A
+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 "S-TRUST Universal Root CA"
+CKA_CERT_SHA1_HASH MULTILINE_OCTAL
+\033\075\021\024\352\172\017\225\130\124\101\225\277\153\045\202
+\253\100\316\232
+END
+CKA_CERT_MD5_HASH MULTILINE_OCTAL
+\130\366\101\001\256\365\133\121\231\116\134\041\350\117\324\146
+END
+CKA_ISSUER MULTILINE_OCTAL
+\060\201\205\061\013\060\011\006\003\125\004\006\023\002\104\105
+\061\051\060\047\006\003\125\004\012\023\040\104\145\165\164\163
+\143\150\145\162\040\123\160\141\162\153\141\163\163\145\156\040
+\126\145\162\154\141\147\040\107\155\142\110\061\047\060\045\006
+\003\125\004\013\023\036\123\055\124\122\125\123\124\040\103\145
+\162\164\151\146\151\143\141\164\151\157\156\040\123\145\162\166
+\151\143\145\163\061\042\060\040\006\003\125\004\003\023\031\123
+\055\124\122\125\123\124\040\125\156\151\166\145\162\163\141\154
+\040\122\157\157\164\040\103\101
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\020\140\126\305\113\043\100\133\144\324\355\045\332\331\326
+\036\036
+END
+CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
+CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
+CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
+CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
+
+#
+# Certificate "Entrust Root Certification Authority - G2"
+#
+# Issuer: CN=Entrust Root Certification Authority - G2,OU="(c) 2009 Entrust, Inc. - for authorized use only",OU=See www.entrust.net/legal-terms,O="Entrust, Inc.",C=US
+# Serial Number: 1246989352 (0x4a538c28)
+# Subject: CN=Entrust Root Certification Authority - G2,OU="(c) 2009 Entrust, Inc. - for authorized use only",OU=See www.entrust.net/legal-terms,O="Entrust, Inc.",C=US
+# Not Valid Before: Tue Jul 07 17:25:54 2009
+# Not Valid After : Sat Dec 07 17:55:54 2030
+# Fingerprint (SHA-256): 43:DF:57:74:B0:3E:7F:EF:5F:E4:0D:93:1A:7B:ED:F1:BB:2E:6B:42:73:8C:4E:6D:38:41:10:3D:3A:A7:F3:39
+# Fingerprint (SHA1): 8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4
+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 "Entrust Root Certification Authority - G2"
+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
+CKA_SUBJECT MULTILINE_OCTAL
+\060\201\276\061\013\060\011\006\003\125\004\006\023\002\125\123
+\061\026\060\024\006\003\125\004\012\023\015\105\156\164\162\165
+\163\164\054\040\111\156\143\056\061\050\060\046\006\003\125\004
+\013\023\037\123\145\145\040\167\167\167\056\145\156\164\162\165
+\163\164\056\156\145\164\057\154\145\147\141\154\055\164\145\162
+\155\163\061\071\060\067\006\003\125\004\013\023\060\050\143\051
+\040\062\060\060\071\040\105\156\164\162\165\163\164\054\040\111
+\156\143\056\040\055\040\146\157\162\040\141\165\164\150\157\162
+\151\172\145\144\040\165\163\145\040\157\156\154\171\061\062\060
+\060\006\003\125\004\003\023\051\105\156\164\162\165\163\164\040
+\122\157\157\164\040\103\145\162\164\151\146\151\143\141\164\151
+\157\156\040\101\165\164\150\157\162\151\164\171\040\055\040\107
+\062
+END
+CKA_ID UTF8 "0"
+CKA_ISSUER MULTILINE_OCTAL
+\060\201\276\061\013\060\011\006\003\125\004\006\023\002\125\123
+\061\026\060\024\006\003\125\004\012\023\015\105\156\164\162\165
+\163\164\054\040\111\156\143\056\061\050\060\046\006\003\125\004
+\013\023\037\123\145\145\040\167\167\167\056\145\156\164\162\165
+\163\164\056\156\145\164\057\154\145\147\141\154\055\164\145\162
+\155\163\061\071\060\067\006\003\125\004\013\023\060\050\143\051
+\040\062\060\060\071\040\105\156\164\162\165\163\164\054\040\111
+\156\143\056\040\055\040\146\157\162\040\141\165\164\150\157\162
+\151\172\145\144\040\165\163\145\040\157\156\154\171\061\062\060
+\060\006\003\125\004\003\023\051\105\156\164\162\165\163\164\040
+\122\157\157\164\040\103\145\162\164\151\146\151\143\141\164\151
+\157\156\040\101\165\164\150\157\162\151\164\171\040\055\040\107
+\062
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\004\112\123\214\050
+END
+CKA_VALUE MULTILINE_OCTAL
+\060\202\004\076\060\202\003\046\240\003\002\001\002\002\004\112
+\123\214\050\060\015\006\011\052\206\110\206\367\015\001\001\013
+\005\000\060\201\276\061\013\060\011\006\003\125\004\006\023\002
+\125\123\061\026\060\024\006\003\125\004\012\023\015\105\156\164
+\162\165\163\164\054\040\111\156\143\056\061\050\060\046\006\003
+\125\004\013\023\037\123\145\145\040\167\167\167\056\145\156\164
+\162\165\163\164\056\156\145\164\057\154\145\147\141\154\055\164
+\145\162\155\163\061\071\060\067\006\003\125\004\013\023\060\050
+\143\051\040\062\060\060\071\040\105\156\164\162\165\163\164\054
+\040\111\156\143\056\040\055\040\146\157\162\040\141\165\164\150
+\157\162\151\172\145\144\040\165\163\145\040\157\156\154\171\061
+\062\060\060\006\003\125\004\003\023\051\105\156\164\162\165\163
+\164\040\122\157\157\164\040\103\145\162\164\151\146\151\143\141
+\164\151\157\156\040\101\165\164\150\157\162\151\164\171\040\055
+\040\107\062\060\036\027\015\060\071\060\067\060\067\061\067\062
+\065\065\064\132\027\015\063\060\061\062\060\067\061\067\065\065
+\065\064\132\060\201\276\061\013\060\011\006\003\125\004\006\023
+\002\125\123\061\026\060\024\006\003\125\004\012\023\015\105\156
+\164\162\165\163\164\054\040\111\156\143\056\061\050\060\046\006
+\003\125\004\013\023\037\123\145\145\040\167\167\167\056\145\156
+\164\162\165\163\164\056\156\145\164\057\154\145\147\141\154\055
+\164\145\162\155\163\061\071\060\067\006\003\125\004\013\023\060
+\050\143\051\040\062\060\060\071\040\105\156\164\162\165\163\164
+\054\040\111\156\143\056\040\055\040\146\157\162\040\141\165\164
+\150\157\162\151\172\145\144\040\165\163\145\040\157\156\154\171
+\061\062\060\060\006\003\125\004\003\023\051\105\156\164\162\165
+\163\164\040\122\157\157\164\040\103\145\162\164\151\146\151\143
+\141\164\151\157\156\040\101\165\164\150\157\162\151\164\171\040
+\055\040\107\062\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\272\204\266\162\333\236\014\153\342\231\351
+\060\001\247\166\352\062\270\225\101\032\311\332\141\116\130\162
+\317\376\366\202\171\277\163\141\006\012\245\047\330\263\137\323
+\105\116\034\162\326\116\062\362\162\212\017\367\203\031\320\152
+\200\200\000\105\036\260\307\347\232\277\022\127\047\034\243\150
+\057\012\207\275\152\153\016\136\145\363\034\167\325\324\205\215
+\160\041\264\263\062\347\213\242\325\206\071\002\261\270\322\107
+\316\344\311\111\304\073\247\336\373\124\175\127\276\360\350\156
+\302\171\262\072\013\125\342\120\230\026\062\023\134\057\170\126
+\301\302\224\263\362\132\344\047\232\237\044\327\306\354\320\233
+\045\202\343\314\302\304\105\305\214\227\172\006\153\052\021\237
+\251\012\156\110\073\157\333\324\021\031\102\367\217\007\277\365
+\123\137\234\076\364\027\054\346\151\254\116\062\114\142\167\352
+\267\350\345\273\064\274\031\213\256\234\121\347\267\176\265\123
+\261\063\042\345\155\317\160\074\032\372\342\233\147\266\203\364
+\215\245\257\142\114\115\340\130\254\144\064\022\003\370\266\215
+\224\143\044\244\161\002\003\001\000\001\243\102\060\100\060\016
+\006\003\125\035\017\001\001\377\004\004\003\002\001\006\060\017
+\006\003\125\035\023\001\001\377\004\005\060\003\001\001\377\060
+\035\006\003\125\035\016\004\026\004\024\152\162\046\172\320\036
+\357\175\347\073\151\121\324\154\215\237\220\022\146\253\060\015
+\006\011\052\206\110\206\367\015\001\001\013\005\000\003\202\001
+\001\000\171\237\035\226\306\266\171\077\042\215\207\323\207\003
+\004\140\152\153\232\056\131\211\163\021\254\103\321\365\023\377
+\215\071\053\300\362\275\117\160\214\251\057\352\027\304\013\124
+\236\324\033\226\230\063\074\250\255\142\242\000\166\253\131\151
+\156\006\035\176\304\271\104\215\230\257\022\324\141\333\012\031
+\106\107\363\353\367\143\301\100\005\100\245\322\267\364\265\232
+\066\277\251\210\166\210\004\125\004\053\234\207\177\032\067\074
+\176\055\245\032\330\324\211\136\312\275\254\075\154\330\155\257
+\325\363\166\017\315\073\210\070\042\235\154\223\232\304\075\277
+\202\033\145\077\246\017\135\252\374\345\262\025\312\265\255\306
+\274\075\320\204\350\352\006\162\260\115\071\062\170\277\076\021
+\234\013\244\235\232\041\363\360\233\013\060\170\333\301\334\207
+\103\376\274\143\232\312\305\302\034\311\307\215\377\073\022\130
+\010\346\266\075\354\172\054\116\373\203\226\316\014\074\151\207
+\124\163\244\163\302\223\377\121\020\254\025\124\001\330\374\005
+\261\211\241\177\164\203\232\111\327\334\116\173\212\110\157\213
+\105\366
+END
+
+# Trust for "Entrust Root Certification Authority - G2"
+# Issuer: CN=Entrust Root Certification Authority - G2,OU="(c) 2009 Entrust, Inc. - for authorized use only",OU=See www.entrust.net/legal-terms,O="Entrust, Inc.",C=US
+# Serial Number: 1246989352 (0x4a538c28)
+# Subject: CN=Entrust Root Certification Authority - G2,OU="(c) 2009 Entrust, Inc. - for authorized use only",OU=See www.entrust.net/legal-terms,O="Entrust, Inc.",C=US
+# Not Valid Before: Tue Jul 07 17:25:54 2009
+# Not Valid After : Sat Dec 07 17:55:54 2030
+# Fingerprint (SHA-256): 43:DF:57:74:B0:3E:7F:EF:5F:E4:0D:93:1A:7B:ED:F1:BB:2E:6B:42:73:8C:4E:6D:38:41:10:3D:3A:A7:F3:39
+# Fingerprint (SHA1): 8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4
+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 "Entrust Root Certification Authority - G2"
+CKA_CERT_SHA1_HASH MULTILINE_OCTAL
+\214\364\047\375\171\014\072\321\146\006\215\350\036\127\357\273
+\223\042\162\324
+END
+CKA_CERT_MD5_HASH MULTILINE_OCTAL
+\113\342\311\221\226\145\014\364\016\132\223\222\240\012\376\262
+END
+CKA_ISSUER MULTILINE_OCTAL
+\060\201\276\061\013\060\011\006\003\125\004\006\023\002\125\123
+\061\026\060\024\006\003\125\004\012\023\015\105\156\164\162\165
+\163\164\054\040\111\156\143\056\061\050\060\046\006\003\125\004
+\013\023\037\123\145\145\040\167\167\167\056\145\156\164\162\165
+\163\164\056\156\145\164\057\154\145\147\141\154\055\164\145\162
+\155\163\061\071\060\067\006\003\125\004\013\023\060\050\143\051
+\040\062\060\060\071\040\105\156\164\162\165\163\164\054\040\111
+\156\143\056\040\055\040\146\157\162\040\141\165\164\150\157\162
+\151\172\145\144\040\165\163\145\040\157\156\154\171\061\062\060
+\060\006\003\125\004\003\023\051\105\156\164\162\165\163\164\040
+\122\157\157\164\040\103\145\162\164\151\146\151\143\141\164\151
+\157\156\040\101\165\164\150\157\162\151\164\171\040\055\040\107
+\062
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\004\112\123\214\050
+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
+
+#
+# Certificate "Entrust Root Certification Authority - EC1"
+#
+# Issuer: CN=Entrust Root Certification Authority - EC1,OU="(c) 2012 Entrust, Inc. - for authorized use only",OU=See www.entrust.net/legal-terms,O="Entrust, Inc.",C=US
+# Serial Number:00:a6:8b:79:29:00:00:00:00:50:d0:91:f9
+# Subject: CN=Entrust Root Certification Authority - EC1,OU="(c) 2012 Entrust, Inc. - for authorized use only",OU=See www.entrust.net/legal-terms,O="Entrust, Inc.",C=US
+# Not Valid Before: Tue Dec 18 15:25:36 2012
+# Not Valid After : Fri Dec 18 15:55:36 2037
+# Fingerprint (SHA-256): 02:ED:0E:B2:8C:14:DA:45:16:5C:56:67:91:70:0D:64:51:D7:FB:56:F0:B2:AB:1D:3B:8E:B0:70:E5:6E:DF:F5
+# Fingerprint (SHA1): 20:D8:06:40:DF:9B:25:F5:12:25:3A:11:EA:F7:59:8A:EB:14:B5:47
+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 "Entrust Root Certification Authority - EC1"
+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
+CKA_SUBJECT MULTILINE_OCTAL
+\060\201\277\061\013\060\011\006\003\125\004\006\023\002\125\123
+\061\026\060\024\006\003\125\004\012\023\015\105\156\164\162\165
+\163\164\054\040\111\156\143\056\061\050\060\046\006\003\125\004
+\013\023\037\123\145\145\040\167\167\167\056\145\156\164\162\165
+\163\164\056\156\145\164\057\154\145\147\141\154\055\164\145\162
+\155\163\061\071\060\067\006\003\125\004\013\023\060\050\143\051
+\040\062\060\061\062\040\105\156\164\162\165\163\164\054\040\111
+\156\143\056\040\055\040\146\157\162\040\141\165\164\150\157\162
+\151\172\145\144\040\165\163\145\040\157\156\154\171\061\063\060
+\061\006\003\125\004\003\023\052\105\156\164\162\165\163\164\040
+\122\157\157\164\040\103\145\162\164\151\146\151\143\141\164\151
+\157\156\040\101\165\164\150\157\162\151\164\171\040\055\040\105
+\103\061
+END
+CKA_ID UTF8 "0"
+CKA_ISSUER MULTILINE_OCTAL
+\060\201\277\061\013\060\011\006\003\125\004\006\023\002\125\123
+\061\026\060\024\006\003\125\004\012\023\015\105\156\164\162\165
+\163\164\054\040\111\156\143\056\061\050\060\046\006\003\125\004
+\013\023\037\123\145\145\040\167\167\167\056\145\156\164\162\165
+\163\164\056\156\145\164\057\154\145\147\141\154\055\164\145\162
+\155\163\061\071\060\067\006\003\125\004\013\023\060\050\143\051
+\040\062\060\061\062\040\105\156\164\162\165\163\164\054\040\111
+\156\143\056\040\055\040\146\157\162\040\141\165\164\150\157\162
+\151\172\145\144\040\165\163\145\040\157\156\154\171\061\063\060
+\061\006\003\125\004\003\023\052\105\156\164\162\165\163\164\040
+\122\157\157\164\040\103\145\162\164\151\146\151\143\141\164\151
+\157\156\040\101\165\164\150\157\162\151\164\171\040\055\040\105
+\103\061
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\015\000\246\213\171\051\000\000\000\000\120\320\221\371
+END
+CKA_VALUE MULTILINE_OCTAL
+\060\202\002\371\060\202\002\200\240\003\002\001\002\002\015\000
+\246\213\171\051\000\000\000\000\120\320\221\371\060\012\006\010
+\052\206\110\316\075\004\003\003\060\201\277\061\013\060\011\006
+\003\125\004\006\023\002\125\123\061\026\060\024\006\003\125\004
+\012\023\015\105\156\164\162\165\163\164\054\040\111\156\143\056
+\061\050\060\046\006\003\125\004\013\023\037\123\145\145\040\167
+\167\167\056\145\156\164\162\165\163\164\056\156\145\164\057\154
+\145\147\141\154\055\164\145\162\155\163\061\071\060\067\006\003
+\125\004\013\023\060\050\143\051\040\062\060\061\062\040\105\156
+\164\162\165\163\164\054\040\111\156\143\056\040\055\040\146\157
+\162\040\141\165\164\150\157\162\151\172\145\144\040\165\163\145
+\040\157\156\154\171\061\063\060\061\006\003\125\004\003\023\052
+\105\156\164\162\165\163\164\040\122\157\157\164\040\103\145\162
+\164\151\146\151\143\141\164\151\157\156\040\101\165\164\150\157
+\162\151\164\171\040\055\040\105\103\061\060\036\027\015\061\062
+\061\062\061\070\061\065\062\065\063\066\132\027\015\063\067\061
+\062\061\070\061\065\065\065\063\066\132\060\201\277\061\013\060
+\011\006\003\125\004\006\023\002\125\123\061\026\060\024\006\003
+\125\004\012\023\015\105\156\164\162\165\163\164\054\040\111\156
+\143\056\061\050\060\046\006\003\125\004\013\023\037\123\145\145
+\040\167\167\167\056\145\156\164\162\165\163\164\056\156\145\164
+\057\154\145\147\141\154\055\164\145\162\155\163\061\071\060\067
+\006\003\125\004\013\023\060\050\143\051\040\062\060\061\062\040
+\105\156\164\162\165\163\164\054\040\111\156\143\056\040\055\040
+\146\157\162\040\141\165\164\150\157\162\151\172\145\144\040\165
+\163\145\040\157\156\154\171\061\063\060\061\006\003\125\004\003
+\023\052\105\156\164\162\165\163\164\040\122\157\157\164\040\103
+\145\162\164\151\146\151\143\141\164\151\157\156\040\101\165\164
+\150\157\162\151\164\171\040\055\040\105\103\061\060\166\060\020
+\006\007\052\206\110\316\075\002\001\006\005\053\201\004\000\042
+\003\142\000\004\204\023\311\320\272\155\101\173\342\154\320\353
+\125\137\146\002\032\044\364\133\211\151\107\343\270\302\175\361
+\362\002\305\237\240\366\133\325\213\006\031\206\117\123\020\155
+\007\044\047\241\240\370\325\107\031\141\114\175\312\223\047\352
+\164\014\357\157\226\011\376\143\354\160\135\066\255\147\167\256
+\311\235\174\125\104\072\242\143\121\037\365\343\142\324\251\107
+\007\076\314\040\243\102\060\100\060\016\006\003\125\035\017\001
+\001\377\004\004\003\002\001\006\060\017\006\003\125\035\023\001
+\001\377\004\005\060\003\001\001\377\060\035\006\003\125\035\016
+\004\026\004\024\267\143\347\032\335\215\351\010\246\125\203\244
+\340\152\120\101\145\021\102\111\060\012\006\010\052\206\110\316
+\075\004\003\003\003\147\000\060\144\002\060\141\171\330\345\102
+\107\337\034\256\123\231\027\266\157\034\175\341\277\021\224\321
+\003\210\165\344\215\211\244\212\167\106\336\155\141\357\002\365
+\373\265\337\314\376\116\377\376\251\346\247\002\060\133\231\327
+\205\067\006\265\173\010\375\353\047\213\112\224\371\341\372\247
+\216\046\010\350\174\222\150\155\163\330\157\046\254\041\002\270
+\231\267\046\101\133\045\140\256\320\110\032\356\006
+END
+
+# Trust for "Entrust Root Certification Authority - EC1"
+# Issuer: CN=Entrust Root Certification Authority - EC1,OU="(c) 2012 Entrust, Inc. - for authorized use only",OU=See www.entrust.net/legal-terms,O="Entrust, Inc.",C=US
+# Serial Number:00:a6:8b:79:29:00:00:00:00:50:d0:91:f9
+# Subject: CN=Entrust Root Certification Authority - EC1,OU="(c) 2012 Entrust, Inc. - for authorized use only",OU=See www.entrust.net/legal-terms,O="Entrust, Inc.",C=US
+# Not Valid Before: Tue Dec 18 15:25:36 2012
+# Not Valid After : Fri Dec 18 15:55:36 2037
+# Fingerprint (SHA-256): 02:ED:0E:B2:8C:14:DA:45:16:5C:56:67:91:70:0D:64:51:D7:FB:56:F0:B2:AB:1D:3B:8E:B0:70:E5:6E:DF:F5
+# Fingerprint (SHA1): 20:D8:06:40:DF:9B:25:F5:12:25:3A:11:EA:F7:59:8A:EB:14:B5:47
+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 "Entrust Root Certification Authority - EC1"
+CKA_CERT_SHA1_HASH MULTILINE_OCTAL
+\040\330\006\100\337\233\045\365\022\045\072\021\352\367\131\212
+\353\024\265\107
+END
+CKA_CERT_MD5_HASH MULTILINE_OCTAL
+\266\176\035\360\130\305\111\154\044\073\075\355\230\030\355\274
+END
+CKA_ISSUER MULTILINE_OCTAL
+\060\201\277\061\013\060\011\006\003\125\004\006\023\002\125\123
+\061\026\060\024\006\003\125\004\012\023\015\105\156\164\162\165
+\163\164\054\040\111\156\143\056\061\050\060\046\006\003\125\004
+\013\023\037\123\145\145\040\167\167\167\056\145\156\164\162\165
+\163\164\056\156\145\164\057\154\145\147\141\154\055\164\145\162
+\155\163\061\071\060\067\006\003\125\004\013\023\060\050\143\051
+\040\062\060\061\062\040\105\156\164\162\165\163\164\054\040\111
+\156\143\056\040\055\040\146\157\162\040\141\165\164\150\157\162
+\151\172\145\144\040\165\163\145\040\157\156\154\171\061\063\060
+\061\006\003\125\004\003\023\052\105\156\164\162\165\163\164\040
+\122\157\157\164\040\103\145\162\164\151\146\151\143\141\164\151
+\157\156\040\101\165\164\150\157\162\151\164\171\040\055\040\105
+\103\061
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\015\000\246\213\171\051\000\000\000\000\120\320\221\371
+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
+
+#
+# Certificate "CFCA EV ROOT"
+#
+# Issuer: CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN
+# Serial Number: 407555286 (0x184accd6)
+# Subject: CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN
+# Not Valid Before: Wed Aug 08 03:07:01 2012
+# Not Valid After : Mon Dec 31 03:07:01 2029
+# Fingerprint (SHA-256): 5C:C3:D7:8E:4E:1D:5E:45:54:7A:04:E6:87:3E:64:F9:0C:F9:53:6D:1C:CC:2E:F8:00:F3:55:C4:C5:FD:70:FD
+# Fingerprint (SHA1): E2:B8:29:4B:55:84:AB:6B:58:C2:90:46:6C:AC:3F:B8:39:8F:84:83
+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 "CFCA EV ROOT"
+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
+CKA_SUBJECT MULTILINE_OCTAL
+\060\126\061\013\060\011\006\003\125\004\006\023\002\103\116\061
+\060\060\056\006\003\125\004\012\014\047\103\150\151\156\141\040
+\106\151\156\141\156\143\151\141\154\040\103\145\162\164\151\146
+\151\143\141\164\151\157\156\040\101\165\164\150\157\162\151\164
+\171\061\025\060\023\006\003\125\004\003\014\014\103\106\103\101
+\040\105\126\040\122\117\117\124
+END
+CKA_ID UTF8 "0"
+CKA_ISSUER MULTILINE_OCTAL
+\060\126\061\013\060\011\006\003\125\004\006\023\002\103\116\061
+\060\060\056\006\003\125\004\012\014\047\103\150\151\156\141\040
+\106\151\156\141\156\143\151\141\154\040\103\145\162\164\151\146
+\151\143\141\164\151\157\156\040\101\165\164\150\157\162\151\164
+\171\061\025\060\023\006\003\125\004\003\014\014\103\106\103\101
+\040\105\126\040\122\117\117\124
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\004\030\112\314\326
+END
+CKA_VALUE MULTILINE_OCTAL
+\060\202\005\215\060\202\003\165\240\003\002\001\002\002\004\030
+\112\314\326\060\015\006\011\052\206\110\206\367\015\001\001\013
+\005\000\060\126\061\013\060\011\006\003\125\004\006\023\002\103
+\116\061\060\060\056\006\003\125\004\012\014\047\103\150\151\156
+\141\040\106\151\156\141\156\143\151\141\154\040\103\145\162\164
+\151\146\151\143\141\164\151\157\156\040\101\165\164\150\157\162
+\151\164\171\061\025\060\023\006\003\125\004\003\014\014\103\106
+\103\101\040\105\126\040\122\117\117\124\060\036\027\015\061\062
+\060\070\060\070\060\063\060\067\060\061\132\027\015\062\071\061
+\062\063\061\060\063\060\067\060\061\132\060\126\061\013\060\011
+\006\003\125\004\006\023\002\103\116\061\060\060\056\006\003\125
+\004\012\014\047\103\150\151\156\141\040\106\151\156\141\156\143
+\151\141\154\040\103\145\162\164\151\146\151\143\141\164\151\157
+\156\040\101\165\164\150\157\162\151\164\171\061\025\060\023\006
+\003\125\004\003\014\014\103\106\103\101\040\105\126\040\122\117
+\117\124\060\202\002\042\060\015\006\011\052\206\110\206\367\015
+\001\001\001\005\000\003\202\002\017\000\060\202\002\012\002\202
+\002\001\000\327\135\153\315\020\077\037\005\131\325\005\115\067
+\261\016\354\230\053\216\025\035\372\223\113\027\202\041\161\020
+\122\327\121\144\160\026\302\125\151\115\216\025\155\237\277\014
+\033\302\340\243\147\326\014\254\317\042\256\257\167\124\052\113
+\114\212\123\122\172\303\356\056\336\263\161\045\301\351\135\075
+\356\241\057\243\367\052\074\311\043\035\152\253\035\241\247\361
+\363\354\240\325\104\317\025\317\162\057\035\143\227\350\231\371
+\375\223\244\124\200\114\122\324\122\253\056\111\337\220\315\270
+\137\276\077\336\241\312\115\040\324\045\350\204\051\123\267\261
+\210\037\377\372\332\220\237\012\251\055\101\077\261\361\030\051
+\356\026\131\054\064\111\032\250\006\327\250\210\322\003\162\172
+\062\342\352\150\115\156\054\226\145\173\312\131\372\362\342\335
+\356\060\054\373\314\106\254\304\143\353\157\177\066\053\064\163
+\022\224\177\337\314\046\236\361\162\135\120\145\131\217\151\263
+\207\136\062\157\303\030\212\265\225\217\260\172\067\336\132\105
+\073\307\066\341\357\147\321\071\323\227\133\163\142\031\110\055
+\207\034\006\373\164\230\040\111\163\360\005\322\033\261\240\243
+\267\033\160\323\210\151\271\132\326\070\364\142\334\045\213\170
+\277\370\350\176\270\134\311\225\117\137\247\055\271\040\153\317
+\153\335\365\015\364\202\267\364\262\146\056\020\050\366\227\132
+\173\226\026\217\001\031\055\154\156\177\071\130\006\144\203\001
+\203\203\303\115\222\335\062\306\207\244\067\351\026\316\252\055
+\150\257\012\201\145\072\160\301\233\255\115\155\124\312\052\055
+\113\205\033\263\200\346\160\105\015\153\136\065\360\177\073\270
+\234\344\004\160\211\022\045\223\332\012\231\042\140\152\143\140
+\116\166\006\230\116\275\203\255\035\130\212\045\205\322\307\145
+\036\055\216\306\337\266\306\341\177\212\004\041\025\051\164\360
+\076\234\220\235\014\056\361\212\076\132\252\014\011\036\307\325
+\074\243\355\227\303\036\064\372\070\371\010\016\343\300\135\053
+\203\321\126\152\311\266\250\124\123\056\170\062\147\075\202\177
+\164\320\373\341\266\005\140\271\160\333\216\013\371\023\130\157
+\161\140\020\122\020\271\301\101\011\357\162\037\147\061\170\377
+\226\005\215\002\003\001\000\001\243\143\060\141\060\037\006\003
+\125\035\043\004\030\060\026\200\024\343\376\055\375\050\320\013
+\265\272\266\242\304\277\006\252\005\214\223\373\057\060\017\006
+\003\125\035\023\001\001\377\004\005\060\003\001\001\377\060\016
+\006\003\125\035\017\001\001\377\004\004\003\002\001\006\060\035
+\006\003\125\035\016\004\026\004\024\343\376\055\375\050\320\013
+\265\272\266\242\304\277\006\252\005\214\223\373\057\060\015\006
+\011\052\206\110\206\367\015\001\001\013\005\000\003\202\002\001
+\000\045\306\272\153\353\207\313\336\202\071\226\075\360\104\247
+\153\204\163\003\336\235\053\117\272\040\177\274\170\262\317\227
+\260\033\234\363\327\171\056\365\110\266\322\373\027\210\346\323
+\172\077\355\123\023\320\342\057\152\171\313\000\043\050\346\036
+\067\127\065\211\204\302\166\117\064\066\255\147\303\316\101\006
+\210\305\367\356\330\032\270\326\013\177\120\377\223\252\027\113
+\214\354\355\122\140\262\244\006\352\116\353\364\153\031\375\353
+\365\032\340\045\052\232\334\307\101\066\367\310\164\005\204\071
+\225\071\326\013\073\244\047\372\010\330\134\036\370\004\140\122
+\021\050\050\003\377\357\123\146\000\245\112\064\026\146\174\375
+\011\244\256\236\147\032\157\101\013\153\006\023\233\217\206\161
+\005\264\057\215\211\146\063\051\166\124\232\021\370\047\372\262
+\077\221\340\316\015\033\363\060\032\255\277\042\135\033\323\277
+\045\005\115\341\222\032\177\231\237\074\104\223\312\324\100\111
+\154\200\207\327\004\072\303\062\122\065\016\126\370\245\335\175
+\304\213\015\021\037\123\313\036\262\027\266\150\167\132\340\324
+\313\310\007\256\365\072\056\216\067\267\320\001\113\103\051\167
+\214\071\227\217\202\132\370\121\345\211\240\030\347\150\177\135
+\012\056\373\243\107\016\075\246\043\172\306\001\307\217\310\136
+\277\155\200\126\276\212\044\272\063\352\237\341\062\021\236\361
+\322\117\200\366\033\100\257\070\236\021\120\171\163\022\022\315
+\346\154\235\054\210\162\074\060\201\006\221\042\352\131\255\332
+\031\056\042\302\215\271\214\207\340\146\274\163\043\137\041\144
+\143\200\110\365\240\074\030\075\224\310\110\101\035\100\272\136
+\376\376\126\071\241\310\317\136\236\031\144\106\020\332\027\221
+\267\005\200\254\213\231\222\175\347\242\330\007\013\066\047\347
+\110\171\140\212\303\327\023\134\370\162\100\337\112\313\317\231
+\000\012\000\013\021\225\332\126\105\003\210\012\237\147\320\325
+\171\261\250\215\100\155\015\302\172\100\372\363\137\144\107\222
+\313\123\271\273\131\316\117\375\320\025\123\001\330\337\353\331
+\346\166\357\320\043\273\073\251\171\263\325\002\051\315\211\243
+\226\017\112\065\347\116\102\300\165\315\007\317\346\054\353\173
+\056
+END
+
+# Trust for "CFCA EV ROOT"
+# Issuer: CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN
+# Serial Number: 407555286 (0x184accd6)
+# Subject: CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN
+# Not Valid Before: Wed Aug 08 03:07:01 2012
+# Not Valid After : Mon Dec 31 03:07:01 2029
+# Fingerprint (SHA-256): 5C:C3:D7:8E:4E:1D:5E:45:54:7A:04:E6:87:3E:64:F9:0C:F9:53:6D:1C:CC:2E:F8:00:F3:55:C4:C5:FD:70:FD
+# Fingerprint (SHA1): E2:B8:29:4B:55:84:AB:6B:58:C2:90:46:6C:AC:3F:B8:39:8F:84:83
+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 "CFCA EV ROOT"
+CKA_CERT_SHA1_HASH MULTILINE_OCTAL
+\342\270\051\113\125\204\253\153\130\302\220\106\154\254\077\270
+\071\217\204\203
+END
+CKA_CERT_MD5_HASH MULTILINE_OCTAL
+\164\341\266\355\046\172\172\104\060\063\224\253\173\047\201\060
+END
+CKA_ISSUER MULTILINE_OCTAL
+\060\126\061\013\060\011\006\003\125\004\006\023\002\103\116\061
+\060\060\056\006\003\125\004\012\014\047\103\150\151\156\141\040
+\106\151\156\141\156\143\151\141\154\040\103\145\162\164\151\146
+\151\143\141\164\151\157\156\040\101\165\164\150\157\162\151\164
+\171\061\025\060\023\006\003\125\004\003\014\014\103\106\103\101
+\040\105\126\040\122\117\117\124
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\004\030\112\314\326
+END
+CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
+CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
+CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
+CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
+
+#
+# Certificate "Explicitly Distrusted MCSHOLDING CA"
+#
+# Issuer: CN=CNNIC ROOT,O=CNNIC,C=CN
+# Serial Number: 1228079246 (0x4933008e)
+# Subject: CN=MCSHOLDING TEST,O=MCSHOLDING,C=EG
+# Not Valid Before: Thu Mar 19 06:20:09 2015
+# Not Valid After : Fri Apr 03 06:20:09 2015
+# Fingerprint (SHA-256): 27:40:D9:56:B1:12:7B:79:1A:A1:B3:CC:64:4A:4D:BE:DB:A7:61:86:A2:36:38:B9:51:02:35:1A:83:4E:A8:61
+# Fingerprint (SHA1): E1:F3:59:1E:76:98:65:C4:E4:47:AC:C3:7E:AF:C9:E2:BF:E4:C5:76
+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 "Explicitly Distrusted MCSHOLDING CA"
+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
+CKA_SUBJECT MULTILINE_OCTAL
+\060\074\061\013\060\011\006\003\125\004\006\023\002\105\107\061
+\023\060\021\006\003\125\004\012\014\012\115\103\123\110\117\114
+\104\111\116\107\061\030\060\026\006\003\125\004\003\014\017\115
+\103\123\110\117\114\104\111\116\107\040\124\105\123\124
+END
+CKA_ID UTF8 "0"
+CKA_ISSUER MULTILINE_OCTAL
+\060\062\061\013\060\011\006\003\125\004\006\023\002\103\116\061
+\016\060\014\006\003\125\004\012\023\005\103\116\116\111\103\061
+\023\060\021\006\003\125\004\003\023\012\103\116\116\111\103\040
+\122\117\117\124
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\004\111\063\000\216
+END
+CKA_VALUE MULTILINE_OCTAL
+\060\202\004\222\060\202\003\172\240\003\002\001\002\002\004\111
+\063\000\216\060\015\006\011\052\206\110\206\367\015\001\001\013
+\005\000\060\062\061\013\060\011\006\003\125\004\006\023\002\103
+\116\061\016\060\014\006\003\125\004\012\023\005\103\116\116\111
+\103\061\023\060\021\006\003\125\004\003\023\012\103\116\116\111
+\103\040\122\117\117\124\060\036\027\015\061\065\060\063\061\071
+\060\066\062\060\060\071\132\027\015\061\065\060\064\060\063\060
+\066\062\060\060\071\132\060\074\061\013\060\011\006\003\125\004
+\006\023\002\105\107\061\023\060\021\006\003\125\004\012\014\012
+\115\103\123\110\117\114\104\111\116\107\061\030\060\026\006\003
+\125\004\003\014\017\115\103\123\110\117\114\104\111\116\107\040
+\124\105\123\124\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\245\371\165\014\006\256\356\014\021\315\226
+\063\115\153\316\300\112\014\075\135\353\322\113\011\177\347\107
+\054\254\161\000\371\010\257\064\361\243\152\307\374\346\253\316
+\320\276\312\315\052\230\230\271\320\216\063\111\007\141\040\321
+\132\064\316\203\024\006\171\216\032\277\333\344\240\070\072\356
+\224\271\243\240\130\072\211\024\254\140\076\003\324\307\315\073
+\034\260\232\210\032\111\020\251\260\262\375\345\350\341\004\342
+\352\202\155\376\014\121\105\221\255\165\042\256\377\117\220\013
+\300\123\145\167\076\036\302\126\265\066\306\326\205\314\016\203
+\032\063\037\166\231\133\053\227\053\213\327\321\024\025\114\235
+\131\327\200\057\244\242\205\325\210\066\002\140\125\312\130\337
+\223\374\112\142\007\226\323\304\372\277\215\001\047\227\057\246
+\134\164\361\072\102\156\135\171\024\060\061\032\074\331\262\127
+\115\340\270\077\017\151\061\242\235\145\231\331\326\061\207\265
+\230\046\337\360\313\273\025\300\044\023\142\122\032\153\313\105
+\007\227\343\304\224\136\311\015\107\054\351\317\351\364\217\376
+\065\341\062\347\061\002\003\001\000\001\243\202\001\244\060\202
+\001\240\060\166\006\010\053\006\001\005\005\007\001\001\004\152
+\060\150\060\051\006\010\053\006\001\005\005\007\060\001\206\035
+\150\164\164\160\072\057\057\157\143\163\160\143\156\156\151\143
+\162\157\157\164\056\143\156\156\151\143\056\143\156\060\073\006
+\010\053\006\001\005\005\007\060\002\206\057\150\164\164\160\072
+\057\057\167\167\167\056\143\156\156\151\143\056\143\156\057\144
+\157\167\156\154\157\141\144\057\143\145\162\164\057\103\116\116
+\111\103\122\117\117\124\056\143\145\162\060\037\006\003\125\035
+\043\004\030\060\026\200\024\145\362\061\255\052\367\367\335\122
+\226\012\307\002\301\016\357\246\325\073\021\060\017\006\003\125
+\035\023\001\001\377\004\005\060\003\001\001\377\060\077\006\003
+\125\035\040\004\070\060\066\060\064\006\012\053\006\001\004\001
+\201\351\014\001\006\060\046\060\044\006\010\053\006\001\005\005
+\007\002\001\026\030\150\164\164\160\072\057\057\167\167\167\056
+\143\156\156\151\143\056\143\156\057\143\160\163\057\060\201\206
+\006\003\125\035\037\004\177\060\175\060\102\240\100\240\076\244
+\074\060\072\061\013\060\011\006\003\125\004\006\023\002\103\116
+\061\016\060\014\006\003\125\004\012\014\005\103\116\116\111\103
+\061\014\060\012\006\003\125\004\013\014\003\143\162\154\061\015
+\060\013\006\003\125\004\003\014\004\143\162\154\061\060\067\240
+\065\240\063\206\061\150\164\164\160\072\057\057\143\162\154\056
+\143\156\156\151\143\056\143\156\057\144\157\167\156\154\157\141
+\144\057\162\157\157\164\163\150\141\062\143\162\154\057\103\122
+\114\061\056\143\162\154\060\013\006\003\125\035\017\004\004\003
+\002\001\006\060\035\006\003\125\035\016\004\026\004\024\104\244
+\211\253\024\137\075\157\040\074\252\174\372\031\256\364\110\140
+\005\265\060\015\006\011\052\206\110\206\367\015\001\001\013\005
+\000\003\202\001\001\000\134\264\365\123\233\117\271\340\204\211
+\061\276\236\056\352\236\041\113\245\217\155\241\246\363\057\110
+\353\351\333\255\036\061\200\320\171\073\020\357\232\044\367\223
+\033\065\363\032\302\307\302\054\012\177\157\133\361\137\163\221
+\004\373\015\171\015\351\032\006\326\203\375\116\140\235\154\222
+\103\114\352\144\230\104\253\327\373\107\320\257\037\144\114\342
+\335\167\150\026\302\054\241\240\201\227\000\102\037\176\040\170
+\350\306\120\035\013\177\025\223\131\130\100\024\204\360\247\220
+\153\066\005\147\352\177\042\155\273\321\245\046\115\263\060\244
+\130\324\133\265\032\214\120\214\270\015\341\240\007\263\017\130
+\316\327\005\265\175\065\171\157\242\333\014\000\052\150\044\214
+\176\234\301\166\111\272\174\146\021\336\362\107\316\376\320\316
+\125\276\010\332\362\171\046\052\025\071\316\153\030\246\337\330
+\207\050\231\224\016\055\150\241\232\316\122\066\234\053\354\264
+\150\263\154\025\254\313\160\102\362\304\101\245\310\374\041\170
+\123\167\062\040\251\041\114\162\342\323\262\311\166\033\030\130
+\102\013\102\222\263\344
+END
+
+# Distrust "Explicitly Distrusted MCSHOLDING CA"
+# Issuer: CN=CNNIC ROOT,O=CNNIC,C=CN
+# Serial Number: 1228079246 (0x4933008e)
+# Subject: CN=MCSHOLDING TEST,O=MCSHOLDING,C=EG
+# Not Valid Before: Thu Mar 19 06:20:09 2015
+# Not Valid After : Fri Apr 03 06:20:09 2015
+# Fingerprint (SHA-256): 27:40:D9:56:B1:12:7B:79:1A:A1:B3:CC:64:4A:4D:BE:DB:A7:61:86:A2:36:38:B9:51:02:35:1A:83:4E:A8:61
+# Fingerprint (SHA1): E1:F3:59:1E:76:98:65:C4:E4:47:AC:C3:7E:AF:C9:E2:BF:E4:C5:76
+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 "Explicitly Distrusted MCSHOLDING CA"
+CKA_CERT_SHA1_HASH MULTILINE_OCTAL
+\341\363\131\036\166\230\145\304\344\107\254\303\176\257\311\342
+\277\344\305\166
+END
+CKA_CERT_MD5_HASH MULTILINE_OCTAL
+\366\212\253\024\076\326\060\045\267\111\015\167\205\160\231\313
+END
+CKA_ISSUER MULTILINE_OCTAL
+\060\062\061\013\060\011\006\003\125\004\006\023\002\103\116\061
+\016\060\014\006\003\125\004\012\023\005\103\116\116\111\103\061
+\023\060\021\006\003\125\004\003\023\012\103\116\116\111\103\040
+\122\117\117\124
+END
+CKA_SERIAL_NUMBER MULTILINE_OCTAL
+\002\004\111\063\000\216
+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
--- a/security/nss/lib/ckfw/builtins/config.mk
+++ b/security/nss/lib/ckfw/builtins/config.mk
@@ -25,13 +25,10 @@ endif
 
 # Needed for compilation of $(OBJDIR)/certdata.c
 INCLUDES += -I.
 
 #
 # To create a loadable module on Darwin, we must use -bundle.
 #
 ifeq ($(OS_TARGET),Darwin)
-ifndef USE_64
 DSO_LDOPTS = -bundle
 endif
-endif
-
--- a/security/nss/lib/ckfw/builtins/nssckbi.h
+++ b/security/nss/lib/ckfw/builtins/nssckbi.h
@@ -40,18 +40,18 @@
  *     ...
  *   - NSS 3.29 branch: 250-255
  *
  * NSS_BUILTINS_LIBRARY_VERSION_MINOR is a CK_BYTE.  It's not clear
  * whether we may use its full range (0-255) or only 0-99 because
  * of the comment in the CK_VERSION type definition.
  */
 #define NSS_BUILTINS_LIBRARY_VERSION_MAJOR 2
-#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 2
-#define NSS_BUILTINS_LIBRARY_VERSION "2.2"
+#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 4
+#define NSS_BUILTINS_LIBRARY_VERSION "2.4"
 
 /* These version numbers detail the semantic changes to the ckfw engine. */
 #define NSS_BUILTINS_HARDWARE_VERSION_MAJOR 1
 #define NSS_BUILTINS_HARDWARE_VERSION_MINOR 0
 
 /* These version numbers detail the semantic changes to ckbi itself 
  * (new PKCS #11 objects), etc. */
 #define NSS_BUILTINS_FIRMWARE_VERSION_MAJOR 1
--- a/security/nss/lib/ckfw/capi/config.mk
+++ b/security/nss/lib/ckfw/capi/config.mk
@@ -22,13 +22,10 @@ endif
 ifdef BUILD_IDG
     DEFINES += -DNSSDEBUG
 endif
 
 #
 # To create a loadable module on Darwin, we must use -bundle.
 #
 ifeq ($(OS_TARGET),Darwin)
-ifndef USE_64
 DSO_LDOPTS = -bundle
 endif
-endif
-
--- a/security/nss/lib/cryptohi/keyhi.h
+++ b/security/nss/lib/cryptohi/keyhi.h
@@ -32,16 +32,21 @@ extern SECStatus SECKEY_CopySubjectPubli
 
 /*
 ** Update the PQG parameters for a cert's public key.
 ** Only done for DSA certs
 */
 extern SECStatus
 SECKEY_UpdateCertPQG(CERTCertificate * subjectCert);
 
+/*
+** Return the number of bits in the provided big integer.  This assumes that the
+** SECItem contains a big-endian number and counts from the first non-zero bit.
+*/
+extern unsigned SECKEY_BigIntegerBitLength(const SECItem *number);
 
 /*
 ** Return the strength of the public key in bytes
 */
 extern unsigned SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk);
 
 /*
 ** Return the strength of the public key in bits
--- a/security/nss/lib/cryptohi/seckey.c
+++ b/security/nss/lib/cryptohi/seckey.c
@@ -173,18 +173,18 @@ SECKEY_CreateRSAPrivateKey(int keySizeIn
 */
 SECKEYPrivateKey *
 SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *cx)
 {
     SECKEYPrivateKey *privk;
     PK11SlotInfo *slot;
 
     if (!param || !param->base.data || !param->prime.data ||
-        param->prime.len < 512/8 || param->base.len == 0 || 
-        param->base.len > param->prime.len + 1 || 
+        SECKEY_BigIntegerBitLength(&param->prime) < DH_MIN_P_BITS ||
+        param->base.len == 0 || param->base.len > param->prime.len + 1 ||
 	(param->base.len == 1 && param->base.data[0] == 0)) {
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	return NULL;
     }
 
     slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,cx);
     if (!slot) {
 	return NULL;
@@ -936,71 +936,86 @@ SECKEY_ECParamsToBasePointOrderLen(const
 	return 570;
 
     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
+SECKEY_BigIntegerBitLength(const SECItem *number)
+{
+    const unsigned char *p;
+    unsigned octets;
+    unsigned bits;
+
+    if (!number || !number->data) {
+        PORT_SetError(SEC_ERROR_INVALID_KEY);
+        return 0;
+    }
+
+    p = number->data;
+    octets = number->len;
+    while (octets > 0 && !*p) {
+        ++p;
+        --octets;
+    }
+    if (octets == 0) {
+        return 0;
+    }
+    /* bits = 7..1 because we know at least one bit is set already */
+    /* Note: This could do a binary search, but this is faster for keys if we
+     * assume that good keys will have the MSB set. */
+    for (bits = 7; bits > 0; --bits) {
+        if (*p & (1 << bits)) {
+            break;
+        }
+    }
+    return octets * 8 + bits - 7;
+}
+
 /* returns key strength in bytes (not bits) */
 unsigned
 SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
 {
-    unsigned char b0;
-    unsigned size;
-
-    /* interpret modulus length as key strength */
-    if (!pubk)
-    	goto loser;
-    switch (pubk->keyType) {
-    case rsaKey:
-	if (!pubk->u.rsa.modulus.data) break;
-    	b0 = pubk->u.rsa.modulus.data[0];
-    	return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
-    case dsaKey:
-	if (!pubk->u.dsa.publicValue.data) break;
-    	b0 = pubk->u.dsa.publicValue.data[0];
-    	return b0 ? pubk->u.dsa.publicValue.len :
-	    pubk->u.dsa.publicValue.len - 1;
-    case dhKey:
-	if (!pubk->u.dh.publicValue.data) break;
-    	b0 = pubk->u.dh.publicValue.data[0];
-    	return b0 ? pubk->u.dh.publicValue.len :
-	    pubk->u.dh.publicValue.len - 1;
-    case ecKey:
-	/* Get the key size in bits and adjust */
-	size =	SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
-	return (size + 7)/8;
-    default:
-	break;
-    }
-loser:
-    PORT_SetError(SEC_ERROR_INVALID_KEY);
-    return 0;
+    return (SECKEY_PublicKeyStrengthInBits(pubk) + 7) / 8;
 }
 
 /* returns key strength in bits */
 unsigned
 SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk)
 {
-    unsigned size;
+    unsigned bitSize = 0;
+
+    if (!pubk) {
+        PORT_SetError(SEC_ERROR_INVALID_KEY);
+        return 0;
+    }
+
+    /* interpret modulus length as key strength */
     switch (pubk->keyType) {
     case rsaKey:
+        bitSize = SECKEY_BigIntegerBitLength(&pubk->u.rsa.modulus);
+        break;
     case dsaKey:
+        bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dsa.publicValue);
+        break;
     case dhKey:
-	return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */
+        bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dh.publicValue);
+        break;
     case ecKey:
-	size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
-	return size;
+        bitSize = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
+        break;
     default:
-	break;
+        PORT_SetError(SEC_ERROR_INVALID_KEY);
+        break;
     }
-    PORT_SetError(SEC_ERROR_INVALID_KEY);
-    return 0;
+    return bitSize;
 }
 
 /* returns signature length in bytes (not bits) */
 unsigned
 SECKEY_SignatureLen(const SECKEYPublicKey *pubk)
 {
     unsigned char b0;
     unsigned size;
--- a/security/nss/lib/freebl/blapit.h
+++ b/security/nss/lib/freebl/blapit.h
@@ -133,20 +133,23 @@ typedef int __BLAPI_DEPRECATED __attribu
 #define SEED_KEY_LENGTH 16              /* bytes */
 
 #define NSS_FREEBL_DEFAULT_CHUNKSIZE 2048
 
 /*
  * These values come from the initial key size limits from the PKCS #11
  * module. They may be arbitrarily adjusted to any value freebl supports.
  */
-#define RSA_MIN_MODULUS_BITS   128
+#define RSA_MIN_MODULUS_BITS   512
 #define RSA_MAX_MODULUS_BITS 16384
 #define RSA_MAX_EXPONENT_BITS   64
-#define DH_MIN_P_BITS	       128
+/* 1023 to avoid cases where p = 2q+1 for a 512-bit q turns out to be
+ * only 1023 bits and similar.  We don't have good data on whether this
+ * happens because NSS used to count bit lengths incorrectly. */
+#define DH_MIN_P_BITS	      1023
 #define DH_MAX_P_BITS        16384
 
 /*
  * The FIPS 186-1 algorithm for generating primes P and Q allows only 9
  * distinct values for the length of P, and only one value for the
  * length of Q.
  * The algorithm uses a variable j to indicate which of the 9 lengths
  * of P is to be used.
@@ -176,17 +179,17 @@ typedef int __BLAPI_DEPRECATED __attribu
  *      3072           256
  *
  * The FIPS-186-3 complaiant PQG generator (PQG V2) takes arbitrary p and q
  * lengths as input and returns an error if they aren't in this list.
  */
 
 #define DSA1_Q_BITS      160
 #define DSA_MAX_P_BITS	3072
-#define DSA_MIN_P_BITS	 512
+#define DSA_MIN_P_BITS  1023
 #define DSA_MAX_Q_BITS   256
 #define DSA_MIN_Q_BITS   160
 
 #if DSA_MAX_Q_BITS != DSA_MAX_SUBPRIME_LEN*8
 #error "Inconsistent declaration of DSA SUBPRIME/Q parameters in blapit.h"
 #endif
 
 
--- a/security/nss/lib/freebl/ecl/ecp_jac.c
+++ b/security/nss/lib/freebl/ecl/ecp_jac.c
@@ -139,16 +139,30 @@ ec_GFp_pt_add_jac_aff(const mp_int *px, 
 	MP_CHECKOK(group->meth->field_mul(&A, pz, &B, group->meth));
 	MP_CHECKOK(group->meth->field_mul(&A, qx, &A, group->meth));
 	MP_CHECKOK(group->meth->field_mul(&B, qy, &B, group->meth));
 
 	/* C = A - px, D = B - py */
 	MP_CHECKOK(group->meth->field_sub(&A, px, &C, group->meth));
 	MP_CHECKOK(group->meth->field_sub(&B, py, &D, group->meth));
 
+	if (mp_cmp_z(&C) == 0) {
+		/* P == Q or P == -Q */
+		if (mp_cmp_z(&D) == 0) {
+			/* P == Q */
+			/* It is cheaper to double (qx, qy, 1) than (px, py, pz). */
+			MP_DIGIT(&D, 0) = 1; /* Set D to 1. */
+			MP_CHECKOK(ec_GFp_pt_dbl_jac(qx, qy, &D, rx, ry, rz, group));
+		} else {
+			/* P == -Q */
+			MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
+		}
+		goto CLEANUP;
+	}
+
 	/* C2 = C^2, C3 = C^3 */
 	MP_CHECKOK(group->meth->field_sqr(&C, &C2, group->meth));
 	MP_CHECKOK(group->meth->field_mul(&C, &C2, &C3, group->meth));
 
 	/* rz = pz * C */
 	MP_CHECKOK(group->meth->field_mul(pz, &C, rz, group->meth));
 
 	/* C = px * C^2 */
@@ -200,17 +214,18 @@ ec_GFp_pt_dbl_jac(const mp_int *px, cons
 	MP_DIGITS(&t1) = 0;
 	MP_DIGITS(&M) = 0;
 	MP_DIGITS(&S) = 0;
 	MP_CHECKOK(mp_init(&t0));
 	MP_CHECKOK(mp_init(&t1));
 	MP_CHECKOK(mp_init(&M));
 	MP_CHECKOK(mp_init(&S));
 
-	if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
+	/* P == inf or P == -P */
+	if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES || mp_cmp_z(py) == 0) {
 		MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
 		goto CLEANUP;
 	}
 
 	if (mp_cmp_d(pz, 1) == 0) {
 		/* M = 3 * px^2 + a */
 		MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
 		MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth));
--- a/security/nss/lib/freebl/ecl/ecp_jm.c
+++ b/security/nss/lib/freebl/ecl/ecp_jm.c
@@ -11,17 +11,17 @@
 
 /* Computes R = 2P.  Elliptic curve points P and R can be identical.  Uses 
  * Modified Jacobian coordinates.
  *
  * Assumes input is already field-encoded using field_enc, and returns 
  * output that is still field-encoded.
  *
  */
-mp_err
+static mp_err
 ec_GFp_pt_dbl_jm(const mp_int *px, const mp_int *py, const mp_int *pz,
 				 const mp_int *paz4, mp_int *rx, mp_int *ry, mp_int *rz,
 				 mp_int *raz4, mp_int scratch[], const ECGroup *group)
 {
 	mp_err res = MP_OKAY;
 	mp_int *t0, *t1, *M, *S;
 
 	t0 = &scratch[0];
@@ -81,17 +81,17 @@ ec_GFp_pt_dbl_jm(const mp_int *px, const
 	return res;
 }
 
 /* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
  * (qx, qy, 1).  Elliptic curve points P, Q, and R can all be identical.
  * Uses mixed Modified_Jacobian-affine coordinates. Assumes input is
  * already field-encoded using field_enc, and returns output that is still
  * field-encoded. */
-mp_err
+static mp_err
 ec_GFp_pt_add_jm_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
 					 const mp_int *paz4, const mp_int *qx,
 					 const mp_int *qy, mp_int *rx, mp_int *ry, mp_int *rz,
 					 mp_int *raz4, mp_int scratch[], const ECGroup *group)
 {
 	mp_err res = MP_OKAY;
 	mp_int *A, *B, *C, *D, *C2, *C3;
 
--- a/security/nss/lib/freebl/mpi/mpmontg.c
+++ b/security/nss/lib/freebl/mpi/mpmontg.c
@@ -878,58 +878,55 @@ mp_err mp_exptmod_safe_i(const mp_int * 
 {
   mp_int *pa1, *pa2, *ptmp;
   mp_size i;
   mp_size first_window;
   mp_err  res;
   int     expOff;
   mp_int  accum1, accum2, accum[WEAVE_WORD_SIZE];
   mp_int  tmp;
-  unsigned char *powersArray;
-  unsigned char *powers;
+  unsigned char *powersArray = NULL;
+  unsigned char *powers = NULL;
 
   MP_DIGITS(&accum1) = 0;
   MP_DIGITS(&accum2) = 0;
   MP_DIGITS(&accum[0]) = 0;
   MP_DIGITS(&accum[1]) = 0;
   MP_DIGITS(&accum[2]) = 0;
   MP_DIGITS(&accum[3]) = 0;
   MP_DIGITS(&tmp) = 0;
 
-  powersArray = (unsigned char *)malloc(num_powers*(nLen*sizeof(mp_digit)+1));
-  if (powersArray == NULL) {
-    res = MP_MEM;
-    goto CLEANUP;
-  }
-
-  /* powers[i] = base ** (i); */
-  powers = (unsigned char *)MP_ALIGN(powersArray,num_powers);
-
   /* grab the first window value. This allows us to preload accumulator1
    * and save a conversion, some squares and a multiple*/
   MP_CHECKOK( mpl_get_bits(exponent, 
 				bits_in_exponent-window_bits, window_bits) );
   first_window = (mp_size)res;
 
   MP_CHECKOK( mp_init_size(&accum1, 3 * nLen + 2) );
   MP_CHECKOK( mp_init_size(&accum2, 3 * nLen + 2) );
-  MP_CHECKOK( mp_init_size(&tmp, 3 * nLen + 2) );
 
   /* build the first WEAVE_WORD powers inline */
   /* if WEAVE_WORD_SIZE is not 4, this code will have to change */
   if (num_powers > 2) {
     MP_CHECKOK( mp_init_size(&accum[0], 3 * nLen + 2) );
     MP_CHECKOK( mp_init_size(&accum[1], 3 * nLen + 2) );
     MP_CHECKOK( mp_init_size(&accum[2], 3 * nLen + 2) );
     MP_CHECKOK( mp_init_size(&accum[3], 3 * nLen + 2) );
     mp_set(&accum[0], 1);
     MP_CHECKOK( s_mp_to_mont(&accum[0], mmm, &accum[0]) );
     MP_CHECKOK( mp_copy(montBase, &accum[1]) );
     SQR(montBase, &accum[2]);
     MUL_NOWEAVE(montBase, &accum[2], &accum[3]);
+    powersArray = (unsigned char *)malloc(num_powers*(nLen*sizeof(mp_digit)+1));
+    if (!powersArray) {
+      res = MP_MEM;
+      goto CLEANUP;
+    }
+    /* powers[i] = base ** (i); */ \
+    powers = (unsigned char *)MP_ALIGN(powersArray,num_powers); \
     MP_CHECKOK( mpi_to_weave(accum, powers, nLen, num_powers) );
     if (first_window < 4) {
       MP_CHECKOK( mp_copy(&accum[first_window], &accum1) );
       first_window = num_powers;
     }
   } else {
       if (first_window == 0) {
         mp_set(&accum1, 1);
@@ -941,17 +938,20 @@ mp_err mp_exptmod_safe_i(const mp_int * 
   }
 
   /*
    * calculate all the powers in the powers array.
    * this adds 2**(k-1)-2 square operations over just calculating the
    * odd powers where k is the window size in the two other mp_modexpt
    * implementations in this file. We will get some of that
    * back by not needing the first 'k' squares and one multiply for the 
-   * first window */ 
+   * first window.
+   * Given the value of 4 for WEAVE_WORD_SIZE, this loop will only execute if
+   * num_powers > 2, in which case powers will have been allocated.
+   */
   for (i = WEAVE_WORD_SIZE; i < num_powers; i++) {
     int acc_index = i & (WEAVE_WORD_SIZE-1); /* i % WEAVE_WORD_SIZE */
     if ( i & 1 ) {
       MUL_NOWEAVE(montBase, &accum[acc_index-1] , &accum[acc_index]);
       /* we've filled the array do our 'per array' processing */
       if (acc_index == (WEAVE_WORD_SIZE-1)) {
         MP_CHECKOK( mpi_to_weave(accum, powers + i - (WEAVE_WORD_SIZE-1),
 							 nLen, num_powers) );
@@ -988,16 +988,21 @@ mp_err mp_exptmod_safe_i(const mp_int * 
 #if MP_ARGCHK == 2
   assert(MP_USED(&accum1) != 0);
 #endif
 
   /* set accumulator to montgomery residue of 1 */
   pa1 = &accum1;
   pa2 = &accum2;
 
+  /* tmp is not used if window_bits == 1. */
+  if (window_bits != 1) {
+    MP_CHECKOK( mp_init_size(&tmp, 3 * nLen + 2) );
+  }
+
   for (expOff = bits_in_exponent - window_bits*2; expOff >= 0; expOff -= window_bits) {
     mp_size smallExp;
     MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) );
     smallExp = (mp_size)res;
 
     /* handle unroll the loops */
     switch (window_bits) {
     case 1:
--- a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c
@@ -1127,31 +1127,27 @@ cleanup:
 }
 
 PKIX_Error *
 pkix_pl_HttpDefaultClient_KeepAliveSession(
         SEC_HTTP_SERVER_SESSION session,
         PRPollDesc **pPollDesc,
         void *plContext)
 {
-        PKIX_PL_HttpDefaultClient *client = NULL;
-
         PKIX_ENTER
                 (HTTPDEFAULTCLIENT,
                 "pkix_pl_HttpDefaultClient_KeepAliveSession");
         PKIX_NULLCHECK_TWO(session, pPollDesc);
 
         PKIX_CHECK(pkix_CheckType
                 ((PKIX_PL_Object *)session,
                 PKIX_HTTPDEFAULTCLIENT_TYPE,
                 plContext),
                 PKIX_SESSIONNOTANHTTPDEFAULTCLIENT);
 
-        client = (PKIX_PL_HttpDefaultClient *)session;
-
         /* XXX Not implemented */
 
 cleanup:
 
         PKIX_RETURN(HTTPDEFAULTCLIENT);
 
 }
 
--- a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c
@@ -206,17 +206,16 @@ pkix_pl_PublicKey_Hashcode(
 {
         PKIX_PL_PublicKey *pkixPubKey = NULL;
         SECItem algOID;
         SECItem algParams;
         SECItem nssPubKey;
         PKIX_UInt32 algOIDHash;
         PKIX_UInt32 algParamsHash;
         PKIX_UInt32 pubKeyHash;
-        PKIX_UInt32 fullHash;
 
         PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Hashcode");
         PKIX_NULLCHECK_TWO(object, pHashcode);
 
         PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext),
                     PKIX_OBJECTNOTPUBLICKEY);
 
         pkixPubKey = (PKIX_PL_PublicKey *)object;
@@ -234,18 +233,16 @@ pkix_pl_PublicKey_Hashcode(
         PKIX_CHECK(pkix_hash
                     (algParams.data, algParams.len, &algParamsHash, plContext),
                     PKIX_HASHFAILED);
 
         PKIX_CHECK(pkix_hash
                     (nssPubKey.data, nssPubKey.len, &pubKeyHash, plContext),
                     PKIX_HASHFAILED);
 
-        fullHash = algOIDHash + algParamsHash + pubKeyHash;
-
         *pHashcode = pubKeyHash;
 
 cleanup:
 
         PKIX_RETURN(PUBLICKEY);
 }
 
 
--- a/security/nss/lib/nss/nss.def
+++ b/security/nss/lib/nss/nss.def
@@ -1057,8 +1057,28 @@ SECMOD_InternaltoPubMechFlags;
 ;+    global:
 CERT_AddExtensionByOID;
 CERT_GetGeneralNameTypeFromString;
 PK11_PubEncrypt;
 PK11_PrivDecrypt;
 ;+    local:
 ;+       *;
 ;+};
+;+NSS_3.18 { 	# NSS 3.18 release
+;+    global:
+__PK11_SetCertificateNickname;
+SEC_CheckCrlTimes;
+SEC_GetCrlTimes;
+;+    local:
+;+       *;
+;+};
+;+NSS_3.19 { 	# NSS 3.19 release
+;+    global:
+CERT_GetImposedNameConstraints;
+;+    local:
+;+       *;
+;+};
+;+NSS_3.19.1 { 	# NSS 3.19.1 release
+;+    global:
+SECKEY_BigIntegerBitLength;
+;+    local:
+;+       *;
+;+};
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -28,20 +28,20 @@
 
 /*
  * 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.17.4" _NSS_ECC_STRING _NSS_CUSTOMIZED
+#define NSS_VERSION  "3.19.1" _NSS_ECC_STRING _NSS_CUSTOMIZED
 #define NSS_VMAJOR   3
-#define NSS_VMINOR   17
-#define NSS_VPATCH   4
+#define NSS_VMINOR   19
+#define NSS_VPATCH   1
 #define NSS_VBUILD   0
 #define NSS_BETA     PR_FALSE
 
 #ifndef RC_INVOKED
 
 #include "seccomon.h"
 
 typedef struct NSSInitParametersStr NSSInitParameters;
--- a/security/nss/lib/pk11wrap/pk11cert.c
+++ b/security/nss/lib/pk11wrap/pk11cert.c
@@ -2677,8 +2677,30 @@ PK11_GetAllSlotsForCert(CERTCertificate 
 	PK11_FreeSlotList(slotList);
 	PORT_SetError(SEC_ERROR_NO_TOKEN);
 	slotList = NULL;
     }
 
     nssCryptokiObjectArray_Destroy(instances);
     return slotList;
 }
+
+/*
+ * Using __PK11_SetCertificateNickname is *DANGEROUS*.
+ *
+ * The API will update the NSS database, but it *will NOT* update the in-memory data.
+ * As a result, after calling this API, there will be INCONSISTENCY between
+ * in-memory data and the database.
+ *
+ * Use of the API should be limited to short-lived tools, which will exit immediately
+ * after using this API.
+ *
+ * If you ignore this warning, your process is TAINTED and will most likely misbehave.
+ */
+SECStatus
+__PK11_SetCertificateNickname(CERTCertificate *cert, const char *nickname)
+{
+    /* Can't set nickname of temp cert. */
+    if (!cert->slot || cert->pkcs11ID == CK_INVALID_HANDLE) {
+        return SEC_ERROR_INVALID_ARGS;
+    }
+    return PK11_SetObjectNickname(cert->slot, cert->pkcs11ID, nickname);
+}
--- a/security/nss/lib/pk11wrap/pk11pub.h
+++ b/security/nss/lib/pk11wrap/pk11pub.h
@@ -454,16 +454,31 @@ char * PK11_GetSymKeyNickname(PK11SymKey
 char * PK11_GetPrivateKeyNickname(SECKEYPrivateKey *privKey);
 char * PK11_GetPublicKeyNickname(SECKEYPublicKey *pubKey);
 SECStatus PK11_SetSymKeyNickname(PK11SymKey *symKey, const char *nickname);
 SECStatus PK11_SetPrivateKeyNickname(SECKEYPrivateKey *privKey, 
 							const char *nickname);
 SECStatus PK11_SetPublicKeyNickname(SECKEYPublicKey *pubKey, 
 							const char *nickname);
 
+/*
+ * Using __PK11_SetCertificateNickname is *DANGEROUS*.
+ *
+ * The API will update the NSS database, but it *will NOT* update the in-memory data.
+ * As a result, after calling this API, there will be INCONSISTENCY between
+ * in-memory data and the database.
+ *
+ * Use of the API should be limited to short-lived tools, which will exit immediately
+ * after using this API.
+ *
+ * If you ignore this warning, your process is TAINTED and will most likely misbehave.
+ */
+SECStatus __PK11_SetCertificateNickname(CERTCertificate *cert,
+                                      const char *nickname);
+
 /* size to hold key in bytes */
 unsigned int PK11_GetKeyLength(PK11SymKey *key);
 /* size of actual secret parts of key in bits */
 /* algid is because RC4 strength is determined by the effective bits as well
  * as the key bits */
 unsigned int PK11_GetKeyStrength(PK11SymKey *key,SECAlgorithmID *algid);
 SECStatus PK11_ExtractKeyValue(PK11SymKey *symKey);
 SECItem * PK11_GetKeyData(PK11SymKey *symKey);
--- a/security/nss/lib/pkcs12/p12.h
+++ b/security/nss/lib/pkcs12/p12.h
@@ -31,24 +31,59 @@ typedef void (PR_CALLBACK * SEC_PKCS12En
                             unsigned long len);
 typedef void (PR_CALLBACK * SEC_PKCS12DecoderOutputCallback)(
                             void *arg, const char *buf,
                             unsigned long len);
 /*
  * In NSS 3.12 or later, 'arg' actually points to a CERTCertificate,
  * the 'leafCert' variable in sec_pkcs12_validate_cert in p12d.c. 
  * See r1.35 of p12d.c ("Patch 2" in bug 321584).
+ *
+ * This callback might be called by SEC_PKCS12DecoderValidateBags each time
+ * a nickname collission is detected. The callback must return a new
+ * nickname. The returned SECItem should be of type siAsciiString,
+ * it should be allocated using:
+ *     SECITEM_AllocItem(NULL, NULL, LENGTH_OF_NEW_NICKNAME + 1)
+ * and data must contain the new nickname as a zero terminated string.
  */
 typedef SECItem * (PR_CALLBACK * SEC_PKCS12NicknameCollisionCallback)(
                                  SECItem *old_nickname,
                                  PRBool *cancel,
                                  void *arg);
-
-
-
+/*
+ * This callback is called by SEC_PKCS12DecoderRenameCertNicknames for each
+ * certificate found in the p12 source data.
+ *
+ * cert: A decoded certificate.
+ * default_nickname: The nickname as found in the source data.
+ *                   Will be NULL if source data doesn't have nickname.
+ * new_nickname: Output parameter that may contain the renamed nickname.
+ * arg: The user data that was passed to SEC_PKCS12DecoderRenameCertNicknames.
+ *
+ * If the callback accept that NSS will use a nickname based on the
+ * default_nickname (potentially resolving conflicts), then the callback
+ * must set *new_nickname to NULL.
+ *
+ * If the callback wishes to override the nickname, it must set *new_nickname
+ * to a new SECItem which should be allocated using
+ *     SECITEM_AllocItem(NULL, NULL, LENGTH_OF_NEW_NICKNAME + 1)
+ * new_nickname->type should be set to siAsciiString, and new_nickname->data
+ * must contain the new nickname as a zero terminated string.
+ *
+ * A return value of SECFailure indicates that the renaming operation failed,
+ * and callback should release new_nickname before returning if it's already
+ * being allocated.
+ * Otherwise, the callback function must return SECSuccess, including use
+ * default nickname as mentioned above.
+ */
+typedef SECStatus (PR_CALLBACK * SEC_PKCS12NicknameRenameCallback)(
+                                 const CERTCertificate *cert,
+                                 const SECItem *default_nickname,
+                                 SECItem **new_nickname,
+                                 void *arg);
 
 typedef SECStatus (PR_CALLBACK *digestOpenFn)(void *arg, PRBool readData);
 typedef SECStatus (PR_CALLBACK *digestCloseFn)(void *arg, PRBool removeFile);
 typedef int (PR_CALLBACK *digestIOFn)(void *arg, unsigned char *buf, 
                                       unsigned long len);
 
 typedef struct SEC_PKCS12ExportContextStr SEC_PKCS12ExportContext;
 typedef struct SEC_PKCS12SafeInfoStr SEC_PKCS12SafeInfo;
@@ -162,16 +197,36 @@ SEC_PKCS12DecoderFinish(SEC_PKCS12Decode
 
 extern SECStatus
 SEC_PKCS12DecoderVerify(SEC_PKCS12DecoderContext *p12dcx);
 
 extern SECStatus
 SEC_PKCS12DecoderValidateBags(SEC_PKCS12DecoderContext *p12dcx,
 			      SEC_PKCS12NicknameCollisionCallback nicknameCb);
 
+/*
+ * SEC_PKCS12DecoderRenameCertNicknames() can be used to change
+ * certificate nicknames in SEC_PKCS12DecoderContext, prior to calling
+ * SEC_PKCS12DecoderImportBags.
+ *
+ * arg: User-defined data that will be passed to nicknameCb.
+ *
+ * If SEC_PKCS12DecoderRenameCertNicknames() is called after calling
+ * SEC_PKCS12DecoderValidateBags(), then only the certificate nickname
+ * will be changed.
+ * If SEC_PKCS12DecoderRenameCertNicknames() is called prior to calling
+ * SEC_PKCS12DecoderValidateBags(), then SEC_PKCS12DecoderValidateBags()
+ * will change the nickname of the corresponding private key, too.
+ */
+extern SECStatus
+SEC_PKCS12DecoderRenameCertNicknames(SEC_PKCS12DecoderContext *p12dcx,
+                                     SEC_PKCS12NicknameRenameCallback nicknameCb,
+                                     void *arg);
+
+
 extern SECStatus
 SEC_PKCS12DecoderImportBags(SEC_PKCS12DecoderContext *p12dcx);
 
 CERTCertList *
 SEC_PKCS12DecoderGetCerts(SEC_PKCS12DecoderContext *p12dcx);
 
 SECStatus
 SEC_PKCS12DecoderIterateInit(SEC_PKCS12DecoderContext *p12dcx);
--- a/security/nss/lib/pkcs12/p12d.c
+++ b/security/nss/lib/pkcs12/p12d.c
@@ -2790,16 +2790,74 @@ SEC_PKCS12DecoderValidateBags(SEC_PKCS12
     if(probCnt) {
 	PORT_SetError(errorVal);
 	return SECFailure;
     }
 
     return rv;
 }
 
+SECStatus
+SEC_PKCS12DecoderRenameCertNicknames(SEC_PKCS12DecoderContext *p12dcx,
+                                     SEC_PKCS12NicknameRenameCallback nicknameCb,
+                                     void *arg)
+{
+    int i;
+    sec_PKCS12SafeBag *safeBag;
+    CERTCertificate *cert;
+    SECStatus srv;
+
+    if(!p12dcx || p12dcx->error || !p12dcx->safeBags || !nicknameCb) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+
+    for (i = 0; safeBag = p12dcx->safeBags[i]; i++) {
+        SECItem *newNickname = NULL;
+        SECItem *defaultNickname = NULL;
+        SECStatus rename_rv;
+
+        if (SECOID_FindOIDTag(&(safeBag->safeBagType)) !=
+            SEC_OID_PKCS12_V1_CERT_BAG_ID) {
+            continue;
+        }
+
+        cert = CERT_DecodeDERCertificate(
+                   &safeBag->safeBagContent.certBag->value.x509Cert,
+                   PR_FALSE, NULL);
+        if (!cert) {
+            return SECFailure;
+        }
+
+        defaultNickname = sec_pkcs12_get_nickname(safeBag);
+        rename_rv = (*nicknameCb)(cert, defaultNickname, &newNickname, arg);
+
+        CERT_DestroyCertificate(cert);
+
+        if (defaultNickname) {
+            SECITEM_ZfreeItem(defaultNickname, PR_TRUE);
+            defaultNickname = NULL;
+        }
+
+        if (rename_rv != SECSuccess) {
+            return rename_rv;
+        }
+
+        if (newNickname) {
+            srv = sec_pkcs12_set_nickname(safeBag, newNickname);
+            SECITEM_ZfreeItem(newNickname, PR_TRUE);
+            newNickname = NULL;
+            if (srv != SECSuccess) {
+                return SECFailure;
+            }
+        }
+    }
+
+    return SECSuccess;
+}
 
 static SECKEYPublicKey *
 sec_pkcs12_get_public_key_and_usage(sec_PKCS12SafeBag *certBag,
 					 unsigned int *usage)
 {
     SECKEYPublicKey *pubKey = NULL;
     CERTCertificate *cert = NULL;
 
--- a/security/nss/lib/pkcs12/p12local.c
+++ b/security/nss/lib/pkcs12/p12local.c
@@ -923,17 +923,18 @@ sec_pkcs12_convert_item_to_unicode(PLAre
 	if(!arena) {
 	    PORT_Free(dest->data);
 	    dest->data = NULL;
 	    dest->len = 0;
 	}
 	return PR_FALSE;
     }
 
-    if((dest->data[dest->len-1] || dest->data[dest->len-2]) && zeroTerm) {
+    if ((dest->len >= 2) &&
+	(dest->data[dest->len-1] || dest->data[dest->len-2]) && zeroTerm) {
 	if(dest->len + 2 > 3 * src->len) {
 	    if(arena) {
 		dest->data = (unsigned char*)PORT_ArenaGrow(arena, 
 						     dest->data, dest->len,
 						     dest->len + 2);
 	    } else {
 		dest->data = (unsigned char*)PORT_Realloc(dest->data, 
 							  dest->len + 2);
--- a/security/nss/lib/pki/tdcache.c
+++ b/security/nss/lib/pki/tdcache.c
@@ -432,27 +432,31 @@ nssTrustDomain_RemoveTokenCertsFromCache
 	return PR_FAILURE;
     }
     dtor.cache = td->cache;
     dtor.token = token;
     dtor.certs = certs;
     dtor.numCerts = 0;
     dtor.arrSize = arrSize;
     PZ_Lock(td->cache->lock);
-    nssHash_Iterate(td->cache->issuerAndSN, remove_token_certs, (void *)&dtor);
+    nssHash_Iterate(td->cache->issuerAndSN, remove_token_certs, &dtor);
     for (i=0; i<dtor.numCerts; i++) {
 	if (dtor.certs[i]->object.numInstances == 0) {
 	    nssTrustDomain_RemoveCertFromCacheLOCKED(td, dtor.certs[i]);
 	    dtor.certs[i] = NULL;  /* skip this cert in the second for loop */
+	} else {
+	    /* make sure it doesn't disappear on us before we finish */
+	    nssCertificate_AddRef(dtor.certs[i]);
 	}
     }
     PZ_Unlock(td->cache->lock);
     for (i=0; i<dtor.numCerts; i++) {
 	if (dtor.certs[i]) {
 	    STAN_ForceCERTCertificateUpdate(dtor.certs[i]);
+	    nssCertificate_Destroy(dtor.certs[i]);
 	}
     }
     nss_ZFreeIf(dtor.certs);
     return PR_SUCCESS;
 }
 
 NSS_IMPLEMENT PRStatus
 nssTrustDomain_UpdateCachedTokenCerts (
--- a/security/nss/lib/smime/cmsmessage.c
+++ b/security/nss/lib/smime/cmsmessage.c
@@ -23,36 +23,36 @@
 NSSCMSMessage *
 NSS_CMSMessage_Create(PLArenaPool *poolp)
 {
     void *mark = NULL;
     NSSCMSMessage *cmsg;
     PRBool poolp_is_ours = PR_FALSE;
 
     if (poolp == NULL) {
-	poolp = PORT_NewArena (1024);           /* XXX what is right value? */
-	if (poolp == NULL)
-	    return NULL;
-	poolp_is_ours = PR_TRUE;
-    } 
+        poolp = PORT_NewArena (1024);           /* XXX what is right value? */
+        if (poolp == NULL)
+            return NULL;
+        poolp_is_ours = PR_TRUE;
+    }
 
     if (!poolp_is_ours)
-	mark = PORT_ArenaMark(poolp);
+        mark = PORT_ArenaMark(poolp);
 
-    cmsg = (NSSCMSMessage *)PORT_ArenaZAlloc (poolp, sizeof(NSSCMSMessage));
-    if (cmsg == NULL) {
-	if (!poolp_is_ours) {
-	    if (mark) {
-		PORT_ArenaRelease(poolp, mark);
-	    }
-	} else
-	    PORT_FreeArena(poolp, PR_FALSE);
-	return NULL;
+    cmsg = (NSSCMSMessage *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSMessage));
+    if (cmsg == NULL ||
+        NSS_CMSContentInfo_Private_Init(&(cmsg->contentInfo)) != SECSuccess) {
+        if (!poolp_is_ours) {
+            if (mark) {
+                PORT_ArenaRelease(poolp, mark);
+            }
+        } else
+            PORT_FreeArena(poolp, PR_FALSE);
+        return NULL;
     }
-    NSS_CMSContentInfo_Private_Init(&(cmsg->contentInfo));
 
     cmsg->poolp = poolp;
     cmsg->poolp_is_ours = poolp_is_ours;
     cmsg->refCount = 1;
 
     if (mark)
 	PORT_ArenaUnmark(poolp, mark);
 
--- a/security/nss/lib/smime/smime.def
+++ b/security/nss/lib/smime/smime.def
@@ -274,8 +274,14 @@ SEC_PKCS7VerifyDetachedSignatureAtTime;
 ;+       *;
 ;+};
 ;+NSS_3.16 {    # NSS 3.16 release
 ;+    global:
 NSS_CMSSignerInfo_Verify;
 ;+    local:
 ;+       *;
 ;+};
+;+NSS_3.18 {    # NSS 3.18 release
+;+    global:
+SEC_PKCS12DecoderRenameCertNicknames;
+;+    local:
+;+       *;
+;+};
--- a/security/nss/lib/smime/smimeutil.c
+++ b/security/nss/lib/smime/smimeutil.c
@@ -432,20 +432,22 @@ smime_choose_cipher(CERTCertificate *sce
 	     * XXX This is probably only good for RSA keys.  What I would
 	     * really like is a function to just say;  Is the public key in
 	     * this cert an export-length key?  Then I would not have to
 	     * know things like the value 512, or the kind of key, or what
 	     * a subjectPublicKeyInfo is, etc.
 	     */
 	    key = CERT_ExtractPublicKey(rcerts[rcount]);
 	    pklen_bits = 0;
+	    key_type = nullKey;
 	    if (key != NULL) {
 		pklen_bits = SECKEY_PublicKeyStrengthInBits (key);
 		key_type = SECKEY_GetPublicKeyType(key);
 		SECKEY_DestroyPublicKey (key);
+		key = NULL;
 	    }
 
 	    if (key_type == ecKey) {
 		/* While RFC 5753 mandates support for AES-128 CBC, should use
 		 * AES 256 if user's key provides more than 128 bits of
 		 * security strength so that symmetric key is not weak link. */
 
 		/* RC2-40 is not compatible with elliptic curve keys. */
--- a/security/nss/lib/softoken/config.mk
+++ b/security/nss/lib/softoken/config.mk
@@ -17,42 +17,42 @@ ifeq (,$(filter-out WIN%,$(OS_TARGET)))
 SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
 IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
 
 RES = $(OBJDIR)/$(LIBRARY_NAME).res
 RESNAME = $(LIBRARY_NAME).rc
 
 ifdef NS_USE_GCC
 EXTRA_SHARED_LIBS += \
-	-L$(DIST)/lib \
+	-L$(SQLITE_LIB_DIR) \
 	-l$(SQLITE_LIB_NAME) \
 	-L$(NSSUTIL_LIB_DIR) \
 	-lnssutil3 \
 	-L$(NSPR_LIB_DIR) \
 	-lplc4 \
 	-lplds4 \
 	-lnspr4 \
 	$(NULL)
 else # ! NS_USE_GCC
 
 EXTRA_SHARED_LIBS += \
-	$(DIST)/lib/$(SQLITE_LIB_NAME).lib \
+	$(SQLITE_LIB_DIR)/$(SQLITE_LIB_NAME).lib \
 	$(NSSUTIL_LIB_DIR)/nssutil3.lib \
 	$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
 	$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
 	$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
 	$(NULL)
 endif # NS_USE_GCC
 
 else
 
 # $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
 # $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
 EXTRA_SHARED_LIBS += \
-	-L$(DIST)/lib \
+	-L$(SQLITE_LIB_DIR) \
 	-l$(SQLITE_LIB_NAME) \
 	-L$(NSSUTIL_LIB_DIR) \
 	-lnssutil3 \
 	-L$(NSPR_LIB_DIR) \
 	-lplc4 \
 	-lplds4 \
 	-lnspr4 \
 	$(NULL)
--- a/security/nss/lib/softoken/lowpbe.c
+++ b/security/nss/lib/softoken/lowpbe.c
@@ -314,18 +314,18 @@ do_xor(unsigned char *dest, unsigned cha
     while (len--) {
     	*dest = *dest ^ *src;
 	dest++;
 	src++;
     }
 }
 
 static SECStatus
-nsspkcs5_PBKFD2_F(const SECHashObject *hashobj, SECItem *pwitem, SECItem *salt,
-			int iterations, unsigned int i, unsigned char *T)
+nsspkcs5_PBKDF2_F(const SECHashObject *hashobj, SECItem *pwitem, SECItem *salt,
+                  int iterations, unsigned int i, unsigned char *T)
 {
     int j;
     HMACContext *cx = NULL;
     unsigned int hLen = hashobj->length;
     SECStatus rv = SECFailure;
     unsigned char *last = NULL;
     unsigned int lastLength = salt->len + 4;
     unsigned int lastBufLength;
@@ -388,34 +388,34 @@ nsspkcs5_PBKDF2(const SECHashObject *has
     }
 
     T = PORT_Alloc(hLen);
     if (T == NULL) {
 	goto loser;
     }
 
     for (i=1,rp=result->data; i <= nblocks ; i++, rp +=hLen) {
-	rv = nsspkcs5_PBKFD2_F(hashobj,pwitem,salt,iterations,i,T);
+        rv = nsspkcs5_PBKDF2_F(hashobj, pwitem, salt, iterations, i, T);
 	if (rv != SECSuccess) {
 	    break;
 	}
 	PORT_Memcpy(rp,T,hLen);
     }
 
 loser:
     if (T) {
 	PORT_ZFree(T,hLen);
     }
     if (rv != SECSuccess) {
 	SECITEM_FreeItem(result,PR_TRUE);
 	result = NULL;
     } else {
 	result->len = dkLen;
     }
-	
+
     return result;
 }
 #endif
 
 #define HMAC_BUFFER 64
 #define NSSPBE_ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y))
 #define NSSPBE_MIN(x,y) ((x) < (y) ? (x) : (y))
 /*
--- a/security/nss/lib/softoken/sftkpwd.c
+++ b/security/nss/lib/softoken/sftkpwd.c
@@ -1242,17 +1242,17 @@ sftkdb_ChangePassword(SFTKDBHandle *keyd
 
     sftkdb_switchKeys(keydb, &newKey);
 
 loser:
     if (newKey.data) {
 	PORT_ZFree(newKey.data,newKey.len);
     }
     if (result) {
-	SECITEM_FreeItem(result, PR_FALSE);
+	SECITEM_FreeItem(result, PR_TRUE);
     }
     if (rv != SECSuccess) {
         (*keydb->db->sdb_Abort)(keydb->db);
     }
     
     return rv;
 }
 
--- 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.17.4" SOFTOKEN_ECC_STRING
+#define SOFTOKEN_VERSION  "3.19.1" SOFTOKEN_ECC_STRING
 #define SOFTOKEN_VMAJOR   3
-#define SOFTOKEN_VMINOR   17
-#define SOFTOKEN_VPATCH   4
+#define SOFTOKEN_VMINOR   19
+#define SOFTOKEN_VPATCH   1
 #define SOFTOKEN_VBUILD   0
 #define SOFTOKEN_BETA     PR_FALSE
 
 #endif /* _SOFTKVER_H_ */
--- a/security/nss/lib/ssl/SSLerrs.h
+++ b/security/nss/lib/ssl/SSLerrs.h
@@ -417,8 +417,11 @@ ER3(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK,
 "The next protocol negotiation extension was enabled, but the callback was cleared prior to being needed.")
 
 ER3(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL, (SSL_ERROR_BASE + 130),
 "The server supports no protocols that the client advertises in the ALPN extension.")
 
 ER3(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT, (SSL_ERROR_BASE + 131),
 "The server rejected the handshake because the client downgraded to a lower "
 "TLS version than the server supports.")
+
+ER3(SSL_ERROR_WEAK_SERVER_CERT_KEY, (SSL_ERROR_BASE + 132),
+"The server certificate included a public key that was too weak.")
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -279,40 +279,40 @@ static const ssl3BulkCipherDef bulk_ciph
     {cipher_aes_256,      calg_aes,         32,32, type_block, 16,16, 0, 0},
     {cipher_camellia_128, calg_camellia,    16,16, type_block, 16,16, 0, 0},
     {cipher_camellia_256, calg_camellia,    32,32, type_block, 16,16, 0, 0},
     {cipher_seed,         calg_seed,        16,16, type_block, 16,16, 0, 0},
     {cipher_aes_128_gcm,  calg_aes_gcm,     16,16, type_aead,   4, 0,16, 8},
     {cipher_missing,      calg_null,         0, 0, type_stream, 0, 0, 0, 0},
 };
 
-static const ssl3KEADef kea_defs[] = 
+static const ssl3KEADef kea_defs[] =
 { /* indexed by SSL3KeyExchangeAlgorithm */
-    /* kea              exchKeyType signKeyType is_limited limit  tls_keygen */
-    {kea_null,           kt_null,     sign_null, PR_FALSE,   0, PR_FALSE},
-    {kea_rsa,            kt_rsa,      sign_rsa,  PR_FALSE,   0, PR_FALSE},
-    {kea_rsa_export,     kt_rsa,      sign_rsa,  PR_TRUE,  512, PR_FALSE},
-    {kea_rsa_export_1024,kt_rsa,      sign_rsa,  PR_TRUE, 1024, PR_FALSE},
-    {kea_dh_dss,         kt_dh,       sign_dsa,  PR_FALSE,   0, PR_FALSE},
-    {kea_dh_dss_export,  kt_dh,       sign_dsa,  PR_TRUE,  512, PR_FALSE},
-    {kea_dh_rsa,         kt_dh,       sign_rsa,  PR_FALSE,   0, PR_FALSE},
-    {kea_dh_rsa_export,  kt_dh,       sign_rsa,  PR_TRUE,  512, PR_FALSE},
-    {kea_dhe_dss,        kt_dh,       sign_dsa,  PR_FALSE,   0, PR_FALSE},
-    {kea_dhe_dss_export, kt_dh,       sign_dsa,  PR_TRUE,  512, PR_FALSE},
-    {kea_dhe_rsa,        kt_dh,       sign_rsa,  PR_FALSE,   0, PR_FALSE},
-    {kea_dhe_rsa_export, kt_dh,       sign_rsa,  PR_TRUE,  512, PR_FALSE},
-    {kea_dh_anon,        kt_dh,       sign_null, PR_FALSE,   0, PR_FALSE},
-    {kea_dh_anon_export, kt_dh,       sign_null, PR_TRUE,  512, PR_FALSE},
-    {kea_rsa_fips,       kt_rsa,      sign_rsa,  PR_FALSE,   0, PR_TRUE },
+    /* kea            exchKeyType signKeyType is_limited limit tls_keygen ephemeral */
+    {kea_null,           kt_null, sign_null,  PR_FALSE,   0, PR_FALSE, PR_FALSE},
+    {kea_rsa,            kt_rsa,  sign_rsa,   PR_FALSE,   0, PR_FALSE, PR_FALSE},
+    {kea_rsa_export,     kt_rsa,  sign_rsa,   PR_TRUE,  512, PR_FALSE, PR_TRUE},
+    {kea_rsa_export_1024,kt_rsa,  sign_rsa,   PR_TRUE, 1024, PR_FALSE, PR_TRUE},
+    {kea_dh_dss,         kt_dh,   sign_dsa,   PR_FALSE,   0, PR_FALSE, PR_FALSE},
+    {kea_dh_dss_export,  kt_dh,   sign_dsa,   PR_TRUE,  512, PR_FALSE, PR_FALSE},
+    {kea_dh_rsa,         kt_dh,   sign_rsa,   PR_FALSE,   0, PR_FALSE, PR_FALSE},
+    {kea_dh_rsa_export,  kt_dh,   sign_rsa,   PR_TRUE,  512, PR_FALSE, PR_FALSE},
+    {kea_dhe_dss,        kt_dh,   sign_dsa,   PR_FALSE,   0, PR_FALSE, PR_TRUE},
+    {kea_dhe_dss_export, kt_dh,   sign_dsa,   PR_TRUE,  512, PR_FALSE, PR_TRUE},
+    {kea_dhe_rsa,        kt_dh,   sign_rsa,   PR_FALSE,   0, PR_FALSE, PR_TRUE},
+    {kea_dhe_rsa_export, kt_dh,   sign_rsa,   PR_TRUE,  512, PR_FALSE, PR_TRUE},
+    {kea_dh_anon,        kt_dh,   sign_null,  PR_FALSE,   0, PR_FALSE, PR_TRUE},
+    {kea_dh_anon_export, kt_dh,   sign_null,  PR_TRUE,  512, PR_FALSE, PR_TRUE},
+    {kea_rsa_fips,       kt_rsa,  sign_rsa,   PR_FALSE,   0, PR_TRUE,  PR_FALSE},
 #ifndef NSS_DISABLE_ECC
-    {kea_ecdh_ecdsa,     kt_ecdh,     sign_ecdsa,  PR_FALSE, 0, PR_FALSE},
-    {kea_ecdhe_ecdsa,    kt_ecdh,     sign_ecdsa,  PR_FALSE,   0, PR_FALSE},
-    {kea_ecdh_rsa,       kt_ecdh,     sign_rsa,  PR_FALSE,   0, PR_FALSE},
-    {kea_ecdhe_rsa,      kt_ecdh,     sign_rsa,  PR_FALSE,   0, PR_FALSE},
-    {kea_ecdh_anon,      kt_ecdh,     sign_null,  PR_FALSE,   0, PR_FALSE},
+    {kea_ecdh_ecdsa,     kt_ecdh, sign_ecdsa, PR_FALSE,   0, PR_FALSE, PR_FALSE},
+    {kea_ecdhe_ecdsa,    kt_ecdh, sign_ecdsa, PR_FALSE,   0, PR_FALSE, PR_TRUE},
+    {kea_ecdh_rsa,       kt_ecdh, sign_rsa,   PR_FALSE,   0, PR_FALSE, PR_FALSE},
+    {kea_ecdhe_rsa,      kt_ecdh, sign_rsa,   PR_FALSE,   0, PR_FALSE, PR_TRUE},
+    {kea_ecdh_anon,      kt_ecdh, sign_null,  PR_FALSE,   0, PR_FALSE, PR_TRUE},
 #endif /* NSS_DISABLE_ECC */
 };
 
 /* must use ssl_LookupCipherSuiteDef to access */
 static const ssl3CipherSuiteDef cipher_suite_defs[] = 
 {
 /*  cipher_suite                    bulk_cipher_alg mac_alg key_exchange_alg */
 
@@ -2783,16 +2783,22 @@ ssl3_SendRecord(   sslSocket *        ss
 
     SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d",
 		SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type),
 		nIn));
     PRINT_BUF(50, (ss, "Send record (plain text)", pIn, nIn));
 
     PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
 
+    if (ss->ssl3.fatalAlertSent) {
+        SSL_TRC(3, ("%d: SSL3[%d] Suppress write, fatal alert already sent",
+                    SSL_GETPID(), ss->fd));
+        return SECFailure;
+    }
+
     capRecordVersion = ((flags & ssl_SEND_FLAG_CAP_RECORD_VERSION) != 0);
 
     if (capRecordVersion) {
 	/* ssl_SEND_FLAG_CAP_RECORD_VERSION can only be used with the
 	 * TLS initial ClientHello. */
 	PORT_Assert(!IS_DTLS(ss));
 	PORT_Assert(!ss->firstHsDone);
 	PORT_Assert(type == content_handshake);
@@ -3228,16 +3234,19 @@ SSL3_SendAlert(sslSocket *ss, SSL3AlertL
     rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
     if (rv == SECSuccess) {
 	PRInt32 sent;
 	sent = ssl3_SendRecord(ss, 0, content_alert, bytes, 2, 
 			       desc == no_certificate 
 			       ? ssl_SEND_FLAG_FORCE_INTO_BUFFER : 0);
 	rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
     }
+    if (level == alert_fatal) {
+        ss->ssl3.fatalAlertSent = PR_TRUE;
+    }
     ssl_ReleaseXmitBufLock(ss);
     ssl_ReleaseSSL3HandshakeLock(ss);
     return rv;	/* error set by ssl3_FlushHandshake or ssl3_SendRecord */
 }
 
 /*
  * Send illegal_parameter alert.  Set generic error number.
  */
@@ -4973,50 +4982,56 @@ ssl3_SendClientHello(sslSocket *ss, PRBo
 	/* If we previously did client-auth, make sure that the token that
 	** holds the private key still exists, is logged in, hasn't been
 	** removed, etc.
 	*/
 	if (sidOK && !ssl3_ClientAuthTokenPresent(sid)) {
 	    sidOK = PR_FALSE;
 	}
 
-	/* TLS 1.0 (RFC 2246) Appendix E says:
-	 *   Whenever a client already knows the highest protocol known to
-	 *   a server (for example, when resuming a session), it should
-	 *   initiate the connection in that native protocol.
-	 * So we pass sid->version to ssl3_NegotiateVersion() here, except
-	 * when renegotiating.
-	 *
-	 * Windows SChannel compares the client_version inside the RSA
-	 * EncryptedPreMasterSecret of a renegotiation with the
-	 * client_version of the initial ClientHello rather than the
-	 * ClientHello in the renegotiation. To work around this bug, we
-	 * continue to use the client_version used in the initial
-	 * ClientHello when renegotiating.
-	 */
 	if (sidOK) {
+            /* Set ss->version based on the session cache */
 	    if (ss->firstHsDone) {
 		/*
+	         * Windows SChannel compares the client_version inside the RSA
+	         * EncryptedPreMasterSecret of a renegotiation with the
+	         * client_version of the initial ClientHello rather than the
+	         * ClientHello in the renegotiation. To work around this bug, we
+	         * continue to use the client_version used in the initial
+	         * ClientHello when renegotiating.
+	         *
 		 * The client_version of the initial ClientHello is still
 		 * available in ss->clientHelloVersion. Ensure that
 		 * sid->version is bounded within
 		 * [ss->vrange.min, ss->clientHelloVersion], otherwise we
 		 * can't use sid.
 		 */
 		if (sid->version >= ss->vrange.min &&
 		    sid->version <= ss->clientHelloVersion) {
 		    ss->version = ss->clientHelloVersion;
 		} else {
 		    sidOK = PR_FALSE;
 		}
 	    } else {
-		if (ssl3_NegotiateVersion(ss, sid->version,
-					  PR_FALSE) != SECSuccess) {
+                /*
+                 * Check sid->version is OK first.
+                 * Previously, we would cap the version based on sid->version,
+                 * but that prevents negotiation of a higher version if the
+                 * previous session was reduced (e.g., with version fallback)
+                 */
+		if (sid->version < ss->vrange.min || 
+                    sid->version > ss->vrange.max) {
 		    sidOK = PR_FALSE;
-		}
+		} else {
+	            rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED,
+                                               PR_TRUE);
+	            if (rv != SECSuccess) {
+                        return rv;	/* error code was set */
+                    }
+	        }
 	    }
 	}
 
 	if (!sidOK) {
 	    SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_not_ok );
 	    if (ss->sec.uncache)
                 (*ss->sec.uncache)(sid);
 	    ssl_FreeSID(sid);
@@ -5381,19 +5396,17 @@ ssl3_HandleHelloRequest(sslSocket *ss)
     if (ss->ssl3.hs.ws == wait_server_hello)
 	return SECSuccess;
     if (ss->ssl3.hs.ws != idle_handshake || ss->sec.isServer) {
 	(void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
 	PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST);
 	return SECFailure;
     }
     if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
-	ssl_GetXmitBufLock(ss);
-	rv = SSL3_SendAlert(ss, alert_warning, no_renegotiation);
-	ssl_ReleaseXmitBufLock(ss);
+	(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);
 	ssl_FreeSID(sid);
@@ -6561,50 +6574,36 @@ ssl3_HandleServerHello(sslSocket *ss, SS
 	goto alert_loser;	/* memory error is set. */
     }
 
     sid->version = ss->version;
     sid->u.ssl3.sessionIDLength = sidBytes.len;
     PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len);
 
     ss->ssl3.hs.isResuming = PR_FALSE;
-    ss->ssl3.hs.ws         = wait_server_cert;
+    if (ss->ssl3.hs.kea_def->signKeyType != sign_null) {
+        /* All current cipher suites other than those with sign_null (i.e.,
+         * DH_anon_* suites) require a certificate, so use that signal. */
+        ss->ssl3.hs.ws = wait_server_cert;
+    } else if (ss->ssl3.hs.kea_def->ephemeral) {
+        /* Only ephemeral cipher suites use ServerKeyExchange. */
+        ss->ssl3.hs.ws = wait_server_key;
+    } else {
+        ss->ssl3.hs.ws = wait_cert_request;
+    }
     return SECSuccess;
 
 alert_loser:
     (void)SSL3_SendAlert(ss, alert_fatal, desc);
 
 loser:
     errCode = ssl_MapLowLevelError(errCode);
     return SECFailure;
 }
 
-/* ssl3_BigIntGreaterThanOne returns true iff |mpint|, taken as an unsigned,
- * big-endian integer is > 1 */
-static PRBool
-ssl3_BigIntGreaterThanOne(const SECItem* mpint) {
-    unsigned char firstNonZeroByte = 0;
-    unsigned int i;
-
-    for (i = 0; i < mpint->len; i++) {
-	if (mpint->data[i]) {
-	    firstNonZeroByte = mpint->data[i];
-	    break;
-	}
-    }
-
-    if (firstNonZeroByte == 0)
-	return PR_FALSE;
-    if (firstNonZeroByte > 1)
-	return PR_TRUE;
-
-    /* firstNonZeroByte == 1, therefore mpint > 1 iff the first non-zero byte
-     * is followed by another byte. */
-    return (i < mpint->len - 1);
-}
 
 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
  * ssl3 ServerKeyExchange message.
  * Caller must hold Handshake and RecvBuf locks.
  */
 static SECStatus
 ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 {
@@ -6620,41 +6619,41 @@ ssl3_HandleServerKeyExchange(sslSocket *
 
     sigAndHash.hashAlg = SEC_OID_UNKNOWN;
 
     SSL_TRC(3, ("%d: SSL3[%d]: handle server_key_exchange handshake",
 		SSL_GETPID(), ss->fd));
     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
 
-    if (ss->ssl3.hs.ws != wait_server_key &&
-	ss->ssl3.hs.ws != wait_server_cert) {
-	errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH;
-	desc    = unexpected_message;
-	goto alert_loser;
-    }
-    if (ss->sec.peerCert == NULL) {
-	errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH;
-	desc    = unexpected_message;
-	goto alert_loser;
+    if (ss->ssl3.hs.ws != wait_server_key) {
+        errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH;
+        desc = unexpected_message;
+        goto alert_loser;
     }
 
     isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
     isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
 
     switch (ss->ssl3.hs.kea_def->exchKeyType) {
 
     case kt_rsa: {
 	SECItem          modulus   = {siBuffer, NULL, 0};
 	SECItem          exponent  = {siBuffer, NULL, 0};
 
     	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 (isTLS12) {
 	    rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
 						       &sigAndHash);
 	    if (rv != SECSuccess) {
@@ -6730,36 +6729,43 @@ ssl3_HandleServerKeyExchange(sslSocket *
     	ss->ssl3.hs.ws = wait_cert_request;
     	return SECSuccess;
     }
 
     case kt_dh: {
 	SECItem          dh_p      = {siBuffer, NULL, 0};
 	SECItem          dh_g      = {siBuffer, NULL, 0};
 	SECItem          dh_Ys     = {siBuffer, NULL, 0};
+        unsigned dh_p_bits;
+        unsigned dh_g_bits;
+        unsigned dh_Ys_bits;
 
     	rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length);
     	if (rv != SECSuccess) {
 	    goto loser;		/* malformed. */
 	}
-	if (dh_p.len < 512/8) {
+        dh_p_bits = SECKEY_BigIntegerBitLength(&dh_p);
+        if (dh_p_bits < DH_MIN_P_BITS) {
 	    errCode = SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY;
 	    goto alert_loser;
 	}
     	rv = ssl3_ConsumeHandshakeVariable(ss, &dh_g, 2, &b, &length);
     	if (rv != SECSuccess) {
 	    goto loser;		/* malformed. */
 	}
-	if (dh_g.len > dh_p.len || !ssl3_BigIntGreaterThanOne(&dh_g))
+        /* Abort if dh_g is 0, 1, or obviously too big. */
+        dh_g_bits = SECKEY_BigIntegerBitLength(&dh_g);
+        if (dh_g_bits > dh_p_bits || dh_g_bits <= 1)
 	    goto alert_loser;
     	rv = ssl3_ConsumeHandshakeVariable(ss, &dh_Ys, 2, &b, &length);
     	if (rv != SECSuccess) {
 	    goto loser;		/* malformed. */
 	}
-	if (dh_Ys.len > dh_p.len || !ssl3_BigIntGreaterThanOne(&dh_Ys))
+        dh_Ys_bits = SECKEY_BigIntegerBitLength(&dh_Ys);
+        if (dh_Ys_bits > dh_p_bits || dh_Ys_bits <= 1)
 	    goto alert_loser;
 	if (isTLS12) {
 	    rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
 						       &sigAndHash);
 	    if (rv != SECSuccess) {
 		goto loser;	/* malformed or unsupported. */
 	    }
 	    rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
@@ -6856,17 +6862,16 @@ loser:
     PORT_SetError( errCode );
     return SECFailure;
 
 no_memory:	/* no-memory error has already been set. */
     ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
     return SECFailure;
 }
 
-
 /*
  * Returns the TLS signature algorithm for the client authentication key and
  * whether it is an RSA or DSA key that may be able to sign only SHA-1 hashes.
  */
 static SECStatus
 ssl3_ExtractClientKeyInfo(sslSocket *ss,
 			  TLSSignatureAlgorithm *sigAlg,
 			  PRBool *preferSha1)
@@ -6984,21 +6989,20 @@ ssl3_HandleCertificateRequest(sslSocket 
     SECItem              algorithms  = {siBuffer, NULL, 0};
     CERTDistNames        ca_list;
 
     SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_request handshake",
 		SSL_GETPID(), ss->fd));
     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
 
-    if (ss->ssl3.hs.ws != wait_cert_request &&
-    	ss->ssl3.hs.ws != wait_server_key) {
-	desc    = unexpected_message;
-	errCode = SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST;
-	goto alert_loser;
+    if (ss->ssl3.hs.ws != wait_cert_request) {
+        desc = unexpected_message;
+        errCode = SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST;
+        goto alert_loser;
     }
 
     PORT_Assert(ss->ssl3.clientCertChain == NULL);
     PORT_Assert(ss->ssl3.clientCertificate == NULL);
     PORT_Assert(ss->ssl3.clientPrivateKey == NULL);
 
     isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
     isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
@@ -7237,19 +7241,18 @@ ssl3_HandleServerHelloDone(sslSocket *ss
     SECStatus     rv;
     SSL3WaitState ws          = ss->ssl3.hs.ws;
 
     SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello_done handshake",
 		SSL_GETPID(), ss->fd));
     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
 
+    /* Skipping CertificateRequest is always permitted. */
     if (ws != wait_hello_done  &&
-        ws != wait_server_cert &&
-	ws != wait_server_key  &&
 	ws != wait_cert_request) {
 	SSL3_SendAlert(ss, alert_fatal, unexpected_message);
 	PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE);
 	return SECFailure;
     }
 
     rv = ssl3_SendClientSecondRound(ss);
 
@@ -7575,24 +7578,21 @@ ssl3_SendServerHelloSequence(sslSocket *
 		return rv;	/* err code was set. */
 	    }
 	} else {
 #ifndef HACKED_EXPORT_SERVER
 	    PORT_SetError(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED);
 	    return rv;
 #endif
 	}
-#ifndef NSS_DISABLE_ECC
-    } else if ((kea_def->kea == kea_ecdhe_rsa) ||
-	       (kea_def->kea == kea_ecdhe_ecdsa)) {
-	rv = ssl3_SendServerKeyExchange(ss);
-	if (rv != SECSuccess) {
-	    return rv;	/* err code was set. */
-	}
-#endif /* NSS_DISABLE_ECC */
+    } else 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);
 	if (rv != SECSuccess) {
 	    return rv;		/* err code is set. */
 	}
     }
@@ -7634,16 +7634,31 @@ ssl3_HandleClientHello(sslSocket *ss, SS
 
     SSL_TRC(3, ("%d: SSL3[%d]: handle client_hello handshake",
     	SSL_GETPID(), ss->fd));
 
     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert( ss->ssl3.initialized );
 
+    if (!ss->sec.isServer ||
+        (ss->ssl3.hs.ws != wait_client_hello &&
+         ss->ssl3.hs.ws != idle_handshake)) {
+        desc = unexpected_message;
+        errCode = SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO;
+        goto alert_loser;
+    }
+    if (ss->ssl3.hs.ws == idle_handshake &&
+        ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
+        desc = no_renegotiation;
+        level = alert_warning;
+        errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
+        goto alert_loser;
+    }
+
     /* Get peer name of client */
     rv = ssl_GetPeerInfo(ss);
     if (rv != SECSuccess) {
 	return rv;		/* error code is set. */
     }
 
     /* Clearing the handshake pointers so that ssl_Do1stHandshake won't
      * call ssl2_HandleMessage.
@@ -7660,30 +7675,16 @@ ssl3_HandleClientHello(sslSocket *ss, SS
     }
 
     /* We might be starting session renegotiation in which case we should
      * clear previous state.
      */
     PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData));
     ss->statelessResume = PR_FALSE;
 
-    if ((ss->ssl3.hs.ws != wait_client_hello) &&
-	(ss->ssl3.hs.ws != idle_handshake)) {
-	desc    = unexpected_message;
-	errCode = SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO;
-	goto alert_loser;
-    }
-    if (ss->ssl3.hs.ws == idle_handshake  &&
-        ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
-	desc    = no_renegotiation;
-	level   = alert_warning;
-	errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
-	goto alert_loser;
-    }
-
     if (IS_DTLS(ss)) {
 	dtls_RehandshakeCleanup(ss);
     }
 
     tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
     if (tmp < 0)
 	goto loser;		/* malformed, alert already sent */
 
@@ -8863,16 +8864,20 @@ ssl3_SendServerKeyExchange(sslSocket *ss
 	    /* 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) {
@@ -9039,17 +9044,17 @@ ssl3_HandleCertificateVerify(sslSocket *
     SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_verify handshake",
 		SSL_GETPID(), ss->fd));
     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
 
     isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
     isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
 
-    if (ss->ssl3.hs.ws != wait_cert_verify || ss->sec.peerCert == NULL) {
+    if (ss->ssl3.hs.ws != wait_cert_verify) {
 	desc    = unexpected_message;
 	errCode = SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY;
 	goto alert_loser;
     }
 
     if (isTLS12) {
 	rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
 						   &sigAndHash);
@@ -9825,21 +9830,21 @@ ssl3_HandleCertificate(sslSocket *ss, SS
     int              errCode    = SSL_ERROR_RX_MALFORMED_CERTIFICATE;
     SECItem          certItem;
 
     SSL_TRC(3, ("%d: SSL3[%d]: handle certificate handshake",
 		SSL_GETPID(), ss->fd));
     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
 
-    if ((ss->ssl3.hs.ws != wait_server_cert) &&
-	(ss->ssl3.hs.ws != wait_client_cert)) {
-	desc    = unexpected_message;
-	errCode = SSL_ERROR_RX_UNEXPECTED_CERTIFICATE;
-	goto alert_loser;
+    if ((isServer && ss->ssl3.hs.ws != wait_client_cert) ||
+        (!isServer && ss->ssl3.hs.ws != wait_server_cert)) {
+        desc = unexpected_message;
+        errCode = SSL_ERROR_RX_UNEXPECTED_CERTIFICATE;
+        goto alert_loser;
     }
 
     if (ss->sec.peerCert != NULL) {
 	if (ss->sec.peerKey) {
 	    SECKEY_DestroyPublicKey(ss->sec.peerKey);
 	    ss->sec.peerKey = NULL;
 	}
 	CERT_DestroyCertificate(ss->sec.peerCert);
@@ -10035,59 +10040,47 @@ ssl3_AuthCertificate(sslSocket *ss)
 	/* set the server authentication and key exchange types and sizes
 	** from the value in the cert.  If the key exchange key is different,
 	** it will get fixed when we handle the server key exchange message.
 	*/
 	SECKEYPublicKey * pubKey  = CERT_ExtractPublicKey(cert);
 	ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType;
 	ss->sec.keaType       = ss->ssl3.hs.kea_def->exchKeyType;
 	if (pubKey) {
+	    KeyType pubKeyType;
 	    ss->sec.keaKeyBits = ss->sec.authKeyBits =
 		SECKEY_PublicKeyStrengthInBits(pubKey);
-#ifndef NSS_DISABLE_ECC
-	    if (ss->sec.keaType == kt_ecdh) {
-		/* Get authKeyBits from signing key.
-		 * XXX The code below uses a quick approximation of
-		 * key size based on cert->signatureWrap.signature.data
-		 * (which contains the DER encoded signature). The field
-		 * cert->signatureWrap.signature.len contains the
-		 * length of the encoded signature in bits.
-		 */
-		if (ss->ssl3.hs.kea_def->kea == kea_ecdh_ecdsa) {
-		    ss->sec.authKeyBits = 
-			cert->signatureWrap.signature.data[3]*8;
-		    if (cert->signatureWrap.signature.data[4] == 0x00)
-			    ss->sec.authKeyBits -= 8;
-		    /* 
-		     * XXX: if cert is not signed by ecdsa we should
-		     * destroy pubKey and goto bad_cert
-		     */
-		} else if (ss->ssl3.hs.kea_def->kea == kea_ecdh_rsa) {
-		    ss->sec.authKeyBits = cert->signatureWrap.signature.len;
-		    /* 
-		     * XXX: if cert is not signed by rsa we should
-		     * destroy pubKey and goto bad_cert
-		     */
-		}
-	    }
-#endif /* NSS_DISABLE_ECC */
+            pubKeyType = SECKEY_GetPublicKeyType(pubKey);
+            /* Too small: not good enough. Send a fatal alert. */
+            /* TODO: Use 1023 for RSA because a higher RSA_MIN_MODULUS_BITS
+             * breaks export cipher suites, not 1024 to be conservative; when
+             * export removed, increase RSA_MIN_MODULUS_BITS and use that. */
+            /* We aren't checking EC here on the understanding that we only
+             * support curves we like, a decision that might need revisiting. */
+            if (((pubKeyType == rsaKey || pubKeyType == rsaPssKey ||
+                  pubKeyType == rsaOaepKey) && ss->sec.authKeyBits < 1023) ||
+                (pubKeyType == dsaKey && ss->sec.authKeyBits < DSA_MIN_P_BITS) ||
+                (pubKeyType == dhKey && ss->sec.authKeyBits < DH_MIN_P_BITS)) {
+                PORT_SetError(SSL_ERROR_WEAK_SERVER_CERT_KEY);
+                (void)SSL3_SendAlert(ss, alert_fatal,
+                                     ss->version >= SSL_LIBRARY_VERSION_TLS_1_0
+                                     ? insufficient_security
+                                     : illegal_parameter);
+                SECKEY_DestroyPublicKey(pubKey);
+                return SECFailure;
+            }
 	    SECKEY_DestroyPublicKey(pubKey); 
 	    pubKey = NULL;
     	}
 
-	ss->ssl3.hs.ws = wait_cert_request; /* disallow server_key_exchange */
-	if (ss->ssl3.hs.kea_def->is_limited ||
-	    /* XXX OR server cert is signing only. */
-#ifndef NSS_DISABLE_ECC
-	    ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa ||
-	    ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa ||
-#endif /* NSS_DISABLE_ECC */
-	    ss->ssl3.hs.kea_def->exchKeyType == kt_dh) {
-	    ss->ssl3.hs.ws = wait_server_key; /* allow server_key_exchange */
-	}
+        if (ss->ssl3.hs.kea_def->ephemeral) {
+            ss->ssl3.hs.ws = wait_server_key; /* require server_key_exchange */
+        } else {
+            ss->ssl3.hs.ws = wait_cert_request; /* disallow server_key_exchange */
+        }
     } else {
 	ss->ssl3.hs.ws = wait_client_key;
     }
 
     PORT_Assert(rv == SECSuccess);
     if (rv != SECSuccess) {
 	errCode = SEC_ERROR_LIBRARY_FAILURE;
 	rv = SECFailure;
--- a/security/nss/lib/ssl/ssl3ecc.c
+++ b/security/nss/lib/ssl/ssl3ecc.c
@@ -1,8 +1,9 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /*
  * SSL3 Protocol
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* ECC code moved here from ssl3con.c */
@@ -1179,32 +1180,31 @@ ssl3_SendSupportedPointFormatsXtn(
 SECStatus
 ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss, PRUint16 ex_type,
                                     SECItem *data)
 {
     int i;
 
     if (data->len < 2 || data->len > 255 || !data->data ||
         data->len != (unsigned int)data->data[0] + 1) {
-        /* malformed */
-        goto loser;
+        return ssl3_DecodeError(ss);
     }
     for (i = data->len; --i > 0; ) {
         if (data->data[i] == 0) {
             /* indicate that we should send a reply */
             SECStatus rv;
             rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
                               &ssl3_SendSupportedPointFormatsXtn);
             return rv;
         }
     }
-loser:
+
     /* evil client doesn't support uncompressed */
     ssl3_DisableECCSuites(ss, ecSuites);
-    return SECFailure;
+    return SECSuccess;
 }
 
 
 #define SSL3_GET_SERVER_PUBLICKEY(sock, type) \
     (ss->serverCerts[type].serverKeyPair ? \
     ss->serverCerts[type].serverKeyPair->pubKey : NULL)
 
 /* Extract the TLS curve name for the public key in our EC server cert. */
@@ -1215,63 +1215,66 @@ ECName ssl3_GetSvrCertCurveName(sslSocke
 
     srvPublicKey = SSL3_GET_SERVER_PUBLICKEY(ss, kt_ecdh);
     if (srvPublicKey) {
         ec_curve = params2ecName(&srvPublicKey->u.ec.DEREncodedParams);
     }
     return ec_curve;
 }
 
-/* Ensure that the curve in our server cert is one of the ones suppored
+/* Ensure that the curve in our server cert is one of the ones supported
  * by the remote client, and disable all ECC cipher suites if not.
  */
 SECStatus
 ssl3_HandleSupportedCurvesXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
 {
     PRInt32  list_len;
     PRUint32 peerCurves   = 0;
     PRUint32 mutualCurves = 0;
     PRUint16 svrCertCurveName;
 
-    if (!data->data || data->len < 4 || data->len > 65535)
-        goto loser;
+    if (!data->data || data->len < 4) {
+        (void)ssl3_DecodeError(ss);
+        return SECFailure;
+    }
+
     /* get the length of elliptic_curve_list */
     list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
     if (list_len < 0 || data->len != list_len || (data->len % 2) != 0) {
-        /* malformed */
-        goto loser;
+        (void)ssl3_DecodeError(ss);
+        return SECFailure;
     }
     /* build bit vector of peer's supported curve names */
     while (data->len) {
-        PRInt32  curve_name =
-                 ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
+        PRInt32 curve_name =
+                ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
+        if (curve_name < 0) {
+            return SECFailure; /* fatal alert already sent */
+        }
         if (curve_name > ec_noName && curve_name < ec_pastLastName) {
             peerCurves |= (1U << curve_name);
         }
     }
     /* What curves do we support in common? */
     mutualCurves = ss->ssl3.hs.negotiatedECCurves &= peerCurves;
-    if (!mutualCurves) { /* no mutually supported EC Curves */
-        goto loser;
+    if (!mutualCurves) {
+        /* no mutually supported EC Curves, disable ECC */
+        ssl3_DisableECCSuites(ss, ecSuites);
+        return SECSuccess;
     }
 
     /* if our ECC cert doesn't use one of these supported curves,
      * disable ECC cipher suites that require an ECC cert.
      */
     svrCertCurveName = ssl3_GetSvrCertCurveName(ss);
     if (svrCertCurveName != ec_noName &&
         (mutualCurves & (1U << svrCertCurveName)) != 0) {
         return SECSuccess;
     }
     /* Our EC cert doesn't contain a mutually supported curve.
      * Disable all ECC cipher suites that require an EC cert
      */
     ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
     ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites);
-    return SECFailure;
-
-loser:
-    /* no common curve supported */
-    ssl3_DisableECCSuites(ss, ecSuites);
-    return SECFailure;
+    return SECSuccess;
 }
 
 #endif /* NSS_DISABLE_ECC */
--- a/security/nss/lib/ssl/ssl3ext.c
+++ b/security/nss/lib/ssl/ssl3ext.c
@@ -1,8 +1,9 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /*
  * SSL3 Protocol
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* TLS extension code moved here from ssl3ecc.c */
@@ -59,20 +60,24 @@ static SECStatus ssl3_ServerHandleNextPr
 static SECStatus ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type,
                                               SECItem *data);
 static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
                                                PRUint32 maxBytes);
 static PRInt32 ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append,
                                           PRUint32 maxBytes);
 static PRInt32 ssl3_ServerSendAppProtoXtn(sslSocket *ss, PRBool append,
                                           PRUint32 maxBytes);
-static PRInt32 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append,
-    PRUint32 maxBytes);
-static SECStatus ssl3_HandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type,
-    SECItem *data);
+static PRInt32 ssl3_ClientSendUseSRTPXtn(sslSocket *ss, PRBool append,
+                                         PRUint32 maxBytes);
+static PRInt32 ssl3_ServerSendUseSRTPXtn(sslSocket *ss, PRBool append,
+                                         PRUint32 maxBytes);
+static SECStatus ssl3_ClientHandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type,
+                                             SECItem *data);
+static SECStatus ssl3_ServerHandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type,
+                                             SECItem *data);
 static PRInt32 ssl3_ServerSendStatusRequestXtn(sslSocket * ss,
     PRBool append, PRUint32 maxBytes);
 static SECStatus ssl3_ServerHandleStatusRequestXtn(sslSocket *ss,
     PRUint16 ex_type, SECItem *data);
 static SECStatus ssl3_ClientHandleStatusRequestXtn(sslSocket *ss,
                                                    PRUint16 ex_type,
                                                    SECItem *data);
 static PRInt32 ssl3_ClientSendStatusRequestXtn(sslSocket * ss, PRBool append,
@@ -242,33 +247,33 @@ static const ssl3HelloExtensionHandler c
 #ifndef NSS_DISABLE_ECC
     { ssl_elliptic_curves_xtn,    &ssl3_HandleSupportedCurvesXtn },
     { ssl_ec_point_formats_xtn,   &ssl3_HandleSupportedPointFormatsXtn },
 #endif
     { 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_HandleUseSRTPXtn },
+    { ssl_use_srtp_xtn,           &ssl3_ServerHandleUseSRTPXtn },
     { ssl_cert_status_xtn,        &ssl3_ServerHandleStatusRequestXtn },
     { ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn },
     { ssl_tls13_draft_version_xtn, &ssl3_ServerHandleDraftVersionXtn },
     { -1, NULL }
 };
 
 /* These two tables are used by the client, to handle server hello
  * extensions. */
 static const ssl3HelloExtensionHandler 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_HandleUseSRTPXtn },
+    { ssl_use_srtp_xtn,           &ssl3_ClientHandleUseSRTPXtn },
     { ssl_cert_status_xtn,        &ssl3_ClientHandleStatusRequestXtn },
     { -1, NULL }
 };
 
 static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = {
     { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
     { -1, NULL }
 };
@@ -285,17 +290,17 @@ ssl3HelloExtensionSender clientHelloSend
     { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn },
 #ifndef NSS_DISABLE_ECC
     { ssl_elliptic_curves_xtn,    &ssl3_SendSupportedCurvesXtn },
     { ssl_ec_point_formats_xtn,   &ssl3_SendSupportedPointFormatsXtn },
 #endif
     { ssl_session_ticket_xtn,     &ssl3_SendSessionTicketXtn },
     { ssl_next_proto_nego_xtn,    &ssl3_ClientSendNextProtoNegoXtn },
     { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn },
-    { ssl_use_srtp_xtn,           &ssl3_SendUseSRTPXtn },
+    { ssl_use_srtp_xtn,           &ssl3_ClientSendUseSRTPXtn },
     { ssl_cert_status_xtn,        &ssl3_ClientSendStatusRequestXtn },
     { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
     { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn },
     /* any extra entries will appear as { 0, NULL }    */
 };
 
 static const
 ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] = {
@@ -393,101 +398,100 @@ ssl3_HandleServerNameXtn(sslSocket * ss,
 {
     SECItem *names = NULL;
     PRUint32 listCount = 0, namesPos = 0, i;
     TLSExtensionData *xtnData = &ss->xtnData;
     SECItem  ldata;
     PRInt32  listLenBytes = 0;
 
     if (!ss->sec.isServer) {
-        /* Verify extension_data is empty. */
-        if (data->data || data->len ||
-            !ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn)) {
-            /* malformed or was not initiated by the client.*/
-            return SECFailure;
-        }
-        return SECSuccess;
+        return SECSuccess; /* ignore extension */
     }
 
     /* Server side - consume client data and register server sender. */
     /* do not parse the data if don't have user extension handling function. */
     if (!ss->sniSocketConfig) {
         return SECSuccess;
     }
     /* length of server_name_list */
     listLenBytes = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
-    if (listLenBytes == 0 || listLenBytes != data->len) {
+    if (listLenBytes < 0 || listLenBytes != data->len) {
+        (void)ssl3_DecodeError(ss);
         return SECFailure;
     }
+    if (listLenBytes == 0) {
+        return SECSuccess; /* ignore an empty extension */
+    }
     ldata = *data;
     /* Calculate the size of the array.*/
     while (listLenBytes > 0) {
         SECItem litem;
         SECStatus rv;
-        PRInt32  type;
-        /* Name Type (sni_host_name) */
+        PRInt32 type;
+        /* Skip Name Type (sni_host_name); checks are on the second pass */
         type = ssl3_ConsumeHandshakeNumber(ss, 1, &ldata.data, &ldata.len);
-        if (!ldata.len) {
+        if (type < 0) { /* i.e., SECFailure cast to PRint32 */
             return SECFailure;
         }
         rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 2, &ldata.data, &ldata.len);
         if (rv != SECSuccess) {
-            return SECFailure;
+            return rv;
         }
-        /* Adjust total length for cunsumed item, item len and type.*/
+        /* Adjust total length for consumed item, item len and type.*/
         listLenBytes -= litem.len + 3;
         if (listLenBytes > 0 && !ldata.len) {
+            (void)ssl3_DecodeError(ss);
             return SECFailure;
         }
         listCount += 1;
     }
     if (!listCount) {
-        return SECFailure;
+        return SECFailure;  /* nothing we can act on */
     }
     names = PORT_ZNewArray(SECItem, listCount);
     if (!names) {
         return SECFailure;
     }
     for (i = 0;i < listCount;i++) {
         int j;
         PRInt32  type;
         SECStatus rv;
         PRBool nametypePresent = PR_FALSE;
         /* Name Type (sni_host_name) */
         type = ssl3_ConsumeHandshakeNumber(ss, 1, &data->data, &data->len);
         /* Check if we have such type in the list */
         for (j = 0;j < listCount && names[j].data;j++) {
+            /* TODO bug 998524: .type is not assigned a value */
             if (names[j].type == type) {
                 nametypePresent = PR_TRUE;
                 break;
             }
         }
         /* HostName (length and value) */
         rv = ssl3_ConsumeHandshakeVariable(ss, &names[namesPos], 2,
                                            &data->data, &data->len);
         if (rv != SECSuccess) {
-            goto loser;
+            PORT_Assert(0);
+            PORT_Free(names);
+            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+            return rv;
         }
         if (nametypePresent == PR_FALSE) {
             namesPos += 1;
         }
     }
     /* Free old and set the new data. */
     if (xtnData->sniNameArr) {
         PORT_Free(ss->xtnData.sniNameArr);
     }
     xtnData->sniNameArr = names;
     xtnData->sniNameArrSize = namesPos;
     xtnData->negotiated[xtnData->numNegotiated++] = ssl_server_name_xtn;
 
     return SECSuccess;
-
-loser:
-    PORT_Free(names);
-    return SECFailure;
 }
 
 /* Called by both clients and servers.
  * Clients sends a filled in session ticket if one is available, and otherwise
  * sends an empty ticket.  Servers always send empty tickets.
  */
 PRInt32
 ssl3_SendSessionTicketXtn(
@@ -598,109 +602,114 @@ ssl3_ValidateNextProtoNego(const unsigne
     unsigned int offset = 0;
 
     while (offset < length) {
         unsigned int newOffset = offset + 1 + (unsigned int) data[offset];
         /* Reject embedded nulls to protect against buggy applications that
          * store protocol identifiers in null-terminated strings.
          */
         if (newOffset > length || data[offset] == 0) {
-            PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
             return SECFailure;
         }
         offset = newOffset;
     }
 
-    if (offset > length) {
-        PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-        return SECFailure;
-    }
-
     return SECSuccess;
 }
 
 /* protocol selection handler for ALPN (server side) and NPN (client side) */
 static SECStatus
 ssl3_SelectAppProtocol(sslSocket *ss, PRUint16 ex_type, SECItem *data)
 {
     SECStatus rv;
     unsigned char resultBuffer[255];
     SECItem result = { siBuffer, resultBuffer, 0 };
 
     rv = ssl3_ValidateNextProtoNego(data->data, data->len);
-    if (rv != SECSuccess)
+    if (rv != SECSuccess) {
+        (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
+        PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
         return rv;
+    }
 
     PORT_Assert(ss->nextProtoCallback);
     rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd, data->data, data->len,
-                               result.data, &result.len, sizeof resultBuffer);
-    if (rv != SECSuccess)
-        return rv;
-    /* If the callback wrote more than allowed to |result| it has corrupted our
-     * stack. */
-    if (result.len > sizeof resultBuffer) {
-        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+                               result.data, &result.len, sizeof(resultBuffer));
+    if (rv != SECSuccess) {
+        /* Expect callback to call PORT_SetError() */
+        (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
         return SECFailure;
     }
 
+    /* If the callback wrote more than allowed to |result| it has corrupted our
+     * stack. */
+    if (result.len > sizeof(resultBuffer)) {
+        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+        /* TODO: crash */
+        return SECFailure;
+    }
+
+    SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
+
     if (ex_type == ssl_app_layer_protocol_xtn &&
         ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NEGOTIATED) {
-        /* The callback might say OK, but then it's picked a default.
-         * That's OK for NPN, but not ALPN. */
-        SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
+        /* The callback might say OK, but then it picks a default value - one
+         * that was not listed.  That's OK for NPN, but not ALPN. */
+        (void)SSL3_SendAlert(ss, alert_fatal, no_application_protocol);
         PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL);
-        (void)SSL3_SendAlert(ss, alert_fatal, no_application_protocol);
         return SECFailure;
     }
 
     ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
-
-    SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
     return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result);
 }
 
 /* handle an incoming ALPN extension at the server */
 static SECStatus
 ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
 {
     int count;
     SECStatus rv;
 
     /* We expressly don't want to allow ALPN on renegotiation,
      * despite it being permitted by the spec. */
     if (ss->firstHsDone || data->len == 0) {
         /* Clients MUST send a non-empty ALPN extension. */
+        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
         PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
         return SECFailure;
     }
 
-    /* unlike NPN, ALPN has extra redundant length information so that
-     * the extension is the same in both ClientHello and ServerHello */
+    /* Unlike NPN, ALPN has extra redundant length information so that
+     * the extension is the same in both ClientHello and ServerHello. */
     count = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
-    if (count < 0) {
-        return SECFailure; /* fatal alert was sent */
-    }
     if (count != data->len) {
-        return ssl3_DecodeError(ss);
+        (void)ssl3_DecodeError(ss);
+        return SECFailure;
     }
 
     if (!ss->nextProtoCallback) {
         /* we're not configured for it */
         return SECSuccess;
     }
 
     rv = ssl3_SelectAppProtocol(ss, ex_type, data);
     if (rv != SECSuccess) {
       return rv;
     }
 
     /* prepare to send back a response, if we negotiated */
     if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NEGOTIATED) {
-        return ssl3_RegisterServerHelloExtensionSender(
+        rv = ssl3_RegisterServerHelloExtensionSender(
             ss, ex_type, ssl3_ServerSendAppProtoXtn);
+        if (rv != SECSuccess) {
+