Bug 1334127 - land NSS 6511e19a2c6c, r=me
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Tue, 28 Feb 2017 13:52:02 +0100
changeset 394207 5b35dfe81b6843650b28fddb727b515310311dc9
parent 394206 697dbeae416bf99e4a43b60ee246d68b576be330
child 394208 a1d03f028cb1f12ae824a49e692d87617eca1377
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1334127
milestone54.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 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.