Bug 1020695: Update Mozilla to use NSS 3.16.2 Beta 3. Includes fixes for
authorWan-Teh Chang <wtc@google.com>
Wed, 04 Jun 2014 21:03:47 -0700
changeset 207049 8406a2b981c58de5a466dbb482a4f4c5ebd70f11
parent 207048 e7b0ccbaa5a45a93ed461af811a0bf5fe2ef9818
child 207050 8137176a31734f39f120dab27b7ddad578c8deab
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1020695, 1013088, 996237, 970539, 1016567, 485732, 334013, 959864, 1016836, 1016811, 1018536, 996250, 1009227, 963150
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1020695: Update Mozilla to use NSS 3.16.2 Beta 3. Includes fixes for bug 1013088, bug 996237, bug 970539, bug 1016567, bug 485732, bug 334013, bug 959864, bug 1016836, bug 1016811, bug 1018536, bug 996250, bug 1009227, bug 963150.
security/nss/TAG-INFO
security/nss/cmd/btoa/btoa.c
security/nss/cmd/certutil/certext.c
security/nss/cmd/certutil/certutil.c
security/nss/cmd/certutil/certutil.h
security/nss/cmd/httpserv/httpserv.c
security/nss/cmd/lib/secutil.c
security/nss/cmd/lib/secutil.h
security/nss/cmd/pp/pp.c
security/nss/coreconf/coreconf.dep
security/nss/lib/certdb/alg1485.c
security/nss/lib/certdb/genname.c
security/nss/lib/certdb/genname.h
security/nss/lib/cryptohi/cryptohi.h
security/nss/lib/cryptohi/secsign.c
security/nss/lib/freebl/rsa.c
security/nss/lib/nss/nss.def
security/nss/lib/pk11wrap/pk11cert.c
security/nss/lib/pk11wrap/pk11load.c
security/nss/lib/softoken/legacydb/pcertdb.c
security/nss/lib/softoken/pkcs11.c
security/nss/lib/ssl/SSLerrs.h
security/nss/lib/ssl/dtlscon.c
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3ext.c
security/nss/lib/ssl/ssl3prot.h
security/nss/lib/ssl/sslerr.h
security/nss/lib/ssl/sslproto.h
security/nss/lib/ssl/sslsock.c
security/nss/tests/cert/cert.sh
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-NSS_3_16_2_BETA2
+NSS_3_16_2_BETA3
--- a/security/nss/cmd/btoa/btoa.c
+++ b/security/nss/cmd/btoa/btoa.c
@@ -87,36 +87,41 @@ static void Usage(char *progName)
 {
     fprintf(stderr,
 	    "Usage: %s [-i input] [-o output]\n",
 	    progName);
     fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
 	    "-i input");
     fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
 	    "-o output");
+    fprintf(stderr, "%-20s Wrap output in BEGIN/END lines and the given suffix\n",
+	    "-w suffix");
+    fprintf(stderr, "%-20s (use \"c\" as a shortcut for suffix CERTIFICATE)\n",
+	    "");
     exit(-1);
 }
 
 int main(int argc, char **argv)
 {
     char *progName;
     SECStatus rv;
     FILE *inFile, *outFile;
     PLOptState *optstate;
     PLOptStatus status;
+    char *suffix = NULL;
 
     inFile = 0;
     outFile = 0;
     progName = strrchr(argv[0], '/');
     if (!progName)
 	progName = strrchr(argv[0], '\\');
     progName = progName ? progName+1 : argv[0];
 
     /* Parse command line arguments */
-    optstate = PL_CreateOptState(argc, argv, "i:o:");
+    optstate = PL_CreateOptState(argc, argv, "i:o:w:");
     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
 	switch (optstate->option) {
 	  default:
 	    Usage(progName);
 	    break;
 
 	  case 'i':
 	    inFile = fopen(optstate->value, "rb");
@@ -130,16 +135,23 @@ int main(int argc, char **argv)
 	  case 'o':
 	    outFile = fopen(optstate->value, "wb");
 	    if (!outFile) {
 		fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
 			progName, optstate->value);
 		return -1;
 	    }
 	    break;
+	
+	  case 'w':
+	    if (!strcmp(optstate->value, "c"))
+		suffix = strdup("CERTIFICATE");
+	    else
+		suffix = strdup(optstate->value);
+	    break;
 	}
     }
     if (status == PL_OPT_BAD)
 	Usage(progName);
     if (!inFile) {
 #if defined(WIN32)
 	/* If we're going to read binary data from stdin, we must put stdin
 	** into O_BINARY mode or else incoming \r\n's will become \n's.
@@ -166,16 +178,22 @@ int main(int argc, char **argv)
 	    fprintf(stderr,
 	    "%s: Cannot change stdout to binary mode. Use -o option instead.\n",
 	            progName);
 	    return smrv;
 	}
 #endif
     	outFile = stdout;
     }
+    if (suffix) {
+	fprintf(outFile, "-----BEGIN %s-----\n", suffix);
+    }
     rv = encode_file(outFile, inFile);
     if (rv != SECSuccess) {
 	fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
 		progName, PORT_GetError(), errno);
 	return -1;
     }
+    if (suffix) {
+	fprintf(outFile, "-----END %s-----\n", suffix);
+    }
     return 0;
 }
--- a/security/nss/cmd/certutil/certext.c
+++ b/security/nss/cmd/certutil/certext.c
@@ -22,16 +22,18 @@
 #if defined(XP_UNIX)
 #include <unistd.h>
 #endif
 
 #include "cert.h"
 #include "xconst.h"
 #include "prprf.h"
 #include "certutil.h"
+#include "genname.h"
+#include "prnetdb.h"
 
 #define GEN_BREAK(e) rv=e; break;
 
 static char *
 Gets_s(char *buff, size_t size) {
     char *str;
     
     if (buff == NULL || size < 1) {
@@ -660,63 +662,223 @@ AddNscpCertType (void *extHandle, const 
     bitStringValue.len = 1;
 
     return (CERT_EncodeAndAddBitStrExtension
             (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
              isCriticalExt));
 
 }
 
+SECStatus
+GetOidFromString(PLArenaPool *arena, SECItem *to,
+                 const char *from, size_t fromLen)
+{
+    SECStatus rv;
+    SECOidTag tag;
+    SECOidData *coid;
+
+    /* try dotted form first */
+    rv = SEC_StringToOID(arena, to, from, fromLen);
+    if (rv == SECSuccess) {
+        return rv;
+    }
+
+    /* Check to see if it matches a name in our oid table.
+     * SECOID_FindOIDByTag returns NULL if tag is out of bounds.
+     */
+    tag = SEC_OID_UNKNOWN;
+    coid = SECOID_FindOIDByTag(tag);
+    for ( ; coid; coid = SECOID_FindOIDByTag(++tag)) {
+        if (PORT_Strncasecmp(from, coid->desc, fromLen) == 0) {
+            break;
+        }
+    }
+    if (coid == NULL) {
+        /* none found */
+        return SECFailure;
+    }
+    return SECITEM_CopyItem(arena, to, &coid->oid);
+}
+
 static SECStatus 
 AddSubjectAltNames(PLArenaPool *arena, CERTGeneralName **existingListp,
-                   const char *names, CERTGeneralNameType type)
+                   const char *constNames, CERTGeneralNameType type)
 {
     CERTGeneralName *nameList = NULL;
     CERTGeneralName *current = NULL;
     PRCList *prev = NULL;
-    const char *cp;
-    char *tbuf;
+    char *cp, *nextName = NULL;
     SECStatus rv = SECSuccess;
+    PRBool readTypeFromName = (PRBool) (type == 0);
+    char *names = NULL;
+    
+    if (constNames)
+        names = PORT_Strdup(constNames);
+
+    if (names == NULL) {
+        return SECFailure;
+    }
 
     /*
      * walk down the comma separated list of names. NOTE: there is
      * no sanity checks to see if the email address look like
      * email addresses.
+     *
+     * Each name may optionally be prefixed with a type: string.
+     * If it isn't, the type from the previous name will be used.
+     * If there wasn't a previous name yet, the type given
+     * as a parameter to this function will be used.
+     * If the type value is zero (undefined), we'll fail.
      */
-    for (cp=names; cp; cp = PORT_Strchr(cp,',')) {
+    for (cp=names; cp; cp=nextName) {
         int len;
-        char *end;
+        char *oidString;
+        char *nextComma;
+        CERTName *name;
+        PRStatus status;
+        unsigned char *data;
+        PRNetAddr addr;
 
+        nextName = NULL;
         if (*cp == ',') {
             cp++;
         }
-        end = PORT_Strchr(cp,',');
-        len = end ? end-cp : PORT_Strlen(cp);
-        if (len <= 0) {
+        nextComma = PORT_Strchr(cp, ',');
+        if (nextComma) {
+            *nextComma = 0;
+            nextName = nextComma+1;
+        }
+        if ((*cp) == 0) {
             continue;
         }
-        tbuf = PORT_ArenaAlloc(arena,len+1);
-        PORT_Memcpy(tbuf,cp,len);
-        tbuf[len] = 0;
-        current = (CERTGeneralName *) PORT_ZAlloc(sizeof(CERTGeneralName));
+        if (readTypeFromName) {
+            char *save=cp;
+            /* Because we already replaced nextComma with end-of-string,
+             * a found colon belongs to the current name */
+            cp = PORT_Strchr(cp, ':');
+            if (cp) {
+                *cp = 0;
+                cp++;
+                type = CERT_GetGeneralNameTypeFromString(save);
+                if (*cp == 0) {
+                    continue;
+                }
+            } else {
+                if (type == 0) {
+                    /* no type known yet */
+                    rv = SECFailure;
+                    break;
+                }
+                cp = save;
+            }
+        }
+
+        current = PORT_ArenaZNew(arena, CERTGeneralName);
         if (!current) {
             rv = SECFailure;
             break;
         }
+
+        current->type = type;
+        switch (type) {
+        /* string types */
+        case certRFC822Name:
+        case certDNSName:
+        case certURI:
+            current->name.other.data =
+                (unsigned char *) PORT_ArenaStrdup(arena,cp);
+            current->name.other.len = PORT_Strlen(cp);
+            break;
+        /* unformated data types */
+        case certX400Address:
+        case certEDIPartyName:
+            /* turn a string into a data and len */
+            rv = SECFailure; /* punt on these for now */
+            fprintf(stderr,"EDI Party Name and X.400 Address not supported\n");
+            break;
+        case certDirectoryName:
+            /* certDirectoryName */
+            name = CERT_AsciiToName(cp);
+            if (name == NULL) {
+                rv = SECFailure;
+                fprintf(stderr, "Invalid Directory Name (\"%s\")\n", cp);
+                break;
+            }
+            rv = CERT_CopyName(arena,&current->name.directoryName,name);
+            CERT_DestroyName(name);
+            break;
+        /* types that require more processing */
+        case certIPAddress:
+            /* convert the string to an ip address */
+            status = PR_StringToNetAddr(cp, &addr);
+            if (status != PR_SUCCESS) {
+                rv = SECFailure;
+                fprintf(stderr, "Invalid IP Address (\"%s\")\n", cp);
+                break;
+            }
+
+            if (PR_NetAddrFamily(&addr) == PR_AF_INET) {
+                len = sizeof(addr.inet.ip);
+                data = (unsigned char *)&addr.inet.ip;
+            } else if (PR_NetAddrFamily(&addr) == PR_AF_INET6) {
+                len = sizeof(addr.ipv6.ip);
+                data = (unsigned char *)&addr.ipv6.ip;
+            } else {
+                fprintf(stderr, "Invalid IP Family\n");
+                rv = SECFailure;
+                break;
+            }
+            current->name.other.data =  PORT_ArenaAlloc(arena, len);
+            if (current->name.other.data == NULL) {
+                rv = SECFailure;
+                break;
+            }
+            current->name.other.len = len;
+            PORT_Memcpy(current->name.other.data,data, len);
+            break;
+        case certRegisterID:
+            rv = GetOidFromString(arena, &current->name.other, cp, strlen(cp));
+            break;
+        case certOtherName:
+            oidString = cp;
+            cp = PORT_Strchr(cp,';');
+            if (cp == NULL) {
+                rv = SECFailure;
+                fprintf(stderr, "missing name in other name\n");
+                break;
+            }
+            *cp++ = 0;
+            current->name.OthName.name.data =
+                (unsigned char *) PORT_ArenaStrdup(arena,cp);
+            if (current->name.OthName.name.data == NULL) {
+                rv = SECFailure;
+                break;
+            }
+            current->name.OthName.name.len = PORT_Strlen(cp);
+            rv = GetOidFromString(arena, &current->name.OthName.oid,
+                                  oidString, strlen(oidString));
+            break;
+        default:
+            rv = SECFailure;
+            fprintf(stderr, "Missing or invalid Subject Alternate Name type\n");
+            break;
+        }
+        if (rv == SECFailure) {
+            break;
+        }
+        
         if (prev) {
             current->l.prev = prev;
             prev->next = &(current->l);
         } else {
             nameList = current;
         }
-        current->type = type;
-        current->name.other.data = (unsigned char *)tbuf;
-        current->name.other.len = PORT_Strlen(tbuf);
         prev = &(current->l);
     }
+    PORT_Free(names);
     /* at this point nameList points to the head of a doubly linked,
      * but not yet circular, list and current points to its tail. */
     if (rv == SECSuccess && nameList) {
         if (*existingListp != NULL) {
             PRCList *existingprev;
             /* add nameList to the end of the existing list */
             existingprev = (*existingListp)->l.prev;
             (*existingListp)->l.prev = &(current->l);
@@ -744,16 +906,22 @@ AddEmailSubjectAlt(PLArenaPool *arena, C
 
 static SECStatus 
 AddDNSSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
                  const char *dnsNames)
 {
     return AddSubjectAltNames(arena, existingListp, dnsNames, certDNSName);
 }
 
+static SECStatus 
+AddGeneralSubjectAlt(PLArenaPool *arena, CERTGeneralName **existingListp,
+                     const char *altNames)
+{
+    return AddSubjectAltNames(arena, existingListp, altNames, 0);
+}
 
 static SECStatus 
 AddBasicConstraint(void *extHandle)
 {
     CERTBasicConstraints basicConstraint;    
     SECStatus rv;
     char buffer[10];
     PRBool yesNoAns;
@@ -1741,22 +1909,83 @@ AddInfoAccess(void *extHandle, PRBool ad
 		 yesNoAns, oidIdent,
 		 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeInfoAccessExtension);
     }
     if (arena)
         PORT_FreeArena(arena, PR_FALSE);
     return (rv);
 }
 
+/* Example of valid input:
+ *     1.2.3.4:critical:/tmp/abc,5.6.7.8:not-critical:/tmp/xyz
+ */
+static SECStatus
+parseNextGenericExt(const char *nextExtension, const char **oid, int *oidLen,
+                    const char **crit, int *critLen,
+                    const char **filename, int *filenameLen,
+                    const char **next)
+{
+    const char *nextColon;
+    const char *nextComma;
+    const char *iter = nextExtension;
+    
+    if (!iter || !*iter)
+        return SECFailure;
+
+    /* Require colons at earlier positions than nextComma (or end of string ) */
+    nextComma = strchr(iter, ',');
+
+    *oid = iter;
+    nextColon = strchr(iter, ':');
+    if (!nextColon || (nextComma && nextColon > nextComma))
+        return SECFailure;
+    *oidLen = (nextColon - *oid);
+
+    if (!*oidLen)
+        return SECFailure;
+
+    iter = nextColon;
+    ++iter;
+
+    *crit = iter;
+    nextColon = strchr(iter, ':');
+    if (!nextColon || (nextComma && nextColon > nextComma))
+        return SECFailure;
+    *critLen = (nextColon - *crit);
+
+    if (!*critLen)
+        return SECFailure;
+
+    iter = nextColon;
+    ++iter;
+
+    *filename = iter;
+    if (nextComma) {
+        *filenameLen = (nextComma - *filename);
+        iter = nextComma;
+        ++iter;
+        *next = iter;
+    } else {
+        *filenameLen = strlen(*filename);
+        *next = NULL;
+    }
+
+    if (!*filenameLen)
+        return SECFailure;
+
+    return SECSuccess;
+}
+
 SECStatus
 AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
-              certutilExtnList extList)
+              certutilExtnList extList, const char *extGeneric)
 {
     SECStatus rv = SECSuccess;
     char *errstring = NULL;
+    const char *nextExtension = NULL;
     
     do {
         /* Add key usage extension */
         if (extList[ext_keyUsage].activated) {
             rv = AddKeyUsage(extHandle, extList[ext_keyUsage].arg);
             if (rv) {
 		errstring = "KeyUsage";
                 break;
@@ -1859,30 +2088,41 @@ AddExtensions(void *extHandle, const cha
         if (extList[ext_inhibitAnyPolicy].activated) {
             rv = AddInhibitAnyPolicy(extHandle);
             if (rv) {
 		errstring = "InhibitAnyPolicy";
                 break;
 	    }
         }
 
-        if (emailAddrs || dnsNames) {
+        if (emailAddrs || dnsNames || extList[ext_subjectAltName].activated) {
             PLArenaPool *arena;
             CERTGeneralName *namelist = NULL;
             SECItem item = { 0, NULL, 0 };
             
             arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
             if (arena == NULL) {
                 rv = SECFailure;
                 break;
             }
+            
+            rv = SECSuccess;
 
-            rv = AddEmailSubjectAlt(arena, &namelist, emailAddrs);
+            if (emailAddrs) {
+                rv |= AddEmailSubjectAlt(arena, &namelist, emailAddrs);
+            }
 
-            rv |= AddDNSSubjectAlt(arena, &namelist, dnsNames);
+            if (dnsNames) {
+                rv |= AddDNSSubjectAlt(arena, &namelist, dnsNames);
+            }
+
+            if (extList[ext_subjectAltName].activated) {
+                rv |= AddGeneralSubjectAlt(arena, &namelist, 
+                                           extList[ext_subjectAltName].arg);
+            }
 
             if (rv == SECSuccess) {
 		rv = CERT_EncodeAltNameExtension(arena, namelist, &item);
 	        if (rv == SECSuccess) {
                     rv = CERT_AddExtension(extHandle,
                                           SEC_OID_X509_SUBJECT_ALT_NAME,
                                           &item, PR_FALSE, PR_TRUE);
 		}
@@ -1893,10 +2133,76 @@ AddExtensions(void *extHandle, const cha
                 break;
 	    }
         }
     } while (0);
     
     if (rv != SECSuccess) {
         SECU_PrintError(progName, "Problem creating %s extension", errstring);
     }
+
+    nextExtension = extGeneric;
+    while (nextExtension && *nextExtension) {
+        SECItem oid_item, value;
+        PRBool isCritical;
+        const char *oid, *crit, *filename, *next;
+        int oidLen, critLen, filenameLen;
+        PRFileDesc *inFile = NULL;
+        char *zeroTerminatedFilename = NULL;
+
+        rv = parseNextGenericExt(nextExtension, &oid, &oidLen, &crit, &critLen,
+                                 &filename, &filenameLen, &next);
+        if (rv!= SECSuccess) {
+            SECU_PrintError(progName,
+                            "error parsing generic extension parameter %s",
+                            nextExtension);
+            break;
+        }
+        oid_item.data = NULL;
+        oid_item.len = 0;
+        rv = GetOidFromString(NULL, &oid_item, oid, oidLen);
+        if (rv != SECSuccess) {
+            SECU_PrintError(progName, "malformed extension OID %s", nextExtension);
+            break;
+        }
+        if (!strncmp("critical", crit, critLen)) {
+            isCritical = PR_TRUE;
+        } else if (!strncmp("not-critical", crit, critLen)) {
+            isCritical = PR_FALSE;
+        } else {
+            rv = SECFailure;
+            SECU_PrintError(progName, "expected 'critical' or 'not-critical'");
+            break;
+        }
+        zeroTerminatedFilename = PL_strndup(filename, filenameLen);
+        if (!zeroTerminatedFilename) {
+            rv = SECFailure;
+            SECU_PrintError(progName, "out of memory");
+            break;
+        }
+        rv = SECFailure;
+        inFile = PR_Open(zeroTerminatedFilename, PR_RDONLY, 0);
+        if (inFile) {
+            rv = SECU_ReadDERFromFile(&value, inFile, PR_FALSE, PR_FALSE);
+            PR_Close(inFile);
+            inFile = NULL;
+        }
+        if (rv != SECSuccess) {
+            SECU_PrintError(progName, "unable to read file %s",
+                            zeroTerminatedFilename);
+        }
+        PL_strfree(zeroTerminatedFilename);
+        if (rv != SECSuccess) {
+            break;
+        }
+        rv = CERT_AddExtensionByOID(extHandle, &oid_item, &value, isCritical,
+                                    PR_FALSE /*copyData*/);
+        if (rv != SECSuccess) {
+            SECITEM_FreeItem(&oid_item, PR_FALSE);
+            SECITEM_FreeItem(&value, PR_FALSE);
+            SECU_PrintError(progName, "failed to add extension %s", nextExtension);
+            break;
+        }
+        nextExtension = next;
+    }
+
     return rv;
 }
--- a/security/nss/cmd/certutil/certutil.c
+++ b/security/nss/cmd/certutil/certutil.c
@@ -177,17 +177,17 @@ AddCert(PK11SlotInfo *slot, CERTCertDBHa
 
     return rv;
 }
 
 static SECStatus
 CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
         SECOidTag hashAlgTag, CERTName *subject, char *phone, int ascii, 
 	const char *emailAddrs, const char *dnsNames,
-        certutilExtnList extnList,
+        certutilExtnList extnList, const char *extGeneric,
         /*out*/ SECItem *result)
 {
     CERTSubjectPublicKeyInfo *spki;
     CERTCertificateRequest *cr;
     SECItem *encoding;
     SECOidTag signAlgTag;
     SECStatus rv;
     PLArenaPool *arena;
@@ -215,17 +215,17 @@ CertReq(SECKEYPrivateKey *privk, SECKEYP
 	return SECFailure;
     }
     
     extHandle = CERT_StartCertificateRequestAttributes(cr);
     if (extHandle == NULL) {
         PORT_FreeArena (arena, PR_FALSE);
 	return SECFailure;
     }
-    if (AddExtensions(extHandle, emailAddrs, dnsNames, extnList)
+    if (AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric)
                   != SECSuccess) {
         PORT_FreeArena (arena, PR_FALSE);
         return SECFailure;
     }
     CERT_FinishExtensions(extHandle);
     CERT_FinishCertificateRequestAttributes(cr);
 
     /* Der encode the request */
@@ -415,22 +415,75 @@ DumpChain(CERTCertDBHandle *handle, char
 	printf("\"%s\" [%s]\n\n", c->nickname, c->subjectName);
 	CERT_DestroyCertificate(c);
     }
     CERT_DestroyCertificateList(chain);
     return SECSuccess;
 }
 
 static SECStatus
-listCerts(CERTCertDBHandle *handle, char *name, char *email, PK11SlotInfo *slot,
-          PRBool raw, PRBool ascii, PRFileDesc *outfile, void *pwarg)
+outputCertOrExtension(CERTCertificate *the_cert, PRBool raw, PRBool ascii,
+                      SECItem *extensionOID, PRFileDesc *outfile)
 {
     SECItem data;
     PRInt32 numBytes;
     SECStatus rv = SECFailure;
+    if (extensionOID) {
+	int i;
+	PRBool found = PR_FALSE;
+	for (i=0; the_cert->extensions[i] != NULL; i++) {
+	    CERTCertExtension *extension = the_cert->extensions[i];
+	    if (SECITEM_CompareItem(&extension->id, extensionOID) == SECEqual) {
+		found = PR_TRUE;
+		numBytes = PR_Write(outfile, extension->value.data,
+				    extension->value.len);
+		rv = SECSuccess;
+		if (numBytes != (PRInt32) extension->value.len) {
+		    SECU_PrintSystemError(progName, "error writing extension");
+		    rv = SECFailure;
+		}
+		rv = SECSuccess;
+		break;
+	    }
+	}
+	if (!found) {
+	    SECU_PrintSystemError(progName, "extension not found");
+	    rv = SECFailure;
+	}
+    } else {
+	data.data = the_cert->derCert.data;
+	data.len = the_cert->derCert.len;
+	if (ascii) {
+	    PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER, 
+		    BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER);
+	    rv = SECSuccess;
+	} else if (raw) {
+	    numBytes = PR_Write(outfile, data.data, data.len);
+	    rv = SECSuccess;
+	    if (numBytes != (PRInt32) data.len) {
+		SECU_PrintSystemError(progName, "error writing raw cert");
+		rv = SECFailure;
+	    }
+	} else {
+	    rv = SEC_PrintCertificateAndTrust(the_cert, "Certificate", NULL);
+	    if (rv != SECSuccess) {
+		SECU_PrintError(progName, "problem printing certificate");
+	    }
+	}
+    }
+    return rv;
+}
+
+static SECStatus
+listCerts(CERTCertDBHandle *handle, char *name, char *email,
+	  PK11SlotInfo *slot, PRBool raw, PRBool ascii,
+	  SECItem *extensionOID,
+	  PRFileDesc *outfile, void *pwarg)
+{
+    SECStatus rv = SECFailure;
     CERTCertList *certs;
     CERTCertListNode *node;
 
     /* List certs on a non-internal slot. */
     if (!PK11_IsFriendly(slot) && PK11_NeedLogin(slot)) {
         SECStatus newrv = PK11_Authenticate(slot, PR_TRUE, pwarg);
         if (newrv != SECSuccess) {
             SECU_PrintError(progName, "could not authenticate to token %s.",
@@ -456,75 +509,34 @@ listCerts(CERTCertDBHandle *handle, char
 	CERT_DestroyCertificate(the_cert);
 	if (!certs) {
 	    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
 	    SECU_PrintError(progName, "problem printing certificates");
 	    return SECFailure;
 	}
 	for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
 						node = CERT_LIST_NEXT(node)) {
-	    the_cert = node->cert;
-	    /* now get the subjectList that matches this cert */
-	    data.data = the_cert->derCert.data;
-	    data.len = the_cert->derCert.len;
-	    if (ascii) {
-		PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER, 
-		        BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER);
-		rv = SECSuccess;
-	    } else if (raw) {
-		numBytes = PR_Write(outfile, data.data, data.len);
-		if (numBytes != (PRInt32) data.len) {
-		   SECU_PrintSystemError(progName, "error writing raw cert");
-		    rv = SECFailure;
-		}
-		rv = SECSuccess;
-	    } else {
-		rv = SEC_PrintCertificateAndTrust(the_cert, "Certificate", NULL);
-		if (rv != SECSuccess) {
-		    SECU_PrintError(progName, "problem printing certificate");
-		}
-
-	    }
+	    rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
+                                       outfile);
 	    if (rv != SECSuccess) {
 		break;
 	    }
 	}
     } else if (email) {
-	CERTCertificate *the_cert;
 	certs = PK11_FindCertsFromEmailAddress(email, NULL);
 	if (!certs) {
 	    SECU_PrintError(progName, 
 			"Could not find certificates for email address: %s\n", 
 			email);
 	    return SECFailure;
 	}
 	for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
 						node = CERT_LIST_NEXT(node)) {
-	    the_cert = node->cert;
-	    /* now get the subjectList that matches this cert */
-	    data.data = the_cert->derCert.data;
-	    data.len  = the_cert->derCert.len;
-	    if (ascii) {
-		PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER, 
-		           BTOA_DataToAscii(data.data, data.len), 
-			   NS_CERT_TRAILER);
-		rv = SECSuccess;
-	    } else if (raw) {
-		numBytes = PR_Write(outfile, data.data, data.len);
-		rv = SECSuccess;
-		if (numBytes != (PRInt32) data.len) {
-		    SECU_PrintSystemError(progName, "error writing raw cert");
-		    rv = SECFailure;
-		}
-	    } else {
-		rv = SEC_PrintCertificateAndTrust(the_cert, "Certificate", NULL);
-		if (rv != SECSuccess) {
-		    SECU_PrintError(progName, "problem printing certificate");
-		}
-	    }
+	    rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
+                                       outfile);
 	    if (rv != SECSuccess) {
 		break;
 	    }
 	}
     } else {
 	certs = PK11_ListCertsInSlot(slot);
 	if (certs) {
 	    for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
@@ -542,18 +554,19 @@ listCerts(CERTCertDBHandle *handle, char
 	return SECFailure;
     }
 
     return SECSuccess;	/* not rv ?? */
 }
 
 static SECStatus
 ListCerts(CERTCertDBHandle *handle, char *nickname, char *email, 
-          PK11SlotInfo *slot, PRBool raw, PRBool ascii, PRFileDesc *outfile, 
-	  secuPWData *pwdata)
+          PK11SlotInfo *slot, PRBool raw, PRBool ascii,
+	  SECItem *extensionOID,
+	  PRFileDesc *outfile, secuPWData *pwdata)
 {
     SECStatus rv;
 
     if (!ascii && !raw && !nickname && !email) {
         PR_fprintf(outfile, "\n%-60s %-5s\n%-60s %-5s\n\n",
                    "Certificate Nickname", "Trust Attributes", "",
                    "SSL,S/MIME,JAR/XPI");
     }
@@ -564,17 +577,18 @@ ListCerts(CERTCertDBHandle *handle, char
 	list = PK11_ListCerts(PK11CertListAll, pwdata);
 	for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
 	     node = CERT_LIST_NEXT(node)) {
 	    SECU_PrintCertNickname(node, stdout);
 	}
 	CERT_DestroyCertList(list);
 	return SECSuccess;
     } 
-    rv = listCerts(handle, nickname, email, slot, raw, ascii, outfile, pwdata);
+    rv = listCerts(handle, nickname, email, slot, raw, ascii,
+                   extensionOID, outfile, pwdata);
     return rv;
 }
 
 static SECStatus 
 DeleteCert(CERTCertDBHandle *handle, char *name)
 {
     SECStatus rv;
     CERTCertificate *cert;
@@ -610,16 +624,25 @@ ValidateCert(CERTCertDBHandle *handle, c
 	    PORT_SetError (SEC_ERROR_INVALID_ARGS);
 	    return (SECFailure);
     }
     
     switch (*certUsage) {
 	case 'O':
 	    usage = certificateUsageStatusResponder;
 	    break;
+	case 'L':
+	    usage = certificateUsageSSLCA;
+	    break;
+	case 'A':
+	    usage = certificateUsageAnyCA;
+	    break;
+	case 'Y':
+	    usage = certificateUsageVerifyCA;
+	    break;
 	case 'C':
 	    usage = certificateUsageSSLClient;
 	    break;
 	case 'V':
 	    usage = certificateUsageSSLServer;
 	    break;
 	case 'S':
 	    usage = certificateUsageEmailSigner;
@@ -984,17 +1007,17 @@ PrintSyntax(char *progName)
     FPS "\t\t [-P targetDBPrefix] [--source-prefix upgradeDBPrefix]\n");
     FPS "\t\t [-f targetPWfile] [-@ upgradePWFile]\n");
     FPS "\t%s --merge --source-dir sourceDBDir [-d targetDBdir]\n",
 	progName);
     FPS "\t\t [-P targetDBPrefix] [--source-prefix sourceDBPrefix]\n");
     FPS "\t\t [-f targetPWfile] [-@ sourcePWFile]\n");
     FPS "\t%s -L [-n cert-name] [--email email-address] [-X] [-r] [-a]\n",
 	progName);
-    FPS "\t\t [-d certdir] [-P dbprefix]\n");
+    FPS "\t\t [--dump-ext-val OID] [-d certdir] [-P dbprefix]\n");
     FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n",
 	progName);
     FPS "\t%s -O -n cert-name [-X] [-d certdir] [-a] [-P dbprefix]\n", progName);
     FPS "\t%s -R -s subj -o cert-request-file [-d certdir] [-P dbprefix] [-p phone] [-a]\n"
 	"\t\t [-7 emailAddrs] [-k key-type-or-id] [-h token-name] [-f pwfile] [-g key-size]\n",
 	progName);
     FPS "\t%s -V -n cert-name -u usage [-b time] [-e] [-a]\n"
 	"\t\t[-X] [-d certdir] [-P dbprefix]\n",
@@ -1003,17 +1026,18 @@ PrintSyntax(char *progName)
 	progName);
     FPS "\t%s -S -n cert-name -s subj [-c issuer-name | -x]  -t trustargs\n"
 	"\t\t [-k key-type-or-id] [-q key-params] [-h token-name] [-g key-size]\n"
         "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
 	"\t\t [-f pwfile] [-d certdir] [-P dbprefix]\n"
         "\t\t [-p phone] [-1] [-2] [-3] [-4] [-5] [-6] [-7 emailAddrs]\n"
         "\t\t [-8 DNS-names]\n"
         "\t\t [--extAIA] [--extSIA] [--extCP] [--extPM] [--extPC] [--extIA]\n"
-        "\t\t [--extSKID] [--extNC]\n", progName);
+        "\t\t [--extSKID] [--extNC] [--extSAN type:name[,type:name]...]\n"
+	"\t\t [--extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...]\n", progName);
     FPS "\t%s -U [-X] [-d certdir] [-P dbprefix]\n", progName);
     exit(1);
 }
 
 enum usage_level {
     usage_all = 0, usage_selected = 1
 };
 
@@ -1303,17 +1327,17 @@ static void luK(enum usage_level ul, con
         "   -X");
     FPS "\n");
 }
 
 static void luL(enum usage_level ul, const char *command)
 {
     int is_my_command = (command && 0 == strcmp(command, "L"));
     if (ul == usage_all || !command || is_my_command)
-    FPS "%-15s List all certs, or print out a single named cert\n",
+    FPS "%-15s List all certs, or print out a single named cert (or a subset)\n",
         "-L");
     if (ul == usage_selected && !is_my_command)
         return;
     FPS "%-20s Pretty print named cert (list all if unspecified)\n",
         "   -n cert-name");
     FPS "%-20s \n"
               "%-20s Pretty print cert with email address (list all if unspecified)\n",
         "   --email email-address", "");
@@ -1322,16 +1346,19 @@ static void luL(enum usage_level ul, con
     FPS "%-20s Cert & Key database prefix\n",
         "   -P dbprefix");
     FPS "%-20s force the database to open R/W\n",
         "   -X");
     FPS "%-20s For single cert, print binary DER encoding\n",
         "   -r");
     FPS "%-20s For single cert, print ASCII encoding (RFC1113)\n",
         "   -a");
+    FPS "%-20s \n"
+              "%-20s For single cert, print binary DER encoding of extension OID\n",
+        "   --dump-ext-val OID", "");
     FPS "\n");
 }
 
 static void luM(enum usage_level ul, const char *command)
 {
     int is_my_command = (command && 0 == strcmp(command, "M"));
     if (ul == usage_all || !command || is_my_command)
     FPS "%-15s Modify trust attributes of certificate\n",
@@ -1467,16 +1494,19 @@ static void luV(enum usage_level ul, con
         "   -n cert-name");
     FPS "%-20s validity time (\"YYMMDDHHMMSS[+HHMM|-HHMM|Z]\")\n",
         "   -b time");
     FPS "%-20s Check certificate signature \n",
         "   -e ");   
     FPS "%-20s Specify certificate usage:\n", "   -u certusage");
     FPS "%-25s C \t SSL Client\n", "");
     FPS "%-25s V \t SSL Server\n", "");
+    FPS "%-25s L \t SSL CA\n", "");
+    FPS "%-25s A \t Any CA\n", "");
+    FPS "%-25s Y \t Verify CA\n", "");
     FPS "%-25s S \t Email signer\n", "");
     FPS "%-25s R \t Email Recipient\n", "");   
     FPS "%-25s O \t OCSP status responder\n", "");   
     FPS "%-25s J \t Object signer\n", "");   
     FPS "%-20s Cert database directory (default is ~/.netscape)\n",
         "   -d certdir");
     FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n",
         "   -a");
@@ -1633,16 +1663,28 @@ static void luS(enum usage_level ul, con
     FPS "%-20s Create an Inhibit Any Policy extension\n",
         "   --extIA ");
     FPS "%-20s Create a subject key ID extension\n",
         "   --extSKID ");
     FPS "%-20s \n",
         "   See -G for available key flag options");
     FPS "%-20s Create a name constraints extension\n",
         "   --extNC ");
+    FPS "%-20s \n"
+        "%-20s Create a Subject Alt Name extension with one or multiple names\n",
+	"   --extSAN type:name[,type:name]...", "");
+    FPS "%-20s - type: directory, dn, dns, edi, ediparty, email, ip, ipaddr,\n", "");
+    FPS "%-20s         other, registerid, rfc822, uri, x400, x400addr\n", "");
+    FPS "%-20s \n"
+        "%-20s Add one or multiple extensions that certutil cannot encode yet,\n"
+	"%-20s by loading their encodings from external files.\n",
+        "   --extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...", "", "");
+    FPS "%-20s - OID (example): 1.2.3.4\n", "");
+    FPS "%-20s - critical-flag: critical or not-critical\n", "");
+    FPS "%-20s - filename: full path to a file containing an encoded extension\n", "");
     FPS "\n");
 }
 
 static void LongUsage(char *progName, enum usage_level ul, const char *command)
 {
     luA(ul, command);
     luB(ul, command);
     luE(ul, command);
@@ -1831,16 +1873,17 @@ CreateCert(
 	unsigned int serialNumber, 
 	int     warpmonths,
 	int     validityMonths,
 	const char *emailAddrs,
 	const char *dnsNames,
 	PRBool ascii,
 	PRBool  selfsign,
 	certutilExtnList extnList,
+	const char *extGeneric,
         int certVersion,
 	SECItem * certDER)
 {
     void *	extHandle;
     CERTCertificate *subjectCert 	= NULL;
     CERTCertificateRequest *certReq	= NULL;
     SECStatus 	rv 			= SECSuccess;
     CERTCertExtension **CRexts;
@@ -1859,17 +1902,17 @@ CreateCert(
 	}
         
         
 	extHandle = CERT_StartCertExtensions (subjectCert);
 	if (extHandle == NULL) {
 	    GEN_BREAK (SECFailure)
 	}
         
-        rv = AddExtensions(extHandle, emailAddrs, dnsNames, extnList);
+        rv = AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric);
         if (rv != SECSuccess) {
 	    GEN_BREAK (SECFailure)
 	}
         
         if (certReq->attributes != NULL &&
 	    certReq->attributes[0] != NULL &&
 	    certReq->attributes[0]->attrType.data != NULL &&
 	    certReq->attributes[0]->attrType.len   > 0    &&
@@ -2207,16 +2250,19 @@ enum certutilOpts {
     opt_SourcePrefix,
     opt_UpgradeID,
     opt_UpgradeTokenName,
     opt_KeyOpFlagsOn,
     opt_KeyOpFlagsOff,
     opt_KeyAttrFlags,
     opt_EmptyPassword,
     opt_CertVersion,
+    opt_AddSubjectAltNameExt,
+    opt_DumpExtensionValue,
+    opt_GenericExtensions,
     opt_Help
 };
 
 static const
 secuCommandFlag commands_init[] =
 {
 	{ /* cmd_AddCert             */  'A', PR_FALSE, 0, PR_FALSE },
 	{ /* cmd_CreateNewCert       */  'C', PR_FALSE, 0, PR_FALSE },
@@ -2318,16 +2364,21 @@ secuCommandFlag options_init[] =
 	{ /* opt_KeyOpFlagsOff       */  0,   PR_TRUE, 0, PR_FALSE, 
                                                    "keyOpFlagsOff"},
 	{ /* opt_KeyAttrFlags        */  0,   PR_TRUE, 0, PR_FALSE, 
                                                    "keyAttrFlags"},
 	{ /* opt_EmptyPassword       */  0,   PR_FALSE, 0, PR_FALSE, 
                                                    "empty-password"},
         { /* opt_CertVersion         */  0,   PR_FALSE, 0, PR_FALSE,
                                                    "certVersion"},
+	{ /* opt_AddSubjectAltExt    */  0,   PR_TRUE,  0, PR_FALSE, "extSAN"},
+	{ /* opt_DumpExtensionValue  */  0,   PR_TRUE, 0, PR_FALSE, 
+                                                   "dump-ext-val"},
+	{ /* opt_GenericExtensions   */  0,   PR_TRUE, 0, PR_FALSE, 
+                                                   "extGeneric"},
 };
 #define NUM_OPTIONS ((sizeof options_init)  / (sizeof options_init[0]))
 
 static secuCommandFlag certutil_commands[NUM_COMMANDS];
 static secuCommandFlag certutil_options [NUM_OPTIONS ];
 
 static const secuCommand certutil = {
     NUM_COMMANDS, 
@@ -2658,19 +2709,20 @@ certutil_main(int argc, char **argv, PRB
          certutil.commands[cmd_CreateAndAddCert].activated) &&
         !certutil.options[opt_Trust].activated) {
 	PR_fprintf(PR_STDERR, 
 	          "%s -%c: trust is required for this command (-t).\n",
 	           progName, commandToRun);
 	return 255;
     }
 
-    /*  if -L is given raw or ascii mode, it must be for only one cert.  */
+    /*  if -L is given raw, ascii or dump mode, it must be for only one cert. */
     if (certutil.commands[cmd_ListCerts].activated &&
         (certutil.options[opt_ASCIIForIO].activated ||
+         certutil.options[opt_DumpExtensionValue].activated ||
          certutil.options[opt_BinaryDER].activated) &&
         !certutil.options[opt_Nickname].activated) {
 	PR_fprintf(PR_STDERR, 
 	        "%s: nickname is required to dump cert in raw or ascii mode.\n",
 	           progName);
 	return 255;
     }
     
@@ -2980,20 +3032,39 @@ merge_fail:
 	PK11_FreeSlot(sourceSlot);
 	goto shutdown;
     }
 
     /* The following 8 options are mutually exclusive with all others. */
 
     /*  List certs (-L)  */
     if (certutil.commands[cmd_ListCerts].activated) {
-	rv = ListCerts(certHandle, name, email, slot,
-	               certutil.options[opt_BinaryDER].activated,
-	               certutil.options[opt_ASCIIForIO].activated, 
-		       outFile, &pwdata);
+	if (certutil.options[opt_DumpExtensionValue].activated) {
+	    const char *oid_str;
+	    SECItem oid_item;
+            SECStatus srv;
+	    oid_item.data = NULL;
+	    oid_item.len = 0;
+	    oid_str = certutil.options[opt_DumpExtensionValue].arg;
+	    srv = GetOidFromString(NULL, &oid_item, oid_str, strlen(oid_str));
+	    if (srv != SECSuccess) {
+         	SECU_PrintError(progName, "malformed extension OID %s",
+				oid_str);
+		goto shutdown;
+	    }
+	    rv = ListCerts(certHandle, name, email, slot,
+			   PR_TRUE /*binary*/, PR_FALSE /*ascii*/,
+			   &oid_item,
+			   outFile, &pwdata);
+	} else {
+	    rv = ListCerts(certHandle, name, email, slot,
+			   certutil.options[opt_BinaryDER].activated,
+			   certutil.options[opt_ASCIIForIO].activated,
+			   NULL, outFile, &pwdata);
+	}
 	goto shutdown;
     }
     if (certutil.commands[cmd_DumpChain].activated) {
 	rv = DumpChain(certHandle, name,
                        certutil.options[opt_ASCIIForIO].activated);
 	goto shutdown;
     }
     /*  XXX needs work  */
@@ -3174,16 +3245,22 @@ merge_fail:
             certutil.options[opt_AddCmdExtKeyUsageExt].activated;
         if (!certutil_extns[ext_extKeyUsage].activated) {
             certutil_extns[ext_extKeyUsage].activated =
                 certutil.options[opt_AddExtKeyUsageExt].activated;
         } else {
             certutil_extns[ext_extKeyUsage].arg =
                 certutil.options[opt_AddCmdExtKeyUsageExt].arg;
         }
+        certutil_extns[ext_subjectAltName].activated =
+                certutil.options[opt_AddSubjectAltNameExt].activated;
+        if (certutil_extns[ext_subjectAltName].activated) {
+            certutil_extns[ext_subjectAltName].arg =
+                certutil.options[opt_AddSubjectAltNameExt].arg;
+        }
 
         certutil_extns[ext_authInfoAcc].activated =
 				certutil.options[opt_AddAuthInfoAccExt].activated;
         certutil_extns[ext_subjInfoAcc].activated =
 				certutil.options[opt_AddSubjInfoAccExt].activated;
         certutil_extns[ext_certPolicies].activated =
 				certutil.options[opt_AddCertPoliciesExt].activated;
         certutil_extns[ext_policyMappings].activated =
@@ -3213,16 +3290,18 @@ merge_fail:
     /*  Make a cert request (-R).  */
     if (certutil.commands[cmd_CertReq].activated) {
 	rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
 	             certutil.options[opt_PhoneNumber].arg,
 	             certutil.options[opt_ASCIIForIO].activated,
 		     certutil.options[opt_ExtendedEmailAddrs].arg,
 		     certutil.options[opt_ExtendedDNSNames].arg,
                      certutil_extns,
+		     (certutil.options[opt_GenericExtensions].activated ?
+		         certutil.options[opt_GenericExtensions].arg : NULL),
                      &certReqDER);
 	if (rv)
 	    goto shutdown;
 	privkey->wincx = &pwdata;
     }
 
     /*
      *  Certificate creation
@@ -3235,16 +3314,18 @@ merge_fail:
     if (certutil.commands[cmd_CreateAndAddCert].activated) {
 	static certutilExtnList nullextnlist = {{PR_FALSE, NULL}};
 	rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
 	             certutil.options[opt_PhoneNumber].arg,
 		     PR_FALSE, /* do not BASE64-encode regardless of -a option */
 		     NULL,
 		     NULL,
                      nullextnlist,
+		     (certutil.options[opt_GenericExtensions].activated ?
+		         certutil.options[opt_GenericExtensions].arg : NULL),
 		     &certReqDER);
 	if (rv) 
 	    goto shutdown;
 	privkey->wincx = &pwdata;
     }
 
     /*  Create a certificate (-C or -S).  */
     if (certutil.commands[cmd_CreateAndAddCert].activated ||
@@ -3254,16 +3335,18 @@ merge_fail:
 			&certReqDER, &privkey, &pwdata, hashAlgTag,
 	                serialNumber, warpmonths, validityMonths,
 		        certutil.options[opt_ExtendedEmailAddrs].arg,
 		        certutil.options[opt_ExtendedDNSNames].arg,
 		        certutil.options[opt_ASCIIForIO].activated &&
 			    certutil.commands[cmd_CreateNewCert].activated,
 	                certutil.options[opt_SelfSign].activated,
 	                certutil_extns,
+			(certutil.options[opt_GenericExtensions].activated ?
+			    certutil.options[opt_GenericExtensions].arg : NULL),
                         certVersion,
 			&certDER);
 	if (rv) 
 	    goto shutdown;
     }
 
     /* 
      * Adding a cert to the database (or slot)
--- a/security/nss/cmd/certutil/certutil.h
+++ b/security/nss/cmd/certutil/certutil.h
@@ -30,24 +30,29 @@ enum certutilExtns {
     ext_authInfoAcc,
     ext_subjInfoAcc,
     ext_certPolicies,
     ext_policyMappings,
     ext_policyConstr,
     ext_inhibitAnyPolicy,
     ext_subjectKeyID,
     ext_nameConstraints,
+    ext_subjectAltName,
     ext_End
 };
 
 typedef struct ExtensionEntryStr {
     PRBool activated;
     const char  *arg;
 } ExtensionEntry;
 
 typedef ExtensionEntry certutilExtnList[ext_End];
 
 extern SECStatus
 AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
-              certutilExtnList extList);
+              certutilExtnList extList, const char *extGeneric);
+
+extern SECStatus
+GetOidFromString(PLArenaPool *arena, SECItem *to,
+                 const char *from, size_t fromLen);
 
 #endif	/* _CERTUTIL_H */
 
--- a/security/nss/cmd/httpserv/httpserv.c
+++ b/security/nss/cmd/httpserv/httpserv.c
@@ -1307,18 +1307,20 @@ main(int argc, char **argv)
 	      if (!revoInfo->cert) {
 		  fprintf(stderr, "cannot find cert with nickname %s\n",
 			  revoInfo->nickname);
 		  exit(1);
 	      }
 	      inFile = PR_Open(revoInfo->crlFilename, PR_RDONLY, 0);
 	      if (inFile) {
 		rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
+		PR_Close(inFile);
+		inFile = NULL;
 	      }
-	      if (!inFile || rv != SECSuccess) {
+	      if (rv != SECSuccess) {
 		  fprintf(stderr, "unable to read crl file %s\n",
 			  revoInfo->crlFilename);
 		  exit(1);
 	      }
 	      revoInfo->crl = 
 		  CERT_DecodeDERCrlWithFlags(NULL, &crlDER, SEC_CRL_TYPE,
 					     CRL_DECODE_DEFAULT_OPTIONS);
 	      if (!revoInfo->crl) {
--- a/security/nss/cmd/lib/secutil.c
+++ b/security/nss/cmd/lib/secutil.c
@@ -47,16 +47,29 @@ static char consoleName[] =  {
 #endif
 #endif
 };
 
 #include "nssutil.h"
 #include "ssl.h"
 #include "sslproto.h"
 
+static PRBool utf8DisplayEnabled = PR_FALSE;
+
+void
+SECU_EnableUtf8Display(PRBool enable)
+{
+    utf8DisplayEnabled = enable;
+}
+
+PRBool
+SECU_GetUtf8DisplayEnabled(void)
+{
+    return utf8DisplayEnabled;
+}
 
 static void
 secu_ClearPassword(char *p)
 {
     if (p) {
 	PORT_Memset(p, 0, PORT_Strlen(p));
 	PORT_Free(p);
     }
@@ -604,22 +617,32 @@ secu_PrintRawStringQuotesOptional(FILE *
 	column = level*INDENT_MULT;
     }
     if (quotes) {
 	fprintf(out, "\""); column++;
     }
 
     for (i = 0; i < si->len; i++) {
 	unsigned char val = si->data[i];
+	unsigned char c;
 	if (SECU_GetWrapEnabled() && column > 76) {
 	    SECU_Newline(out);
 	    SECU_Indent(out, level); column = level*INDENT_MULT;
 	}
 
-	fprintf(out,"%c", printable[val]); column++;
+	if (utf8DisplayEnabled) {
+	    if (val < 32)
+		c = '.';
+	    else
+		c = val;
+	} else {
+	    c = printable[val];
+	}
+	fprintf(out,"%c", c);
+	column++;
     }
 
     if (quotes) {
 	fprintf(out, "\""); column++;
     }
     if (SECU_GetWrapEnabled() &&
         (column != level*INDENT_MULT || column > 76)) {
 	SECU_Newline(out);
@@ -2436,29 +2459,29 @@ loser:
     PORT_FreeArena(arena, PR_TRUE);
     return rv;
 }
 #endif
 
 int
 SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
 {
-    unsigned char fingerprint[20];
+    unsigned char fingerprint[SHA256_LENGTH];
     char *fpStr = NULL;
     int err     = PORT_GetError();
     SECStatus rv;
     SECItem fpItem;
 
-    /* print MD5 fingerprint */
+    /* Print SHA-256 fingerprint */
     memset(fingerprint, 0, sizeof fingerprint);
-    rv = PK11_HashBuf(SEC_OID_MD5,fingerprint, derCert->data, derCert->len);
+    rv = PK11_HashBuf(SEC_OID_SHA256, fingerprint, derCert->data, derCert->len);
     fpItem.data = fingerprint;
-    fpItem.len = MD5_LENGTH;
+    fpItem.len = SHA256_LENGTH;
     fpStr = CERT_Hexify(&fpItem, 1);
-    SECU_Indent(out, level);  fprintf(out, "%s (MD5):", m);
+    SECU_Indent(out, level);  fprintf(out, "%s (SHA-256):", m);
     if (SECU_GetWrapEnabled()) {
 	fprintf(out, "\n");
 	SECU_Indent(out, level+1);
     }
     else {
 	fprintf(out, " ");
     }
     fprintf(out, "%s\n", fpStr);
--- a/security/nss/cmd/lib/secutil.h
+++ b/security/nss/cmd/lib/secutil.h
@@ -134,16 +134,19 @@ extern int
 SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
 		       struct CERTDistNamesStr *caNames,
 		       struct CERTCertificateStr **pRetCert,
 		       struct SECKEYPrivateKeyStr **pRetKey);
 
 extern PRBool SECU_GetWrapEnabled(void);
 extern void SECU_EnableWrap(PRBool enable);
 
+extern PRBool SECU_GetUtf8DisplayEnabled(void);
+extern void SECU_EnableUtf8Display(PRBool enable);
+
 /* revalidate the cert and print information about cert verification
  * failure at time == now */
 extern void
 SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle, 
 	CERTCertificate *cert, PRBool checksig, 
 	SECCertificateUsage certUsage, void *pinArg, PRBool verbose);
 
 /* revalidate the cert and print information about cert verification
--- a/security/nss/cmd/pp/pp.c
+++ b/security/nss/cmd/pp/pp.c
@@ -17,32 +17,37 @@ extern int fprintf(FILE *, char *, ...);
 
 #include "pk11func.h"
 #include "nspr.h"
 #include "nss.h"
 
 static void Usage(char *progName)
 {
     fprintf(stderr,
-	    "Usage:  %s -t type [-a] [-i input] [-o output] [-w]\n",
+	    "Usage:  %s [-t type] [-a] [-i input] [-o output] [-w] [-u]\n",
 	    progName);
-    fprintf(stderr, "%-20s Specify the input type (must be one of %s,\n",
+    fprintf(stderr, "Pretty prints a file containing ASN.1 data in DER or ascii format.\n");
+    fprintf(stderr, "%-14s Specify input and display type: %s (sk),\n",
 	    "-t type", SEC_CT_PRIVATE_KEY);
-    fprintf(stderr, "%-20s %s, %s, %s,\n", "", SEC_CT_PUBLIC_KEY,
+    fprintf(stderr, "%-14s %s (pk), %s (c), %s (cr),\n", "", SEC_CT_PUBLIC_KEY,
 	    SEC_CT_CERTIFICATE, SEC_CT_CERTIFICATE_REQUEST);
-    fprintf(stderr, "%-20s %s, %s, %s or %s)\n", "", SEC_CT_CERTIFICATE_ID,
+    fprintf(stderr, "%-14s %s (ci), %s (p7), %s or %s (n).\n", "", SEC_CT_CERTIFICATE_ID,
+            SEC_CT_PKCS7, SEC_CT_CRL, SEC_CT_NAME);
+    fprintf(stderr, "%-14s (Use either the long type name or the shortcut.)\n", "", SEC_CT_CERTIFICATE_ID,
             SEC_CT_PKCS7, SEC_CT_CRL, SEC_CT_NAME);
-    fprintf(stderr, "%-20s Input is in ascii encoded form (RFC1113)\n",
+    fprintf(stderr, "%-14s Input is in ascii encoded form (RFC1113)\n",
 	    "-a");
-    fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+    fprintf(stderr, "%-14s Define an input file to use (default is stdin)\n",
 	    "-i input");
-    fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+    fprintf(stderr, "%-14s Define an output file to use (default is stdout)\n",
 	    "-o output");
-    fprintf(stderr, "%-20s Don't wrap long output lines\n",
+    fprintf(stderr, "%-14s Don't wrap long output lines\n",
 	    "-w");
+    fprintf(stderr, "%-14s Use UTF-8 (default is to show non-ascii as .)\n",
+	    "-u");
     exit(-1);
 }
 
 int main(int argc, char **argv)
 {
     int rv, ascii;
     char *progName;
     FILE *outFile;
@@ -54,17 +59,17 @@ int main(int argc, char **argv)
 
     progName = strrchr(argv[0], '/');
     progName = progName ? progName+1 : argv[0];
 
     ascii = 0;
     inFile = 0;
     outFile = 0;
     typeTag = 0;
-    optstate = PL_CreateOptState(argc, argv, "at:i:o:w");
+    optstate = PL_CreateOptState(argc, argv, "at:i:o:uw");
     while ( PL_GetNextOpt(optstate) == PL_OPT_OK ) {
 	switch (optstate->option) {
 	  case '?':
 	    Usage(progName);
 	    break;
 
 	  case 'a':
 	    ascii = 1;
@@ -87,16 +92,20 @@ int main(int argc, char **argv)
 		return -1;
 	    }
 	    break;
 
 	  case 't':
 	    typeTag = strdup(optstate->value);
 	    break;
 
+	  case 'u':
+	    SECU_EnableUtf8Display(PR_TRUE);
+	    break;
+
 	  case 'w':
 	    wrap = PR_FALSE;
 	    break;
 	}
     }
     PL_DestroyOptState(optstate);
     if (!typeTag) Usage(progName);
 
@@ -120,37 +129,44 @@ int main(int argc, char **argv)
 
     /* Data is untyped, using the specified type */
     data.data = der.data;
     data.len = der.len;
 
     SECU_EnableWrap(wrap);
 
     /* Pretty print it */
-    if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE) == 0) {
+    if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE) == 0 ||
+        PORT_Strcmp(typeTag, "c") == 0) {
 	rv = SECU_PrintSignedData(outFile, &data, "Certificate", 0,
 			     SECU_PrintCertificate);
-    } else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_ID) == 0) {
+    } else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_ID) == 0 ||
+               PORT_Strcmp(typeTag, "ci") == 0) {
         rv = SECU_PrintSignedContent(outFile, &data, 0, 0,
                                      SECU_PrintDumpDerIssuerAndSerial);
-    } else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_REQUEST) == 0) {
+    } else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_REQUEST) == 0 ||
+               PORT_Strcmp(typeTag, "cr") == 0) {
 	rv = SECU_PrintSignedData(outFile, &data, "Certificate Request", 0,
 			     SECU_PrintCertificateRequest);
-    } else if (PORT_Strcmp (typeTag, SEC_CT_CRL) == 0) {
+    } else if (PORT_Strcmp(typeTag, SEC_CT_CRL) == 0) {
 	rv = SECU_PrintSignedData (outFile, &data, "CRL", 0, SECU_PrintCrl);
 #ifdef HAVE_EPV_TEMPLATE
-    } else if (PORT_Strcmp(typeTag, SEC_CT_PRIVATE_KEY) == 0) {
+    } else if (PORT_Strcmp(typeTag, SEC_CT_PRIVATE_KEY) == 0 ||
+               PORT_Strcmp(typeTag, "sk") == 0) {
 	rv = SECU_PrintPrivateKey(outFile, &data, "Private Key", 0);
 #endif
-    } else if (PORT_Strcmp(typeTag, SEC_CT_PUBLIC_KEY) == 0) {
+    } else if (PORT_Strcmp(typeTag, SEC_CT_PUBLIC_KEY) == 0 ||
+               PORT_Strcmp (typeTag, "pk") == 0) {
 	rv = SECU_PrintSubjectPublicKeyInfo(outFile, &data, "Public Key", 0);
-    } else if (PORT_Strcmp(typeTag, SEC_CT_PKCS7) == 0) {
+    } else if (PORT_Strcmp(typeTag, SEC_CT_PKCS7) == 0 ||
+               PORT_Strcmp (typeTag, "p7") == 0) {
 	rv = SECU_PrintPKCS7ContentInfo(outFile, &data,
 					"PKCS #7 Content Info", 0);
-    } else if (PORT_Strcmp(typeTag, SEC_CT_NAME) == 0) {
+    } else if (PORT_Strcmp(typeTag, SEC_CT_NAME) == 0 ||
+               PORT_Strcmp (typeTag, "n") == 0) {
 	rv = SECU_PrintDERName(outFile, &data, "Name", 0);
     } else {
 	fprintf(stderr, "%s: don't know how to print out '%s' files\n",
 		progName, typeTag);
 	SECU_PrintAny(outFile, &data, "File contains", 0);
 	return -1;
     }
 
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/security/nss/lib/certdb/alg1485.c
+++ b/security/nss/lib/certdb/alg1485.c
@@ -23,22 +23,22 @@ typedef struct NameToKindStr {
 #define SEC_ASN1_DS SEC_ASN1_HIGH_TAG_NUMBER
 
 /* Add new entries to this table, and maybe to function ParseRFC1485AVA */
 static const NameToKind name2kinds[] = {
 /* IANA registered type names
  * (See: http://www.iana.org/assignments/ldap-parameters) 
  */
 /* RFC 3280, 4630 MUST SUPPORT */
-    { "CN",             64, SEC_OID_AVA_COMMON_NAME,    SEC_ASN1_DS},
+    { "CN",            640, SEC_OID_AVA_COMMON_NAME,    SEC_ASN1_DS},
     { "ST",            128, SEC_OID_AVA_STATE_OR_PROVINCE,
 							SEC_ASN1_DS},
-    { "O",              64, SEC_OID_AVA_ORGANIZATION_NAME,
+    { "O",             128, SEC_OID_AVA_ORGANIZATION_NAME,
 							SEC_ASN1_DS},
-    { "OU",             64, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME,
+    { "OU",            128, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME,
                                                         SEC_ASN1_DS},
     { "dnQualifier", 32767, SEC_OID_AVA_DN_QUALIFIER, SEC_ASN1_PRINTABLE_STRING},
     { "C",               2, SEC_OID_AVA_COUNTRY_NAME, SEC_ASN1_PRINTABLE_STRING},
     { "serialNumber",   64, SEC_OID_AVA_SERIAL_NUMBER,SEC_ASN1_PRINTABLE_STRING},
 
 /* RFC 3280, 4630 SHOULD SUPPORT */
     { "L",             128, SEC_OID_AVA_LOCALITY,       SEC_ASN1_DS},
     { "title",          64, SEC_OID_AVA_TITLE,          SEC_ASN1_DS},
@@ -372,17 +372,17 @@ ParseRFC1485AVA(PLArenaPool *arena, cons
     int       valLen;
     SECOidTag kind  = SEC_OID_UNKNOWN;
     SECStatus rv    = SECFailure;
     SECItem   derOid = { 0, NULL, 0 };
     SECItem   derVal = { 0, NULL, 0};
     char      sep   = 0;
 
     char tagBuf[32];
-    char valBuf[384];
+    char valBuf[1024];
 
     PORT_Assert(arena);
     if (SECSuccess != scanTag(pbp, endptr, tagBuf, sizeof tagBuf) ||
 	!(valLen    = scanVal(pbp, endptr, valBuf, sizeof valBuf))) {
 	goto loser;
     }
 
     bp = *pbp;
@@ -884,17 +884,17 @@ get_hex_string(SECItem *data)
  *
  * As a simplification, we assume the value is correctly encoded for 
  * its encoding type.  That is, we do not test that all the characters
  * in a string encoded type are allowed by that type.  We assume it.
  */
 static SECStatus
 AppendAVA(stringBuf *bufp, CERTAVA *ava, CertStrictnessLevel strict)
 {
-#define TMPBUF_LEN 384
+#define TMPBUF_LEN 2048
     const NameToKind *pn2k   = name2kinds;
     SECItem     *avaValue    = NULL;
     char        *unknownTag  = NULL;
     char        *encodedAVA  = NULL;
     PRBool       useHex      = PR_FALSE;  /* use =#hexXXXX form */
     PRBool       truncateName  = PR_FALSE;
     PRBool       truncateValue = PR_FALSE;
     SECOidTag    endKind;
--- a/security/nss/lib/certdb/genname.c
+++ b/security/nss/lib/certdb/genname.c
@@ -132,16 +132,49 @@ static const SEC_ASN1Template CERT_Regis
 };
 
 
 const SEC_ASN1Template CERT_GeneralNamesTemplate[] = {
     { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN , 0, SEC_ASN1_SUB(SEC_AnyTemplate) }
 };
 
 
+static struct {
+    CERTGeneralNameType type;
+    char *name;
+} typesArray[] = {
+    { certOtherName, "other" },
+    { certRFC822Name, "email" },
+    { certRFC822Name, "rfc822" },
+    { certDNSName, "dns" },
+    { certX400Address, "x400" },
+    { certX400Address, "x400addr" },
+    { certDirectoryName, "directory" },
+    { certDirectoryName, "dn" },
+    { certEDIPartyName, "edi" },
+    { certEDIPartyName, "ediparty" },
+    { certURI, "uri" },
+    { certIPAddress, "ip" },
+    { certIPAddress, "ipaddr" },
+    { certRegisterID, "registerid" }
+};
+
+CERTGeneralNameType
+CERT_GetGeneralNameTypeFromString(const char *string)
+{
+    int types_count = sizeof(typesArray)/sizeof(typesArray[0]);
+    int i;
+
+    for (i=0; i < types_count; i++) {
+        if (PORT_Strcasecmp(string, typesArray[i].name) == 0) {
+            return typesArray[i].type;
+        }
+    }
+    return 0;
+}
 
 CERTGeneralName *
 CERT_NewGeneralName(PLArenaPool *arena, CERTGeneralNameType type)
 {
     CERTGeneralName *name = arena 
                             ? PORT_ArenaZNew(arena, CERTGeneralName)
 	                    : PORT_ZNew(CERTGeneralName);
     if (name) {
--- a/security/nss/lib/certdb/genname.h
+++ b/security/nss/lib/certdb/genname.h
@@ -21,16 +21,19 @@ extern SECItem **
 cert_EncodeGeneralNames(PLArenaPool *arena, CERTGeneralName *names);
 
 extern CERTGeneralName *
 cert_DecodeGeneralNames(PLArenaPool *arena, SECItem **encodedGenName);
 
 extern SECStatus
 cert_DestroyGeneralNames(CERTGeneralName *name);
 
+extern CERTGeneralNameType
+CERT_GetGeneralNameTypeFromString(const char *string);
+
 extern SECStatus 
 cert_EncodeNameConstraints(CERTNameConstraints *constraints, PLArenaPool *arena,
 			   SECItem *dest);
 
 extern CERTNameConstraints *
 cert_DecodeNameConstraints(PLArenaPool *arena, const SECItem *encodedConstraints);
 
 extern CERTGeneralName *
--- a/security/nss/lib/cryptohi/cryptohi.h
+++ b/security/nss/lib/cryptohi/cryptohi.h
@@ -51,17 +51,17 @@ extern SECItem *DSAU_DecodeDerSigToLen(c
 
 /****************************************/
 /*
 ** Signature creation operations
 */
 
 /*
 ** Create a new signature context used for signing a data stream.
-**	"alg" the signature algorithm to use (e.g. SEC_OID_RSA_WITH_MD5)
+**      "alg" the signature algorithm to use (e.g. SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION)
 **	"privKey" the private key to use
 */
 extern SGNContext *SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *privKey);
 
 /*
 ** Destroy a signature-context object
 **	"cx" the object
 **	"freeit" if PR_TRUE then free the object as well as its sub-objects
--- a/security/nss/lib/cryptohi/secsign.c
+++ b/security/nss/lib/cryptohi/secsign.c
@@ -32,17 +32,17 @@ SGN_NewContext(SECOidTag alg, SECKEYPriv
     KeyType keyType;
     SECStatus rv;
 
     /* OK, map a PKCS #7 hash and encrypt algorithm into
      * a standard hashing algorithm. Why did we pass in the whole
      * PKCS #7 algTag if we were just going to change here you might
      * ask. Well the answer is for some cards we may have to do the
      * hashing on card. It may not support CKM_RSA_PKCS sign algorithm,
-     * it may just support CKM_RSA_PKCS_WITH_SHA1 and/or CKM_RSA_PKCS_WITH_MD5.
+     * it may just support CKM_SHA1_RSA_PKCS and/or CKM_MD5_RSA_PKCS.
      */
     /* we have a private key, not a public key, so don't pass it in */
     rv =  sec_DecodeSigAlg(NULL, alg, NULL, &signalg, &hashalg);
     if (rv != SECSuccess) {
 	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
 	return 0;
     }
     keyType = seckey_GetKeyType(signalg);
--- a/security/nss/lib/freebl/rsa.c
+++ b/security/nss/lib/freebl/rsa.c
@@ -1401,16 +1401,27 @@ RSA_PrivateKeyCheck(RSAPrivateKey *key)
     CHECK_MPI_OK( mp_init(&psub1));
     CHECK_MPI_OK( mp_init(&qsub1));
     CHECK_MPI_OK( mp_init(&e)    );
     CHECK_MPI_OK( mp_init(&d)    );
     CHECK_MPI_OK( mp_init(&d_p)  );
     CHECK_MPI_OK( mp_init(&d_q)  );
     CHECK_MPI_OK( mp_init(&qInv) );
     CHECK_MPI_OK( mp_init(&res)  );
+
+    if (!key->modulus.data || !key->prime1.data || !key->prime2.data ||
+        !key->publicExponent.data || !key->privateExponent.data ||
+        !key->exponent1.data || !key->exponent2.data ||
+        !key->coefficient.data) {
+        /*call RSA_PopulatePrivateKey first, if the application wishes to
+         * recover these parameters */
+        err = MP_BADARG;
+        goto cleanup;
+    }
+
     SECITEM_TO_MPINT(key->modulus,         &n);
     SECITEM_TO_MPINT(key->prime1,          &p);
     SECITEM_TO_MPINT(key->prime2,          &q);
     SECITEM_TO_MPINT(key->publicExponent,  &e);
     SECITEM_TO_MPINT(key->privateExponent, &d);
     SECITEM_TO_MPINT(key->exponent1,       &d_p);
     SECITEM_TO_MPINT(key->exponent2,       &d_q);
     SECITEM_TO_MPINT(key->coefficient,     &qInv);
@@ -1453,37 +1464,29 @@ RSA_PrivateKeyCheck(RSAPrivateKey *key)
     VERIFY_MPI_EQUAL_1(&res);
     /* d*e == 1 mod p-1 */
     CHECK_MPI_OK( mp_mulmod(&d, &e, &psub1, &res) );
     VERIFY_MPI_EQUAL_1(&res);
     /* d*e == 1 mod q-1 */
     CHECK_MPI_OK( mp_mulmod(&d, &e, &qsub1, &res) );
     VERIFY_MPI_EQUAL_1(&res);
     /*
-     * The following errors can be recovered from.
+     * The following errors can be recovered from. However, the purpose of this
+     * function is to check consistency, so they are not.
      */
     /* d_p == d mod p-1 */
     CHECK_MPI_OK( mp_mod(&d, &psub1, &res) );
-    if (mp_cmp(&d_p, &res) != 0) {
-	/* swap in the correct value */
-	CHECK_SEC_OK( swap_in_key_value(key->arena, &res, &key->exponent1) );
-    }
+    VERIFY_MPI_EQUAL(&res, &d_p);
     /* d_q == d mod q-1 */
     CHECK_MPI_OK( mp_mod(&d, &qsub1, &res) );
-    if (mp_cmp(&d_q, &res) != 0) {
-	/* swap in the correct value */
-	CHECK_SEC_OK( swap_in_key_value(key->arena, &res, &key->exponent2) );
-    }
+    VERIFY_MPI_EQUAL(&res, &d_q);
     /* q * q**-1 == 1 mod p */
     CHECK_MPI_OK( mp_mulmod(&q, &qInv, &p, &res) );
-    if (mp_cmp_d(&res, 1) != 0) {
-	/* compute the correct value */
-	CHECK_MPI_OK( mp_invmod(&q, &p, &qInv) );
-	CHECK_SEC_OK( swap_in_key_value(key->arena, &qInv, &key->coefficient) );
-    }
+    VERIFY_MPI_EQUAL_1(&res);
+
 cleanup:
     mp_clear(&n);
     mp_clear(&p);
     mp_clear(&q);
     mp_clear(&psub1);
     mp_clear(&qsub1);
     mp_clear(&e);
     mp_clear(&d);
--- a/security/nss/lib/nss/nss.def
+++ b/security/nss/lib/nss/nss.def
@@ -1050,13 +1050,15 @@ CERT_GetSubjectPublicKeyDigest;
 PK11_ExportDERPrivateKeyInfo;
 PK11_ExportPrivKeyInfo;
 SECMOD_InternaltoPubMechFlags;
 ;+    local:
 ;+       *;
 ;+};
 ;+NSS_3.16.2 { 	# NSS 3.16.2 release
 ;+    global:
+CERT_AddExtensionByOID;
+CERT_GetGeneralNameTypeFromString;
 PK11_PubEncrypt;
 PK11_PrivDecrypt;
 ;+    local:
 ;+       *;
 ;+};
--- a/security/nss/lib/pk11wrap/pk11cert.c
+++ b/security/nss/lib/pk11wrap/pk11cert.c
@@ -976,18 +976,25 @@ PK11_ImportCert(PK11SlotInfo *slot, CERT
 	cert->istemp = PR_FALSE;
 	cert->isperm = PR_TRUE;
     }
 
     /* add the new instance to the cert, force an update of the
      * CERTCertificate, and finish
      */
     nssPKIObject_AddInstance(&c->object, certobj);
+    /* nssTrustDomain_AddCertsToCache may release a reference to 'c' and
+     * replace 'c' by a different value. So we add a reference to 'c' to
+     * prevent 'c' from being destroyed. */
+    nssCertificate_AddRef(c);
     nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1);
+    /* XXX should we pass the original value of 'c' to
+     * STAN_ForceCERTCertificateUpdate? */
     (void)STAN_ForceCERTCertificateUpdate(c);
+    nssCertificate_Destroy(c);
     SECITEM_FreeItem(keyID,PR_TRUE);
     return SECSuccess;
 loser:
     CERT_MapStanError();
     SECITEM_FreeItem(keyID,PR_TRUE);
     if (PORT_GetError() != SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
 	PORT_SetError(SEC_ERROR_ADDING_CERT);
     }
--- a/security/nss/lib/pk11wrap/pk11load.c
+++ b/security/nss/lib/pk11wrap/pk11load.c
@@ -50,16 +50,21 @@ CK_RV PR_CALLBACK secmodUnlockMutext(CK_
 
 static SECMODModuleID  nextModuleID = 1;
 static const CK_C_INITIALIZE_ARGS secmodLockFunctions = {
     secmodCreateMutext, secmodDestroyMutext, secmodLockMutext, 
     secmodUnlockMutext, CKF_LIBRARY_CANT_CREATE_OS_THREADS|
 	CKF_OS_LOCKING_OK
     ,NULL
 };
+static const CK_C_INITIALIZE_ARGS secmodNoLockArgs = {
+    NULL, NULL, NULL, NULL,
+    CKF_LIBRARY_CANT_CREATE_OS_THREADS
+    ,NULL
+};
 
 static PRBool loadSingleThreadedModules = PR_TRUE;
 static PRBool enforceAlreadyInitializedError = PR_TRUE;
 static PRBool finalizeModules = PR_TRUE;
 
 /* set global options for NSS PKCS#11 module loader */
 SECStatus pk11_setGlobalOptions(PRBool noSingleThreadedModules,
                                 PRBool allowAlreadyInitializedModules,
@@ -204,22 +209,28 @@ secmod_ModuleInit(SECMODModule *mod, SEC
 	*reload = NULL;
     }
 
     if (!mod || !alreadyLoaded) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
-    if (mod->isThreadSafe == PR_FALSE) {
-	pInitArgs = NULL;
-    } else if (mod->libraryParams == NULL) {
-	pInitArgs = (void *) &secmodLockFunctions;
+    if (mod->libraryParams == NULL) {
+	if (mod->isThreadSafe) {
+	    pInitArgs = (void *) &secmodLockFunctions;
+	} else {
+	    pInitArgs = NULL;
+	}
     } else {
-	moduleArgs = secmodLockFunctions;
+	if (mod->isThreadSafe) {
+	    moduleArgs = secmodLockFunctions;
+	} else {
+	    moduleArgs = secmodNoLockArgs;
+	}
 	moduleArgs.LibraryParameters = (void *) mod->libraryParams;
 	pInitArgs = &moduleArgs;
     }
     crv = PK11_GETTAB(mod)->C_Initialize(pInitArgs);
     if (CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) {
 	SECMODModule *oldModule = NULL;
 
 	/* Library has already been loaded once, if caller expects it, and it
@@ -246,28 +257,40 @@ secmod_ModuleInit(SECMODModule *mod, SEC
 	}
 	/* reload not possible, fall back to old semantics */
 	if (!enforceAlreadyInitializedError) {
        	    *alreadyLoaded = PR_TRUE;
             return SECSuccess;
 	}
     }
     if (crv != CKR_OK) {
-	if (pInitArgs == NULL ||
+	if (!mod->isThreadSafe ||
 		crv == CKR_NETSCAPE_CERTDB_FAILED ||
 		crv == CKR_NETSCAPE_KEYDB_FAILED) {
 	    PORT_SetError(PK11_MapError(crv));
 	    return SECFailure;
 	}
+	/* If we had attempted to init a single threaded module "with"
+	 * parameters and it failed, should we retry "without" parameters?
+	 * (currently we don't retry in this scenario) */
+
 	if (!loadSingleThreadedModules) {
 	    PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11);
 	    return SECFailure;
 	}
+	/* If we arrive here, the module failed a ThreadSafe init. */
 	mod->isThreadSafe = PR_FALSE;
-    	crv = PK11_GETTAB(mod)->C_Initialize(NULL);
+	if (!mod->libraryParams) {
+	    pInitArgs = NULL;
+	} else {
+	    moduleArgs = secmodNoLockArgs;
+	    moduleArgs.LibraryParameters = (void *) mod->libraryParams;
+	    pInitArgs = &moduleArgs;
+	}
+    	crv = PK11_GETTAB(mod)->C_Initialize(pInitArgs);
 	if ((CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) &&
 	    (!enforceAlreadyInitializedError)) {
 	    *alreadyLoaded = PR_TRUE;
 	    return SECSuccess;
 	}
     	if (crv != CKR_OK)  {
 	    PORT_SetError(PK11_MapError(crv));
 	    return SECFailure;
--- a/security/nss/lib/softoken/legacydb/pcertdb.c
+++ b/security/nss/lib/softoken/legacydb/pcertdb.c
@@ -4593,19 +4593,22 @@ nsslowcert_OpenCertDB(NSSLOWCERTCertDBHa
 
     rv = nsslowcert_OpenPermCertDB(handle, readOnly, appName, prefix, 
 							namecb, cbarg);
     if ( rv ) {
 	goto loser;
     }
 
     return (SECSuccess);
-    
+
 loser:
-
+    if (handle->dbMon) {
+        PZ_DestroyMonitor(handle->dbMon);
+        handle->dbMon = NULL;
+    }
     PORT_SetError(SEC_ERROR_BAD_DATABASE);
     return(SECFailure);
 }
 
 PRBool
 nsslowcert_needDBVerify(NSSLOWCERTCertDBHandle *handle)
 {
     if (!handle) return PR_FALSE;
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -984,38 +984,40 @@ sftk_handlePublicKeyObject(SFTKSession *
 
     return CKR_OK;
 }
 
 static NSSLOWKEYPrivateKey * 
 sftk_mkPrivKey(SFTKObject *object,CK_KEY_TYPE key, CK_RV *rvp);
 
 static SECStatus
-sftk_fillRSAPrivateKey(SFTKObject *object);
+sftk_verifyRSAPrivateKey(SFTKObject *object, PRBool fillIfNeeded);
 
 /*
  * check the consistancy and initialize a Private Key Object 
  */
 static CK_RV
 sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE key_type)
 {
     CK_BBOOL cktrue = CK_TRUE;
     CK_BBOOL encrypt = CK_TRUE;
     CK_BBOOL sign = CK_FALSE;
     CK_BBOOL recover = CK_TRUE;
     CK_BBOOL wrap = CK_TRUE;
     CK_BBOOL derive = CK_TRUE;
     CK_BBOOL ckfalse = CK_FALSE;
     PRBool createObjectInfo = PR_TRUE;
+    PRBool fillPrivateKey = PR_FALSE;
     int missing_rsa_mod_component = 0;
     int missing_rsa_exp_component = 0;
     int missing_rsa_crt_component = 0;
-    
+
     SECItem mod;
     CK_RV crv;
+    SECStatus rv;
 
     switch (key_type) {
     case CKK_RSA:
 	if ( !sftk_hasAttribute(object, CKA_MODULUS)) {
 	    missing_rsa_mod_component++;
 	}
 	if ( !sftk_hasAttribute(object, CKA_PUBLIC_EXPONENT)) {
 	    missing_rsa_exp_component++;
@@ -1040,29 +1042,29 @@ sftk_handlePrivateKeyObject(SFTKSession 
 	}
 	if (missing_rsa_mod_component || missing_rsa_exp_component || 
 					 missing_rsa_crt_component) {
 	    /* we are missing a component, see if we have enough to rebuild
 	     * the rest */
 	    int have_exp = 2- missing_rsa_exp_component;
 	    int have_component = 5- 
 		(missing_rsa_exp_component+missing_rsa_mod_component);
-	    SECStatus rv;
 
 	    if ((have_exp == 0) || (have_component < 3)) {
 		/* nope, not enough to reconstruct the private key */
 		return CKR_TEMPLATE_INCOMPLETE;
 	    }
-	    /*fill in the missing parameters */
-	    rv = sftk_fillRSAPrivateKey(object);
-	    if (rv != SECSuccess) {
+	    fillPrivateKey = PR_TRUE;
+	}
+	/*verify the parameters for consistency*/
+	rv = sftk_verifyRSAPrivateKey(object, fillPrivateKey);
+	if (rv != SECSuccess) {
 		return CKR_TEMPLATE_INCOMPLETE;
-	    }
 	}
-		
+
 	/* make sure Netscape DB attribute is set correctly */
 	crv = sftk_Attribute2SSecItem(NULL, &mod, object, CKA_MODULUS);
 	if (crv != CKR_OK) return crv;
 	crv = sftk_forceAttribute(object, CKA_NETSCAPE_DB, 
 						sftk_item_expand(&mod));
 	if (mod.data) PORT_Free(mod.data);
 	if (crv != CKR_OK) return crv;
 
@@ -1146,17 +1148,16 @@ sftk_handlePrivateKeyObject(SFTKSession 
 						&ckfalse,sizeof(CK_BBOOL));
     if (crv != CKR_OK)  return crv; 
 
     /* should we check the non-token RSA private keys? */
 
     if (sftk_isTrue(object,CKA_TOKEN)) {
 	SFTKSlot *slot = session->slot;
 	SFTKDBHandle *keyHandle = sftk_getKeyDB(slot);
-	CK_RV crv;
 
 	if (keyHandle == NULL) {
 	    return CKR_TOKEN_WRITE_PROTECTED;
 	}
 
 	crv = sftkdb_write(keyHandle, object, &object->handle);
 	sftk_freeDB(keyHandle);
 	return crv;
@@ -1937,27 +1938,31 @@ sftk_mkPrivKey(SFTKObject *object, CK_KE
     if (crv != CKR_OK) {
 	PORT_FreeArena(arena,PR_FALSE);
 	return NULL;
     }
     return privKey;
 }
 
 /*
- * we have a partial rsa private key, fill in the rest
+ * If a partial RSA private key is present, fill in the rest if necessary,
+ * and then verify the parameters are well-formed
  */
 static SECStatus
-sftk_fillRSAPrivateKey(SFTKObject *object)
+sftk_verifyRSAPrivateKey(SFTKObject *object, PRBool fillIfNeeded)
 {
     RSAPrivateKey tmpKey = { 0 };
     SFTKAttribute *modulus = NULL;
     SFTKAttribute *prime1 = NULL;
     SFTKAttribute *prime2 = NULL;
     SFTKAttribute *privateExponent = NULL;
     SFTKAttribute *publicExponent = NULL;
+    SFTKAttribute *exponent1 = NULL;
+    SFTKAttribute *exponent2 = NULL;
+    SFTKAttribute *coefficient = NULL;
     SECStatus rv;
     CK_RV crv;
 
     /* first fill in the components that we have. Populate only uses
      * the non-crt components, so only fill those in  */
     tmpKey.arena = NULL;
     modulus = sftk_FindAttribute(object, CKA_MODULUS);
     if (modulus) {
@@ -1978,54 +1983,92 @@ sftk_fillRSAPrivateKey(SFTKObject *objec
     if (privateExponent) {
 	tmpKey.privateExponent.data = privateExponent->attrib.pValue;
 	tmpKey.privateExponent.len  = privateExponent->attrib.ulValueLen;
     } 
     publicExponent = sftk_FindAttribute(object, CKA_PUBLIC_EXPONENT);
     if (publicExponent) {
 	tmpKey.publicExponent.data = publicExponent->attrib.pValue;
 	tmpKey.publicExponent.len  = publicExponent->attrib.ulValueLen;
-    } 
-
-    /*
-     * populate requires one exponent plus 2 other components to work.
-     * we expected our caller to check that first. If that didn't happen,
-     * populate will simply return an error here.
-     */
-    rv = RSA_PopulatePrivateKey(&tmpKey);
+    }
+    exponent1 = sftk_FindAttribute(object, CKA_EXPONENT_1);
+    if (exponent1) {
+	tmpKey.exponent1.data = exponent1->attrib.pValue;
+	tmpKey.exponent1.len  = exponent1->attrib.ulValueLen;
+    }
+    exponent2 = sftk_FindAttribute(object, CKA_EXPONENT_2);
+    if (exponent2) {
+	tmpKey.exponent2.data = exponent2->attrib.pValue;
+	tmpKey.exponent2.len  = exponent2->attrib.ulValueLen;
+    }
+    coefficient = sftk_FindAttribute(object, CKA_COEFFICIENT);
+    if (coefficient) {
+	tmpKey.coefficient.data = coefficient->attrib.pValue;
+	tmpKey.coefficient.len  = coefficient->attrib.ulValueLen;
+    }
+
+    if (fillIfNeeded) {
+	/*
+	* populate requires one exponent plus 2 other components to work.
+	* we expected our caller to check that first. If that didn't happen,
+	* populate will simply return an error here.
+	*/
+	rv = RSA_PopulatePrivateKey(&tmpKey);
+	if (rv != SECSuccess) {
+		goto loser;
+	}
+    }
+    rv = RSA_PrivateKeyCheck(&tmpKey);
     if (rv != SECSuccess) {
 	goto loser;
     }
-
     /* now that we have a fully populated key, set all our attribute values */
     rv = SECFailure;
-    crv = sftk_forceAttribute(object,CKA_MODULUS,
-                       sftk_item_expand(&tmpKey.modulus));
-    if (crv != CKR_OK) goto loser;
-    crv = sftk_forceAttribute(object,CKA_PUBLIC_EXPONENT,
-                       sftk_item_expand(&tmpKey.publicExponent));
-    if (crv != CKR_OK) goto loser;
-    crv = sftk_forceAttribute(object,CKA_PRIVATE_EXPONENT,
-                       sftk_item_expand(&tmpKey.privateExponent));
-    if (crv != CKR_OK) goto loser;
-    crv = sftk_forceAttribute(object,CKA_PRIME_1,
-                       sftk_item_expand(&tmpKey.prime1));
-    if (crv != CKR_OK) goto loser;
-    crv = sftk_forceAttribute(object,CKA_PRIME_2,
-                       sftk_item_expand(&tmpKey.prime2));
-    if (crv != CKR_OK) goto loser;
-    crv = sftk_forceAttribute(object,CKA_EXPONENT_1,
-                       sftk_item_expand(&tmpKey.exponent1));
-    if (crv != CKR_OK) goto loser;
-    crv = sftk_forceAttribute(object,CKA_EXPONENT_2,
-                       sftk_item_expand(&tmpKey.exponent2));
-    if (crv != CKR_OK) goto loser;
-    crv = sftk_forceAttribute(object,CKA_COEFFICIENT,
-                       sftk_item_expand(&tmpKey.coefficient));
-    if (crv != CKR_OK) goto loser;
+    if (!modulus || modulus->attrib.pValue != tmpKey.modulus.data) {
+        crv = sftk_forceAttribute(object,CKA_MODULUS,
+                                  sftk_item_expand(&tmpKey.modulus));
+        if (crv != CKR_OK) goto loser;
+    }
+    if (!publicExponent ||
+        publicExponent->attrib.pValue != tmpKey.publicExponent.data) {
+        crv = sftk_forceAttribute(object, CKA_PUBLIC_EXPONENT,
+                                  sftk_item_expand(&tmpKey.publicExponent));
+        if (crv != CKR_OK) goto loser;
+    }
+    if (!privateExponent ||
+        privateExponent->attrib.pValue != tmpKey.privateExponent.data) {
+        crv = sftk_forceAttribute(object, CKA_PRIVATE_EXPONENT,
+                                  sftk_item_expand(&tmpKey.privateExponent));
+        if (crv != CKR_OK) goto loser;
+    }
+    if (!prime1 || prime1->attrib.pValue != tmpKey.prime1.data) {
+        crv = sftk_forceAttribute(object, CKA_PRIME_1,
+                                  sftk_item_expand(&tmpKey.prime1));
+        if (crv != CKR_OK) goto loser;
+    }
+    if (!prime2 || prime2->attrib.pValue != tmpKey.prime2.data) {
+        crv = sftk_forceAttribute(object, CKA_PRIME_2,
+                                  sftk_item_expand(&tmpKey.prime2));
+        if (crv != CKR_OK) goto loser;
+    }
+    if (!exponent1 || exponent1->attrib.pValue != tmpKey.exponent1.data) {
+        crv = sftk_forceAttribute(object, CKA_EXPONENT_1,
+                                 sftk_item_expand(&tmpKey.exponent1));
+        if (crv != CKR_OK) goto loser;
+    }
+    if (!exponent1 || exponent1->attrib.pValue != tmpKey.exponent1.data) {
+        crv = sftk_forceAttribute(object, CKA_EXPONENT_2,
+                                  sftk_item_expand(&tmpKey.exponent2));
+        if (crv != CKR_OK) goto loser;
+    }
+    if (!exponent1 || exponent1->attrib.pValue != tmpKey.exponent1.data) {
+        crv = sftk_forceAttribute(object, CKA_COEFFICIENT,
+                                  sftk_item_expand(&tmpKey.coefficient));
+        if (crv != CKR_OK) goto loser;
+    }
     rv = SECSuccess;
 
     /* we're done (one way or the other), clean up all our stuff */
 loser:
     if (tmpKey.arena) {
 	PORT_FreeArena(tmpKey.arena,PR_TRUE);
     }
     if (modulus) {
@@ -2041,22 +2084,16 @@ loser:
 	sftk_FreeAttribute(privateExponent);
     }
     if (publicExponent) {
 	sftk_FreeAttribute(publicExponent);
     }
     return rv;
 }
 
-
-
-
-
-
-
 /* Generate a low private key structure from an object */
 NSSLOWKEYPrivateKey *
 sftk_GetPrivKey(SFTKObject *object,CK_KEY_TYPE key_type, CK_RV *crvp)
 {
     NSSLOWKEYPrivateKey *priv = NULL;
 
     if (object->objclass != CKO_PRIVATE_KEY) {
 	*crvp = CKR_KEY_TYPE_INCONSISTENT;
@@ -3125,19 +3162,16 @@ CK_RV NSC_GetSlotList(CK_BBOOL tokenPres
 CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
 {
     SFTKSlot *slot = sftk_SlotFromID(slotID, PR_TRUE);
 
     CHECK_FORK();
 
     if (slot == NULL) return CKR_SLOT_ID_INVALID;
 
-    pInfo->firmwareVersion.major = 0;
-    pInfo->firmwareVersion.minor = 0;
-
     PORT_Memcpy(pInfo->manufacturerID,manufacturerID,
 		sizeof(pInfo->manufacturerID));
     PORT_Memcpy(pInfo->slotDescription,slot->slotDescription,
 		sizeof(pInfo->slotDescription));
     pInfo->flags = (slot->present) ? CKF_TOKEN_PRESENT : 0;
 
     /* all user defined slots are defined as removable */
     if (slotID >= SFTK_MIN_USER_SLOT_ID) {
@@ -3154,16 +3188,18 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID,
             sftk_freeDB(handle);
 	}
     }
 
     /* ok we really should read it out of the keydb file. */
     /* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */
     pInfo->hardwareVersion.major = SOFTOKEN_VMAJOR;
     pInfo->hardwareVersion.minor = SOFTOKEN_VMINOR;
+    pInfo->firmwareVersion.major = SOFTOKEN_VPATCH;
+    pInfo->firmwareVersion.minor = SOFTOKEN_VBUILD;
     return CKR_OK;
 }
 
 /*
  * check the current state of the 'needLogin' flag in case the database has
  * been changed underneath us.
  */
 static PRBool
--- a/security/nss/lib/ssl/SSLerrs.h
+++ b/security/nss/lib/ssl/SSLerrs.h
@@ -407,8 +407,14 @@ ER3(SSL_ERROR_RX_UNEXPECTED_CERT_STATUS,
 ER3(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM, (SSL_ERROR_BASE + 126),
 "Unsupported hash algorithm used by TLS peer.")
 
 ER3(SSL_ERROR_DIGEST_FAILURE, (SSL_ERROR_BASE + 127),
 "Digest function failed.")
 
 ER3(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 128),
 "Incorrect signature algorithm specified in a digitally-signed element.")
+
+ER3(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK, (SSL_ERROR_BASE + 129),
+"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.")
--- a/security/nss/lib/ssl/dtlscon.c
+++ b/security/nss/lib/ssl/dtlscon.c
@@ -46,77 +46,86 @@ static const ssl3CipherSuite nonDTLSSuit
     0 /* End of list marker */
 };
 
 /* Map back and forth between TLS and DTLS versions in wire format.
  * Mapping table is:
  *
  * TLS             DTLS
  * 1.1 (0302)      1.0 (feff)
+ * 1.2 (0303)      1.2 (fefd)
  */
 SSL3ProtocolVersion
 dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv)
 {
-    /* Anything other than TLS 1.1 is an error, so return
-     * the invalid version ffff. */
-    if (tlsv != SSL_LIBRARY_VERSION_TLS_1_1)
-	return 0xffff;
+    if (tlsv == SSL_LIBRARY_VERSION_TLS_1_1) {
+        return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
+    }
+    if (tlsv == SSL_LIBRARY_VERSION_TLS_1_2) {
+        return SSL_LIBRARY_VERSION_DTLS_1_2_WIRE;
+    }
 
-    return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
+    /* Anything other than TLS 1.1 or 1.2 is an error, so return
+     * the invalid version 0xffff. */
+    return 0xffff;
 }
 
 /* Map known DTLS versions to known TLS versions.
  * - Invalid versions (< 1.0) return a version of 0
  * - Versions > known return a version one higher than we know of
  * to accomodate a theoretically newer version */
 SSL3ProtocolVersion
 dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv)
 {
     if (MSB(dtlsv) == 0xff) {
-	return 0;
+        return 0;
     }
 
-    if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_0_WIRE)
-	return SSL_LIBRARY_VERSION_TLS_1_1;
+    if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_0_WIRE) {
+        return SSL_LIBRARY_VERSION_TLS_1_1;
+    }
+    if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_2_WIRE) {
+        return SSL_LIBRARY_VERSION_TLS_1_2;
+    }
 
     /* Return a fictional higher version than we know of */
-    return SSL_LIBRARY_VERSION_TLS_1_1 + 1;
+    return SSL_LIBRARY_VERSION_TLS_1_2 + 1;
 }
 
 /* On this socket, Disable non-DTLS cipher suites in the argument's list */
 SECStatus
 ssl3_DisableNonDTLSSuites(sslSocket * ss)
 {
     const ssl3CipherSuite * suite;
 
     for (suite = nonDTLSSuites; *suite; ++suite) {
-	SECStatus rv = ssl3_CipherPrefSet(ss, *suite, PR_FALSE);
+        SECStatus rv = ssl3_CipherPrefSet(ss, *suite, PR_FALSE);
 
-	PORT_Assert(rv == SECSuccess); /* else is coding error */
+        PORT_Assert(rv == SECSuccess); /* else is coding error */
     }
     return SECSuccess;
 }
 
 /* Allocate a DTLSQueuedMessage.
  *
  * Called from dtls_QueueMessage()
  */
 static DTLSQueuedMessage *
 dtls_AllocQueuedMessage(PRUint16 epoch, SSL3ContentType type,
-			const unsigned char *data, PRUint32 len)
+                        const unsigned char *data, PRUint32 len)
 {
     DTLSQueuedMessage *msg = NULL;
 
     msg = PORT_ZAlloc(sizeof(DTLSQueuedMessage));
     if (!msg)
-	return NULL;
+        return NULL;
 
     msg->data = PORT_Alloc(len);
     if (!msg->data) {
-	PORT_Free(msg);
+        PORT_Free(msg);
         return NULL;
     }
     PORT_Memcpy(msg->data, data, len);
 
     msg->len = len;
     msg->epoch = epoch;
     msg->type = type;
 
@@ -127,17 +136,17 @@ dtls_AllocQueuedMessage(PRUint16 epoch, 
  * Free a handshake message
  *
  * Called from dtls_FreeHandshakeMessages()
  */
 static void
 dtls_FreeHandshakeMessage(DTLSQueuedMessage *msg)
 {
     if (!msg)
-	return;
+        return;
 
     PORT_ZFree(msg->data, msg->len);
     PORT_Free(msg);
 }
 
 /*
  * Free a list of handshake messages
  *
@@ -146,19 +155,19 @@ dtls_FreeHandshakeMessage(DTLSQueuedMess
  *              ssl3_DestroySSL3Info()
  */
 void
 dtls_FreeHandshakeMessages(PRCList *list)
 {
     PRCList *cur_p;
 
     while (!PR_CLIST_IS_EMPTY(list)) {
-	cur_p = PR_LIST_TAIL(list);
-	PR_REMOVE_LINK(cur_p);
-	dtls_FreeHandshakeMessage((DTLSQueuedMessage *)cur_p);
+        cur_p = PR_LIST_TAIL(list);
+        PR_REMOVE_LINK(cur_p);
+        dtls_FreeHandshakeMessage((DTLSQueuedMessage *)cur_p);
     }
 }
 
 /* Called only from ssl3_HandleRecord, for each (deciphered) DTLS record.
  * origBuf is the decrypted ssl record content and is expected to contain
  * complete handshake records
  * Caller must hold the handshake and RecvBuf locks.
  *
@@ -199,161 +208,161 @@ dtls_HandleHandshake(sslSocket *ss, sslB
 
         if (buf.len < 12) {
             PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
             rv = SECFailure;
             break;
         }
 
         /* Parse the header */
-	type = buf.buf[0];
+        type = buf.buf[0];
         message_length = (buf.buf[1] << 16) | (buf.buf[2] << 8) | buf.buf[3];
         message_seq = (buf.buf[4] << 8) | buf.buf[5];
         fragment_offset = (buf.buf[6] << 16) | (buf.buf[7] << 8) | buf.buf[8];
         fragment_length = (buf.buf[9] << 16) | (buf.buf[10] << 8) | buf.buf[11];
-	
-#define MAX_HANDSHAKE_MSG_LEN 0x1ffff	/* 128k - 1 */
-	if (message_length > MAX_HANDSHAKE_MSG_LEN) {
-	    (void)ssl3_DecodeError(ss);
-	    PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
-	    return SECFailure;
-	}
+
+#define MAX_HANDSHAKE_MSG_LEN 0x1ffff   /* 128k - 1 */
+        if (message_length > MAX_HANDSHAKE_MSG_LEN) {
+            (void)ssl3_DecodeError(ss);
+            PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
+            return SECFailure;
+        }
 #undef MAX_HANDSHAKE_MSG_LEN
 
         buf.buf += 12;
         buf.len -= 12;
 
         /* This fragment must be complete */
         if (buf.len < fragment_length) {
             PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
             rv = SECFailure;
             break;
         }
 
         /* Sanity check the packet contents */
-	if ((fragment_length + fragment_offset) > message_length) {
+        if ((fragment_length + fragment_offset) > message_length) {
             PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
             rv = SECFailure;
             break;
         }
 
         /* There are three ways we could not be ready for this packet.
          *
          * 1. It's a partial next message.
          * 2. It's a partial or complete message beyond the next
          * 3. It's a message we've already seen
          *
          * If it's the complete next message we accept it right away.
          * This is the common case for short messages
          */
         if ((message_seq == ss->ssl3.hs.recvMessageSeq)
-	    && (fragment_offset == 0)
-	    && (fragment_length == message_length)) {
+            && (fragment_offset == 0)
+            && (fragment_length == message_length)) {
             /* Complete next message. Process immediately */
             ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
             ss->ssl3.hs.msg_len = message_length;
 
             /* At this point we are advancing our state machine, so
              * we can free our last flight of messages */
             dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
-	    ss->ssl3.hs.recvdHighWater = -1;
-	    dtls_CancelTimer(ss);
+            ss->ssl3.hs.recvdHighWater = -1;
+            dtls_CancelTimer(ss);
 
-	    /* Reset the timer to the initial value if the retry counter
-	     * is 0, per Sec. 4.2.4.1 */
-	    if (ss->ssl3.hs.rtRetries == 0) {
-		ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
-	    }
+            /* Reset the timer to the initial value if the retry counter
+             * is 0, per Sec. 4.2.4.1 */
+            if (ss->ssl3.hs.rtRetries == 0) {
+                ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
+            }
 
             rv = ssl3_HandleHandshakeMessage(ss, buf.buf, ss->ssl3.hs.msg_len);
             if (rv == SECFailure) {
                 /* Do not attempt to process rest of messages in this record */
                 break;
             }
         } else {
-	    if (message_seq < ss->ssl3.hs.recvMessageSeq) {
-		/* Case 3: we do an immediate retransmit if we're
-		 * in a waiting state*/
-		if (ss->ssl3.hs.rtTimerCb == NULL) {
-		    /* Ignore */
-		} else if (ss->ssl3.hs.rtTimerCb ==
-			 dtls_RetransmitTimerExpiredCb) {
-		    SSL_TRC(30, ("%d: SSL3[%d]: Retransmit detected",
-				 SSL_GETPID(), ss->fd));
-		    /* Check to see if we retransmitted recently. If so,
-		     * suppress the triggered retransmit. This avoids
-		     * retransmit wars after packet loss.
-		     * This is not in RFC 5346 but should be
-		     */
-		    if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
-			(ss->ssl3.hs.rtTimeoutMs / 4)) {
-			    SSL_TRC(30,
-			    ("%d: SSL3[%d]: Shortcutting retransmit timer",
+            if (message_seq < ss->ssl3.hs.recvMessageSeq) {
+                /* Case 3: we do an immediate retransmit if we're
+                 * in a waiting state*/
+                if (ss->ssl3.hs.rtTimerCb == NULL) {
+                    /* Ignore */
+                } else if (ss->ssl3.hs.rtTimerCb ==
+                         dtls_RetransmitTimerExpiredCb) {
+                    SSL_TRC(30, ("%d: SSL3[%d]: Retransmit detected",
+                                 SSL_GETPID(), ss->fd));
+                    /* Check to see if we retransmitted recently. If so,
+                     * suppress the triggered retransmit. This avoids
+                     * retransmit wars after packet loss.
+                     * This is not in RFC 5346 but should be
+                     */
+                    if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
+                        (ss->ssl3.hs.rtTimeoutMs / 4)) {
+                            SSL_TRC(30,
+                            ("%d: SSL3[%d]: Shortcutting retransmit timer",
                             SSL_GETPID(), ss->fd));
 
-			    /* Cancel the timer and call the CB,
-			     * which re-arms the timer */
-			    dtls_CancelTimer(ss);
-			    dtls_RetransmitTimerExpiredCb(ss);
-			    rv = SECSuccess;
-			    break;
-			} else {
-			    SSL_TRC(30,
-			    ("%d: SSL3[%d]: We just retransmitted. Ignoring.",
+                            /* Cancel the timer and call the CB,
+                             * which re-arms the timer */
+                            dtls_CancelTimer(ss);
+                            dtls_RetransmitTimerExpiredCb(ss);
+                            rv = SECSuccess;
+                            break;
+                        } else {
+                            SSL_TRC(30,
+                            ("%d: SSL3[%d]: We just retransmitted. Ignoring.",
                             SSL_GETPID(), ss->fd));
-			    rv = SECSuccess;
-			    break;
-			}
-		} else if (ss->ssl3.hs.rtTimerCb == dtls_FinishedTimerCb) {
-		    /* Retransmit the messages and re-arm the timer
-		     * Note that we are not backing off the timer here.
-		     * The spec isn't clear and my reasoning is that this
-		     * may be a re-ordered packet rather than slowness,
-		     * so let's be aggressive. */
-		    dtls_CancelTimer(ss);
-		    rv = dtls_TransmitMessageFlight(ss);
-		    if (rv == SECSuccess) {
-			rv = dtls_StartTimer(ss, dtls_FinishedTimerCb);
-		    }
-		    if (rv != SECSuccess)
-			return rv;
-		    break;
-		}
-	    } else if (message_seq > ss->ssl3.hs.recvMessageSeq) {
-		/* Case 2
+                            rv = SECSuccess;
+                            break;
+                        }
+                } else if (ss->ssl3.hs.rtTimerCb == dtls_FinishedTimerCb) {
+                    /* Retransmit the messages and re-arm the timer
+                     * Note that we are not backing off the timer here.
+                     * The spec isn't clear and my reasoning is that this
+                     * may be a re-ordered packet rather than slowness,
+                     * so let's be aggressive. */
+                    dtls_CancelTimer(ss);
+                    rv = dtls_TransmitMessageFlight(ss);
+                    if (rv == SECSuccess) {
+                        rv = dtls_StartTimer(ss, dtls_FinishedTimerCb);
+                    }
+                    if (rv != SECSuccess)
+                        return rv;
+                    break;
+                }
+            } else if (message_seq > ss->ssl3.hs.recvMessageSeq) {
+                /* Case 2
                  *
-		 * Ignore this message. This means we don't handle out of
-		 * order complete messages that well, but we're still
-		 * compliant and this probably does not happen often
+                 * Ignore this message. This means we don't handle out of
+                 * order complete messages that well, but we're still
+                 * compliant and this probably does not happen often
                  *
-		 * XXX OK for now. Maybe do something smarter at some point?
-		 */
-	    } else {
-		/* Case 1
+                 * XXX OK for now. Maybe do something smarter at some point?
+                 */
+            } else {
+                /* Case 1
                  *
-		 * Buffer the fragment for reassembly
-		 */
+                 * Buffer the fragment for reassembly
+                 */
                 /* Make room for the message */
                 if (ss->ssl3.hs.recvdHighWater == -1) {
                     PRUint32 map_length = OFFSET_BYTE(message_length) + 1;
 
                     rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, message_length);
                     if (rv != SECSuccess)
                         break;
                     /* Make room for the fragment map */
                     rv = sslBuffer_Grow(&ss->ssl3.hs.recvdFragments,
                                         map_length);
                     if (rv != SECSuccess)
                         break;
 
                     /* Reset the reassembly map */
                     ss->ssl3.hs.recvdHighWater = 0;
                     PORT_Memset(ss->ssl3.hs.recvdFragments.buf, 0,
-				ss->ssl3.hs.recvdFragments.space);
-		    ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
+                                ss->ssl3.hs.recvdFragments.space);
+                    ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
                     ss->ssl3.hs.msg_len = message_length;
                 }
 
                 /* If we have a message length mismatch, abandon the reassembly
                  * in progress and hope that the next retransmit will give us
                  * something sane
                  */
                 if (message_length != ss->ssl3.hs.msg_len) {
@@ -376,35 +385,35 @@ dtls_HandleHandshake(sslSocket *ss, sslB
                  *   bytes received
                  * - recvdFragments contains a bitmask of packets received
                  *   above recvdHighWater
                  *
                  * This avoids having to fill in the bitmask in the common
                  * case of adjacent fragments received in sequence
                  */
                 if (fragment_offset <= ss->ssl3.hs.recvdHighWater) {
-		    /* Either this is the adjacent fragment or an overlapping
+                    /* Either this is the adjacent fragment or an overlapping
                      * fragment */
                     ss->ssl3.hs.recvdHighWater = fragment_offset +
                                                  fragment_length;
                 } else {
                     for (offset = fragment_offset;
                          offset < fragment_offset + fragment_length;
                          offset++) {
                         ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] |=
                             OFFSET_MASK(offset);
                     }
                 }
 
                 /* Now figure out the new high water mark if appropriate */
                 for (offset = ss->ssl3.hs.recvdHighWater;
                      offset < ss->ssl3.hs.msg_len; offset++) {
-		    /* Note that this loop is not efficient, since it counts
-		     * bit by bit. If we have a lot of out-of-order packets,
-		     * we should optimize this */
+                    /* Note that this loop is not efficient, since it counts
+                     * bit by bit. If we have a lot of out-of-order packets,
+                     * we should optimize this */
                     if (ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] &
                         OFFSET_MASK(offset)) {
                         ss->ssl3.hs.recvdHighWater++;
                     } else {
                         break;
                     }
                 }
 
@@ -413,35 +422,35 @@ dtls_HandleHandshake(sslSocket *ss, sslB
                     ss->ssl3.hs.recvdHighWater = -1;
 
                     rv = ssl3_HandleHandshakeMessage(ss,
                                                      ss->ssl3.hs.msg_body.buf,
                                                      ss->ssl3.hs.msg_len);
                     if (rv == SECFailure)
                         break; /* Skip rest of record */
 
-		    /* At this point we are advancing our state machine, so
-		     * we can free our last flight of messages */
-		    dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
-		    dtls_CancelTimer(ss);
+                    /* At this point we are advancing our state machine, so
+                     * we can free our last flight of messages */
+                    dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
+                    dtls_CancelTimer(ss);
 
-		    /* If there have been no retries this time, reset the
-		     * timer value to the default per Section 4.2.4.1 */
-		    if (ss->ssl3.hs.rtRetries == 0) {
-			ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
-		    }
+                    /* If there have been no retries this time, reset the
+                     * timer value to the default per Section 4.2.4.1 */
+                    if (ss->ssl3.hs.rtRetries == 0) {
+                        ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
+                    }
                 }
             }
         }
 
-	buf.buf += fragment_length;
+        buf.buf += fragment_length;
         buf.len -= fragment_length;
     }
 
-    origBuf->len = 0;	/* So ssl3_GatherAppDataRecord will keep looping. */
+    origBuf->len = 0;   /* So ssl3_GatherAppDataRecord will keep looping. */
 
     /* XXX OK for now. In future handle rv == SECWouldBlock safely in order
      * to deal with asynchronous certificate verification */
     return rv;
 }
 
 /* Enqueue a message (either handshake or CCS)
  *
@@ -456,20 +465,20 @@ SECStatus dtls_QueueMessage(sslSocket *s
     DTLSQueuedMessage *msg = NULL;
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
     msg = dtls_AllocQueuedMessage(ss->ssl3.cwSpec->epoch, type, pIn, nIn);
 
     if (!msg) {
-	PORT_SetError(SEC_ERROR_NO_MEMORY);
-	rv = SECFailure;
+        PORT_SetError(SEC_ERROR_NO_MEMORY);
+        rv = SECFailure;
     } else {
-	PR_APPEND_LINK(&msg->link, &ss->ssl3.hs.lastMessageFlight);
+        PR_APPEND_LINK(&msg->link, &ss->ssl3.hs.lastMessageFlight);
     }
 
     return rv;
 }
 
 /* Add DTLS handshake message to the pending queue
  * Empty the sendBuf buffer.
  * This function returns SECSuccess or SECFailure, never SECWouldBlock.
@@ -485,17 +494,17 @@ dtls_StageHandshakeMessage(sslSocket *ss
     SECStatus rv = SECSuccess;
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
     /* This function is sometimes called when no data is actually to
      * be staged, so just return SECSuccess. */
     if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
-	return rv;
+        return rv;
 
     rv = dtls_QueueMessage(ss, content_handshake,
                            ss->sec.ci.sendBuf.buf, ss->sec.ci.sendBuf.len);
 
     /* Whether we succeeded or failed, toss the old handshake data. */
     ss->sec.ci.sendBuf.len = 0;
     return rv;
 }
@@ -517,21 +526,21 @@ dtls_FlushHandshakeMessages(sslSocket *s
     rv = dtls_StageHandshakeMessage(ss);
     if (rv != SECSuccess)
         return rv;
 
     if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
         rv = dtls_TransmitMessageFlight(ss);
         if (rv != SECSuccess)
             return rv;
-	
-	if (!(flags & ssl_SEND_FLAG_NO_RETRANSMIT)) {
-	    ss->ssl3.hs.rtRetries = 0;
-	    rv = dtls_StartTimer(ss, dtls_RetransmitTimerExpiredCb);
-	}
+
+        if (!(flags & ssl_SEND_FLAG_NO_RETRANSMIT)) {
+            ss->ssl3.hs.rtRetries = 0;
+            rv = dtls_StartTimer(ss, dtls_RetransmitTimerExpiredCb);
+        }
     }
 
     return rv;
 }
 
 /* The callback for when the retransmit timer expires
  *
  * Called from:
@@ -541,32 +550,32 @@ dtls_FlushHandshakeMessages(sslSocket *s
 static void
 dtls_RetransmitTimerExpiredCb(sslSocket *ss)
 {
     SECStatus rv = SECFailure;
 
     ss->ssl3.hs.rtRetries++;
 
     if (!(ss->ssl3.hs.rtRetries % 3)) {
-	/* If one of the messages was potentially greater than > MTU,
-	 * then downgrade. Do this every time we have retransmitted a
-	 * message twice, per RFC 6347 Sec. 4.1.1 */
-	dtls_SetMTU(ss, ss->ssl3.hs.maxMessageSent - 1);
+        /* If one of the messages was potentially greater than > MTU,
+         * then downgrade. Do this every time we have retransmitted a
+         * message twice, per RFC 6347 Sec. 4.1.1 */
+        dtls_SetMTU(ss, ss->ssl3.hs.maxMessageSent - 1);
     }
-	
+
     rv = dtls_TransmitMessageFlight(ss);
     if (rv == SECSuccess) {
 
-	/* Re-arm the timer */
-	rv = dtls_RestartTimer(ss, PR_TRUE, dtls_RetransmitTimerExpiredCb);
+        /* Re-arm the timer */
+        rv = dtls_RestartTimer(ss, PR_TRUE, dtls_RetransmitTimerExpiredCb);
     }
 
     if (rv == SECFailure) {
-	/* XXX OK for now. In future maybe signal the stack that we couldn't
-	 * transmit. For now, let the read handle any real network errors */
+        /* XXX OK for now. In future maybe signal the stack that we couldn't
+         * transmit. For now, let the read handle any real network errors */
     }
 }
 
 /* Transmit a flight of handshake messages, stuffing them
  * into as few records as seems reasonable
  *
  * Called from:
  *             dtls_FlushHandshake()
@@ -586,97 +595,97 @@ dtls_TransmitMessageFlight(sslSocket *ss
     /* DTLS does not buffer its handshake messages in
      * ss->pendingBuf, but rather in the lastMessageFlight
      * structure. This is just a sanity check that
      * some programming error hasn't inadvertantly
      * stuffed something in ss->pendingBuf
      */
     PORT_Assert(!ss->pendingBuf.len);
     for (msg_p = PR_LIST_HEAD(&ss->ssl3.hs.lastMessageFlight);
-	 msg_p != &ss->ssl3.hs.lastMessageFlight;
-	 msg_p = PR_NEXT_LINK(msg_p)) {
+         msg_p != &ss->ssl3.hs.lastMessageFlight;
+         msg_p = PR_NEXT_LINK(msg_p)) {
         DTLSQueuedMessage *msg = (DTLSQueuedMessage *)msg_p;
 
         /* The logic here is:
          *
-	 * 1. If this is a message that will not fit into the remaining
-	 *    space, then flush.
-	 * 2. If the message will now fit into the remaining space,
+         * 1. If this is a message that will not fit into the remaining
+         *    space, then flush.
+         * 2. If the message will now fit into the remaining space,
          *    encrypt, buffer, and loop.
          * 3. If the message will not fit, then fragment.
          *
-	 * At the end of the function, flush.
+         * At the end of the function, flush.
          */
         if ((msg->len + SSL3_BUFFER_FUDGE) > room_left) {
-	    /* The message will not fit into the remaining space, so flush */
-	    rv = dtls_SendSavedWriteData(ss);
-	    if (rv != SECSuccess)
-		break;
+            /* The message will not fit into the remaining space, so flush */
+            rv = dtls_SendSavedWriteData(ss);
+            if (rv != SECSuccess)
+                break;
 
             room_left = ss->ssl3.mtu;
-	}
+        }
 
         if ((msg->len + SSL3_BUFFER_FUDGE) <= room_left) {
             /* The message will fit, so encrypt and then continue with the
-	     * next packet */
+             * next packet */
             sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
-				   msg->data, msg->len,
-				   ssl_SEND_FLAG_FORCE_INTO_BUFFER |
-				   ssl_SEND_FLAG_USE_EPOCH);
+                                   msg->data, msg->len,
+                                   ssl_SEND_FLAG_FORCE_INTO_BUFFER |
+                                   ssl_SEND_FLAG_USE_EPOCH);
             if (sent != msg->len) {
-		rv = SECFailure;
-		if (sent != -1) {
-		    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-		}
+                rv = SECFailure;
+                if (sent != -1) {
+                    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+                }
                 break;
-	    }
+            }
 
             room_left = ss->ssl3.mtu - ss->pendingBuf.len;
         } else {
             /* The message will not fit, so fragment.
              *
-	     * XXX OK for now. Arrange to coalesce the last fragment
-	     * of this message with the next message if possible.
-	     * That would be more efficient.
-	     */
+             * XXX OK for now. Arrange to coalesce the last fragment
+             * of this message with the next message if possible.
+             * That would be more efficient.
+             */
             PRUint32 fragment_offset = 0;
             unsigned char fragment[DTLS_MAX_MTU]; /* >= than largest
                                                    * plausible MTU */
 
-	    /* Assert that we have already flushed */
-	    PORT_Assert(room_left == ss->ssl3.mtu);
+            /* Assert that we have already flushed */
+            PORT_Assert(room_left == ss->ssl3.mtu);
 
             /* Case 3: We now need to fragment this message
              * DTLS only supports fragmenting handshaking messages */
             PORT_Assert(msg->type == content_handshake);
 
-	    /* The headers consume 12 bytes so the smalles possible
-	     *  message (i.e., an empty one) is 12 bytes
-	     */
-	    PORT_Assert(msg->len >= 12);
+            /* The headers consume 12 bytes so the smalles possible
+             *  message (i.e., an empty one) is 12 bytes
+             */
+            PORT_Assert(msg->len >= 12);
 
             while ((fragment_offset + 12) < msg->len) {
                 PRUint32 fragment_len;
                 const unsigned char *content = msg->data + 12;
                 PRUint32 content_len = msg->len - 12;
 
-		/* The reason we use 8 here is that that's the length of
-		 * the new DTLS data that we add to the header */
+                /* The reason we use 8 here is that that's the length of
+                 * the new DTLS data that we add to the header */
                 fragment_len = PR_MIN(room_left - (SSL3_BUFFER_FUDGE + 8),
                                       content_len - fragment_offset);
-		PORT_Assert(fragment_len < DTLS_MAX_MTU - 12);
-		/* Make totally sure that we are within the buffer.
-		 * Note that the only way that fragment len could get
-		 * adjusted here is if
+                PORT_Assert(fragment_len < DTLS_MAX_MTU - 12);
+                /* Make totally sure that we are within the buffer.
+                 * Note that the only way that fragment len could get
+                 * adjusted here is if
                  *
-		 * (a) we are in release mode so the PORT_Assert is compiled out
-		 * (b) either the MTU table is inconsistent with DTLS_MAX_MTU
-		 * or ss->ssl3.mtu has become corrupt.
-		 */
-		fragment_len = PR_MIN(fragment_len, DTLS_MAX_MTU - 12);
+                 * (a) we are in release mode so the PORT_Assert is compiled out
+                 * (b) either the MTU table is inconsistent with DTLS_MAX_MTU
+                 * or ss->ssl3.mtu has become corrupt.
+                 */
+                fragment_len = PR_MIN(fragment_len, DTLS_MAX_MTU - 12);
 
                 /* Construct an appropriate-sized fragment */
                 /* Type, length, sequence */
                 PORT_Memcpy(fragment, msg->data, 6);
 
                 /* Offset */
                 fragment[6] = (fragment_offset >> 16) & 0xff;
                 fragment[7] = (fragment_offset >> 8) & 0xff;
@@ -686,44 +695,44 @@ dtls_TransmitMessageFlight(sslSocket *ss
                 fragment[9] = (fragment_len >> 16) & 0xff;
                 fragment[10] = (fragment_len >> 8) & 0xff;
                 fragment[11] = (fragment_len) & 0xff;
 
                 PORT_Memcpy(fragment + 12, content + fragment_offset,
                             fragment_len);
 
                 /*
-		 *  Send the record. We do this in two stages
-		 * 1. Encrypt
-		 */
+                 *  Send the record. We do this in two stages
+                 * 1. Encrypt
+                 */
                 sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
                                        fragment, fragment_len + 12,
                                        ssl_SEND_FLAG_FORCE_INTO_BUFFER |
-				       ssl_SEND_FLAG_USE_EPOCH);
+                                       ssl_SEND_FLAG_USE_EPOCH);
                 if (sent != (fragment_len + 12)) {
-		    rv = SECFailure;
-		    if (sent != -1) {
-			PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-		    }
-		    break;
-		}
-		
-		/* 2. Flush */
-		rv = dtls_SendSavedWriteData(ss);
-		if (rv != SECSuccess)
-		    break;
+                    rv = SECFailure;
+                    if (sent != -1) {
+                        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+                    }
+                    break;
+                }
+
+                /* 2. Flush */
+                rv = dtls_SendSavedWriteData(ss);
+                if (rv != SECSuccess)
+                    break;
 
                 fragment_offset += fragment_len;
             }
         }
     }
 
     /* Finally, we need to flush */
     if (rv == SECSuccess)
-	rv = dtls_SendSavedWriteData(ss);
+        rv = dtls_SendSavedWriteData(ss);
 
     /* Give up the locks */
     ssl_ReleaseSpecReadLock(ss);
     ssl_ReleaseXmitBufLock(ss);
 
     return rv;
 }
 
@@ -735,82 +744,82 @@ dtls_TransmitMessageFlight(sslSocket *ss
  */
 static
 SECStatus dtls_SendSavedWriteData(sslSocket *ss)
 {
     PRInt32 sent;
 
     sent = ssl_SendSavedWriteData(ss);
     if (sent < 0)
-	return SECFailure;
+        return SECFailure;
 
     /* We should always have complete writes b/c datagram sockets
      * don't really block */
     if (ss->pendingBuf.len > 0) {
-	ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
-    	return SECFailure;
+        ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
+        return SECFailure;
     }
 
     /* Update the largest message sent so we can adjust the MTU
      * estimate if necessary */
     if (sent > ss->ssl3.hs.maxMessageSent)
-	ss->ssl3.hs.maxMessageSent = sent;
+        ss->ssl3.hs.maxMessageSent = sent;
 
     return SECSuccess;
 }
 
 /* Compress, MAC, encrypt a DTLS record. Allows specification of
  * the epoch using epoch value. If use_epoch is PR_TRUE then
  * we use the provided epoch. If use_epoch is PR_FALSE then
  * whatever the current value is in effect is used.
  *
  * Called from ssl3_SendRecord()
  */
 SECStatus
 dtls_CompressMACEncryptRecord(sslSocket *        ss,
                               DTLSEpoch          epoch,
-			      PRBool             use_epoch,
+                              PRBool             use_epoch,
                               SSL3ContentType    type,
-		              const SSL3Opaque * pIn,
-		              PRUint32           contentLen,
-			      sslBuffer        * wrBuf)
+                              const SSL3Opaque * pIn,
+                              PRUint32           contentLen,
+                              sslBuffer        * wrBuf)
 {
     SECStatus rv = SECFailure;
     ssl3CipherSpec *          cwSpec;
 
-    ssl_GetSpecReadLock(ss);	/********************************/
+    ssl_GetSpecReadLock(ss);    /********************************/
 
     /* The reason for this switch-hitting code is that we might have
      * a flight of records spanning an epoch boundary, e.g.,
      *
      * ClientKeyExchange (epoch = 0)
      * ChangeCipherSpec (epoch = 0)
      * Finished (epoch = 1)
      *
      * Thus, each record needs a different cipher spec. The information
      * about which epoch to use is carried with the record.
      */
     if (use_epoch) {
-	if (ss->ssl3.cwSpec->epoch == epoch)
-	    cwSpec = ss->ssl3.cwSpec;
-	else if (ss->ssl3.pwSpec->epoch == epoch)
-	    cwSpec = ss->ssl3.pwSpec;
-	else
-	    cwSpec = NULL;
+        if (ss->ssl3.cwSpec->epoch == epoch)
+            cwSpec = ss->ssl3.cwSpec;
+        else if (ss->ssl3.pwSpec->epoch == epoch)
+            cwSpec = ss->ssl3.pwSpec;
+        else
+            cwSpec = NULL;
     } else {
-	cwSpec = ss->ssl3.cwSpec;
+        cwSpec = ss->ssl3.cwSpec;
     }
 
     if (cwSpec) {
         rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE,
-					   PR_FALSE, type, pIn, contentLen,
-					   wrBuf);
+                                           PR_FALSE, type, pIn, contentLen,
+                                           wrBuf);
     } else {
         PR_NOT_REACHED("Couldn't find a cipher spec matching epoch");
-	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
     }
     ssl_ReleaseSpecReadLock(ss); /************************************/
 
     return rv;
 }
 
 /* Start a timer
  *
@@ -833,19 +842,19 @@ dtls_StartTimer(sslSocket *ss, DTLSTimer
 /* Restart a timer with optional backoff
  *
  * Called from dtls_RetransmitTimerExpiredCb()
  */
 SECStatus
 dtls_RestartTimer(sslSocket *ss, PRBool backoff, DTLSTimerCb cb)
 {
     if (backoff) {
-	ss->ssl3.hs.rtTimeoutMs *= 2;
-	if (ss->ssl3.hs.rtTimeoutMs > MAX_DTLS_TIMEOUT_MS)
-	    ss->ssl3.hs.rtTimeoutMs = MAX_DTLS_TIMEOUT_MS;
+        ss->ssl3.hs.rtTimeoutMs *= 2;
+        if (ss->ssl3.hs.rtTimeoutMs > MAX_DTLS_TIMEOUT_MS)
+            ss->ssl3.hs.rtTimeoutMs = MAX_DTLS_TIMEOUT_MS;
     }
 
     return dtls_StartTimer(ss, cb);
 }
 
 /* Cancel a pending timer
  *
  * Called from:
@@ -863,28 +872,28 @@ dtls_CancelTimer(sslSocket *ss)
 /* Check the pending timer and fire the callback if it expired
  *
  * Called from ssl3_GatherCompleteHandshake()
  */
 void
 dtls_CheckTimer(sslSocket *ss)
 {
     if (!ss->ssl3.hs.rtTimerCb)
-	return;
+        return;
 
     if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
-	PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs)) {
-	/* Timer has expired */
-	DTLSTimerCb cb = ss->ssl3.hs.rtTimerCb;
-	
-	/* Cancel the timer so that we can call the CB safely */
-	dtls_CancelTimer(ss);
+        PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs)) {
+        /* Timer has expired */
+        DTLSTimerCb cb = ss->ssl3.hs.rtTimerCb;
 
-	/* Now call the CB */
-	cb(ss);
+        /* Cancel the timer so that we can call the CB safely */
+        dtls_CancelTimer(ss);
+
+        /* Now call the CB */
+        cb(ss);
     }
 }
 
 /* The callback to fire when the holddown timer for the Finished
  * message expires and we can delete it
  *
  * Called from dtls_CheckTimer()
  */
@@ -923,92 +932,92 @@ dtls_RehandshakeCleanup(sslSocket *ss)
  *            dtls_RetransmitTimerExpiredCb()
  */
 void
 dtls_SetMTU(sslSocket *ss, PRUint16 advertised)
 {
     int i;
 
     if (advertised == 0) {
-	ss->ssl3.mtu = COMMON_MTU_VALUES[0];
-	SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
-	return;
+        ss->ssl3.mtu = COMMON_MTU_VALUES[0];
+        SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
+        return;
     }
-	
+
     for (i = 0; i < PR_ARRAY_SIZE(COMMON_MTU_VALUES); i++) {
-	if (COMMON_MTU_VALUES[i] <= advertised) {
-	    ss->ssl3.mtu = COMMON_MTU_VALUES[i];
-	    SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
-	    return;
-	}
+        if (COMMON_MTU_VALUES[i] <= advertised) {
+            ss->ssl3.mtu = COMMON_MTU_VALUES[i];
+            SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
+            return;
+        }
     }
 
     /* Fallback */
     ss->ssl3.mtu = COMMON_MTU_VALUES[PR_ARRAY_SIZE(COMMON_MTU_VALUES)-1];
     SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
 }
 
 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a
  * DTLS hello_verify_request
  * Caller must hold Handshake and RecvBuf locks.
  */
 SECStatus
 dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 {
-    int                 errCode	= SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
+    int                 errCode = SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
     SECStatus           rv;
     PRInt32             temp;
     SECItem             cookie = {siBuffer, NULL, 0};
     SSL3AlertDescription desc   = illegal_parameter;
 
     SSL_TRC(3, ("%d: SSL3[%d]: handle hello_verify_request handshake",
-    	SSL_GETPID(), ss->fd));
+        SSL_GETPID(), ss->fd));
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     if (ss->ssl3.hs.ws != wait_server_hello) {
         errCode = SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST;
-	desc    = unexpected_message;
-	goto alert_loser;
+        desc    = unexpected_message;
+        goto alert_loser;
     }
 
     /* The version */
     temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
     if (temp < 0) {
-    	goto loser; 	/* alert has been sent */
+        goto loser;     /* alert has been sent */
     }
 
-    if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE) {
-	/* Note: this will need adjustment for DTLS 1.2 per Section 4.2.1 */
-	goto alert_loser;
+    if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE &&
+        temp != SSL_LIBRARY_VERSION_DTLS_1_2_WIRE) {
+        goto alert_loser;
     }
 
     /* The cookie */
     rv = ssl3_ConsumeHandshakeVariable(ss, &cookie, 1, &b, &length);
     if (rv != SECSuccess) {
-    	goto loser; 	/* alert has been sent */
+        goto loser;     /* alert has been sent */
     }
     if (cookie.len > DTLS_COOKIE_BYTES) {
-	desc = decode_error;
-	goto alert_loser;	/* malformed. */
+        desc = decode_error;
+        goto alert_loser;       /* malformed. */
     }
 
     PORT_Memcpy(ss->ssl3.hs.cookie, cookie.data, cookie.len);
     ss->ssl3.hs.cookieLen = cookie.len;
 
 
-    ssl_GetXmitBufLock(ss);		/*******************************/
+    ssl_GetXmitBufLock(ss);             /*******************************/
 
     /* Now re-send the client hello */
     rv = ssl3_SendClientHello(ss, PR_TRUE);
 
-    ssl_ReleaseXmitBufLock(ss);		/*******************************/
+    ssl_ReleaseXmitBufLock(ss);         /*******************************/
 
     if (rv == SECSuccess)
-	return rv;
+        return rv;
 
 alert_loser:
     (void)SSL3_SendAlert(ss, alert_fatal, desc);
 
 loser:
     errCode = ssl_MapLowLevelError(errCode);
     return SECFailure;
 }
@@ -1037,68 +1046,68 @@ dtls_InitRecvdRecords(DTLSRecvdRecords *
  */
 int
 dtls_RecordGetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
 {
     PRUint64 offset;
 
     /* Out of range to the left */
     if (seq < records->left) {
-	return -1;
+        return -1;
     }
 
     /* Out of range to the right; since we advance the window on
      * receipt, that means that this packet has not been received
      * yet */
     if (seq > records->right)
-	return 0;
+        return 0;
 
     offset = seq % DTLS_RECVD_RECORDS_WINDOW;
 
     return !!(records->data[offset / 8] & (1 << (offset % 8)));
 }
 
 /* Update the DTLS anti-replay window
  *
  * Called from ssl3_HandleRecord()
  */
 void
 dtls_RecordSetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
 {
     PRUint64 offset;
 
     if (seq < records->left)
-	return;
+        return;
 
     if (seq > records->right) {
-	PRUint64 new_left;
-	PRUint64 new_right;
-	PRUint64 right;
+        PRUint64 new_left;
+        PRUint64 new_right;
+        PRUint64 right;
 
-	/* Slide to the right; this is the tricky part
+        /* Slide to the right; this is the tricky part
          *
-	 * 1. new_top is set to have room for seq, on the
-	 *    next byte boundary by setting the right 8
-	 *    bits of seq
+         * 1. new_top is set to have room for seq, on the
+         *    next byte boundary by setting the right 8
+         *    bits of seq
          * 2. new_left is set to compensate.
          * 3. Zero all bits between top and new_top. Since
          *    this is a ring, this zeroes everything as-yet
-	 *    unseen. Because we always operate on byte
-	 *    boundaries, we can zero one byte at a time
-	 */
-	new_right = seq | 0x07;
-	new_left = (new_right - DTLS_RECVD_RECORDS_WINDOW) + 1;
+         *    unseen. Because we always operate on byte
+         *    boundaries, we can zero one byte at a time
+         */
+        new_right = seq | 0x07;
+        new_left = (new_right - DTLS_RECVD_RECORDS_WINDOW) + 1;
 
-	for (right = records->right + 8; right <= new_right; right += 8) {
-	    offset = right % DTLS_RECVD_RECORDS_WINDOW;
-	    records->data[offset / 8] = 0;
-	}
+        for (right = records->right + 8; right <= new_right; right += 8) {
+            offset = right % DTLS_RECVD_RECORDS_WINDOW;
+            records->data[offset / 8] = 0;
+        }
 
-	records->right = new_right;
-	records->left = new_left;
+        records->right = new_right;
+        records->left = new_left;
     }
 
     offset = seq % DTLS_RECVD_RECORDS_WINDOW;
 
     records->data[offset / 8] |= (1 << (offset % 8));
 }
 
 SECStatus
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -628,28 +628,54 @@ ssl3_CipherSuiteAllowedForVersionRange(
      *   TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:   never implemented
      *   TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:   never implemented
      *   TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:  never implemented
      *   TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:  never implemented
      *   TLS_DH_anon_EXPORT_WITH_RC4_40_MD5:     never implemented
      *   TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA:  never implemented
      */
 	return vrange->min <= SSL_LIBRARY_VERSION_TLS_1_0;
+
     case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
     case TLS_RSA_WITH_AES_256_CBC_SHA256:
     case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
     case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
     case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
     case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
     case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
     case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
     case TLS_RSA_WITH_AES_128_CBC_SHA256:
     case TLS_RSA_WITH_AES_128_GCM_SHA256:
     case TLS_RSA_WITH_NULL_SHA256:
 	return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_2;
+
+    /* RFC 4492: ECC cipher suites need TLS extensions to negotiate curves and
+     * point formats.*/
+    case TLS_ECDH_ECDSA_WITH_NULL_SHA:
+    case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+    case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+    case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+    case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+    case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+    case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+    case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+    case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+    case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+    case TLS_ECDH_RSA_WITH_NULL_SHA:
+    case TLS_ECDH_RSA_WITH_RC4_128_SHA:
+    case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+    case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+    case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+    case TLS_ECDHE_RSA_WITH_NULL_SHA:
+    case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+    case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+    case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+    case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+	return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_0;
+
     default:
 	return PR_TRUE;
     }
 }
 
 /* return pointer to ssl3CipherSuiteDef for suite, or NULL */
 /* XXX This does a linear search.  A binary search would be better. */
 static const ssl3CipherSuiteDef *
@@ -3466,16 +3492,24 @@ ssl3_HandleChangeCipherSpecs(sslSocket *
 
     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
 
     SSL_TRC(3, ("%d: SSL3[%d]: handle change_cipher_spec record",
 		SSL_GETPID(), ss->fd));
 
     if (ws != wait_change_cipher) {
+	if (IS_DTLS(ss)) {
+	    /* Ignore this because it's out of order. */
+	    SSL_TRC(3, ("%d: SSL3[%d]: discard out of order "
+			"DTLS change_cipher_spec",
+			SSL_GETPID(), ss->fd));
+	    buf->len = 0;
+	    return SECSuccess;
+	}
 	(void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
 	PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER);
 	return SECFailure;
     }
 
     if(buf->len != 1) {
 	(void)ssl3_DecodeError(ss);
 	PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
--- a/security/nss/lib/ssl/ssl3ext.c
+++ b/security/nss/lib/ssl/ssl3ext.c
@@ -51,20 +51,24 @@ static PRInt32 ssl3_SendRenegotiationInf
 static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss,
     PRUint16 ex_type, SECItem *data);
 static SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss,
                         PRUint16 ex_type, SECItem *data);
 static SECStatus ssl3_ClientHandleAppProtoXtn(sslSocket *ss,
                         PRUint16 ex_type, SECItem *data);
 static SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss,
                         PRUint16 ex_type, SECItem *data);
+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_ClientSendNextProtoNegoXtn(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_ServerSendStatusRequestXtn(sslSocket * ss,
     PRBool append, PRUint32 maxBytes);
 static SECStatus ssl3_ServerHandleStatusRequestXtn(sslSocket *ss,
     PRUint16 ex_type, SECItem *data);
@@ -232,16 +236,17 @@ static const ssl3HelloExtensionHandler c
     { ssl_server_name_xtn,        &ssl3_HandleServerNameXtn },
 #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_cert_status_xtn,        &ssl3_ServerHandleStatusRequestXtn },
     { ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn },
     { -1, NULL }
 };
 
 /* These two tables are used by the client, to handle server hello
  * extensions. */
@@ -554,17 +559,18 @@ ssl3_SendSessionTicketXtn(
 
  loser:
     ss->xtnData.ticketTimestampVerified = PR_FALSE;
     return -1;
 }
 
 /* handle an incoming Next Protocol Negotiation extension. */
 static SECStatus
-ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
+ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type,
+                                  SECItem *data)
 {
     if (ss->firstHsDone || data->len != 0) {
         /* Clients MUST send an empty NPN extension, if any. */
         PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
         return SECFailure;
     }
 
     ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
@@ -599,68 +605,126 @@ ssl3_ValidateNextProtoNego(const unsigne
     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_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
-                                  SECItem *data)
+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)
+        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);
+        return SECFailure;
+    }
+
+    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);
+        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. */
+        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 */
+    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);
+    }
+
+    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(
+            ss, ex_type, ssl3_ServerSendAppProtoXtn);
+    }
+    return SECSuccess;
+}
+
+static SECStatus
+ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
+                                  SECItem *data)
+{
     PORT_Assert(!ss->firstHsDone);
 
     if (ssl3_ExtensionNegotiated(ss, ssl_app_layer_protocol_xtn)) {
         /* If the server negotiated ALPN then it has already told us what
          * protocol to use, so it doesn't make sense for us to try to negotiate
          * a different one by sending the NPN handshake message. However, if
          * we've negotiated NPN then we're required to send the NPN handshake
          * message. Thus, these two extensions cannot both be negotiated on the
          * same connection. */
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
 
-    rv = ssl3_ValidateNextProtoNego(data->data, data->len);
-    if (rv != SECSuccess)
-        return rv;
-
-    /* ss->nextProtoCallback cannot normally be NULL if we negotiated the
-     * extension. However, It is possible that an application erroneously
-     * cleared the callback between the time we sent the ClientHello and now.
-     */
-    PORT_Assert(ss->nextProtoCallback != NULL);
+    /* We should only get this call if we sent the extension, so
+     * ss->nextProtoCallback needs to be non-NULL.  However, it is possible
+     * that an application erroneously cleared the callback between the time
+     * we sent the ClientHello and now. */
     if (!ss->nextProtoCallback) {
-        /* XXX Use a better error code. This is an application error, not an
-         * NSS bug. */
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK);
         return SECFailure;
     }
 
-    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);
-        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);
+    return ssl3_SelectAppProtocol(ss, ex_type, data);
 }
 
 static SECStatus
 ssl3_ClientHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
 {
     const unsigned char* d = data->data;
     PRUint16 name_list_len;
     SECItem protocol_name;
@@ -791,16 +855,58 @@ ssl3_ClientSendAppProtoXtn(sslSocket * s
 
 loser:
     if (alpn_protos) {
         PORT_Free(alpn_protos);
     }
     return -1;
 }
 
+static PRInt32
+ssl3_ServerSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
+{
+    PRInt32 extension_length;
+
+    /* we're in over our heads if any of these fail */
+    PORT_Assert(ss->opt.enableALPN);
+    PORT_Assert(ss->ssl3.nextProto.data);
+    PORT_Assert(ss->ssl3.nextProto.len > 0);
+    PORT_Assert(ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NEGOTIATED);
+    PORT_Assert(!ss->firstHsDone);
+
+    extension_length = 2 /* extension type */ + 2 /* extension length */ +
+                       2 /* protocol name list */ + 1 /* name length */ +
+                       ss->ssl3.nextProto.len;
+
+    if (append && maxBytes >= extension_length) {
+        SECStatus rv;
+        rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2);
+        if (rv != SECSuccess) {
+            return -1;
+        }
+        rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
+        if (rv != SECSuccess) {
+            return -1;
+        }
+        rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.nextProto.len + 1, 2);
+        if (rv != SECSuccess) {
+            return -1;
+        }
+        rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.nextProto.data,
+                                          ss->ssl3.nextProto.len, 1);
+        if (rv != SECSuccess) {
+            return -1;
+        }
+    } else if (maxBytes < extension_length) {
+        return 0;
+    }
+
+    return extension_length;
+}
+
 static SECStatus
 ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type,
                                  SECItem *data)
 {
     /* The echoed extension must be empty. */
     if (data->len != 0)
        return SECFailure;
 
--- a/security/nss/lib/ssl/ssl3prot.h
+++ b/security/nss/lib/ssl/ssl3prot.h
@@ -101,17 +101,18 @@ typedef enum {
     user_canceled           = 90,
     no_renegotiation        = 100,
 
 /* Alerts for client hello extensions */
     unsupported_extension           = 110,
     certificate_unobtainable        = 111,
     unrecognized_name               = 112,
     bad_certificate_status_response = 113,
-    bad_certificate_hash_value      = 114
+    bad_certificate_hash_value      = 114,
+    no_application_protocol         = 120
 
 } SSL3AlertDescription;
 
 typedef struct {
     SSL3AlertLevel       level;
     SSL3AlertDescription description;
 } SSL3Alert;
 
--- a/security/nss/lib/ssl/sslerr.h
+++ b/security/nss/lib/ssl/sslerr.h
@@ -188,13 +188,16 @@ SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQ
 SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION = (SSL_ERROR_BASE + 124),
 
 SSL_ERROR_RX_UNEXPECTED_CERT_STATUS     = (SSL_ERROR_BASE + 125),
 
 SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM    = (SSL_ERROR_BASE + 126),
 SSL_ERROR_DIGEST_FAILURE                = (SSL_ERROR_BASE + 127),
 SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 128),
 
+SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK     = (SSL_ERROR_BASE + 129),
+SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL     = (SSL_ERROR_BASE + 130),
+
 SSL_ERROR_END_OF_LIST   /* let the c compiler determine the value of this. */
 } SSLErrorCodes;
 #endif /* NO_SECURITY_ERROR_ENUM */
 
 #endif /* __SSL_ERR_H_ */
--- a/security/nss/lib/ssl/sslproto.h
+++ b/security/nss/lib/ssl/sslproto.h
@@ -1,90 +1,92 @@
 /*
- * Various and sundry protocol constants. DON'T CHANGE THESE. These values 
+ * Various and sundry protocol constants. DON'T CHANGE THESE. These values
  * are mostly defined by the SSL2, SSL3, or TLS protocol specifications.
  * Cipher kinds and ciphersuites are part of the public API.
  *
  * 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 __sslproto_h_
 #define __sslproto_h_
 
 /* All versions less than 3_0 are treated as SSL version 2 */
-#define SSL_LIBRARY_VERSION_2			0x0002
-#define SSL_LIBRARY_VERSION_3_0			0x0300
-#define SSL_LIBRARY_VERSION_TLS_1_0		0x0301
-#define SSL_LIBRARY_VERSION_TLS_1_1		0x0302
-#define SSL_LIBRARY_VERSION_TLS_1_2		0x0303
+#define SSL_LIBRARY_VERSION_2                   0x0002
+#define SSL_LIBRARY_VERSION_3_0                 0x0300
+#define SSL_LIBRARY_VERSION_TLS_1_0             0x0301
+#define SSL_LIBRARY_VERSION_TLS_1_1             0x0302
+#define SSL_LIBRARY_VERSION_TLS_1_2             0x0303
 /* Note: this is the internal format, not the wire format */
-#define SSL_LIBRARY_VERSION_DTLS_1_0		0x0302
+#define SSL_LIBRARY_VERSION_DTLS_1_0            0x0302
+#define SSL_LIBRARY_VERSION_DTLS_1_2            0x0303
 
 /* deprecated old name */
-#define SSL_LIBRARY_VERSION_3_1_TLS SSL_LIBRARY_VERSION_TLS_1_0 
+#define SSL_LIBRARY_VERSION_3_1_TLS SSL_LIBRARY_VERSION_TLS_1_0
 
-/* The DTLS version used in the spec */
+/* The DTLS versions used in the spec */
 #define SSL_LIBRARY_VERSION_DTLS_1_0_WIRE       ((~0x0100) & 0xffff)
+#define SSL_LIBRARY_VERSION_DTLS_1_2_WIRE       ((~0x0102) & 0xffff)
 
 /* Header lengths of some of the messages */
-#define SSL_HL_ERROR_HBYTES			3
-#define SSL_HL_CLIENT_HELLO_HBYTES		9
-#define SSL_HL_CLIENT_MASTER_KEY_HBYTES		10
-#define SSL_HL_CLIENT_FINISHED_HBYTES		1
-#define SSL_HL_SERVER_HELLO_HBYTES		11
-#define SSL_HL_SERVER_VERIFY_HBYTES		1
-#define SSL_HL_SERVER_FINISHED_HBYTES		1
-#define SSL_HL_REQUEST_CERTIFICATE_HBYTES	2
-#define SSL_HL_CLIENT_CERTIFICATE_HBYTES	6
+#define SSL_HL_ERROR_HBYTES                     3
+#define SSL_HL_CLIENT_HELLO_HBYTES              9
+#define SSL_HL_CLIENT_MASTER_KEY_HBYTES         10
+#define SSL_HL_CLIENT_FINISHED_HBYTES           1
+#define SSL_HL_SERVER_HELLO_HBYTES              11
+#define SSL_HL_SERVER_VERIFY_HBYTES             1
+#define SSL_HL_SERVER_FINISHED_HBYTES           1
+#define SSL_HL_REQUEST_CERTIFICATE_HBYTES       2
+#define SSL_HL_CLIENT_CERTIFICATE_HBYTES        6
 
 /* Security handshake protocol codes */
-#define SSL_MT_ERROR				0
-#define SSL_MT_CLIENT_HELLO			1
-#define SSL_MT_CLIENT_MASTER_KEY		2
-#define SSL_MT_CLIENT_FINISHED			3
-#define SSL_MT_SERVER_HELLO			4
-#define SSL_MT_SERVER_VERIFY			5
-#define SSL_MT_SERVER_FINISHED			6
-#define SSL_MT_REQUEST_CERTIFICATE		7
-#define SSL_MT_CLIENT_CERTIFICATE		8
+#define SSL_MT_ERROR                            0
+#define SSL_MT_CLIENT_HELLO                     1
+#define SSL_MT_CLIENT_MASTER_KEY                2
+#define SSL_MT_CLIENT_FINISHED                  3
+#define SSL_MT_SERVER_HELLO                     4
+#define SSL_MT_SERVER_VERIFY                    5
+#define SSL_MT_SERVER_FINISHED                  6
+#define SSL_MT_REQUEST_CERTIFICATE              7
+#define SSL_MT_CLIENT_CERTIFICATE               8
 
 /* Certificate types */
-#define SSL_CT_X509_CERTIFICATE			0x01
+#define SSL_CT_X509_CERTIFICATE                 0x01
 #if 0 /* XXX Not implemented yet */
-#define SSL_PKCS6_CERTIFICATE			0x02
+#define SSL_PKCS6_CERTIFICATE                   0x02
 #endif
-#define SSL_AT_MD5_WITH_RSA_ENCRYPTION		0x01
+#define SSL_AT_MD5_WITH_RSA_ENCRYPTION          0x01
 
 /* Error codes */
-#define SSL_PE_NO_CYPHERS			0x0001
-#define SSL_PE_NO_CERTIFICATE			0x0002
-#define SSL_PE_BAD_CERTIFICATE			0x0004
-#define SSL_PE_UNSUPPORTED_CERTIFICATE_TYPE	0x0006
+#define SSL_PE_NO_CYPHERS                       0x0001
+#define SSL_PE_NO_CERTIFICATE                   0x0002
+#define SSL_PE_BAD_CERTIFICATE                  0x0004
+#define SSL_PE_UNSUPPORTED_CERTIFICATE_TYPE     0x0006
 
 /* Cypher kinds (not the spec version!) */
-#define SSL_CK_RC4_128_WITH_MD5			0x01
-#define SSL_CK_RC4_128_EXPORT40_WITH_MD5	0x02
-#define SSL_CK_RC2_128_CBC_WITH_MD5		0x03
-#define SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5	0x04
-#define SSL_CK_IDEA_128_CBC_WITH_MD5		0x05
-#define SSL_CK_DES_64_CBC_WITH_MD5		0x06
-#define SSL_CK_DES_192_EDE3_CBC_WITH_MD5	0x07
+#define SSL_CK_RC4_128_WITH_MD5                 0x01
+#define SSL_CK_RC4_128_EXPORT40_WITH_MD5        0x02
+#define SSL_CK_RC2_128_CBC_WITH_MD5             0x03
+#define SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5    0x04
+#define SSL_CK_IDEA_128_CBC_WITH_MD5            0x05
+#define SSL_CK_DES_64_CBC_WITH_MD5              0x06
+#define SSL_CK_DES_192_EDE3_CBC_WITH_MD5        0x07
 
-/* Cipher enables.  These are used only for SSL_EnableCipher 
- * These values define the SSL2 suites, and do not colide with the 
+/* Cipher enables.  These are used only for SSL_EnableCipher
+ * These values define the SSL2 suites, and do not colide with the
  * SSL3 Cipher suites defined below.
  */
-#define SSL_EN_RC4_128_WITH_MD5			0xFF01
-#define SSL_EN_RC4_128_EXPORT40_WITH_MD5	0xFF02
-#define SSL_EN_RC2_128_CBC_WITH_MD5		0xFF03
-#define SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5	0xFF04
-#define SSL_EN_IDEA_128_CBC_WITH_MD5		0xFF05
-#define SSL_EN_DES_64_CBC_WITH_MD5		0xFF06
-#define SSL_EN_DES_192_EDE3_CBC_WITH_MD5	0xFF07
+#define SSL_EN_RC4_128_WITH_MD5                 0xFF01
+#define SSL_EN_RC4_128_EXPORT40_WITH_MD5        0xFF02
+#define SSL_EN_RC2_128_CBC_WITH_MD5             0xFF03
+#define SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5    0xFF04
+#define SSL_EN_IDEA_128_CBC_WITH_MD5            0xFF05
+#define SSL_EN_DES_64_CBC_WITH_MD5              0xFF06
+#define SSL_EN_DES_192_EDE3_CBC_WITH_MD5        0xFF07
 
 /* Deprecated SSL 3.0 & libssl names replaced by IANA-registered TLS names. */
 #ifndef SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES
 #define SSL_NULL_WITH_NULL_NULL                TLS_NULL_WITH_NULL_NULL
 #define SSL_RSA_WITH_NULL_MD5                  TLS_RSA_WITH_NULL_MD5
 #define SSL_RSA_WITH_NULL_SHA                  TLS_RSA_WITH_NULL_SHA
 #define SSL_RSA_EXPORT_WITH_RC4_40_MD5         TLS_RSA_EXPORT_WITH_RC4_40_MD5
 #define SSL_RSA_WITH_RC4_128_MD5               TLS_RSA_WITH_RC4_128_MD5
@@ -112,104 +114,104 @@
 #define SSL_DH_ANON_WITH_3DES_EDE_CBC_SHA      TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
 #define SSL_DH_ANON_EXPORT_WITH_RC4_40_MD5     TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
 #define TLS_DH_ANON_WITH_AES_128_CBC_SHA       TLS_DH_anon_WITH_AES_128_CBC_SHA
 #define TLS_DH_ANON_WITH_AES_256_CBC_SHA       TLS_DH_anon_WITH_AES_256_CBC_SHA
 #define TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA  TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA
 #define TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA  TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA
 #endif
 
-#define TLS_NULL_WITH_NULL_NULL			0x0000
+#define TLS_NULL_WITH_NULL_NULL                 0x0000
 
-#define TLS_RSA_WITH_NULL_MD5			0x0001
-#define TLS_RSA_WITH_NULL_SHA			0x0002
-#define TLS_RSA_EXPORT_WITH_RC4_40_MD5		0x0003
-#define TLS_RSA_WITH_RC4_128_MD5		0x0004
-#define TLS_RSA_WITH_RC4_128_SHA		0x0005
-#define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5	0x0006
-#define TLS_RSA_WITH_IDEA_CBC_SHA		0x0007
-#define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA	0x0008
-#define TLS_RSA_WITH_DES_CBC_SHA		0x0009
-#define TLS_RSA_WITH_3DES_EDE_CBC_SHA		0x000a
+#define TLS_RSA_WITH_NULL_MD5                   0x0001
+#define TLS_RSA_WITH_NULL_SHA                   0x0002
+#define TLS_RSA_EXPORT_WITH_RC4_40_MD5          0x0003
+#define TLS_RSA_WITH_RC4_128_MD5                0x0004
+#define TLS_RSA_WITH_RC4_128_SHA                0x0005
+#define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5      0x0006
+#define TLS_RSA_WITH_IDEA_CBC_SHA               0x0007
+#define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA       0x0008
+#define TLS_RSA_WITH_DES_CBC_SHA                0x0009
+#define TLS_RSA_WITH_3DES_EDE_CBC_SHA           0x000a
 
-#define TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA	0x000b
-#define TLS_DH_DSS_WITH_DES_CBC_SHA		0x000c
-#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA	0x000d
-#define TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA	0x000e
-#define TLS_DH_RSA_WITH_DES_CBC_SHA		0x000f
-#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA	0x0010
+#define TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA    0x000b
+#define TLS_DH_DSS_WITH_DES_CBC_SHA             0x000c
+#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA        0x000d
+#define TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA    0x000e
+#define TLS_DH_RSA_WITH_DES_CBC_SHA             0x000f
+#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA        0x0010
 
-#define TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA	0x0011
-#define TLS_DHE_DSS_WITH_DES_CBC_SHA		0x0012
-#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA	0x0013
-#define TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA	0x0014
-#define TLS_DHE_RSA_WITH_DES_CBC_SHA		0x0015
-#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA	0x0016
+#define TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA   0x0011
+#define TLS_DHE_DSS_WITH_DES_CBC_SHA            0x0012
+#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA       0x0013
+#define TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA   0x0014
+#define TLS_DHE_RSA_WITH_DES_CBC_SHA            0x0015
+#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA       0x0016
 
-#define TLS_DH_anon_EXPORT_WITH_RC4_40_MD5	0x0017
-#define TLS_DH_anon_WITH_RC4_128_MD5		0x0018
-#define TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA	0x0019
-#define TLS_DH_anon_WITH_DES_CBC_SHA		0x001a
-#define TLS_DH_anon_WITH_3DES_EDE_CBC_SHA	0x001b
+#define TLS_DH_anon_EXPORT_WITH_RC4_40_MD5      0x0017
+#define TLS_DH_anon_WITH_RC4_128_MD5            0x0018
+#define TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA   0x0019
+#define TLS_DH_anon_WITH_DES_CBC_SHA            0x001a
+#define TLS_DH_anon_WITH_3DES_EDE_CBC_SHA       0x001b
 
-#define SSL_FORTEZZA_DMS_WITH_NULL_SHA		0x001c /* deprecated */
-#define SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA	0x001d /* deprecated */
-#define SSL_FORTEZZA_DMS_WITH_RC4_128_SHA	0x001e /* deprecated */
+#define SSL_FORTEZZA_DMS_WITH_NULL_SHA          0x001c /* deprecated */
+#define SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA  0x001d /* deprecated */
+#define SSL_FORTEZZA_DMS_WITH_RC4_128_SHA       0x001e /* deprecated */
 
-#define TLS_RSA_WITH_AES_128_CBC_SHA      	0x002F
-#define TLS_DH_DSS_WITH_AES_128_CBC_SHA   	0x0030
-#define TLS_DH_RSA_WITH_AES_128_CBC_SHA   	0x0031
-#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA  	0x0032
-#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA  	0x0033
-#define TLS_DH_anon_WITH_AES_128_CBC_SHA  	0x0034
+#define TLS_RSA_WITH_AES_128_CBC_SHA            0x002F
+#define TLS_DH_DSS_WITH_AES_128_CBC_SHA         0x0030
+#define TLS_DH_RSA_WITH_AES_128_CBC_SHA         0x0031
+#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA        0x0032
+#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA        0x0033
+#define TLS_DH_anon_WITH_AES_128_CBC_SHA        0x0034
 
-#define TLS_RSA_WITH_AES_256_CBC_SHA      	0x0035
-#define TLS_DH_DSS_WITH_AES_256_CBC_SHA   	0x0036
-#define TLS_DH_RSA_WITH_AES_256_CBC_SHA   	0x0037
-#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA  	0x0038
-#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA  	0x0039
-#define TLS_DH_anon_WITH_AES_256_CBC_SHA  	0x003A
-#define TLS_RSA_WITH_NULL_SHA256		0x003B
-#define TLS_RSA_WITH_AES_128_CBC_SHA256  	0x003C
-#define TLS_RSA_WITH_AES_256_CBC_SHA256  	0x003D
+#define TLS_RSA_WITH_AES_256_CBC_SHA            0x0035
+#define TLS_DH_DSS_WITH_AES_256_CBC_SHA         0x0036
+#define TLS_DH_RSA_WITH_AES_256_CBC_SHA         0x0037
+#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA        0x0038
+#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA        0x0039
+#define TLS_DH_anon_WITH_AES_256_CBC_SHA        0x003A
+#define TLS_RSA_WITH_NULL_SHA256                0x003B
+#define TLS_RSA_WITH_AES_128_CBC_SHA256         0x003C
+#define TLS_RSA_WITH_AES_256_CBC_SHA256         0x003D
 
-#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA      	0x0041
-#define TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA   	0x0042
-#define TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA   	0x0043
-#define TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA  	0x0044
-#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA  	0x0045
-#define TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA  	0x0046
+#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA       0x0041
+#define TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA    0x0042
+#define TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA    0x0043
+#define TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA   0x0044
+#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA   0x0045
+#define TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA   0x0046
 
 #define TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA     0x0062
 #define TLS_RSA_EXPORT1024_WITH_RC4_56_SHA      0x0064
 
 #define TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA 0x0063
 #define TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA  0x0065
 #define TLS_DHE_DSS_WITH_RC4_128_SHA            0x0066
 #define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256     0x0067
 #define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256     0x006B
 
-#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA      	0x0084
-#define TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA   	0x0085
-#define TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA   	0x0086
-#define TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA  	0x0087
-#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA  	0x0088
-#define TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA  	0x0089
+#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA       0x0084
+#define TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA    0x0085
+#define TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA    0x0086
+#define TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA   0x0087
+#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA   0x0088
+#define TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA   0x0089
 
-#define TLS_RSA_WITH_SEED_CBC_SHA		0x0096
+#define TLS_RSA_WITH_SEED_CBC_SHA               0x0096
 
 #define TLS_RSA_WITH_AES_128_GCM_SHA256         0x009C
 #define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256     0x009E
 #define TLS_DHE_DSS_WITH_AES_128_GCM_SHA256     0x00A2
 
 /* TLS "Signaling Cipher Suite Value" (SCSV). May be requested by client.
  * Must NEVER be chosen by server.  SSL 3.0 server acknowledges by sending
  * back an empty Renegotiation Info (RI) server hello extension.
  */
-#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV	0x00FF
+#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV       0x00FF
 
 /* Cipher Suite Values starting with 0xC000 are defined in informational
  * RFCs.
  */
 #define TLS_ECDH_ECDSA_WITH_NULL_SHA            0xC001
 #define TLS_ECDH_ECDSA_WITH_RC4_128_SHA         0xC002
 #define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA    0xC003
 #define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA     0xC004
@@ -243,23 +245,23 @@
 #define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256   0xC027
 
 #define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B
 #define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256  0xC02D
 #define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256   0xC02F
 #define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256    0xC031
 
 /* Netscape "experimental" cipher suites. */
-#define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA	0xffe0
-#define SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA	0xffe1
+#define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA   0xffe0
+#define SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA        0xffe1
 
 /* New non-experimental openly spec'ed versions of those cipher suites. */
-#define SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA 	0xfeff
-#define SSL_RSA_FIPS_WITH_DES_CBC_SHA      	0xfefe
+#define SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA      0xfeff
+#define SSL_RSA_FIPS_WITH_DES_CBC_SHA           0xfefe
 
 /* DTLS-SRTP cipher suites from RFC 5764 */
 /* If you modify this, also modify MAX_DTLS_SRTP_CIPHER_SUITES in sslimpl.h */
-#define SRTP_AES128_CM_HMAC_SHA1_80		0x0001
-#define SRTP_AES128_CM_HMAC_SHA1_32		0x0002
-#define SRTP_NULL_HMAC_SHA1_80			0x0005
-#define SRTP_NULL_HMAC_SHA1_32			0x0006
+#define SRTP_AES128_CM_HMAC_SHA1_80             0x0001
+#define SRTP_AES128_CM_HMAC_SHA1_32             0x0002
+#define SRTP_NULL_HMAC_SHA1_80                  0x0005
+#define SRTP_NULL_HMAC_SHA1_32                  0x0006
 
 #endif /* __sslproto_h_ */
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -1365,16 +1365,21 @@ SSL_ImportFD(PRFileDesc *model, PRFileDe
 }
 
 PRFileDesc *
 DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd)
 {
     return ssl_ImportFD(model, fd, ssl_variant_datagram);
 }
 
+/* SSL_SetNextProtoCallback is used to select an application protocol
+ * for ALPN and NPN.  For ALPN, this runs on the server; for NPN it
+ * runs on the client. */
+/* Note: The ALPN version doesn't allow for the use of a default, setting a
+ * status of SSL_NEXT_PROTO_NO_OVERLAP is treated as a failure. */
 SECStatus
 SSL_SetNextProtoCallback(PRFileDesc *fd, SSLNextProtoCallback callback,
                          void *arg)
 {
     sslSocket *ss = ssl_FindSocket(fd);
 
     if (!ss) {
         SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetNextProtoCallback", SSL_GETPID(),
@@ -1385,17 +1390,17 @@ SSL_SetNextProtoCallback(PRFileDesc *fd,
     ssl_GetSSL3HandshakeLock(ss);
     ss->nextProtoCallback = callback;
     ss->nextProtoArg = arg;
     ssl_ReleaseSSL3HandshakeLock(ss);
 
     return SECSuccess;
 }
 
-/* ssl_NextProtoNegoCallback is set as an NPN callback for the case when
+/* ssl_NextProtoNegoCallback is set as an ALPN/NPN callback when
  * SSL_SetNextProtoNego is used.
  */
 static SECStatus
 ssl_NextProtoNegoCallback(void *arg, PRFileDesc *fd,
                           const unsigned char *protos, unsigned int protos_len,
                           unsigned char *protoOut, unsigned int *protoOutLen,
                           unsigned int protoMaxLen)
 {
@@ -1404,39 +1409,36 @@ ssl_NextProtoNegoCallback(void *arg, PRF
     sslSocket *ss = ssl_FindSocket(fd);
 
     if (!ss) {
         SSL_DBG(("%d: SSL[%d]: bad socket in ssl_NextProtoNegoCallback",
                  SSL_GETPID(), fd));
         return SECFailure;
     }
 
-    if (protos_len == 0) {
-        /* The server supports the extension, but doesn't have any protocols
-         * configured. In this case we request our favoured protocol. */
-        goto pick_first;
-    }
-
     /* For each protocol in server preference, see if we support it. */
     for (i = 0; i < protos_len; ) {
         for (j = 0; j < ss->opt.nextProtoNego.len; ) {
             if (protos[i] == ss->opt.nextProtoNego.data[j] &&
                 PORT_Memcmp(&protos[i+1], &ss->opt.nextProtoNego.data[j+1],
                              protos[i]) == 0) {
                 /* We found a match. */
                 ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED;
                 result = &protos[i];
                 goto found;
             }
             j += 1 + (unsigned int)ss->opt.nextProtoNego.data[j];
         }
         i += 1 + (unsigned int)protos[i];
     }
 
-pick_first:
+    /* The other side supports the extension, and either doesn't have any
+     * protocols configured, or none of its options match ours. In this case we
+     * request our favoured protocol. */
+    /* This will be treated as a failure for ALPN. */
     ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP;
     result = ss->opt.nextProtoNego.data;
 
 found:
     if (protoMaxLen < result[0]) {
         PORT_SetError(SEC_ERROR_OUTPUT_LEN);
         return SECFailure;
     }
--- a/security/nss/tests/cert/cert.sh
+++ b/security/nss/tests/cert/cert.sh
@@ -1171,16 +1171,211 @@ cert_extensions()
             cert_extensions_test
             rm -f ${TARG_FILE}
         else
             echo ${ARG} >> ${TARG_FILE}
         fi
     done < ${QADIR}/cert/certext.txt
 }
 
+cert_make_with_param()
+{
+    DIRPASS="$1"
+    CERTNAME="$2"
+    MAKE="$3"
+    SUBJ="$4"
+    EXTRA="$5"
+    EXPECT="$6"
+    TESTNAME="$7"
+
+    echo certutil ${DIRPASS} -s "${SUBJ}" ${MAKE} ${CERTNAME} ${EXTRA}
+    ${BINDIR}/certutil ${DIRPASS} -s "${SUBJ}" ${MAKE} ${CERTNAME} ${EXTRA}
+        
+    RET=$?
+    if [ "${RET}" -ne "${EXPECT}" ]; then
+        # if we expected failure to create, then delete unexpected certificate
+        if [ "${EXPECT}" -ne 0 ]; then
+            ${BINDIR}/certutil ${DIRPASS} -D ${CERTNAME}
+        fi
+    
+        CERTFAILED=1
+        html_failed "${TESTNAME} (${COUNT}) - ${EXTRA}" 
+        cert_log "ERROR: ${TESTNAME} - ${EXTRA} failed"
+        return 1
+    fi
+
+    html_passed "${TESTNAME} (${COUNT})"
+    return 0
+}
+
+cert_list_and_count_dns()
+{
+    DIRPASS="$1"
+    CERTNAME="$2"
+    EXPECT="$3"
+    EXPECTCOUNT="$4"
+    TESTNAME="$5"
+
+    echo certutil ${DIRPASS} -L ${CERTNAME}
+    ${BINDIR}/certutil ${DIRPASS} -L ${CERTNAME}
+
+    RET=$?
+    if [ "${RET}" -ne "${EXPECT}" ]; then
+        CERTFAILED=1
+        html_failed "${TESTNAME} (${COUNT}) - list and count" 
+        cert_log "ERROR: ${TESTNAME} - list and count failed"
+        return 1
+    fi
+
+    LISTCOUNT=`${BINDIR}/certutil ${DIRPASS} -L ${CERTNAME} | grep -wc DNS`
+    if [ "${LISTCOUNT}" -ne "${EXPECTCOUNT}" ]; then
+        CERTFAILED=1
+        html_failed "${TESTNAME} (${COUNT}) - list and count" 
+        cert_log "ERROR: ${TESTNAME} - list and count failed"
+        return 1
+    fi
+
+    html_passed "${TESTNAME} (${COUNT})"
+    return 0
+}
+
+cert_dump_ext_to_file()
+{
+    DIRPASS="$1"
+    CERTNAME="$2"
+    OID="$3"
+    OUTFILE="$4"
+    EXPECT="$5"
+    TESTNAME="$6"
+
+    echo certutil ${DIRPASS} -L ${CERTNAME} --dump-ext-val ${OID}
+    echo "writing output to ${OUTFILE}"
+    ${BINDIR}/certutil ${DIRPASS} -L ${CERTNAME} --dump-ext-val ${OID} > ${OUTFILE}
+        
+    RET=$?
+    if [ "${RET}" -ne "${EXPECT}" ]; then
+        CERTFAILED=1
+        html_failed "${TESTNAME} (${COUNT}) - dump to file"
+        cert_log "ERROR: ${TESTNAME} - dump to file failed"
+        return 1
+    fi
+
+    html_passed "${TESTNAME} (${COUNT})"
+    return 0
+}
+
+cert_delete()
+{
+    DIRPASS="$1"
+    CERTNAME="$2"
+    EXPECT="$3"
+    TESTNAME="$4"
+
+    echo certutil ${DIRPASS} -D ${CERTNAME}
+    ${BINDIR}/certutil ${DIRPASS} -D ${CERTNAME}
+        
+    RET=$?
+    if [ "${RET}" -ne "${EXPECT}" ]; then
+        CERTFAILED=1
+        html_failed "${TESTNAME} (${COUNT}) - delete cert" 
+        cert_log "ERROR: ${TESTNAME} - delete cert failed"
+        return 1
+    fi
+
+    html_passed "${TESTNAME} (${COUNT})"
+    return 0
+}
+
+cert_inc_count()
+{
+    COUNT=`expr ${COUNT} + 1`
+}
+
+############################## cert_crl_ssl ############################
+# test adding subject-alt-name, dumping, and adding generic extension
+########################################################################
+cert_san_and_generic_extensions()
+{
+    EXTDUMP=${CERT_EXTENSIONS_DIR}/sanext.der
+
+    DIR="-d ${CERT_EXTENSIONS_DIR} -f ${R_PWFILE}"
+    CERTNAME="-n WithSAN"
+    MAKE="-S -t ,, -x -z ${R_NOISE_FILE}"
+    SUBJ="CN=example.com"
+
+    TESTNAME="san-and-generic-extensions"
+
+    cert_inc_count
+    cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
+        "--extSAN example.com" 255 \
+        "create cert with invalid SAN parameter"
+
+    cert_inc_count
+    cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
+        "--extSAN example.com,dns:www.example.com" 255 \
+        "create cert with invalid SAN parameter"
+
+    TN="create cert with valid SAN parameter"
+
+    cert_inc_count
+    cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
+        "--extSAN dns:example.com,dns:www.example.com" 0 \
+        "${TN}"
+
+    cert_inc_count
+    cert_list_and_count_dns "${DIR}" "${CERTNAME}" 0 2 \
+        "${TN}"
+
+    cert_inc_count
+    cert_dump_ext_to_file "${DIR}" "${CERTNAME}" "2.5.29.17" "${EXTDUMP}" 0 \
+        "dump extension 2.5.29.17 to file ${EXTDUMP}"
+
+    cert_inc_count
+    cert_delete "${DIR}" "${CERTNAME}" 0 \
+        "${TN}"
+
+    cert_inc_count
+    cert_list_and_count_dns "${DIR}" "${CERTNAME}" 255 0 \
+        "expect failure to list cert, because we deleted it"
+
+    cert_inc_count
+    cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
+        "--extGeneric ${EXTDUMP}" 255 \
+        "create cert with invalid generic ext parameter"
+
+    cert_inc_count
+    cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
+        "--extGeneric not-critical:${EXTDUMP}" 255 \
+        "create cert with invalid generic ext parameter"
+
+    cert_inc_count
+    cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
+        "--extGeneric not-critical:${EXTDUMP},2.5.29.17:critical:${EXTDUMP}" 255 \
+        "create cert with invalid generic ext parameter"
+
+    TN="create cert with valid generic ext parameter"
+
+    cert_inc_count
+    cert_make_with_param "${DIR}" "${CERTNAME}" "${MAKE}" "${SUBJ}" \
+        "--extGeneric 2.5.29.17:not-critical:${EXTDUMP}" 0 \
+        "${TN}"
+
+    cert_inc_count
+    cert_list_and_count_dns "${DIR}" "${CERTNAME}" 0 2 \
+        "${TN}"
+
+    cert_inc_count
+    cert_delete "${DIR}" "${CERTNAME}" 0 \
+        "${TN}"
+
+    cert_inc_count
+    cert_list_and_count_dns "${DIR}" "${CERTNAME}" 255 0 \
+        "expect failure to list cert, because we deleted it"
+}
+
 ############################## cert_crl_ssl ############################
 # local shell function to generate certs and crls for SSL tests
 ########################################################################
 cert_crl_ssl()
 {
     
   ################# Creating Certs ###################################
   #
@@ -1508,16 +1703,17 @@ cert_all_CA
 cert_extended_ssl 
 cert_ssl 
 cert_smime_client        
 if [ -z "$NSS_TEST_DISABLE_FIPS" ]; then
     cert_fips
 fi
 cert_eccurves
 cert_extensions
+cert_san_and_generic_extensions
 cert_test_password
 cert_test_distrust
 cert_test_ocspresp
 
 if [ -z "$NSS_TEST_DISABLE_CRL" ] ; then
     cert_crl_ssl
 else
     echo "$SCRIPTNAME: Skipping CRL Tests"