Bug 1334127 - land NSS 6511e19a2c6c, r=me
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Tue, 28 Feb 2017 13:52:02 +0100
changeset 490596 5b35dfe81b6843650b28fddb727b515310311dc9
parent 490595 697dbeae416bf99e4a43b60ee246d68b576be330
child 490597 a1d03f028cb1f12ae824a49e692d87617eca1377
push id47156
push userbmo:lockhart@cs.dal.ca
push dateTue, 28 Feb 2017 22:47:20 +0000
reviewersme
bugs1334127
milestone54.0a1
Bug 1334127 - land NSS 6511e19a2c6c, r=me
security/nss/TAG-INFO
security/nss/automation/taskcluster/docker/setup.sh
security/nss/automation/taskcluster/graph/src/extend.js
security/nss/cmd/pk12util/pk12util.c
security/nss/cmd/tstclnt/tstclnt.c
security/nss/coreconf/coreconf.dep
security/nss/cpputil/scoped_ptrs.h
security/nss/fuzz/fuzz.gyp
security/nss/fuzz/hash.options
security/nss/fuzz/hash_target.cc
security/nss/gtests/ssl_gtest/tls_connect.cc
security/nss/lib/certdb/certdb.c
security/nss/lib/certdb/stanpcertdb.c
security/nss/lib/certhigh/certhigh.c
security/nss/lib/freebl/Makefile
security/nss/lib/nss/nss.def
security/nss/lib/pk11wrap/pk11cert.c
security/nss/lib/pk11wrap/pk11pbe.c
security/nss/lib/pkcs12/p12d.c
security/nss/lib/pkcs12/p12e.c
security/nss/lib/pkcs12/p12local.c
security/nss/lib/pkcs12/p12local.h
security/nss/lib/pkcs12/p12plcy.c
security/nss/lib/pkcs7/p7create.c
security/nss/lib/pkcs7/secpkcs7.h
security/nss/lib/util/ciferfam.h
security/nss/lib/util/nssb64d.c
security/nss/nss-tool/common/util.cc
security/nss/nss-tool/common/util.h
security/nss/nss-tool/db/dbtool.cc
security/nss/nss-tool/db/dbtool.h
security/nss/nss-tool/nss_tool.cc
security/nss/nss-tool/nss_tool.gyp
security/nss/tests/bogo/bogo.sh
security/nss/tests/tools/tools.sh
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-93b99b0936d3
+6511e19a2c6c
--- a/security/nss/automation/taskcluster/docker/setup.sh
+++ b/security/nss/automation/taskcluster/docker/setup.sh
@@ -45,17 +45,17 @@ echo "deb http://ppa.launchpad.net/ubunt
 apt-get -y update
 apt-get install -y --no-install-recommends ${apt_packages[@]}
 
 # 32-bit builds
 ln -s /usr/include/x86_64-linux-gnu/zconf.h /usr/include
 
 # Install clang-3.9 into /usr/local/.
 # FIXME: verify signature
-curl -L http://releases.llvm.org/3.9.0/clang+llvm-3.9.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz | tar xJv -C /usr/local --strip-components=1
+curl -L http://releases.llvm.org/3.9.1/clang+llvm-3.9.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz | tar xJv -C /usr/local --strip-components=1
 
 # Install latest Rust (stable).
 su worker -c "curl https://sh.rustup.rs -sSf | sh -s -- -y"
 
 locale-gen en_US.UTF-8
 dpkg-reconfigure locales
 
 # Cleanup.
--- a/security/nss/automation/taskcluster/graph/src/extend.js
+++ b/security/nss/automation/taskcluster/graph/src/extend.js
@@ -348,17 +348,16 @@ async function scheduleFuzzing() {
     cycle: "standard",
     symbol: "Gtest",
     kind: "test"
   }));
 
   // Schedule fuzzing runs.
   let run_base = merge(base, {parent: task_build, kind: "test"});
   scheduleFuzzingRun(run_base, "CertDN", "certDN", 4096);
-  scheduleFuzzingRun(run_base, "Hash", "hash", 4096);
   scheduleFuzzingRun(run_base, "QuickDER", "quickder", 10000);
 
   // Schedule MPI fuzzing runs.
   let mpi_base = merge(run_base, {group: "MPI"});
   let mpi_names = ["add", "addmod", "div", "expmod", "mod", "mulmod", "sqr",
                    "sqrmod", "sub", "submod"];
   for (let name of mpi_names) {
     scheduleFuzzingRun(mpi_base, `MPI (${name})`, `mpi-${name}`, 4096, name);
--- a/security/nss/cmd/pk12util/pk12util.c
+++ b/security/nss/cmd/pk12util/pk12util.c
@@ -610,21 +610,17 @@ P12U_ExportPKCS12Object(char *nn, char *
     p12cxt = p12u_InitContext(PR_FALSE, outfile);
     if (!p12cxt) {
         SECU_PrintError(progName, "Initialization failed: %s", outfile);
         pk12uErrno = PK12UERR_INIT_FILE;
         goto loser;
     }
 
     if (certlist) {
-        CERTCertificate *cert = NULL;
-        node = CERT_LIST_HEAD(certlist);
-        if (node) {
-            cert = node->cert;
-        }
+        CERTCertificate *cert = CERT_LIST_HEAD(certlist)->cert;
         if (cert) {
             slot = cert->slot; /* use the slot from the first matching
                 certificate to create the context . This is for keygen */
         }
     }
     if (!slot) {
         SECU_PrintError(progName, "cert does not have a slot");
         pk12uErrno = PK12UERR_FINDCERTBYNN;
@@ -856,16 +852,19 @@ static void
 p12u_EnableAllCiphers()
 {
     SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
     SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
     SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
     SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
     SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
     SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
+    SEC_PKCS12EnableCipher(PKCS12_AES_CBC_128, 1);
+    SEC_PKCS12EnableCipher(PKCS12_AES_CBC_192, 1);
+    SEC_PKCS12EnableCipher(PKCS12_AES_CBC_256, 1);
     SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
 }
 
 static PRUintn
 P12U_Init(char *dir, char *dbprefix, PRBool listonly)
 {
     SECStatus rv;
     PK11_SetPasswordFunc(SECU_GetModulePassword);
--- a/security/nss/cmd/tstclnt/tstclnt.c
+++ b/security/nss/cmd/tstclnt/tstclnt.c
@@ -870,16 +870,20 @@ restartHandshakeAfterServerCertIfNeeded(
         }
     }
     if (rv == SECSuccess) {
         error = 0;
     }
 
     if (SSL_AuthCertificateComplete(fd, error) != SECSuccess) {
         rv = SECFailure;
+    } else {
+        /* restore the original error code, which could be reset by
+         * SSL_AuthCertificateComplete */
+        PORT_SetError(error);
     }
 
     return rv;
 }
 
 char *host = NULL;
 char *nickname = NULL;
 char *cipherString = NULL;
--- 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/cpputil/scoped_ptrs.h
+++ b/security/nss/cpputil/scoped_ptrs.h
@@ -23,16 +23,19 @@ struct ScopedDelete {
   }
   void operator()(PK11SlotInfo* slot) { PK11_FreeSlot(slot); }
   void operator()(PK11SymKey* key) { PK11_FreeSymKey(key); }
   void operator()(PRFileDesc* fd) { PR_Close(fd); }
   void operator()(SECAlgorithmID* id) { SECOID_DestroyAlgorithmID(id, true); }
   void operator()(SECItem* item) { SECITEM_FreeItem(item, true); }
   void operator()(SECKEYPublicKey* key) { SECKEY_DestroyPublicKey(key); }
   void operator()(SECKEYPrivateKey* key) { SECKEY_DestroyPrivateKey(key); }
+  void operator()(SECKEYPrivateKeyList* list) {
+    SECKEY_DestroyPrivateKeyList(list);
+  }
 };
 
 template <class T>
 struct ScopedMaybeDelete {
   void operator()(T* ptr) {
     if (ptr) {
       ScopedDelete del;
       del(ptr);
@@ -48,12 +51,13 @@ SCOPED(CERTCertList);
 SCOPED(CERTSubjectPublicKeyInfo);
 SCOPED(PK11SlotInfo);
 SCOPED(PK11SymKey);
 SCOPED(PRFileDesc);
 SCOPED(SECAlgorithmID);
 SCOPED(SECItem);
 SCOPED(SECKEYPublicKey);
 SCOPED(SECKEYPrivateKey);
+SCOPED(SECKEYPrivateKeyList);
 
 #undef SCOPED
 
 #endif  // scoped_ptrs_h__
--- a/security/nss/fuzz/fuzz.gyp
+++ b/security/nss/fuzz/fuzz.gyp
@@ -108,27 +108,16 @@
         'quickder_target.cc',
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         'fuzz_base',
       ],
     },
     {
-      'target_name': 'nssfuzz-hash',
-      'type': 'executable',
-      'sources': [
-        'hash_target.cc',
-      ],
-      'dependencies': [
-        '<(DEPTH)/exports.gyp:nss_exports',
-        'fuzz_base',
-      ],
-    },
-    {
       'target_name': 'nssfuzz-certDN',
       'type': 'executable',
       'sources': [
         'certDN_target.cc',
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         'fuzz_base',
@@ -282,17 +271,16 @@
         }],
       ],
     },
     {
       'target_name': 'nssfuzz',
       'type': 'none',
       'dependencies': [
         'nssfuzz-certDN',
-        'nssfuzz-hash',
         'nssfuzz-pkcs8',
         'nssfuzz-quickder',
         'nssfuzz-tls-client',
       ],
       'conditions': [
         ['OS=="linux"', {
           'dependencies': [
             'nssfuzz-mpi-add',
deleted file mode 100644
--- a/security/nss/fuzz/hash.options
+++ /dev/null
@@ -1,3 +0,0 @@
-[libfuzzer]
-max_len = 4096
-
deleted file mode 100644
--- a/security/nss/fuzz/hash_target.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <memory>
-#include <vector>
-
-#include "hasht.h"
-#include "pk11pub.h"
-#include "secoidt.h"
-#include "shared.h"
-
-const std::vector<SECOidTag> algos = {SEC_OID_MD5, SEC_OID_SHA1, SEC_OID_SHA256,
-                                      SEC_OID_SHA384, SEC_OID_SHA512};
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  uint8_t hashOut[HASH_LENGTH_MAX];
-
-  static std::unique_ptr<NSSDatabase> db(new NSSDatabase());
-  assert(db != nullptr);
-
-  // simple hashing.
-  for (auto algo : algos) {
-    assert(PK11_HashBuf(algo, hashOut, data, size) == SECSuccess);
-  }
-
-  // hashing with context.
-  for (auto algo : algos) {
-    unsigned int len = 0;
-    PK11Context *context = PK11_CreateDigestContext(algo);
-    assert(context != nullptr);
-    assert(PK11_DigestBegin(context) == SECSuccess);
-    assert(PK11_DigestFinal(context, hashOut, &len, HASH_LENGTH_MAX) ==
-           SECSuccess);
-    PK11_DestroyContext(context, PR_TRUE);
-  }
-
-  return 0;
-}
--- a/security/nss/gtests/ssl_gtest/tls_connect.cc
+++ b/security/nss/gtests/ssl_gtest/tls_connect.cc
@@ -169,17 +169,17 @@ void TlsConnectTestBase::ClearServerCach
   SSL_ShutdownServerSessionIDCache();
   SSLInt_ClearSessionTicketKey();
   SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str());
 }
 
 void TlsConnectTestBase::SetUp() {
   SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str());
   SSLInt_ClearSessionTicketKey();
-  SSLInt_SetTicketLifetime(10);
+  SSLInt_SetTicketLifetime(30);
   ClearStats();
   Init();
 }
 
 void TlsConnectTestBase::TearDown() {
   client_ = nullptr;
   server_ = nullptr;
 
--- a/security/nss/lib/certdb/certdb.c
+++ b/security/nss/lib/certdb/certdb.c
@@ -2554,19 +2554,19 @@ CERT_AddCertToListTail(CERTCertList *cer
 SECStatus
 CERT_AddCertToListHeadWithData(CERTCertList *certs, CERTCertificate *cert,
                                void *appData)
 {
     CERTCertListNode *node;
     CERTCertListNode *head;
 
     head = CERT_LIST_HEAD(certs);
-
-    if (head == NULL)
-        return CERT_AddCertToListTail(certs, cert);
+    if (head == NULL) {
+        goto loser;
+    }
 
     node = (CERTCertListNode *)PORT_ArenaZAlloc(certs->arena,
                                                 sizeof(CERTCertListNode));
     if (node == NULL) {
         goto loser;
     }
 
     PR_INSERT_BEFORE(&node->links, &head->links);
--- a/security/nss/lib/certdb/stanpcertdb.c
+++ b/security/nss/lib/certdb/stanpcertdb.c
@@ -510,38 +510,35 @@ CERT_FindCertByName(CERTCertDBHandle *ha
     return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
 }
 
 CERTCertificate *
 CERT_FindCertByKeyID(CERTCertDBHandle *handle, SECItem *name, SECItem *keyID)
 {
     CERTCertList *list;
     CERTCertificate *cert = NULL;
-    CERTCertListNode *node, *head;
+    CERTCertListNode *node;
 
     list = CERT_CreateSubjectCertList(NULL, handle, name, 0, PR_FALSE);
     if (list == NULL)
         return NULL;
 
-    node = head = CERT_LIST_HEAD(list);
-    if (head) {
-        do {
-            if (node->cert &&
-                SECITEM_ItemsAreEqual(&node->cert->subjectKeyID, keyID)) {
-                cert = CERT_DupCertificate(node->cert);
-                goto done;
-            }
-            node = CERT_LIST_NEXT(node);
-        } while (node && head != node);
+    node = CERT_LIST_HEAD(list);
+    while (!CERT_LIST_END(node, list)) {
+        if (node->cert &&
+            SECITEM_ItemsAreEqual(&node->cert->subjectKeyID, keyID)) {
+            cert = CERT_DupCertificate(node->cert);
+            goto done;
+        }
+        node = CERT_LIST_NEXT(node);
     }
     PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
+
 done:
-    if (list) {
-        CERT_DestroyCertList(list);
-    }
+    CERT_DestroyCertList(list);
     return cert;
 }
 
 CERTCertificate *
 CERT_FindCertByNickname(CERTCertDBHandle *handle, const char *nickname)
 {
     NSSCryptoContext *cc;
     NSSCertificate *c, *ct;
@@ -630,18 +627,17 @@ common_FindCertByNicknameOrEmailAddrForU
                 ct = NULL;
             }
         }
 
         certlist = PK11_FindCertsFromNickname(name, NULL);
         if (certlist) {
             SECStatus rv =
                 CERT_FilterCertListByUsage(certlist, lookingForUsage, PR_FALSE);
-            if (SECSuccess == rv &&
-                !CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist)) {
+            if (SECSuccess == rv && !CERT_LIST_EMPTY(certlist)) {
                 cert = CERT_DupCertificate(CERT_LIST_HEAD(certlist)->cert);
             }
             CERT_DestroyCertList(certlist);
         }
     }
 
     if (cert) {
         c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert));
--- a/security/nss/lib/certhigh/certhigh.c
+++ b/security/nss/lib/certhigh/certhigh.c
@@ -284,17 +284,17 @@ CERT_FindUserCertByUsage(CERTCertDBHandl
 
     /* remove certs with incorrect usage */
     rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);
 
     if (rv != SECSuccess) {
         goto loser;
     }
 
-    if (!CERT_LIST_END(CERT_LIST_HEAD(certList), certList)) {
+    if (!CERT_LIST_EMPTY(certList)) {
         cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert);
     }
 
 loser:
     if (certList != NULL) {
         CERT_DestroyCertList(certList);
     }
 
--- a/security/nss/lib/freebl/Makefile
+++ b/security/nss/lib/freebl/Makefile
@@ -227,18 +227,16 @@ ifeq ($(CPU_ARCH),x86_64)
     INTEL_GCM = 1
     MPI_SRCS += mpi_amd64.c mp_comba.c
 endif
 ifeq ($(CPU_ARCH),x86)
     ASFILES  = mpi_x86.s
     DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE 
     DEFINES += -DMP_ASSEMBLY_DIV_2DX1D -DMP_USE_UINT_DIGIT
     DEFINES += -DMP_IS_LITTLE_ENDIAN
-    # The floating point ECC code doesn't work on Linux x86 (bug 311432).
-    #ECL_USE_FP = 1
 endif
 ifeq ($(CPU_ARCH),arm)
     DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE 
     DEFINES += -DMP_USE_UINT_DIGIT
     DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
     MPI_SRCS += mpi_arm.c
 endif
 ifeq ($(CPU_ARCH),ppc)
@@ -425,30 +423,28 @@ ifeq ($(CPU_ARCH),sparc)
     endif
     ifdef USE_ABI32_FPU
 	# this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers, 
 	# 32-bit ABI, it uses FPU code, and 32-bit word size
 	MPI_SRCS += mpi_sparc.c
 	ASFILES  = mpv_sparcv8.s montmulfv8.s
 	DEFINES  += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY
 	DEFINES  += -DMP_USING_MONT_MULF -DMP_MONT_USE_MP_MUL
-	ECL_USE_FP = 1
     endif
     ifdef USE_ABI64_INT
 	# this builds for Sparc v9a pure 64-bit architecture
 	# best times are with no MP_ flags specified
     endif
     ifdef USE_ABI64_FPU
 	# this builds for Sparc v9a pure 64-bit architecture
 	# It uses floating point, and 32-bit word size
 	MPI_SRCS += mpi_sparc.c
 	ASFILES   = mpv_sparcv9.s montmulfv9.s
 	DEFINES  += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY
 	DEFINES  += -DMP_USING_MONT_MULF -DMP_MONT_USE_MP_MUL
-	ECL_USE_FP = 1
     endif
 
 else
     # Solaris for non-sparc family CPUs
     ifdef NS_USE_GCC
 	LD = gcc
 	AS = gcc
 	ASFLAGS = -x assembler-with-cpp
@@ -486,26 +482,17 @@ else
 	DEFINES += -DMP_ASSEMBLY_DIV_2DX1D
 	ASFILES  = mpi_i86pc.s
  	ifndef NS_USE_GCC
  	   MPCPU_SRCS =
  	   ASFILES += mpcpucache_x86.s
  	endif
     endif
 endif # Solaris for non-sparc family CPUs
-endif # target == SunOS
-
-ifndef NSS_DISABLE_ECC
-    ifdef ECL_USE_FP
-	#enable floating point ECC code	
-	DEFINES  += -DECL_USE_FP
-	ECL_SRCS += ecp_fp160.c ecp_fp192.c ecp_fp224.c ecp_fp.c
-	ECL_HDRS += ecp_fp.h
-    endif
-endif
+endif # target == SunO
 
 # poly1305-donna-x64-sse2-incremental-source.c requires __int128 support
 # in GCC 4.6.0.
 ifdef USE_64
     ifdef CC_IS_CLANG
             HAVE_INT128_SUPPORT = 1
             DEFINES += -DHAVE_INT128_SUPPORT
     else ifeq (1,$(CC_IS_GCC))
--- a/security/nss/lib/nss/nss.def
+++ b/security/nss/lib/nss/nss.def
@@ -1094,12 +1094,13 @@ SECMOD_CreateModuleEx;
 ;+    global:
 PK11_SignWithMechanism;
 PK11_VerifyWithMechanism;
 ;+    local:
 ;+       *;
 ;+};
 ;+NSS_3.30 { 	# NSS 3.30 release
 ;+    global:
+CERT_CompareAVA;
 PK11_HasAttributeSet;
 ;+    local:
 ;+       *;
 ;+};
--- a/security/nss/lib/pk11wrap/pk11cert.c
+++ b/security/nss/lib/pk11wrap/pk11cert.c
@@ -685,18 +685,17 @@ PK11_FindCertsFromEmailAddress(const cha
     rv = PK11_TraverseSlotCerts(FindCertsEmailCallback, &cbparam, NULL);
     if (rv != SECSuccess) {
         CERT_DestroyCertList(cbparam.certList);
         PORT_Free(cbparam.email);
         return NULL;
     }
 
     /* empty list? */
-    if (CERT_LIST_HEAD(cbparam.certList) == NULL ||
-        CERT_LIST_END(CERT_LIST_HEAD(cbparam.certList), cbparam.certList)) {
+    if (CERT_LIST_EMPTY(cbparam.certList)) {
         CERT_DestroyCertList(cbparam.certList);
         cbparam.certList = NULL;
     }
 
     PORT_Free(cbparam.email);
     return cbparam.certList;
 }
 
@@ -819,20 +818,16 @@ PK11_FindCertsFromNickname(const char *n
                     /* CERT_AddCertToListSorted adopts certCert  */
                     CERT_AddCertToListSorted(certList, certCert,
                                              CERT_SortCBValidity, &now);
                 }
             } else {
                 nssCertificate_Destroy(c);
             }
         }
-        if (certList && CERT_LIST_HEAD(certList) == NULL) {
-            CERT_DestroyCertList(certList);
-            certList = NULL;
-        }
         /* all the certs have been adopted or freed, free the  raw array */
         nss_ZFreeIf(foundCerts);
     }
     return certList;
 }
 
 /*
  * extract a key ID for a certificate...
--- a/security/nss/lib/pk11wrap/pk11pbe.c
+++ b/security/nss/lib/pk11wrap/pk11pbe.c
@@ -1,14 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "plarena.h"
 
+#include "blapit.h"
 #include "seccomon.h"
 #include "secitem.h"
 #include "secport.h"
 #include "hasht.h"
 #include "pkcs11t.h"
 #include "sechash.h"
 #include "secasn1.h"
 #include "secder.h"
@@ -296,27 +297,59 @@ SEC_PKCS5GetPBEAlgorithm(SECOidTag algTa
             break;
         default:
             return sec_pkcs5v2_get_pbe(algTag);
     }
 
     return SEC_OID_UNKNOWN;
 }
 
+static PRBool
+sec_pkcs5_is_algorithm_v2_aes_algorithm(SECOidTag algorithm)
+{
+    switch (algorithm) {
+        case SEC_OID_AES_128_CBC:
+        case SEC_OID_AES_192_CBC:
+        case SEC_OID_AES_256_CBC:
+            return PR_TRUE;
+        default:
+            return PR_FALSE;
+    }
+}
+
+static int
+sec_pkcs5v2_aes_key_length(SECOidTag algorithm)
+{
+    switch (algorithm) {
+        /* The key length for the AES-CBC-Pad algorithms are
+         * determined from the undelying cipher algorithm.  */
+        case SEC_OID_AES_128_CBC:
+            return AES_128_KEY_LENGTH;
+        case SEC_OID_AES_192_CBC:
+            return AES_192_KEY_LENGTH;
+        case SEC_OID_AES_256_CBC:
+            return AES_256_KEY_LENGTH;
+        default:
+            break;
+    }
+    return 0;
+}
+
 /*
  * get the key length in bytes from a PKCS5 PBE
  */
-int
-sec_pkcs5v2_key_length(SECAlgorithmID *algid)
+static int
+sec_pkcs5v2_key_length(SECAlgorithmID *algid, SECAlgorithmID *cipherAlgId)
 {
     SECOidTag algorithm;
     PLArenaPool *arena = NULL;
     SEC_PKCS5PBEParameter p5_param;
     SECStatus rv;
     int length = -1;
+    SECOidTag cipherAlg = SEC_OID_UNKNOWN;
 
     algorithm = SECOID_GetAlgorithmTag(algid);
     /* sanity check, they should all be PBKDF2 here */
     if (algorithm != SEC_OID_PKCS5_PBKDF2) {
         return -1;
     }
 
     arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
@@ -325,17 +358,22 @@ sec_pkcs5v2_key_length(SECAlgorithmID *a
     }
     PORT_Memset(&p5_param, 0, sizeof(p5_param));
     rv = SEC_ASN1DecodeItem(arena, &p5_param,
                             SEC_PKCS5V2PBEParameterTemplate, &algid->parameters);
     if (rv != SECSuccess) {
         goto loser;
     }
 
-    if (p5_param.keyLength.data != NULL) {
+    if (cipherAlgId)
+        cipherAlg = SECOID_GetAlgorithmTag(cipherAlgId);
+
+    if (sec_pkcs5_is_algorithm_v2_aes_algorithm(cipherAlg)) {
+        length = sec_pkcs5v2_aes_key_length(cipherAlg);
+    } else if (p5_param.keyLength.data != NULL) {
         length = DER_GetInteger(&p5_param.keyLength);
     }
 
 loser:
     if (arena) {
         PORT_FreeArena(arena, PR_FALSE);
     }
     return length;
@@ -370,24 +408,25 @@ SEC_PKCS5GetKeyLength(SECAlgorithmID *al
         case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
             return 5;
         case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
         case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
         case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
         case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
             return 16;
         case SEC_OID_PKCS5_PBKDF2:
-            return sec_pkcs5v2_key_length(algid);
+            return sec_pkcs5v2_key_length(algid, NULL);
         case SEC_OID_PKCS5_PBES2:
         case SEC_OID_PKCS5_PBMAC1: {
             sec_pkcs5V2Parameter *pbeV2_param;
             int length = -1;
             pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
             if (pbeV2_param != NULL) {
-                length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId);
+                length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId,
+                                                &pbeV2_param->cipherAlgId);
                 sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
             }
             return length;
         }
 
         default:
             break;
     }
@@ -609,16 +648,18 @@ sec_pkcs5CreateAlgorithmID(SECOidTag alg
             algorithm = sec_pkcs5v2_get_pbe(cipherAlgorithm);
         }
 
         /* set the PKCS5v2 specific parameters */
         if (keyLength == 0) {
             SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm);
             if (hashAlg != SEC_OID_UNKNOWN) {
                 keyLength = HASH_ResultLenByOidTag(hashAlg);
+            } else if (sec_pkcs5_is_algorithm_v2_aes_algorithm(cipherAlgorithm)) {
+                keyLength = sec_pkcs5v2_aes_key_length(cipherAlgorithm);
             } else {
                 CK_MECHANISM_TYPE cryptoMech;
                 cryptoMech = PK11_AlgtagToMechanism(cipherAlgorithm);
                 if (cryptoMech == CKM_INVALID_MECHANISM) {
                     goto loser;
                 }
                 keyLength = PK11_GetMaxKeyLength(cryptoMech);
             }
--- a/security/nss/lib/pkcs12/p12d.c
+++ b/security/nss/lib/pkcs12/p12d.c
@@ -172,47 +172,71 @@ sec_pkcs12_proper_version(sec_PKCS12PFXI
 
 /* retrieve the key for decrypting the safe contents */
 static PK11SymKey *
 sec_pkcs12_decoder_get_decrypt_key(void *arg, SECAlgorithmID *algid)
 {
     SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext *)arg;
     PK11SlotInfo *slot;
     PK11SymKey *bulkKey;
+    SECItem *pwitem;
+    SECItem decodedPwitem = { 0 };
+    SECOidTag algorithm;
 
     if (!p12dcx) {
         return NULL;
     }
 
     /* if no slot specified, use the internal key slot */
     if (p12dcx->slot) {
         slot = PK11_ReferenceSlot(p12dcx->slot);
     } else {
         slot = PK11_GetInternalKeySlot();
     }
 
-    bulkKey = PK11_PBEKeyGen(slot, algid, p12dcx->pwitem,
+    algorithm = SECOID_GetAlgorithmTag(algid);
+    pwitem = p12dcx->pwitem;
+
+    /* here we assume that the password is already encoded into
+     * BMPString by the caller.  if the encryption scheme is not the
+     * one defined in PKCS #12, decode the password back into
+     * UTF-8. */
+    if (!sec_pkcs12_is_pkcs12_pbe_algorithm(algorithm)) {
+        if (!sec_pkcs12_convert_item_to_unicode(NULL, &decodedPwitem,
+                                                p12dcx->pwitem,
+                                                PR_TRUE, PR_FALSE, PR_FALSE)) {
+            PORT_SetError(SEC_ERROR_NO_MEMORY);
+            return NULL;
+        }
+        pwitem = &decodedPwitem;
+    }
+
+    bulkKey = PK11_PBEKeyGen(slot, algid, pwitem,
                              PR_FALSE, p12dcx->wincx);
     /* some tokens can't generate PBE keys on their own, generate the
      * key in the internal slot, and let the Import code deal with it,
      * (if the slot can't generate PBEs, then we need to use the internal
      * slot anyway to unwrap). */
     if (!bulkKey && !PK11_IsInternal(slot)) {
         PK11_FreeSlot(slot);
         slot = PK11_GetInternalKeySlot();
-        bulkKey = PK11_PBEKeyGen(slot, algid, p12dcx->pwitem,
+        bulkKey = PK11_PBEKeyGen(slot, algid, pwitem,
                                  PR_FALSE, p12dcx->wincx);
     }
     PK11_FreeSlot(slot);
 
     /* set the password data on the key */
     if (bulkKey) {
         PK11_SetSymKeyUserData(bulkKey, p12dcx->pwitem, NULL);
     }
 
+    if (decodedPwitem.data) {
+        SECITEM_ZfreeItem(&decodedPwitem, PR_FALSE);
+    }
+
     return bulkKey;
 }
 
 /* XXX this needs to be modified to handle enveloped data.  most
  * likely, it should mirror the routines for SMIME in that regard.
  */
 static PRBool
 sec_pkcs12_decoder_decryption_allowed(SECAlgorithmID *algid,
--- a/security/nss/lib/pkcs12/p12e.c
+++ b/security/nss/lib/pkcs12/p12e.c
@@ -5,16 +5,17 @@
 #include "p12t.h"
 #include "p12.h"
 #include "plarena.h"
 #include "secitem.h"
 #include "secoid.h"
 #include "seccomon.h"
 #include "secport.h"
 #include "cert.h"
+#include "secpkcs5.h"
 #include "secpkcs7.h"
 #include "secasn1.h"
 #include "secerr.h"
 #include "pk11func.h"
 #include "p12plcy.h"
 #include "p12local.h"
 #include "prcpucfg.h"
 
@@ -373,29 +374,46 @@ SEC_PKCS12CreatePasswordPrivSafe(SEC_PKC
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         PORT_ArenaRelease(p12ctxt->arena, mark);
         return NULL;
     }
 
     safeInfo->itemCount = 0;
 
     /* create the encrypted safe */
-    safeInfo->cinfo = SEC_PKCS7CreateEncryptedData(privAlg, 0, p12ctxt->pwfn,
-                                                   p12ctxt->pwfnarg);
+    if (!SEC_PKCS5IsAlgorithmPBEAlgTag(privAlg) &&
+        PK11_AlgtagToMechanism(privAlg) == CKM_AES_CBC) {
+        safeInfo->cinfo = SEC_PKCS7CreateEncryptedDataWithPBEV2(SEC_OID_PKCS5_PBES2,
+                                                                privAlg,
+                                                                SEC_OID_UNKNOWN,
+                                                                0,
+                                                                p12ctxt->pwfn,
+                                                                p12ctxt->pwfnarg);
+    } else {
+        safeInfo->cinfo = SEC_PKCS7CreateEncryptedData(privAlg, 0, p12ctxt->pwfn,
+                                                       p12ctxt->pwfnarg);
+    }
     if (!safeInfo->cinfo) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         goto loser;
     }
     safeInfo->arena = p12ctxt->arena;
 
-    /* convert the password to unicode */
-    if (!sec_pkcs12_convert_item_to_unicode(NULL, &uniPwitem, pwitem,
-                                            PR_TRUE, PR_TRUE, PR_TRUE)) {
-        PORT_SetError(SEC_ERROR_NO_MEMORY);
-        goto loser;
+    if (sec_pkcs12_is_pkcs12_pbe_algorithm(privAlg)) {
+        /* convert the password to unicode */
+        if (!sec_pkcs12_convert_item_to_unicode(NULL, &uniPwitem, pwitem,
+                                                PR_TRUE, PR_TRUE, PR_TRUE)) {
+            PORT_SetError(SEC_ERROR_NO_MEMORY);
+            goto loser;
+        }
+    } else {
+        if (SECITEM_CopyItem(NULL, &uniPwitem, pwitem) != SECSuccess) {
+            PORT_SetError(SEC_ERROR_NO_MEMORY);
+            goto loser;
+        }
     }
     if (SECITEM_CopyItem(p12ctxt->arena, &safeInfo->pwitem, &uniPwitem) != SECSuccess) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         goto loser;
     }
 
     /* generate the encryption key */
     slot = PK11_ReferenceSlot(p12ctxt->slot);
--- a/security/nss/lib/pkcs12/p12local.c
+++ b/security/nss/lib/pkcs12/p12local.c
@@ -944,16 +944,43 @@ sec_pkcs12_convert_item_to_unicode(PLAre
         }
         dest->len += 2;
         dest->data[dest->len - 1] = dest->data[dest->len - 2] = 0;
     }
 
     return PR_TRUE;
 }
 
+PRBool
+sec_pkcs12_is_pkcs12_pbe_algorithm(SECOidTag algorithm)
+{
+    switch (algorithm) {
+        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
+        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
+        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
+        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
+        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
+        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
+        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
+        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
+        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
+        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
+        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
+        /* those are actually PKCS #5 v1.5 PBEs, but we
+         * historically treat them in the same way as PKCS #12
+         * PBEs */
+        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
+        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
+        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
+            return PR_TRUE;
+        default:
+            return PR_FALSE;
+    }
+}
+
 /* pkcs 12 templates */
 static const SEC_ASN1TemplateChooserPtr sec_pkcs12_shroud_chooser =
     sec_pkcs12_choose_shroud_type;
 
 const SEC_ASN1Template SEC_PKCS12CodedSafeBagTemplate[] =
     {
       { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
       { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
--- a/security/nss/lib/pkcs12/p12local.h
+++ b/security/nss/lib/pkcs12/p12local.h
@@ -50,9 +50,11 @@ extern SEC_PKCS12AuthenticatedSafe *sec_
 
 /* conversion from old to new */
 extern SEC_PKCS12DecoderContext *
 sec_PKCS12ConvertOldSafeToNew(PLArenaPool *arena, PK11SlotInfo *slot,
                               PRBool swapUnicode, SECItem *pwitem,
                               void *wincx, SEC_PKCS12SafeContents *safe,
                               SEC_PKCS12Baggage *baggage);
 
+extern PRBool sec_pkcs12_is_pkcs12_pbe_algorithm(SECOidTag algorithm);
+
 #endif
--- a/security/nss/lib/pkcs12/p12plcy.c
+++ b/security/nss/lib/pkcs12/p12plcy.c
@@ -19,16 +19,19 @@ typedef struct pkcs12SuiteMapStr {
 
 static pkcs12SuiteMap pkcs12SuiteMaps[] = {
     { SEC_OID_RC4, 40, PKCS12_RC4_40, PR_FALSE, PR_FALSE },
     { SEC_OID_RC4, 128, PKCS12_RC4_128, PR_FALSE, PR_FALSE },
     { SEC_OID_RC2_CBC, 40, PKCS12_RC2_CBC_40, PR_FALSE, PR_TRUE },
     { SEC_OID_RC2_CBC, 128, PKCS12_RC2_CBC_128, PR_FALSE, PR_FALSE },
     { SEC_OID_DES_CBC, 64, PKCS12_DES_56, PR_FALSE, PR_FALSE },
     { SEC_OID_DES_EDE3_CBC, 192, PKCS12_DES_EDE3_168, PR_FALSE, PR_FALSE },
+    { SEC_OID_AES_128_CBC, 128, PKCS12_AES_CBC_128, PR_FALSE, PR_FALSE },
+    { SEC_OID_AES_192_CBC, 192, PKCS12_AES_CBC_192, PR_FALSE, PR_FALSE },
+    { SEC_OID_AES_256_CBC, 256, PKCS12_AES_CBC_256, PR_FALSE, PR_FALSE },
     { SEC_OID_UNKNOWN, 0, PKCS12_NULL, PR_FALSE, PR_FALSE },
     { SEC_OID_UNKNOWN, 0, 0L, PR_FALSE, PR_FALSE }
 };
 
 /* determine if algid is an algorithm which is allowed */
 PRBool
 SEC_PKCS12DecryptionAllowed(SECAlgorithmID *algid)
 {
--- a/security/nss/lib/pkcs7/p7create.c
+++ b/security/nss/lib/pkcs7/p7create.c
@@ -1240,8 +1240,61 @@ SEC_PKCS7CreateEncryptedData(SECOidTag a
                                                algorithm, keysize);
     if (rv != SECSuccess) {
         SEC_PKCS7DestroyContentInfo(cinfo);
         return NULL;
     }
 
     return cinfo;
 }
+
+SEC_PKCS7ContentInfo *
+SEC_PKCS7CreateEncryptedDataWithPBEV2(SECOidTag pbe_algorithm,
+                                      SECOidTag cipher_algorithm,
+                                      SECOidTag prf_algorithm,
+                                      int keysize,
+                                      SECKEYGetPasswordKey pwfn, void *pwfn_arg)
+{
+    SEC_PKCS7ContentInfo *cinfo;
+    SECAlgorithmID *algid;
+    SEC_PKCS7EncryptedData *enc_data;
+    SECStatus rv;
+
+    PORT_Assert(SEC_PKCS5IsAlgorithmPBEAlgTag(pbe_algorithm));
+
+    cinfo = sec_pkcs7_create_content_info(SEC_OID_PKCS7_ENCRYPTED_DATA,
+                                          PR_FALSE, pwfn, pwfn_arg);
+    if (cinfo == NULL)
+        return NULL;
+
+    enc_data = cinfo->content.encryptedData;
+    algid = &(enc_data->encContentInfo.contentEncAlg);
+
+    SECAlgorithmID *pbe_algid;
+    pbe_algid = PK11_CreatePBEV2AlgorithmID(pbe_algorithm,
+                                            cipher_algorithm,
+                                            prf_algorithm,
+                                            keysize,
+                                            NSS_PBE_DEFAULT_ITERATION_COUNT,
+                                            NULL);
+    if (pbe_algid == NULL) {
+        rv = SECFailure;
+    } else {
+        rv = SECOID_CopyAlgorithmID(cinfo->poolp, algid, pbe_algid);
+        SECOID_DestroyAlgorithmID(pbe_algid, PR_TRUE);
+    }
+
+    if (rv != SECSuccess) {
+        SEC_PKCS7DestroyContentInfo(cinfo);
+        return NULL;
+    }
+
+    rv = sec_pkcs7_init_encrypted_content_info(&(enc_data->encContentInfo),
+                                               cinfo->poolp,
+                                               SEC_OID_PKCS7_DATA, PR_FALSE,
+                                               cipher_algorithm, keysize);
+    if (rv != SECSuccess) {
+        SEC_PKCS7DestroyContentInfo(cinfo);
+        return NULL;
+    }
+
+    return cinfo;
+}
--- a/security/nss/lib/pkcs7/secpkcs7.h
+++ b/security/nss/lib/pkcs7/secpkcs7.h
@@ -282,16 +282,36 @@ extern SEC_PKCS7ContentInfo *SEC_PKCS7Cr
  * An error results in a return value of NULL and an error set.
  * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
  */
 extern SEC_PKCS7ContentInfo *
 SEC_PKCS7CreateEncryptedData(SECOidTag algorithm, int keysize,
                              SECKEYGetPasswordKey pwfn, void *pwfn_arg);
 
 /*
+ * Create an empty PKCS7 encrypted content info.
+ *
+ * Similar to SEC_PKCS7CreateEncryptedData(), but this is capable of
+ * creating encrypted content for PKCS #5 v2 algorithms.
+ *
+ * "pbe_algorithm" specifies the PBE algorithm to use.
+ * "cipher_algorithm" specifies the bulk encryption algorithm to use.
+ * "prf_algorithm" specifies the PRF algorithm which pbe_algorithm uses.
+ *
+ * An error results in a return value of NULL and an error set.
+ * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
+ */
+extern SEC_PKCS7ContentInfo *
+SEC_PKCS7CreateEncryptedDataWithPBEV2(SECOidTag pbe_algorithm,
+                                      SECOidTag cipher_algorithm,
+                                      SECOidTag prf_algorithm,
+                                      int keysize,
+                                      SECKEYGetPasswordKey pwfn, void *pwfn_arg);
+
+/*
  * All of the following things return SECStatus to signal success or failure.
  * Failure should have a more specific error status available via
  * PORT_GetError()/XP_GetError().
  */
 
 /*
  * Add the specified attribute to the authenticated (i.e. signed) attributes
  * of "cinfo" -- "oidtag" describes the attribute and "value" is the
--- a/security/nss/lib/util/ciferfam.h
+++ b/security/nss/lib/util/ciferfam.h
@@ -47,13 +47,16 @@
 /* PKCS12 "Cipher Suites" */
 
 #define PKCS12_RC2_CBC_40 (CIPHER_FAMILYID_PKCS12 | 0001)
 #define PKCS12_RC2_CBC_128 (CIPHER_FAMILYID_PKCS12 | 0002)
 #define PKCS12_RC4_40 (CIPHER_FAMILYID_PKCS12 | 0011)
 #define PKCS12_RC4_128 (CIPHER_FAMILYID_PKCS12 | 0012)
 #define PKCS12_DES_56 (CIPHER_FAMILYID_PKCS12 | 0021)
 #define PKCS12_DES_EDE3_168 (CIPHER_FAMILYID_PKCS12 | 0022)
+#define PKCS12_AES_CBC_128 (CIPHER_FAMILYID_PKCS12 | 0031)
+#define PKCS12_AES_CBC_192 (CIPHER_FAMILYID_PKCS12 | 0032)
+#define PKCS12_AES_CBC_256 (CIPHER_FAMILYID_PKCS12 | 0033)
 
 /* SMIME version numbers are negative, to avoid colliding with SSL versions */
 #define SMIME_LIBRARY_VERSION_1_0 -0x0100
 
 #endif /* _CIFERFAM_H_ */
--- a/security/nss/lib/util/nssb64d.c
+++ b/security/nss/lib/util/nssb64d.c
@@ -699,56 +699,57 @@ NSSBase64Decoder_Destroy(NSSBase64Decode
  * Return value is NULL on error, the Item (allocated or provided) otherwise.
  */
 SECItem *
 NSSBase64_DecodeBuffer(PLArenaPool *arenaOpt, SECItem *outItemOpt,
                        const char *inStr, unsigned int inLen)
 {
     SECItem *out_item = NULL;
     PRUint32 max_out_len = 0;
-    PRUint32 out_len;
     void *mark = NULL;
-    unsigned char *dummy;
+    unsigned char *dummy = NULL;
 
     if ((outItemOpt != NULL && outItemOpt->data != NULL) || inLen == 0) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return NULL;
     }
 
     if (arenaOpt != NULL)
         mark = PORT_ArenaMark(arenaOpt);
 
     max_out_len = PL_Base64MaxDecodedLength(inLen);
+    if (max_out_len == 0) {
+        goto loser;
+    }
     out_item = SECITEM_AllocItem(arenaOpt, outItemOpt, max_out_len);
     if (out_item == NULL) {
-        if (arenaOpt != NULL)
-            PORT_ArenaRelease(arenaOpt, mark);
-        return NULL;
+        goto loser;
     }
 
     dummy = PL_Base64DecodeBuffer(inStr, inLen, out_item->data,
-                                  max_out_len, &out_len);
+                                  max_out_len, &out_item->len);
     if (dummy == NULL) {
-        if (arenaOpt != NULL) {
-            PORT_ArenaRelease(arenaOpt, mark);
-            if (outItemOpt != NULL) {
-                outItemOpt->data = NULL;
-                outItemOpt->len = 0;
-            }
-        } else {
-            SECITEM_FreeItem(out_item,
-                             (outItemOpt == NULL) ? PR_TRUE : PR_FALSE);
+        goto loser;
+    }
+    if (arenaOpt != NULL) {
+        PORT_ArenaUnmark(arenaOpt, mark);
+    }
+    return out_item;
+
+loser:
+    if (arenaOpt != NULL) {
+        PORT_ArenaRelease(arenaOpt, mark);
+        if (outItemOpt != NULL) {
+            outItemOpt->data = NULL;
+            outItemOpt->len = 0;
         }
-        return NULL;
+    } else if (dummy == NULL) {
+        SECITEM_FreeItem(out_item, (PRBool)(outItemOpt == NULL));
     }
-
-    if (arenaOpt != NULL)
-        PORT_ArenaUnmark(arenaOpt, mark);
-    out_item->len = out_len;
-    return out_item;
+    return NULL;
 }
 
 /*
  * XXX Everything below is deprecated.  If you add new stuff, put it
  * *above*, not below.
  */
 
 /*
new file mode 100644
--- /dev/null
+++ b/security/nss/nss-tool/common/util.cc
@@ -0,0 +1,135 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "util.h"
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include <prerror.h>
+
+#if defined(__unix__) || defined(__APPLE__)
+#include <termios.h>
+#include <unistd.h>
+#elif defined(WIN32) || defined(_WIN64)
+#include <Windows.h>
+#endif
+
+static std::string GetPassword(const std::string &prompt) {
+  std::cout << prompt << std::endl;
+
+#if defined(__unix__) || defined(__APPLE__)
+  termios oldt;
+  tcgetattr(STDIN_FILENO, &oldt);
+  termios newt = oldt;
+  newt.c_lflag &= ~ECHO;
+  tcsetattr(STDIN_FILENO, TCSANOW, &newt);
+#elif defined(WIN32) || defined(_WIN64)
+  HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
+  DWORD mode = 0;
+  GetConsoleMode(hStdin, &mode);
+  SetConsoleMode(hStdin, mode & (~ENABLE_ECHO_INPUT));
+#endif
+
+  std::string pw;
+  std::getline(std::cin, pw);
+
+#if defined(__unix__) || defined(__APPLE__)
+  tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
+#elif defined(WIN32) || defined(_WIN64)
+  SetConsoleMode(hStdin, mode);
+#endif
+
+  return pw;
+}
+
+static char *GetModulePassword(PK11SlotInfo *slot, int retry, void *arg) {
+  if (arg == nullptr) {
+    return nullptr;
+  }
+
+  PwData *pwData = reinterpret_cast<PwData *>(arg);
+
+  if (retry > 0) {
+    std::cerr << "Incorrect password/PIN entered." << std::endl;
+    return nullptr;
+  }
+
+  switch (pwData->source) {
+    case PW_NONE:
+    case PW_FROMFILE:
+      std::cerr << "Password input method not supported." << std::endl;
+      return nullptr;
+    case PW_PLAINTEXT:
+      return PL_strdup(pwData->data);
+    default:
+      break;
+  }
+
+  std::cerr << "Password check failed:  No password found." << std::endl;
+  return nullptr;
+}
+
+bool InitSlotPassword(void) {
+  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
+  if (slot.get() == nullptr) {
+    std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl;
+    return false;
+  }
+
+  std::cout << "Enter a password which will be used to encrypt your keys."
+            << std::endl
+            << std::endl;
+  std::string pw;
+
+  while (true) {
+    pw = GetPassword("Enter new password: ");
+    if (pw == GetPassword("Re-enter password: ")) {
+      break;
+    }
+
+    std::cerr << "Passwords do not match. Try again." << std::endl;
+  }
+
+  SECStatus rv = PK11_InitPin(slot.get(), nullptr, pw.c_str());
+  if (rv != SECSuccess) {
+    std::cerr << "Init db password failed." << std::endl;
+    return false;
+  }
+
+  return true;
+}
+
+bool DBLoginIfNeeded(const ScopedPK11SlotInfo &slot) {
+  if (!PK11_NeedLogin(slot.get())) {
+    return true;
+  }
+
+  PK11_SetPasswordFunc(&GetModulePassword);
+  std::string pw = GetPassword("Enter your password: ");
+  PwData pwData = {PW_PLAINTEXT, const_cast<char *>(pw.c_str())};
+  SECStatus rv = PK11_Authenticate(slot.get(), true /*loadCerts*/, &pwData);
+  if (rv != SECSuccess) {
+    std::cerr << "Could not authenticate to token "
+              << PK11_GetTokenName(slot.get()) << ". Failed with error "
+              << PR_ErrorToName(PR_GetError()) << std::endl;
+    return false;
+  }
+  std::cout << std::endl;
+
+  return true;
+}
+
+std::string StringToHex(const ScopedSECItem &input) {
+  std::stringstream ss;
+  ss << "0x";
+  for (size_t i = 0; i < input->len; i++) {
+    ss << std::hex << std::setfill('0') << std::setw(2)
+       << static_cast<int>(input->data[i]);
+  }
+
+  return ss.str();
+}
new file mode 100644
--- /dev/null
+++ b/security/nss/nss-tool/common/util.h
@@ -0,0 +1,23 @@
+/* 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 util_h__
+#define util_h__
+
+#include "scoped_ptrs.h"
+
+#include <secmodt.h>
+#include <string>
+
+enum PwDataType { PW_NONE = 0, PW_FROMFILE = 1, PW_PLAINTEXT = 2 };
+typedef struct {
+  PwDataType source;
+  char *data;
+} PwData;
+
+bool InitSlotPassword(void);
+bool DBLoginIfNeeded(const ScopedPK11SlotInfo &slot);
+std::string StringToHex(const ScopedSECItem &input);
+
+#endif  // util_h__
--- a/security/nss/nss-tool/db/dbtool.cc
+++ b/security/nss/nss-tool/db/dbtool.cc
@@ -1,29 +1,39 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "dbtool.h"
 #include "argparse.h"
 #include "scoped_ptrs.h"
+#include "util.h"
 
 #include <dirent.h>
 #include <fstream>
 #include <iomanip>
 #include <iostream>
 #include <memory>
 #include <regex>
 #include <sstream>
 
 #include <cert.h>
 #include <certdb.h>
 #include <nss.h>
+#include <prerror.h>
 #include <prio.h>
 
+const std::vector<std::string> kCommandArgs({"--create", "--list-certs",
+                                             "--import-cert", "--list-keys"});
+
+static bool HasSingleCommandArgument(const ArgParser &parser) {
+  auto pred = [&](const std::string &cmd) { return parser.Has(cmd); };
+  return std::count_if(kCommandArgs.begin(), kCommandArgs.end(), pred) == 1;
+}
+
 static std::string PrintFlags(unsigned int flags) {
   std::stringstream ss;
   if ((flags & CERTDB_VALID_CA) && !(flags & CERTDB_TRUSTED_CA) &&
       !(flags & CERTDB_TRUSTED_CLIENT_CA)) {
     ss << "c";
   }
   if ((flags & CERTDB_TERMINAL_RECORD) && !(flags & CERTDB_TRUSTED)) {
     ss << "p";
@@ -58,29 +68,33 @@ static std::vector<char> ReadFromIstream
     char buf[1024];
     is.read(buf, sizeof(buf));
     certData.insert(certData.end(), buf, buf + is.gcount());
   }
 
   return certData;
 }
 
+static const char *const keyTypeName[] = {"null", "rsa", "dsa", "fortezza",
+                                          "dh",   "kea", "ec"};
+
 void DBTool::Usage() {
   std::cerr << "Usage: nss db [--path <directory>]" << std::endl;
   std::cerr << "  --create" << std::endl;
   std::cerr << "  --list-certs" << std::endl;
   std::cerr << "  --import-cert [<path>] --name <name> [--trusts <trusts>]"
             << std::endl;
+  std::cerr << "  --list-keys" << std::endl;
 }
 
 bool DBTool::Run(const std::vector<std::string> &arguments) {
   ArgParser parser(arguments);
 
-  if (!parser.Has("--create") && !parser.Has("--list-certs") &&
-      !parser.Has("--import-cert")) {
+  if (!HasSingleCommandArgument(parser)) {
+    Usage();
     return false;
   }
 
   PRAccessHow how = PR_ACCESS_READ_OK;
   bool readOnly = true;
   if (parser.Has("--create") || parser.Has("--import-cert")) {
     how = PR_ACCESS_WRITE_OK;
     readOnly = false;
@@ -124,17 +138,22 @@ bool DBTool::Run(const std::vector<std::
   }
 
   bool ret = true;
   if (parser.Has("--list-certs")) {
     ListCertificates();
   } else if (parser.Has("--import-cert")) {
     ret = ImportCertificate(parser);
   } else if (parser.Has("--create")) {
-    std::cout << "DB files created successfully." << std::endl;
+    ret = InitSlotPassword();
+    if (ret) {
+      std::cout << "DB files created successfully." << std::endl;
+    }
+  } else if (parser.Has("--list-keys")) {
+    ret = ListKeys();
   }
 
   // shutdown nss
   if (NSS_Shutdown() != SECSuccess) {
     std::cerr << "NSS Shutdown failed!" << std::endl;
     return false;
   }
 
@@ -228,17 +247,17 @@ bool DBTool::ImportCertificate(const Arg
   SECStatus rv = CERT_DecodeTrustString(&trust, trustString.c_str());
   if (rv != SECSuccess) {
     std::cerr << "Cannot decode trust string!" << std::endl;
     return false;
   }
 
   ScopedPK11SlotInfo slot = ScopedPK11SlotInfo(PK11_GetInternalKeySlot());
   if (slot.get() == nullptr) {
-    std::cerr << "Error: Init PK11SlotInfo failed!\n";
+    std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl;
     return false;
   }
 
   std::vector<char> certData;
   if (derFilePath.empty()) {
     std::cout << "No Certificate file path given, using stdin." << std::endl;
     certData = ReadFromIstream(std::cin);
   } else {
@@ -274,8 +293,77 @@ bool DBTool::ImportCertificate(const Arg
     std::cerr << "Cannot change cert's trust" << std::endl;
     return false;
   }
 
   std::cout << "Certificate import was successful!" << std::endl;
   // TODO show information about imported certificate
   return true;
 }
+
+bool DBTool::ListKeys() {
+  ScopedPK11SlotInfo slot = ScopedPK11SlotInfo(PK11_GetInternalKeySlot());
+  if (slot.get() == nullptr) {
+    std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl;
+    return false;
+  }
+
+  if (!DBLoginIfNeeded(slot)) {
+    return false;
+  }
+
+  ScopedSECKEYPrivateKeyList list(PK11_ListPrivateKeysInSlot(slot.get()));
+  if (list.get() == nullptr) {
+    std::cerr << "Listing private keys failed with error "
+              << PR_ErrorToName(PR_GetError()) << std::endl;
+    return false;
+  }
+
+  SECKEYPrivateKeyListNode *node;
+  int count = 0;
+  for (node = PRIVKEY_LIST_HEAD(list.get());
+       !PRIVKEY_LIST_END(node, list.get()); node = PRIVKEY_LIST_NEXT(node)) {
+    char *keyNameRaw = PK11_GetPrivateKeyNickname(node->key);
+    std::string keyName(keyNameRaw ? "" : keyNameRaw);
+
+    if (keyName.empty()) {
+      ScopedCERTCertificate cert(PK11_GetCertFromPrivateKey(node->key));
+      if (cert.get()) {
+        if (cert->nickname && strlen(cert->nickname) > 0) {
+          keyName = cert->nickname;
+        } else if (cert->emailAddr && strlen(cert->emailAddr) > 0) {
+          keyName = cert->emailAddr;
+        }
+      }
+      if (keyName.empty()) {
+        keyName = "(none)";  // default value
+      }
+    }
+
+    SECKEYPrivateKey *key = node->key;
+    ScopedSECItem keyIDItem(PK11_GetLowLevelKeyIDForPrivateKey(key));
+    if (keyIDItem.get() == nullptr) {
+      std::cerr << "Error: PK11_GetLowLevelKeyIDForPrivateKey failed!"
+                << std::endl;
+      continue;
+    }
+
+    std::string keyID = StringToHex(keyIDItem);
+
+    if (count++ == 0) {
+      // print header
+      std::cout << std::left << std::setw(20) << "<key#, key name>"
+                << std::setw(20) << "key type"
+                << "key id" << std::endl;
+    }
+
+    std::stringstream leftElem;
+    leftElem << "<" << count << ", " << keyName << ">";
+    std::cout << std::left << std::setw(20) << leftElem.str() << std::setw(20)
+              << keyTypeName[key->keyType] << keyID << std::endl;
+  }
+
+  if (count == 0) {
+    std::cout << "No keys found." << std::endl;
+  }
+
+  return true;
+}
--- a/security/nss/nss-tool/db/dbtool.h
+++ b/security/nss/nss-tool/db/dbtool.h
@@ -14,11 +14,12 @@ class DBTool {
   bool Run(const std::vector<std::string>& arguments);
 
   void Usage();
 
  private:
   bool PathHasDBFiles(std::string path);
   void ListCertificates();
   bool ImportCertificate(const ArgParser& parser);
+  bool ListKeys();
 };
 
 #endif  // dbtool_h__
--- a/security/nss/nss-tool/nss_tool.cc
+++ b/security/nss/nss-tool/nss_tool.cc
@@ -28,16 +28,15 @@ int main(int argc, char **argv) {
   }
 
   int exit_code = 0;
   PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
 
   std::vector<std::string> arguments(argv + 2, argv + argc);
   DBTool tool;
   if (!tool.Run(arguments)) {
-    tool.Usage();
     exit_code = 1;
   }
 
   PR_Cleanup();
 
   return exit_code;
 }
--- a/security/nss/nss-tool/nss_tool.gyp
+++ b/security/nss/nss-tool/nss_tool.gyp
@@ -8,16 +8,17 @@
   ],
   'targets' : [
     {
       'target_name' : 'nss',
       'type' : 'executable',
       'sources' : [
         'nss_tool.cc',
         'common/argparse.cc',
+        'common/util.cc',
         'db/dbtool.cc',
       ],
       'include_dirs': [
         'common',
       ],
       'dependencies' : [
         '<(DEPTH)/cpputil/cpputil.gyp:cpputil',
         '<(DEPTH)/exports.gyp:dbm_exports',
--- a/security/nss/tests/bogo/bogo.sh
+++ b/security/nss/tests/bogo/bogo.sh
@@ -20,17 +20,17 @@ bogo_init()
     . ./init.sh
   fi
 
   mkdir -p "${HOSTDIR}/bogo"
   cd "${HOSTDIR}/bogo"
   BORING=${BORING:=boringssl}
   if [ ! -d "$BORING" ]; then
     git clone -q https://boringssl.googlesource.com/boringssl "$BORING"
-    git -C "$BORING" checkout -q 004bff3a1412fcc6ba168d4295a942f9b1e0866e
+    git -C "$BORING" checkout -q 5ae416528a0e554aa4df91bdb1e03f75bfc03cd0
   fi
 
   SCRIPTNAME="bogo.sh"
   html_head "bogo test"
 }
 
 bogo_cleanup()
 {
--- a/security/nss/tests/tools/tools.sh
+++ b/security/nss/tests/tools/tools.sh
@@ -268,30 +268,30 @@ tools_p12_export_list_import_all_pkcs5v2
     AES-128-CBC \
     AES-192-CBC \
     AES-256-CBC \
     CAMELLIA-128-CBC \
     CAMELLIA-192-CBC \
     CAMELLIA-256-CBC; do
 
 #---------------------------------------------------------------
-# Bug 452464 - pk12util -o fails when -C option specifies AES or
+# Bug 452464 - pk12util -o fails when -C option specifies
 # Camellia ciphers
 # FIXME Restore these to the list
-#    AES-128-CBC, \
-#    AES-192-CBC, \
-#    AES-256-CBC, \
 #    CAMELLIA-128-CBC, \
 #    CAMELLIA-192-CBC, \
 #    CAMELLIA-256-CBC, \
 #  when 452464 is fixed
 #---------------------------------------------------------------  
     for cert_cipher in \
       RC2-CBC \
       DES-EDE3-CBC \
+      AES-128-CBC \
+      AES-192-CBC \
+      AES-256-CBC \
       null; do
 	  export_list_import ${key_cipher} ${cert_cipher}
 	done
   done
 }
 
 ########################################################################
 # Export using the pkcs12v2pbe ciphers for key and certificate encryption.