Bug 1267905 - Replace uses of ScopedCERTCertList with UniqueCERTCertList. r=keeler
authorCykesiopka <cykesiopka.bmo@gmail.com>
Thu, 05 May 2016 14:56:36 -0700
changeset 296399 6fc34759465ee7246858c63d090270797cd1f220
parent 296398 84a3e571680149b8fafcfc338aa4e0f27cb16050
child 296400 cecbf2b032672076acea9350cecfa37114aff6a5
push id76312
push userryanvm@gmail.com
push dateFri, 06 May 2016 13:04:04 +0000
treeherdermozilla-inbound@cecbf2b03267 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler
bugs1267905
milestone49.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 1267905 - Replace uses of ScopedCERTCertList with UniqueCERTCertList. r=keeler ScopedCERTCertList is based on Scoped.h, which is deprecated in favour of the standardised UniquePtr. Also changes CERTCertList parameters of various functions to make ownership more explicit. MozReview-Commit-ID: EXqxTK6inqy
security/apps/AppSignatureVerification.cpp
security/apps/AppTrustDomain.cpp
security/apps/AppTrustDomain.h
security/certverifier/CertVerifier.cpp
security/certverifier/CertVerifier.h
security/certverifier/NSSCertDBTrustDomain.cpp
security/certverifier/NSSCertDBTrustDomain.h
security/manager/ssl/CSTrustDomain.cpp
security/manager/ssl/CSTrustDomain.h
security/manager/ssl/ContentSignatureVerifier.cpp
security/manager/ssl/PublicKeyPinningService.cpp
security/manager/ssl/PublicKeyPinningService.h
security/manager/ssl/SSLServerCertVerification.cpp
security/manager/ssl/ScopedNSSTypes.h
security/manager/ssl/TransportSecurityInfo.cpp
security/manager/ssl/TransportSecurityInfo.h
security/manager/ssl/nsCertPicker.cpp
security/manager/ssl/nsCertTree.cpp
security/manager/ssl/nsDataSignatureVerifier.cpp
security/manager/ssl/nsNSSCertHelper.cpp
security/manager/ssl/nsNSSCertHelper.h
security/manager/ssl/nsNSSCertificate.cpp
security/manager/ssl/nsNSSCertificate.h
security/manager/ssl/nsNSSCertificateDB.cpp
security/manager/ssl/nsNSSIOLayer.cpp
security/manager/ssl/nsSiteSecurityService.cpp
security/manager/ssl/nsUsageArrayHelper.cpp
--- a/security/apps/AppSignatureVerification.cpp
+++ b/security/apps/AppSignatureVerification.cpp
@@ -617,17 +617,17 @@ ParseMF(const char* filebuf, nsIZipReade
     // unrecognized attributes must be ignored
   }
 
   return NS_OK;
 }
 
 struct VerifyCertificateContext {
   AppTrustedRoot trustedRoot;
-  ScopedCERTCertList& builtChain;
+  UniqueCERTCertList& builtChain;
 };
 
 nsresult
 VerifyCertificate(CERTCertificate* signerCert, void* voidContext, void* pinArg)
 {
   // TODO: null pinArg is tolerated.
   if (NS_WARN_IF(!signerCert) || NS_WARN_IF(!voidContext)) {
     return NS_ERROR_INVALID_ARG;
@@ -677,17 +677,17 @@ VerifyCertificate(CERTCertificate* signe
   }
 
   return NS_OK;
 }
 
 nsresult
 VerifySignature(AppTrustedRoot trustedRoot, const SECItem& buffer,
                 const SECItem& detachedDigest,
-                /*out*/ ScopedCERTCertList& builtChain)
+                /*out*/ UniqueCERTCertList& builtChain)
 {
   // Currently, this function is only called within the CalculateResult() method
   // of CryptoTasks. As such, NSS should not be shut down at this point and the
   // CryptoTask implementation should already hold a nsNSSShutDownPreventionLock.
   // We acquire a nsNSSShutDownPreventionLock here solely to prove we did to
   // VerifyCMSDetachedSignatureIncludingCertificate().
   nsNSSShutDownPreventionLock locker;
   VerifyCertificateContext context = { trustedRoot, builtChain };
@@ -737,17 +737,17 @@ OpenSignedAppFile(AppTrustedRoot aTruste
   Digest sfCalculatedDigest;
   rv = FindAndLoadOneEntry(zip, NS_LITERAL_CSTRING(JAR_SF_SEARCH_STRING),
                            sfFilename, sfBuffer, &sfCalculatedDigest);
   if (NS_FAILED(rv)) {
     return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID;
   }
 
   sigBuffer.type = siBuffer;
-  ScopedCERTCertList builtChain;
+  UniqueCERTCertList builtChain;
   rv = VerifySignature(aTrustedRoot, sigBuffer, sfCalculatedDigest.get(),
                        builtChain);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   ScopedAutoSECItem mfDigest;
   rv = ParseSF(char_ptr_cast(sfBuffer.data), mfDigest);
@@ -918,17 +918,17 @@ VerifySignedManifest(AppTrustedRoot aTru
   rv = doubleDigest.DigestBuf(SEC_OID_SHA1,
                               reinterpret_cast<uint8_t*>(base64EncDigest.get()),
                               strlen(base64EncDigest.get()));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // Verify the manifest signature (signed digest of the base64 encoded string)
-  ScopedCERTCertList builtChain;
+  UniqueCERTCertList builtChain;
   rv = VerifySignature(aTrustedRoot, signatureBuffer,
                        doubleDigest.get(), builtChain);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   // Return the signer's certificate to the reader if they want it.
   if (aSignerCert) {
@@ -1417,17 +1417,17 @@ VerifySignedDirectory(AppTrustedRoot aTr
   ScopedAutoSECItem sfBuffer;
   Digest sfCalculatedDigest;
   rv = LoadOneMetafile(metaDir, sfFilename, sfBuffer, &sfCalculatedDigest);
   if (NS_FAILED(rv)) {
     return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID;
   }
 
   sigBuffer.type = siBuffer;
-  ScopedCERTCertList builtChain;
+  UniqueCERTCertList builtChain;
   rv = VerifySignature(aTrustedRoot, sigBuffer, sfCalculatedDigest.get(),
                        builtChain);
   if (NS_FAILED(rv)) {
     return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID;
   }
 
   // Get the expected manifest hash from the signed .sf file
 
--- a/security/apps/AppTrustDomain.cpp
+++ b/security/apps/AppTrustDomain.cpp
@@ -44,17 +44,17 @@ static char kDevImportedDER[] =
   "network.http.signed-packages.developer-root";
 
 namespace mozilla { namespace psm {
 
 StaticMutex AppTrustDomain::sMutex;
 UniquePtr<unsigned char[]> AppTrustDomain::sDevImportedDERData;
 unsigned int AppTrustDomain::sDevImportedDERLen = 0;
 
-AppTrustDomain::AppTrustDomain(ScopedCERTCertList& certChain, void* pinArg)
+AppTrustDomain::AppTrustDomain(UniqueCERTCertList& certChain, void* pinArg)
   : mCertChain(certChain)
   , mPinArg(pinArg)
   , mMinRSABits(DEFAULT_MIN_RSA_BITS)
 {
 }
 
 SECStatus
 AppTrustDomain::SetTrustedRoot(AppTrustedRoot trustedRoot)
@@ -189,17 +189,17 @@ AppTrustDomain::FindIssuer(Input encoded
   // checker.Check, we can stop using CERT_CreateSubjectCertList and instead
   // use logic like this:
   //
   // 1. First, try the trusted trust anchor.
   // 2. Secondly, iterate through the certificates that were stored in the CMS
   //    message, passing each one to checker.Check.
   SECItem encodedIssuerNameSECItem =
     UnsafeMapInputToSECItem(encodedIssuerName);
-  ScopedCERTCertList
+  UniqueCERTCertList
     candidates(CERT_CreateSubjectCertList(nullptr, CERT_GetDefaultCertDB(),
                                           &encodedIssuerNameSECItem, 0,
                                           false));
   if (candidates) {
     for (CERTCertListNode* n = CERT_LIST_HEAD(candidates);
          !CERT_LIST_END(n, candidates); n = CERT_LIST_NEXT(n)) {
       Input certDER;
       Result rv = certDER.Init(n->cert->derCert.data, n->cert->derCert.len);
--- a/security/apps/AppTrustDomain.h
+++ b/security/apps/AppTrustDomain.h
@@ -1,32 +1,32 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef mozilla_psm_AppsTrustDomain_h
-#define mozilla_psm_AppsTrustDomain_h
+#ifndef AppTrustDomain_h
+#define AppTrustDomain_h
 
 #include "pkix/pkixtypes.h"
 #include "mozilla/StaticMutex.h"
 #include "mozilla/UniquePtr.h"
 #include "nsDebug.h"
 #include "nsIX509CertDB.h"
 #include "ScopedNSSTypes.h"
 
 namespace mozilla { namespace psm {
 
 class AppTrustDomain final : public mozilla::pkix::TrustDomain
 {
 public:
   typedef mozilla::pkix::Result Result;
 
-  AppTrustDomain(ScopedCERTCertList&, void* pinArg);
+  AppTrustDomain(UniqueCERTCertList& certChain, void* pinArg);
 
   SECStatus SetTrustedRoot(AppTrustedRoot trustedRoot);
 
   virtual Result GetCertTrust(mozilla::pkix::EndEntityOrCA endEntityOrCA,
                               const mozilla::pkix::CertPolicyId& policy,
                               mozilla::pkix::Input candidateCertDER,
                               /*out*/ mozilla::pkix::TrustLevel& trustLevel)
                               override;
@@ -62,21 +62,21 @@ public:
                    mozilla::pkix::EndEntityOrCA endEntityOrCA,
                    mozilla::pkix::KeyPurposeId keyPurpose) override;
   virtual Result DigestBuf(mozilla::pkix::Input item,
                            mozilla::pkix::DigestAlgorithm digestAlg,
                            /*out*/ uint8_t* digestBuf,
                            size_t digestBufLen) override;
 
 private:
-  /*out*/ ScopedCERTCertList& mCertChain;
+  /*out*/ UniqueCERTCertList& mCertChain;
   void* mPinArg; // non-owning!
   UniqueCERTCertificate mTrustedRoot;
   unsigned int mMinRSABits;
 
   static StaticMutex sMutex;
   static UniquePtr<unsigned char[]> sDevImportedDERData;
   static unsigned int sDevImportedDERLen;
 };
 
 } } // namespace mozilla::psm
 
-#endif // mozilla_psm_AppsTrustDomain_h
+#endif // AppTrustDomain_h
--- a/security/certverifier/CertVerifier.cpp
+++ b/security/certverifier/CertVerifier.cpp
@@ -56,17 +56,17 @@ CertVerifier::~CertVerifier()
 }
 
 void
 InitCertVerifierLog()
 {
 }
 
 Result
-IsCertChainRootBuiltInRoot(CERTCertList* chain, bool& result)
+IsCertChainRootBuiltInRoot(const UniqueCERTCertList& chain, bool& result)
 {
   if (!chain || CERT_LIST_EMPTY(chain)) {
     return Result::FATAL_ERROR_LIBRARY_FAILURE;
   }
   CERTCertListNode* rootNode = CERT_LIST_TAIL(chain);
   if (!rootNode) {
     return Result::FATAL_ERROR_LIBRARY_FAILURE;
   }
@@ -176,17 +176,17 @@ CertVerifier::SHA1ModeMoreRestrictiveTha
 }
 
 static const unsigned int MIN_RSA_BITS = 2048;
 static const unsigned int MIN_RSA_BITS_WEAK = 1024;
 
 SECStatus
 CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
                          Time time, void* pinArg, const char* hostname,
-                 /*out*/ ScopedCERTCertList& builtChain,
+                 /*out*/ UniqueCERTCertList& builtChain,
             /*optional*/ const Flags flags,
             /*optional*/ const SECItem* stapledOCSPResponseSECItem,
         /*optional out*/ SECOidTag* evOidPolicy,
         /*optional out*/ OCSPStaplingStatus* ocspStaplingStatus,
         /*optional out*/ KeySizeStatus* keySizeStatus,
         /*optional out*/ SHA1ModeResult* sha1ModeResult,
         /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo)
 {
@@ -645,17 +645,17 @@ CertVerifier::VerifyCert(CERTCertificate
 }
 
 SECStatus
 CertVerifier::VerifySSLServerCert(const UniqueCERTCertificate& peerCert,
                      /*optional*/ const SECItem* stapledOCSPResponse,
                                   Time time,
                      /*optional*/ void* pinarg,
                                   const char* hostname,
-                          /*out*/ ScopedCERTCertList& builtChain,
+                          /*out*/ UniqueCERTCertList& builtChain,
                      /*optional*/ bool saveIntermediatesInPermanentDatabase,
                      /*optional*/ Flags flags,
                  /*optional out*/ SECOidTag* evOidPolicy,
                  /*optional out*/ OCSPStaplingStatus* ocspStaplingStatus,
                  /*optional out*/ KeySizeStatus* keySizeStatus,
                  /*optional out*/ SHA1ModeResult* sha1ModeResult,
                  /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo)
 {
--- a/security/certverifier/CertVerifier.h
+++ b/security/certverifier/CertVerifier.h
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef mozilla_psm__CertVerifier_h
-#define mozilla_psm__CertVerifier_h
+#ifndef CertVerifier_h
+#define CertVerifier_h
 
 #include "BRNameMatchingPolicy.h"
 #include "OCSPCache.h"
 #include "ScopedNSSTypes.h"
 #include "mozilla/Telemetry.h"
 #include "pkix/pkixtypes.h"
 
 namespace mozilla { namespace psm {
@@ -69,32 +69,32 @@ public:
 
   // *evOidPolicy == SEC_OID_UNKNOWN means the cert is NOT EV
   // Only one usage per verification is supported.
   SECStatus VerifyCert(CERTCertificate* cert,
                        SECCertificateUsage usage,
                        mozilla::pkix::Time time,
                        void* pinArg,
                        const char* hostname,
-               /*out*/ ScopedCERTCertList& builtChain,
+               /*out*/ UniqueCERTCertList& builtChain,
                        Flags flags = 0,
        /*optional in*/ const SECItem* stapledOCSPResponse = nullptr,
       /*optional out*/ SECOidTag* evOidPolicy = nullptr,
       /*optional out*/ OCSPStaplingStatus* ocspStaplingStatus = nullptr,
       /*optional out*/ KeySizeStatus* keySizeStatus = nullptr,
       /*optional out*/ SHA1ModeResult* sha1ModeResult = nullptr,
       /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo = nullptr);
 
   SECStatus VerifySSLServerCert(
                     const UniqueCERTCertificate& peerCert,
        /*optional*/ const SECItem* stapledOCSPResponse,
                     mozilla::pkix::Time time,
        /*optional*/ void* pinarg,
                     const char* hostname,
-            /*out*/ ScopedCERTCertList& builtChain,
+            /*out*/ UniqueCERTCertList& builtChain,
        /*optional*/ bool saveIntermediatesInPermanentDatabase = false,
        /*optional*/ Flags flags = 0,
    /*optional out*/ SECOidTag* evOidPolicy = nullptr,
    /*optional out*/ OCSPStaplingStatus* ocspStaplingStatus = nullptr,
    /*optional out*/ KeySizeStatus* keySizeStatus = nullptr,
    /*optional out*/ SHA1ModeResult* sha1ModeResult = nullptr,
    /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo = nullptr);
 
@@ -149,9 +149,9 @@ private:
 void InitCertVerifierLog();
 mozilla::pkix::Result IsCertBuiltInRoot(CERTCertificate* cert, bool& result);
 mozilla::pkix::Result CertListContainsExpectedKeys(
   const CERTCertList* certList, const char* hostname, mozilla::pkix::Time time,
   CertVerifier::PinningMode pinningMode);
 
 } } // namespace mozilla::psm
 
-#endif // mozilla_psm__CertVerifier_h
+#endif // CertVerifier_h
--- a/security/certverifier/NSSCertDBTrustDomain.cpp
+++ b/security/certverifier/NSSCertDBTrustDomain.cpp
@@ -47,17 +47,17 @@ NSSCertDBTrustDomain::NSSCertDBTrustDoma
                                            OCSPCache& ocspCache,
              /*optional but shouldn't be*/ void* pinArg,
                                            CertVerifier::OcspGetConfig ocspGETConfig,
                                            uint32_t certShortLifetimeInDays,
                                            CertVerifier::PinningMode pinningMode,
                                            unsigned int minRSABits,
                                            ValidityCheckingMode validityCheckingMode,
                                            CertVerifier::SHA1Mode sha1Mode,
-                                           ScopedCERTCertList& builtChain,
+                                           UniqueCERTCertList& builtChain,
                               /*optional*/ PinningTelemetryInfo* pinningTelemetryInfo,
                               /*optional*/ const char* hostname)
   : mCertDBTrustType(certDBTrustType)
   , mOCSPFetching(ocspFetching)
   , mOCSPCache(ocspCache)
   , mPinArg(pinArg)
   , mOCSPGetConfig(ocspGETConfig)
   , mCertShortLifetimeInDays(certShortLifetimeInDays)
@@ -71,17 +71,17 @@ NSSCertDBTrustDomain::NSSCertDBTrustDoma
   , mCertBlocklist(do_GetService(NS_CERTBLOCKLIST_CONTRACTID))
   , mOCSPStaplingStatus(CertVerifier::OCSP_STAPLING_NEVER_CHECKED)
 {
 }
 
 // If useRoots is true, we only use root certificates in the candidate list.
 // If useRoots is false, we only use non-root certificates in the list.
 static Result
-FindIssuerInner(ScopedCERTCertList& candidates, bool useRoots,
+FindIssuerInner(const UniqueCERTCertList& candidates, bool useRoots,
                 Input encodedIssuerName, TrustDomain::IssuerChecker& checker,
                 /*out*/ bool& keepGoing)
 {
   keepGoing = true;
   for (CERTCertListNode* n = CERT_LIST_HEAD(candidates);
        !CERT_LIST_END(n, candidates); n = CERT_LIST_NEXT(n)) {
     bool candidateIsRoot = !!n->cert->isRoot;
     if (candidateIsRoot != useRoots) {
@@ -131,17 +131,17 @@ FindIssuerInner(ScopedCERTCertList& cand
 
 Result
 NSSCertDBTrustDomain::FindIssuer(Input encodedIssuerName,
                                  IssuerChecker& checker, Time)
 {
   // TODO: NSS seems to be ambiguous between "no potential issuers found" and
   // "there was an error trying to retrieve the potential issuers."
   SECItem encodedIssuerNameItem = UnsafeMapInputToSECItem(encodedIssuerName);
-  ScopedCERTCertList
+  UniqueCERTCertList
     candidates(CERT_CreateSubjectCertList(nullptr, CERT_GetDefaultCertDB(),
                                           &encodedIssuerNameItem, 0,
                                           false));
   if (candidates) {
     // First, try all the root certs; then try all the non-root certs.
     bool keepGoing;
     Result rv = FindIssuerInner(candidates, true, encodedIssuerName, checker,
                                 keepGoing);
@@ -730,17 +730,17 @@ private:
 };
 
 Result
 NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time)
 {
   MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
          ("NSSCertDBTrustDomain: IsChainValid"));
 
-  ScopedCERTCertList certList;
+  UniqueCERTCertList certList;
   SECStatus srv = ConstructCERTCertListFromReversedDERArray(certArray,
                                                             certList);
   if (srv != SECSuccess) {
     return MapPRErrorCodeToResult(PR_GetError());
   }
   if (CERT_LIST_EMPTY(certList)) {
     return Result::FATAL_ERROR_LIBRARY_FAILURE;
   }
@@ -808,17 +808,17 @@ NSSCertDBTrustDomain::IsChainValid(const
     if (NS_FAILED(nsrv)) {
       return Result::FATAL_ERROR_LIBRARY_FAILURE;
     }
     if (!chainHasValidPins) {
       return Result::ERROR_KEY_PINNING_FAILURE;
     }
   }
 
-  mBuiltChain = certList.forget();
+  mBuiltChain = Move(certList);
 
   return Success;
 }
 
 Result
 NSSCertDBTrustDomain::CheckSignatureDigestAlgorithm(DigestAlgorithm aAlg,
                                                     EndEntityOrCA endEntityOrCA,
                                                     Time notBefore)
@@ -1102,17 +1102,17 @@ DefaultServerNicknameForCert(CERTCertifi
     PR_Free(nickname);
     count++;
   }
   PR_FREEIF(servername);
   return nickname;
 }
 
 void
-SaveIntermediateCerts(const ScopedCERTCertList& certList)
+SaveIntermediateCerts(const UniqueCERTCertList& certList)
 {
   if (!certList) {
     return;
   }
 
   bool isEndEntity = true;
   for (CERTCertListNode* node = CERT_LIST_HEAD(certList);
         !CERT_LIST_END(node, certList);
--- a/security/certverifier/NSSCertDBTrustDomain.h
+++ b/security/certverifier/NSSCertDBTrustDomain.h
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef mozilla_psm__NSSCertDBTrustDomain_h
-#define mozilla_psm__NSSCertDBTrustDomain_h
+#ifndef NSSCertDBTrustDomain_h
+#define NSSCertDBTrustDomain_h
 
 #include "CertVerifier.h"
 #include "nsICertBlocklist.h"
 #include "pkix/pkixtypes.h"
 #include "secmodt.h"
 
 namespace mozilla { namespace psm {
 
@@ -34,17 +34,17 @@ extern const char BUILTIN_ROOTS_MODULE_D
 SECStatus LoadLoadableRoots(/*optional*/ const char* dir,
                             const char* modNameUTF8);
 
 void UnloadLoadableRoots(const char* modNameUTF8);
 
 // Caller must free the result with PR_Free
 char* DefaultServerNicknameForCert(CERTCertificate* cert);
 
-void SaveIntermediateCerts(const ScopedCERTCertList& certList);
+void SaveIntermediateCerts(const UniqueCERTCertList& certList);
 
 class NSSCertDBTrustDomain : public mozilla::pkix::TrustDomain
 {
 
 public:
   typedef mozilla::pkix::Result Result;
 
   enum OCSPFetching {
@@ -58,17 +58,17 @@ public:
   NSSCertDBTrustDomain(SECTrustType certDBTrustType, OCSPFetching ocspFetching,
                        OCSPCache& ocspCache, void* pinArg,
                        CertVerifier::OcspGetConfig ocspGETConfig,
                        uint32_t certShortLifetimeInDays,
                        CertVerifier::PinningMode pinningMode,
                        unsigned int minRSABits,
                        ValidityCheckingMode validityCheckingMode,
                        CertVerifier::SHA1Mode sha1Mode,
-                       ScopedCERTCertList& builtChain,
+                       UniqueCERTCertList& builtChain,
           /*optional*/ PinningTelemetryInfo* pinningTelemetryInfo = nullptr,
           /*optional*/ const char* hostname = nullptr);
 
   virtual Result FindIssuer(mozilla::pkix::Input encodedIssuerName,
                             IssuerChecker& checker,
                             mozilla::pkix::Time time) override;
 
   virtual Result GetCertTrust(mozilla::pkix::EndEntityOrCA endEntityOrCA,
@@ -144,18 +144,18 @@ private:
   OCSPCache& mOCSPCache; // non-owning!
   void* mPinArg; // non-owning!
   const CertVerifier::OcspGetConfig mOCSPGetConfig;
   const uint32_t mCertShortLifetimeInDays;
   CertVerifier::PinningMode mPinningMode;
   const unsigned int mMinRSABits;
   ValidityCheckingMode mValidityCheckingMode;
   CertVerifier::SHA1Mode mSHA1Mode;
-  ScopedCERTCertList& mBuiltChain; // non-owning
+  UniqueCERTCertList& mBuiltChain; // non-owning
   PinningTelemetryInfo* mPinningTelemetryInfo;
   const char* mHostname; // non-owning - only used for pinning checks
   nsCOMPtr<nsICertBlocklist> mCertBlocklist;
   CertVerifier::OCSPStaplingStatus mOCSPStaplingStatus;
 };
 
 } } // namespace mozilla::psm
 
-#endif // mozilla_psm__NSSCertDBTrustDomain_h
+#endif // NSSCertDBTrustDomain_h
--- a/security/manager/ssl/CSTrustDomain.cpp
+++ b/security/manager/ssl/CSTrustDomain.cpp
@@ -15,17 +15,17 @@
 
 using namespace mozilla::pkix;
 
 namespace mozilla { namespace psm {
 
 static LazyLogModule gTrustDomainPRLog("CSTrustDomain");
 #define CSTrust_LOG(args) MOZ_LOG(gTrustDomainPRLog, LogLevel::Debug, args)
 
-CSTrustDomain::CSTrustDomain(ScopedCERTCertList& certChain)
+CSTrustDomain::CSTrustDomain(UniqueCERTCertList& certChain)
   : mCertChain(certChain)
   , mCertBlocklist(do_GetService(NS_CERTBLOCKLIST_CONTRACTID))
 {
 }
 
 Result
 CSTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
                             const CertPolicyId& policy, Input candidateCertDER,
--- a/security/manager/ssl/CSTrustDomain.h
+++ b/security/manager/ssl/CSTrustDomain.h
@@ -17,17 +17,17 @@
 
 namespace mozilla { namespace psm {
 
 class CSTrustDomain final : public mozilla::pkix::TrustDomain
 {
 public:
   typedef mozilla::pkix::Result Result;
 
-  explicit CSTrustDomain(ScopedCERTCertList& certChain);
+  explicit CSTrustDomain(UniqueCERTCertList& certChain);
 
   virtual Result GetCertTrust(
     mozilla::pkix::EndEntityOrCA endEntityOrCA,
     const mozilla::pkix::CertPolicyId& policy,
     mozilla::pkix::Input candidateCertDER,
     /*out*/ mozilla::pkix::TrustLevel& trustLevel) override;
   virtual Result FindIssuer(mozilla::pkix::Input encodedIssuerName,
                             IssuerChecker& checker,
@@ -61,15 +61,15 @@ public:
     mozilla::pkix::EndEntityOrCA endEntityOrCA,
     mozilla::pkix::KeyPurposeId keyPurpose) override;
   virtual Result DigestBuf(mozilla::pkix::Input item,
                            mozilla::pkix::DigestAlgorithm digestAlg,
                            /*out*/ uint8_t* digestBuf,
                            size_t digestBufLen) override;
 
 private:
-  /*out*/ ScopedCERTCertList& mCertChain;
+  /*out*/ UniqueCERTCertList& mCertChain;
   nsCOMPtr<nsICertBlocklist> mCertBlocklist;
 };
 
 } } // namespace mozilla::psm
 
 #endif // CSTrustDomain_h
--- a/security/manager/ssl/ContentSignatureVerifier.cpp
+++ b/security/manager/ssl/ContentSignatureVerifier.cpp
@@ -141,18 +141,17 @@ ContentSignatureVerifier::CreateContext(
     CSVerifier_LOG(("CSVerifier: nss is already shutdown\n"));
     return NS_ERROR_FAILURE;
   }
 
   if (mCx) {
     return NS_ERROR_ALREADY_INITIALIZED;
   }
 
-  ScopedCERTCertList certCertList(CERT_NewCertList());
-
+  UniqueCERTCertList certCertList(CERT_NewCertList());
   if (!certCertList) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   nsresult rv = ReadChainIntoCertList(aCertChain, certCertList.get(), locker);
   if (NS_FAILED(rv)) {
     return rv;
   }
--- a/security/manager/ssl/PublicKeyPinningService.cpp
+++ b/security/manager/ssl/PublicKeyPinningService.cpp
@@ -8,17 +8,16 @@
 #include "mozilla/Telemetry.h"
 #include "nsISiteSecurityService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsSiteSecurityService.h"
 #include "nssb64.h"
 #include "pkix/pkixtypes.h"
 #include "mozilla/Logging.h"
 #include "RootCertificateTelemetryUtils.h"
-#include "ScopedNSSTypes.h"
 #include "seccomon.h"
 #include "sechash.h"
 
 #include "StaticHPKPins.h" // autogenerated by genHPKPStaticpins.js
 
 using namespace mozilla;
 using namespace mozilla::pkix;
 using namespace mozilla::psm;
@@ -93,17 +92,18 @@ EvalCert(const CERTCertificate* cert, co
 }
 
 /*
  * Sets certListIntersectsPinset to true if a given chain matches any
  * fingerprints from the given static fingerprints or the
  * dynamicFingerprints array, or to false otherwise.
  */
 static nsresult
-EvalChain(const CERTCertList* certList, const StaticFingerprints* fingerprints,
+EvalChain(const UniqueCERTCertList& certList,
+          const StaticFingerprints* fingerprints,
           const nsTArray<nsCString>* dynamicFingerprints,
   /*out*/ bool& certListIntersectsPinset)
 {
   certListIntersectsPinset = false;
   CERTCertificate* currentCert;
 
   if (!fingerprints && !dynamicFingerprints) {
     MOZ_ASSERT(false, "Must pass in at least one type of pinset");
@@ -139,17 +139,17 @@ TransportSecurityPreloadCompare(const vo
   const char *keyStr = reinterpret_cast<const char *>(key);
   const TransportSecurityPreload *preloadEntry =
     reinterpret_cast<const TransportSecurityPreload *>(entry);
 
   return strcmp(keyStr, preloadEntry->mHost);
 }
 
 nsresult
-PublicKeyPinningService::ChainMatchesPinset(const CERTCertList* certList,
+PublicKeyPinningService::ChainMatchesPinset(const UniqueCERTCertList& certList,
                                             const nsTArray<nsCString>& aSHA256keys,
                                     /*out*/ bool& chainMatchesPinset)
 {
   return EvalChain(certList, nullptr, &aSHA256keys, chainMatchesPinset);
 }
 
 // Returns via one of the output parameters the most relevant pinning
 // information that is valid for the given host at the given time.
@@ -226,17 +226,17 @@ FindPinningInformation(const char* hostn
 }
 
 // Returns true via the output parameter if the given certificate list meets
 // pinning requirements for the given host at the given time. It must be the
 // case that either there is an intersection between the set of hashes of
 // subject public key info data in the list and the most relevant non-expired
 // pinset for the host or there is no pinning information for the host.
 static nsresult
-CheckPinsForHostname(const CERTCertList* certList, const char* hostname,
+CheckPinsForHostname(const UniqueCERTCertList& certList, const char* hostname,
                      bool enforceTestMode, mozilla::pkix::Time time,
              /*out*/ bool& chainHasValidPins,
     /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo)
 {
   chainHasValidPins = false;
   if (!certList) {
     return NS_ERROR_INVALID_ARG;
   }
@@ -313,17 +313,17 @@ CheckPinsForHostname(const CERTCertList*
             staticFingerprints->mIsMoz ? "mozilla" : "non-mozilla",
             hostname, staticFingerprints->mTestMode ? "test" : "production"));
   }
 
   return NS_OK;
 }
 
 nsresult
-PublicKeyPinningService::ChainHasValidPins(const CERTCertList* certList,
+PublicKeyPinningService::ChainHasValidPins(const UniqueCERTCertList& certList,
                                            const char* hostname,
                                            mozilla::pkix::Time time,
                                            bool enforceTestMode,
                                    /*out*/ bool& chainHasValidPins,
                           /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo)
 {
   chainHasValidPins = false;
   if (!certList) {
--- a/security/manager/ssl/PublicKeyPinningService.h
+++ b/security/manager/ssl/PublicKeyPinningService.h
@@ -1,17 +1,18 @@
 /* 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 PublicKeyPinningService_h
 #define PublicKeyPinningService_h
 
+#include "CertVerifier.h"
+#include "ScopedNSSTypes.h"
 #include "cert.h"
-#include "CertVerifier.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "pkix/Time.h"
 
 namespace mozilla {
 namespace psm {
 
 class PublicKeyPinningService
@@ -21,28 +22,28 @@ public:
    * Sets chainHasValidPins to true if the given (host, certList) passes pinning
    * checks, or to false otherwise. If the host is pinned, returns true via
    * chainHasValidPins if one of the keys in the given certificate chain matches
    * the pin set specified by the hostname. The certList's head is the EE cert
    * and the tail is the trust anchor.
    * Note: if an alt name is a wildcard, it won't necessarily find a pinset
    * that would otherwise be valid for it
    */
-  static nsresult ChainHasValidPins(const CERTCertList* certList,
+  static nsresult ChainHasValidPins(const UniqueCERTCertList& certList,
                                     const char* hostname,
                                     mozilla::pkix::Time time,
                                     bool enforceTestMode,
                             /*out*/ bool& chainHasValidPins,
                    /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo);
   /**
    * Sets chainMatchesPinset to true if there is any intersection between the
    * certificate list and the pins specified in the aSHA256keys array.
    * Values passed in are assumed to be in base64 encoded form.
    */
-  static nsresult ChainMatchesPinset(const CERTCertList* certList,
+  static nsresult ChainMatchesPinset(const UniqueCERTCertList& certList,
                                      const nsTArray<nsCString>& aSHA256keys,
                              /*out*/ bool& chainMatchesPinset);
 
   /**
    * Returns true via the output parameter hostHasPins if there is pinning
    * information for the given host that is valid at the given time, and false
    * otherwise.
    */
@@ -56,9 +57,9 @@ public:
    * trailing '.' (see bug 1118522), canonicalizes it to lowercase with no
    * trailing '.'.
    */
   static nsAutoCString CanonicalizeHostname(const char* hostname);
 };
 
 }} // namespace mozilla::psm
 
-#endif // PublicKeyPinningServiceService_h
+#endif // PublicKeyPinningService_h
--- a/security/manager/ssl/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/SSLServerCertVerification.cpp
@@ -729,56 +729,56 @@ private:
 class SSLServerCertVerificationJob : public Runnable
 {
 public:
   // Must be called only on the socket transport thread
   static SECStatus Dispatch(const RefPtr<SharedCertVerifier>& certVerifier,
                             const void* fdForLogging,
                             nsNSSSocketInfo* infoObject,
                             const UniqueCERTCertificate& serverCert,
-                            ScopedCERTCertList& peerCertChain,
+                            const UniqueCERTCertList& peerCertChain,
                             SECItem* stapledOCSPResponse,
                             uint32_t providerFlags,
                             Time time,
                             PRTime prtime);
 private:
   NS_DECL_NSIRUNNABLE
 
   // Must be called only on the socket transport thread
   SSLServerCertVerificationJob(const RefPtr<SharedCertVerifier>& certVerifier,
                                const void* fdForLogging,
                                nsNSSSocketInfo* infoObject,
                                const UniqueCERTCertificate& cert,
-                               CERTCertList* peerCertChain,
+                               UniqueCERTCertList peerCertChain,
                                SECItem* stapledOCSPResponse,
                                uint32_t providerFlags,
                                Time time,
                                PRTime prtime);
   const RefPtr<SharedCertVerifier> mCertVerifier;
   const void* const mFdForLogging;
   const RefPtr<nsNSSSocketInfo> mInfoObject;
   const UniqueCERTCertificate mCert;
-  ScopedCERTCertList mPeerCertChain;
+  UniqueCERTCertList mPeerCertChain;
   const uint32_t mProviderFlags;
   const Time mTime;
   const PRTime mPRTime;
   const TimeStamp mJobStartTime;
   const ScopedSECItem mStapledOCSPResponse;
 };
 
 SSLServerCertVerificationJob::SSLServerCertVerificationJob(
     const RefPtr<SharedCertVerifier>& certVerifier, const void* fdForLogging,
     nsNSSSocketInfo* infoObject, const UniqueCERTCertificate& cert,
-    CERTCertList* peerCertChain, SECItem* stapledOCSPResponse,
+    UniqueCERTCertList peerCertChain, SECItem* stapledOCSPResponse,
     uint32_t providerFlags, Time time, PRTime prtime)
   : mCertVerifier(certVerifier)
   , mFdForLogging(fdForLogging)
   , mInfoObject(infoObject)
   , mCert(CERT_DupCertificate(cert.get()))
-  , mPeerCertChain(peerCertChain)
+  , mPeerCertChain(Move(peerCertChain))
   , mProviderFlags(providerFlags)
   , mTime(time)
   , mPRTime(prtime)
   , mJobStartTime(TimeStamp::Now())
   , mStapledOCSPResponse(SECITEM_DupItem(stapledOCSPResponse))
 {
 }
 
@@ -888,17 +888,17 @@ TryMatchingWildcardSubjectAltName(const 
 //  - if there is a malformed entry in the subject alt. names extension
 //  - if there is an entry in the subject alt. names extension corresponding
 //    to the subject common name
 // Telemetry is only gathered for certificates that chain to a trusted root
 // in Mozilla's Root CA program.
 // certList consists of a validated certificate chain. The end-entity
 // certificate is first and the root (trust anchor) is last.
 void
-GatherBaselineRequirementsTelemetry(const ScopedCERTCertList& certList)
+GatherBaselineRequirementsTelemetry(const UniqueCERTCertList& certList)
 {
   CERTCertListNode* endEntityNode = CERT_LIST_HEAD(certList);
   CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
   PR_ASSERT(!(CERT_LIST_END(endEntityNode, certList) ||
               CERT_LIST_END(rootNode, certList)));
   if (CERT_LIST_END(endEntityNode, certList) ||
       CERT_LIST_END(rootNode, certList)) {
     return;
@@ -1052,17 +1052,17 @@ GatherBaselineRequirementsTelemetry(cons
 
   AccumulateSubjectCommonNameTelemetry(commonName.get(),
                                        commonNameInSubjectAltNames);
 }
 
 // Gather telemetry on whether the end-entity cert for a server has the
 // required TLS Server Authentication EKU, or any others
 void
-GatherEKUTelemetry(const ScopedCERTCertList& certList)
+GatherEKUTelemetry(const UniqueCERTCertList& certList)
 {
   CERTCertListNode* endEntityNode = CERT_LIST_HEAD(certList);
   CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
   PR_ASSERT(!(CERT_LIST_END(endEntityNode, certList) ||
               CERT_LIST_END(rootNode, certList)));
   if (CERT_LIST_END(endEntityNode, certList) ||
       CERT_LIST_END(rootNode, certList)) {
     return;
@@ -1134,17 +1134,17 @@ GatherEKUTelemetry(const ScopedCERTCertL
     Telemetry::Accumulate(Telemetry::SSL_SERVER_AUTH_EKU, 3);
   }
 }
 
 // Gathers telemetry on which CA is the root of a given cert chain.
 // If the root is a built-in root, then the telemetry makes a count
 // by root.  Roots that are not built-in are counted in one bin.
 void
-GatherRootCATelemetry(const ScopedCERTCertList& certList)
+GatherRootCATelemetry(const UniqueCERTCertList& certList)
 {
   CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
   PR_ASSERT(rootNode);
   if (!rootNode) {
     return;
   }
   PR_ASSERT(!CERT_LIST_END(rootNode, certList));
   if (CERT_LIST_END(rootNode, certList)) {
@@ -1160,17 +1160,17 @@ GatherRootCATelemetry(const ScopedCERTCe
 }
 
 // These time are appoximate, i.e., doesn't account for leap seconds, etc
 const uint64_t ONE_WEEK_IN_SECONDS = (7 * (24 * 60 *60));
 const uint64_t ONE_YEAR_IN_WEEKS   = 52;
 
 // Gathers telemetry on the certificate lifetimes we observe in the wild
 void
-GatherEndEntityTelemetry(const ScopedCERTCertList& certList)
+GatherEndEntityTelemetry(const UniqueCERTCertList& certList)
 {
   CERTCertListNode* endEntityNode = CERT_LIST_HEAD(certList);
   PR_ASSERT(endEntityNode);
   if (!endEntityNode) {
     return;
   }
 
   CERTCertificate * endEntityCert = endEntityNode->cert;
@@ -1201,45 +1201,46 @@ GatherEndEntityTelemetry(const ScopedCER
 
   Telemetry::Accumulate(Telemetry::SSL_OBSERVED_END_ENTITY_CERTIFICATE_LIFETIME,
       durationInWeeks);
 }
 
 // There are various things that we want to measure about certificate
 // chains that we accept.  This is a single entry point for all of them.
 void
-GatherSuccessfulValidationTelemetry(const ScopedCERTCertList& certList)
+GatherSuccessfulValidationTelemetry(const UniqueCERTCertList& certList)
 {
   GatherBaselineRequirementsTelemetry(certList);
   GatherEKUTelemetry(certList);
   GatherRootCATelemetry(certList);
   GatherEndEntityTelemetry(certList);
 }
 
+// Note: Takes ownership of |peerCertChain| if SECSuccess is not returned.
 SECStatus
 AuthCertificate(CertVerifier& certVerifier,
                 nsNSSSocketInfo* infoObject,
                 const UniqueCERTCertificate& cert,
-                ScopedCERTCertList& peerCertChain,
+                UniqueCERTCertList& peerCertChain,
                 SECItem* stapledOCSPResponse,
                 uint32_t providerFlags,
                 Time time)
 {
   MOZ_ASSERT(infoObject);
   MOZ_ASSERT(cert);
 
   SECStatus rv;
 
   // We want to avoid storing any intermediate cert information when browsing
   // in private, transient contexts.
   bool saveIntermediates =
     !(providerFlags & nsISocketProvider::NO_PERMANENT_STORAGE);
 
   SECOidTag evOidPolicy;
-  ScopedCERTCertList certList;
+  UniqueCERTCertList certList;
   CertVerifier::OCSPStaplingStatus ocspStaplingStatus =
     CertVerifier::OCSP_STAPLING_NEVER_CHECKED;
   KeySizeStatus keySizeStatus = KeySizeStatus::NeverChecked;
   SHA1ModeResult sha1ModeResult = SHA1ModeResult::NeverChecked;
   PinningTelemetryInfo pinningTelemetryInfo;
 
   int flags = 0;
   if (!infoObject->SharedState().IsOCSPStaplingEnabled() ||
@@ -1336,32 +1337,31 @@ AuthCertificate(CertVerifier& certVerifi
       status->SetServerCert(nsc, evStatus);
       MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
              ("AuthCertificate setting NEW cert %p\n", nsc.get()));
     }
   }
 
   if (rv != SECSuccess) {
     // Certificate validation failed; store the peer certificate chain on
-    // infoObject so it can be used for error reporting. Note: infoObject
-    // indirectly takes ownership of peerCertChain.
-    infoObject->SetFailedCertChain(peerCertChain);
+    // infoObject so it can be used for error reporting.
+    infoObject->SetFailedCertChain(Move(peerCertChain));
     PR_SetError(savedErrorCode, 0);
   }
 
   return rv;
 }
 
 /*static*/ SECStatus
 SSLServerCertVerificationJob::Dispatch(
   const RefPtr<SharedCertVerifier>& certVerifier,
   const void* fdForLogging,
   nsNSSSocketInfo* infoObject,
   const UniqueCERTCertificate& serverCert,
-  ScopedCERTCertList& peerCertChain,
+  const UniqueCERTCertList& peerCertChain,
   SECItem* stapledOCSPResponse,
   uint32_t providerFlags,
   Time time,
   PRTime prtime)
 {
   // Runs on the socket transport thread
   if (!certVerifier || !infoObject || !serverCert) {
     NS_ERROR("Invalid parameters for SSL server cert validation");
@@ -1369,21 +1369,26 @@ SSLServerCertVerificationJob::Dispatch(
     return SECFailure;
   }
 
   // Copy the certificate list so the runnable can take ownership of it in the
   // constructor.
   // We can safely skip checking if NSS has already shut down here since we're
   // in the middle of verifying a certificate.
   nsNSSShutDownPreventionLock lock;
-  CERTCertList* peerCertChainCopy = nsNSSCertList::DupCertList(peerCertChain, lock);
+  UniqueCERTCertList peerCertChainCopy =
+    nsNSSCertList::DupCertList(peerCertChain, lock);
+  if (!peerCertChainCopy) {
+    PR_SetError(SEC_ERROR_NO_MEMORY, 0);
+    return SECFailure;
+  }
 
   RefPtr<SSLServerCertVerificationJob> job(
     new SSLServerCertVerificationJob(certVerifier, fdForLogging, infoObject,
-                                     serverCert, peerCertChainCopy,
+                                     serverCert, Move(peerCertChainCopy),
                                      stapledOCSPResponse, providerFlags,
                                      time, prtime));
 
   nsresult nrv;
   if (!gCertVerificationThreadPool) {
     nrv = NS_ERROR_NOT_INITIALIZED;
   } else {
     nrv = gCertVerificationThreadPool->Dispatch(job, NS_DISPATCH_NORMAL);
@@ -1427,16 +1432,18 @@ SSLServerCertVerificationJob::Run()
       = Telemetry::SSL_INITIAL_FAILED_CERT_VALIDATION_TIME_MOZILLAPKIX;
 
     // Reset the error code here so we can detect if AuthCertificate fails to
     // set the error code if/when it fails.
     PR_SetError(0, 0);
     SECStatus rv = AuthCertificate(*mCertVerifier, mInfoObject, mCert,
                                    mPeerCertChain, mStapledOCSPResponse,
                                    mProviderFlags, mTime);
+    MOZ_ASSERT(mPeerCertChain || rv != SECSuccess,
+               "AuthCertificate() should take ownership of chain on failure");
     if (rv == SECSuccess) {
       uint32_t interval = (uint32_t) ((TimeStamp::Now() - mJobStartTime).ToMilliseconds());
       RefPtr<SSLServerCertVerificationResult> restart(
         new SSLServerCertVerificationResult(mInfoObject, 0,
                                             successTelemetry, interval));
       restart->Dispatch();
       Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES, 1);
       return NS_OK;
@@ -1527,17 +1534,21 @@ AuthCertificateHook(void* arg, PRFileDes
   UniqueCERTCertificate serverCert(SSL_PeerCertificate(fd));
 
   if (!checkSig || isServer || !socketInfo || !serverCert) {
       PR_SetError(PR_INVALID_STATE_ERROR, 0);
       return SECFailure;
   }
 
   // Get the peer certificate chain for error reporting
-  ScopedCERTCertList peerCertChain(SSL_PeerCertificateChain(fd));
+  UniqueCERTCertList peerCertChain(SSL_PeerCertificateChain(fd));
+  if (!peerCertChain) {
+    PR_SetError(PR_INVALID_STATE_ERROR, 0);
+    return SECFailure;
+  }
 
   socketInfo->SetFullHandshake();
 
   Time now(Now());
   PRTime prnow(PR_Now());
 
   if (BlockServerCertChangeForSpdy(socketInfo, serverCert) != SECSuccess)
     return SECFailure;
@@ -1595,16 +1606,18 @@ AuthCertificateHook(void* arg, PRFileDes
   // We can't do certificate verification on a background thread, because the
   // thread doing the network I/O may not interrupt its network I/O on receipt
   // of our SSLServerCertVerificationResult event, and/or it might not even be
   // a non-blocking socket.
 
   SECStatus rv = AuthCertificate(*certVerifier, socketInfo, serverCert,
                                  peerCertChain, stapledOCSPResponse,
                                  providerFlags, now);
+  MOZ_ASSERT(peerCertChain || rv != SECSuccess,
+             "AuthCertificate() should take ownership of chain on failure");
   if (rv == SECSuccess) {
     Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES, 1);
     return SECSuccess;
   }
 
   PRErrorCode error = PR_GetError();
   if (error != 0) {
     RefPtr<CertErrorRunnable> runnable(
--- a/security/manager/ssl/ScopedNSSTypes.h
+++ b/security/manager/ssl/ScopedNSSTypes.h
@@ -81,19 +81,16 @@ MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLAT
                                           CERTCertificate,
                                           CERT_DestroyCertificate)
 MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTCertificateList,
                                           CERTCertificateList,
                                           CERT_DestroyCertificateList)
 MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTCertificateRequest,
                                           CERTCertificateRequest,
                                           CERT_DestroyCertificateRequest)
-MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTCertList,
-                                          CERTCertList,
-                                          CERT_DestroyCertList)
 MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTName,
                                           CERTName,
                                           CERT_DestroyName)
 MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTSubjectPublicKeyInfo,
                                           CERTSubjectPublicKeyInfo,
                                           SECKEY_DestroySubjectPublicKeyInfo)
 MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTValidity,
                                           CERTValidity,
--- a/security/manager/ssl/TransportSecurityInfo.cpp
+++ b/security/manager/ssl/TransportSecurityInfo.cpp
@@ -1071,23 +1071,22 @@ TransportSecurityInfo::GetFailedCertChai
 
   *_result = mFailedCertChain;
   NS_IF_ADDREF(*_result);
 
   return NS_OK;
 }
 
 nsresult
-TransportSecurityInfo::SetFailedCertChain(ScopedCERTCertList& certList)
+TransportSecurityInfo::SetFailedCertChain(UniqueCERTCertList certList)
 {
   nsNSSShutDownPreventionLock lock;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  nsCOMPtr<nsIX509CertList> comCertList;
   // nsNSSCertList takes ownership of certList
-  mFailedCertChain = new nsNSSCertList(certList, lock);
+  mFailedCertChain = new nsNSSCertList(Move(certList), lock);
 
   return NS_OK;
 }
 
 } } // namespace mozilla::psm
--- a/security/manager/ssl/TransportSecurityInfo.h
+++ b/security/manager/ssl/TransportSecurityInfo.h
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * 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 _MOZILLA_PSM_TRANSPORTSECURITYINFO_H
-#define _MOZILLA_PSM_TRANSPORTSECURITYINFO_H
+#ifndef TransportSecurityInfo_h
+#define TransportSecurityInfo_h
 
 #include "ScopedNSSTypes.h"
 #include "certt.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/RefPtr.h"
 #include "nsDataHashtable.h"
 #include "nsIAssociatedContentSecurity.h"
 #include "nsIInterfaceRequestor.h"
@@ -65,23 +65,23 @@ public:
   PRErrorCode GetErrorCode() const;
   
   void GetErrorLogMessage(PRErrorCode errorCode,
                           ::mozilla::psm::SSLErrorMessageType errorMessageType,
                           nsString &result);
   
   void SetCanceled(PRErrorCode errorCode,
                    ::mozilla::psm::SSLErrorMessageType errorMessageType);
-  
+
   /* Set SSL Status values */
   nsresult SetSSLStatus(nsSSLStatus *aSSLStatus);
   nsSSLStatus* SSLStatus() { return mSSLStatus; }
   void SetStatusErrorBits(nsNSSCertificate* cert, uint32_t collected_errors);
 
-  nsresult SetFailedCertChain(ScopedCERTCertList& certList);
+  nsresult SetFailedCertChain(UniqueCERTCertList certList);
 
 private:
   mutable ::mozilla::Mutex mMutex;
 
 protected:
   nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
 
 private:
@@ -156,9 +156,9 @@ private:
 
 } } // namespace mozilla::psm
 
 // 16786594-0296-4471-8096-8f84497ca428
 #define TRANSPORTSECURITYINFO_CID \
 { 0x16786594, 0x0296, 0x4471, \
     { 0x80, 0x96, 0x8f, 0x84, 0x49, 0x7c, 0xa4, 0x28 } }
 
-#endif /* _MOZILLA_PSM_TRANSPORTSECURITYINFO_H */
+#endif // TransportSecurityInfo_h
--- a/security/manager/ssl/nsCertPicker.cpp
+++ b/security/manager/ssl/nsCertPicker.cpp
@@ -59,24 +59,23 @@ NS_IMETHODIMP nsCertPicker::PickByUsage(
   char16_t **certNicknameList = nullptr;
   char16_t **certDetailsList = nullptr;
   CERTCertListNode* node = nullptr;
   nsresult rv = NS_OK;
 
   {
     // Iterate over all certs. This assures that user is logged in to all hardware tokens.
     nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
-    ScopedCERTCertList allcerts(PK11_ListCerts(PK11CertListUnique, ctx));
+    UniqueCERTCertList allcerts(PK11_ListCerts(PK11CertListUnique, ctx));
   }
 
   /* find all user certs that are valid for the specified usage */
   /* note that we are allowing expired certs in this list */
-
-  ScopedCERTCertList certList(
-    CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(), 
+  UniqueCERTCertList certList(
+    CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
                               (SECCertUsage)certUsage,
                               !allowDuplicateNicknames,
                               !allowInvalid,
                               ctx));
   if (!certList) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
@@ -101,18 +100,17 @@ NS_IMETHODIMP nsCertPicker::PickByUsage(
           CERT_RemoveCertListNode(freenode);
           continue;
         }
       }
       node = CERT_LIST_NEXT(node);
     }
   }
 
-  UniqueCERTCertNicknames nicknames(
-    getNSSCertNicknamesFromCertList(certList.get()));
+  UniqueCERTCertNicknames nicknames(getNSSCertNicknamesFromCertList(certList));
   if (!nicknames) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   certNicknameList = (char16_t **)moz_xmalloc(sizeof(char16_t *) * nicknames->numnicknames);
   certDetailsList = (char16_t **)moz_xmalloc(sizeof(char16_t *) * nicknames->numnicknames);
 
   if (!certNicknameList || !certDetailsList) {
--- a/security/manager/ssl/nsCertTree.cpp
+++ b/security/manager/ssl/nsCertTree.cpp
@@ -608,17 +608,17 @@ nsCertTree::GetCertsByTypeFromCertList(C
 
 nsresult 
 nsCertTree::GetCertsByType(uint32_t           aType,
                            nsCertCompareFunc  aCertCmpFn,
                            void              *aCertCmpFnArg)
 {
   nsNSSShutDownPreventionLock locker;
   nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
-  ScopedCERTCertList certList(PK11_ListCerts(PK11CertListUnique, cxt));
+  UniqueCERTCertList certList(PK11_ListCerts(PK11CertListUnique, cxt));
   return GetCertsByTypeFromCertList(certList.get(), aType, aCertCmpFn,
                                     aCertCmpFnArg);
 }
 
 nsresult
 nsCertTree::GetCertsByTypeFromCache(nsIX509CertList   *aCache,
                                     uint32_t           aType,
                                     nsCertCompareFunc  aCertCmpFn,
--- a/security/manager/ssl/nsDataSignatureVerifier.cpp
+++ b/security/manager/ssl/nsDataSignatureVerifier.cpp
@@ -225,17 +225,17 @@ VerifyCMSDetachedSignatureIncludingCerti
 
 } // namespace mozilla
 
 namespace {
 
 struct VerifyCertificateContext
 {
   nsCOMPtr<nsIX509Cert> signingCert;
-  ScopedCERTCertList builtChain;
+  UniqueCERTCertList builtChain;
 };
 
 static nsresult
 VerifyCertificate(CERTCertificate* cert, void* voidContext, void* pinArg)
 {
   // XXX: missing pinArg is tolerated
   if (NS_WARN_IF(!cert) || NS_WARN_IF(!voidContext)) {
     return NS_ERROR_INVALID_ARG;
--- a/security/manager/ssl/nsNSSCertHelper.cpp
+++ b/security/manager/ssl/nsNSSCertHelper.cpp
@@ -1,17 +1,16 @@
 /* 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 "nsNSSCertHelper.h"
 
 #include <algorithm>
 
-#include "ScopedNSSTypes.h"
 #include "mozilla/Snprintf.h"
 #include "mozilla/UniquePtr.h"
 #include "nsCOMPtr.h"
 #include "nsComponentManagerUtils.h"
 #include "nsDateTimeFormatCID.h"
 #include "nsIDateTimeFormat.h"
 #include "nsNSSASN1Object.h"
 #include "nsNSSCertTrust.h"
@@ -2058,18 +2057,18 @@ getCertType(CERTCertificate *cert)
     return nsIX509Cert::EMAIL_CERT;
   if (CERT_IsCACert(cert, nullptr))
     return nsIX509Cert::CA_CERT;
   if (cert->emailAddr)
     return nsIX509Cert::EMAIL_CERT;
   return nsIX509Cert::UNKNOWN_CERT;
 }
 
-CERTCertNicknames *
-getNSSCertNicknamesFromCertList(CERTCertList *certList)
+CERTCertNicknames*
+getNSSCertNicknamesFromCertList(const UniqueCERTCertList& certList)
 {
   static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
 
   nsresult rv;
 
   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
   if (NS_FAILED(rv))
     return nullptr;
@@ -2084,20 +2083,19 @@ getNSSCertNicknamesFromCertList(CERTCert
   expiredStringLeadingSpace.Append(expiredString);
 
   notYetValidStringLeadingSpace.Append(' ');
   notYetValidStringLeadingSpace.Append(notYetValidString);
 
   NS_ConvertUTF16toUTF8 aUtf8ExpiredString(expiredStringLeadingSpace);
   NS_ConvertUTF16toUTF8 aUtf8NotYetValidString(notYetValidStringLeadingSpace);
 
-  return CERT_NicknameStringsFromCertList(certList,
+  return CERT_NicknameStringsFromCertList(certList.get(),
                                           const_cast<char*>(aUtf8ExpiredString.get()),
                                           const_cast<char*>(aUtf8NotYetValidString.get()));
-  
 }
 
 nsresult
 GetCertFingerprintByOidTag(CERTCertificate* nsscert,
                            SECOidTag aOidTag, 
                            nsCString &fp)
 {
   Digest digest;
--- a/security/manager/ssl/nsNSSCertHelper.h
+++ b/security/manager/ssl/nsNSSCertHelper.h
@@ -1,26 +1,27 @@
 /* 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 _NSNSSCERTHELPER_H_
-#define _NSNSSCERTHELPER_H_
+#ifndef nsNSSCertHelper_h
+#define nsNSSCertHelper_h
 
 #ifndef INET6_ADDRSTRLEN
 #define INET6_ADDRSTRLEN 46
 #endif
 
+#include "ScopedNSSTypes.h"
 #include "certt.h"
 #include "nsString.h"
 
 uint32_t
 getCertType(CERTCertificate *cert);
 
-CERTCertNicknames *
-getNSSCertNicknamesFromCertList(CERTCertList *certList);
+CERTCertNicknames*
+getNSSCertNicknamesFromCertList(const mozilla::UniqueCERTCertList& certList);
 
 nsresult
 GetCertFingerprintByOidTag(CERTCertificate* nsscert,
                            SECOidTag aOidTag, 
                            nsCString &fp);
 
-#endif
+#endif // nsNSSCertHelper_h
--- a/security/manager/ssl/nsNSSCertificate.cpp
+++ b/security/manager/ssl/nsNSSCertificate.cpp
@@ -836,20 +836,20 @@ nsNSSCertificate::GetChain(nsIArray** _r
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
   NS_ENSURE_ARG(_rvChain);
   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Getting chain for \"%s\"\n", mCert->nickname));
 
   mozilla::pkix::Time now(mozilla::pkix::Now());
 
-  ScopedCERTCertList nssChain;
   RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
   NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
 
+  UniqueCERTCertList nssChain;
   // We want to test all usages, but we start with server because most of the
   // time Firefox users care about server certs.
   if (certVerifier->VerifyCert(mCert.get(), certificateUsageSSLServer, now,
                                nullptr, /*XXX fixme*/
                                nullptr, /* hostname */
                                nssChain,
                                CertVerifier::FLAG_LOCAL_ONLY) != SECSuccess) {
     nssChain = nullptr;
@@ -879,26 +879,25 @@ nsNSSCertificate::GetChain(nsIArray** _r
                                  nssChain,
                                  CertVerifier::FLAG_LOCAL_ONLY) != SECSuccess) {
       nssChain = nullptr;
       // keep going
     }
   }
 
   if (!nssChain) {
-    // There is not verified path for the chain, howeever we still want to 
+    // There is not verified path for the chain, however we still want to
     // present to the user as much of a possible chain as possible, in the case
     // where there was a problem with the cert or the issuers.
     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
            ("pipnss: getchain :CertVerify failed to get chain for '%s'\n",
             mCert->nickname));
-    nssChain = CERT_GetCertChainFromCert(mCert.get(), PR_Now(),
-                                         certUsageSSLClient);
-  } 
-
+    nssChain = UniqueCERTCertList(
+      CERT_GetCertChainFromCert(mCert.get(), PR_Now(), certUsageSSLClient));
+  }
   if (!nssChain) {
     return NS_ERROR_FAILURE;
   }
 
   // enumerate the chain for scripting purposes
   nsCOMPtr<nsIMutableArray> array = nsArrayBase::Create();
   if (!array) {
     return NS_ERROR_FAILURE;
@@ -1400,17 +1399,17 @@ nsNSSCertificate::hasValidEVOidTag(SECOi
     certVerifier(mozilla::psm::GetDefaultCertVerifier());
   NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
 
   validEV = false;
   resultOidTag = SEC_OID_UNKNOWN;
 
   uint32_t flags = mozilla::psm::CertVerifier::FLAG_LOCAL_ONLY |
     mozilla::psm::CertVerifier::FLAG_MUST_BE_EV;
-  ScopedCERTCertList unusedBuiltChain;
+  UniqueCERTCertList unusedBuiltChain;
   SECStatus rv = certVerifier->VerifyCert(mCert.get(),
     certificateUsageSSLServer, mozilla::pkix::Now(),
     nullptr /* XXX pinarg */,
     nullptr /* hostname */,
     unusedBuiltChain,
     flags, nullptr /* stapledOCSPResponse */, &resultOidTag);
 
   if (rv != SECSuccess) {
@@ -1473,19 +1472,19 @@ nsNSSCertificate::GetIsExtendedValidatio
 namespace mozilla {
 
 // TODO(bug 1036065): It seems like we only construct CERTCertLists for the
 // purpose of constructing nsNSSCertLists, so maybe we should change this
 // function to output an nsNSSCertList instead.
 SECStatus
 ConstructCERTCertListFromReversedDERArray(
   const mozilla::pkix::DERArray& certArray,
-  /*out*/ ScopedCERTCertList& certList)
+  /*out*/ UniqueCERTCertList& certList)
 {
-  certList = CERT_NewCertList();
+  certList = UniqueCERTCertList(CERT_NewCertList());
   if (!certList) {
     return SECFailure;
   }
 
   CERTCertDBHandle* certDB(CERT_GetDefaultCertDB()); // non-owning
 
   size_t numCerts = certArray.GetLength();
   for (size_t i = 0; i < numCerts; ++i) {
@@ -1513,29 +1512,29 @@ NS_IMPL_CLASSINFO(nsNSSCertList,
                   // inferred from nsIX509Cert
                   nsIClassInfo::THREADSAFE,
                   NS_X509CERTLIST_CID)
 
 NS_IMPL_ISUPPORTS_CI(nsNSSCertList,
                      nsIX509CertList,
                      nsISerializable)
 
-nsNSSCertList::nsNSSCertList(ScopedCERTCertList& certList,
+nsNSSCertList::nsNSSCertList(UniqueCERTCertList certList,
                              const nsNSSShutDownPreventionLock& proofOfLock)
 {
   if (certList) {
-    mCertList = certList.forget();
+    mCertList = Move(certList);
   } else {
-    mCertList = CERT_NewCertList();
+    mCertList = UniqueCERTCertList(CERT_NewCertList());
   }
 }
 
 nsNSSCertList::nsNSSCertList()
 {
-  mCertList = CERT_NewCertList();
+  mCertList = UniqueCERTCertList(CERT_NewCertList());
 }
 
 nsNSSCertList::~nsNSSCertList()
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return;
   }
@@ -1545,19 +1544,17 @@ nsNSSCertList::~nsNSSCertList()
 
 void nsNSSCertList::virtualDestroyNSSReference()
 {
   destructorSafeDestroyNSSReference();
 }
 
 void nsNSSCertList::destructorSafeDestroyNSSReference()
 {
-  if (mCertList) {
-    mCertList = nullptr;
-  }
+  mCertList = nullptr;
 }
 
 NS_IMETHODIMP
 nsNSSCertList::AddCert(nsIX509Cert* aCert)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
@@ -1602,35 +1599,42 @@ nsNSSCertList::DeleteCert(nsIX509Cert* a
     if (node->cert == cert) {
 	CERT_RemoveCertListNode(node);
         return NS_OK;
     }
   }
   return NS_OK; // XXX Should we fail if we couldn't find it?
 }
 
-CERTCertList*
-nsNSSCertList::DupCertList(CERTCertList* aCertList,
+UniqueCERTCertList
+nsNSSCertList::DupCertList(const UniqueCERTCertList& certList,
                            const nsNSSShutDownPreventionLock& /*proofOfLock*/)
 {
-  if (!aCertList) {
+  if (!certList) {
     return nullptr;
   }
 
-  CERTCertList* newList = CERT_NewCertList();
-
+  UniqueCERTCertList newList(CERT_NewCertList());
   if (!newList) {
     return nullptr;
   }
 
-  CERTCertListNode* node;
-  for (node = CERT_LIST_HEAD(aCertList); !CERT_LIST_END(node, aCertList);
-                                              node = CERT_LIST_NEXT(node)) {
-    CERTCertificate* cert = CERT_DupCertificate(node->cert);
-    CERT_AddCertToListTail(newList, cert);
+  for (CERTCertListNode* node = CERT_LIST_HEAD(certList);
+       !CERT_LIST_END(node, certList);
+       node = CERT_LIST_NEXT(node)) {
+    UniqueCERTCertificate cert(CERT_DupCertificate(node->cert));
+    if (!cert) {
+      return nullptr;
+    }
+
+    if (CERT_AddCertToListTail(newList.get(), cert.get()) != SECSuccess) {
+      return nullptr;
+    }
+
+    Unused << cert.release(); // Ownership transferred to the cert list.
   }
   return newList;
 }
 
 void*
 nsNSSCertList::GetRawCertList()
 {
   // This function should only be called after acquiring a
@@ -1727,18 +1731,23 @@ nsNSSCertList::Read(nsIObjectInputStream
 
 NS_IMETHODIMP
 nsNSSCertList::GetEnumerator(nsISimpleEnumerator** _retval)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
+
+  if (!mCertList) {
+    return NS_ERROR_FAILURE;
+  }
+
   nsCOMPtr<nsISimpleEnumerator> enumerator =
-    new nsNSSCertListEnumerator(mCertList.get(), locker);
+    new nsNSSCertListEnumerator(mCertList, locker);
 
   enumerator.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNSSCertList::Equals(nsIX509CertList* other, bool* result)
 {
@@ -1798,18 +1807,20 @@ nsNSSCertList::Equals(nsIX509CertList* o
   }
 
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS(nsNSSCertListEnumerator, nsISimpleEnumerator)
 
 nsNSSCertListEnumerator::nsNSSCertListEnumerator(
-  CERTCertList* certList, const nsNSSShutDownPreventionLock& proofOfLock)
+  const UniqueCERTCertList& certList,
+  const nsNSSShutDownPreventionLock& proofOfLock)
 {
+  MOZ_ASSERT(certList);
   mCertList = nsNSSCertList::DupCertList(certList, proofOfLock);
 }
 
 nsNSSCertListEnumerator::~nsNSSCertListEnumerator()
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return;
@@ -1820,19 +1831,17 @@ nsNSSCertListEnumerator::~nsNSSCertListE
 
 void nsNSSCertListEnumerator::virtualDestroyNSSReference()
 {
   destructorSafeDestroyNSSReference();
 }
 
 void nsNSSCertListEnumerator::destructorSafeDestroyNSSReference()
 {
-  if (mCertList) {
-    mCertList = nullptr;
-  }
+  mCertList = nullptr;
 }
 
 NS_IMETHODIMP
 nsNSSCertListEnumerator::HasMoreElements(bool* _retval)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
--- a/security/manager/ssl/nsNSSCertificate.h
+++ b/security/manager/ssl/nsNSSCertificate.h
@@ -1,27 +1,27 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 _NS_NSSCERTIFICATE_H_
-#define _NS_NSSCERTIFICATE_H_
+#ifndef nsNSSCertificate_h
+#define nsNSSCertificate_h
 
+#include "ScopedNSSTypes.h"
+#include "certt.h"
+#include "nsCOMPtr.h"
+#include "nsIASN1Object.h"
+#include "nsIClassInfo.h"
+#include "nsISerializable.h"
+#include "nsISimpleEnumerator.h"
 #include "nsIX509Cert.h"
 #include "nsIX509CertDB.h"
 #include "nsIX509CertList.h"
-#include "nsIASN1Object.h"
-#include "nsCOMPtr.h"
 #include "nsNSSShutDown.h"
-#include "nsISimpleEnumerator.h"
-#include "nsISerializable.h"
-#include "nsIClassInfo.h"
-#include "ScopedNSSTypes.h"
-#include "certt.h"
 
 namespace mozilla { namespace pkix { class DERArray; } }
 
 class nsAutoString;
 class nsINSSComponent;
 class nsIASN1Sequence;
 
 class nsNSSCertificate final : public nsIX509Cert,
@@ -79,69 +79,70 @@ private:
   nsresult hasValidEVOidTag(SECOidTag& resultOidTag, bool& validEV);
   nsresult getValidEVOidTag(SECOidTag& resultOidTag, bool& validEV);
 };
 
 namespace mozilla {
 
 SECStatus ConstructCERTCertListFromReversedDERArray(
             const mozilla::pkix::DERArray& certArray,
-            /*out*/ mozilla::ScopedCERTCertList& certList);
+            /*out*/ mozilla::UniqueCERTCertList& certList);
 
 } // namespace mozilla
 
 class nsNSSCertList: public nsIX509CertList,
                      public nsISerializable,
                      public nsNSSShutDownObject
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIX509CERTLIST
   NS_DECL_NSISERIALIZABLE
 
   // certList is adopted
-  nsNSSCertList(mozilla::ScopedCERTCertList& certList,
+  nsNSSCertList(mozilla::UniqueCERTCertList certList,
                 const nsNSSShutDownPreventionLock& proofOfLock);
 
   nsNSSCertList();
 
-  static CERTCertList* DupCertList(CERTCertList* aCertList,
-                                   const nsNSSShutDownPreventionLock&
-                                     proofOfLock);
+  static mozilla::UniqueCERTCertList DupCertList(
+    const mozilla::UniqueCERTCertList& certList,
+    const nsNSSShutDownPreventionLock& proofOfLock);
+
 private:
    virtual ~nsNSSCertList();
    virtual void virtualDestroyNSSReference() override;
    void destructorSafeDestroyNSSReference();
 
-   mozilla::ScopedCERTCertList mCertList;
+   mozilla::UniqueCERTCertList mCertList;
 
    nsNSSCertList(const nsNSSCertList&) = delete;
    void operator=(const nsNSSCertList&) = delete;
 };
 
 class nsNSSCertListEnumerator: public nsISimpleEnumerator,
                                public nsNSSShutDownObject
 {
 public:
    NS_DECL_THREADSAFE_ISUPPORTS
    NS_DECL_NSISIMPLEENUMERATOR
 
-   nsNSSCertListEnumerator(CERTCertList* certList,
+   nsNSSCertListEnumerator(const mozilla::UniqueCERTCertList& certList,
                            const nsNSSShutDownPreventionLock& proofOfLock);
 private:
    virtual ~nsNSSCertListEnumerator();
    virtual void virtualDestroyNSSReference() override;
    void destructorSafeDestroyNSSReference();
 
-   mozilla::ScopedCERTCertList mCertList;
+   mozilla::UniqueCERTCertList mCertList;
 
    nsNSSCertListEnumerator(const nsNSSCertListEnumerator&) = delete;
    void operator=(const nsNSSCertListEnumerator&) = delete;
 };
 
 #define NS_X509CERT_CID { /* 660a3226-915c-4ffb-bb20-8985a632df05 */   \
     0x660a3226,                                                        \
     0x915c,                                                            \
     0x4ffb,                                                            \
     { 0xbb, 0x20, 0x89, 0x85, 0xa6, 0x32, 0xdf, 0x05 }                 \
   }
 
-#endif // _NS_NSSCERTIFICATE_H_
+#endif // nsNSSCertificate_h
--- a/security/manager/ssl/nsNSSCertificateDB.cpp
+++ b/security/manager/ssl/nsNSSCertificateDB.cpp
@@ -549,17 +549,17 @@ ImportCertsIntoTempStorage(int numcerts,
         != SECSuccess) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 static SECStatus
-ImportCertsIntoPermanentStorage(const ScopedCERTCertList& certChain,
+ImportCertsIntoPermanentStorage(const UniqueCERTCertList& certChain,
                                 const SECCertUsage usage, const bool caOnly)
 {
   int chainLen = 0;
   for (CERTCertListNode *chainNode = CERT_LIST_HEAD(certChain);
        !CERT_LIST_END(chainNode, certChain);
        chainNode = CERT_LIST_NEXT(chainNode)) {
     chainLen++;
   }
@@ -625,17 +625,17 @@ nsNSSCertificateDB::ImportEmailCertifica
   // Note: We verify the certs in order to prevent DoS attacks. See Bug 249004.
   for (CERTCertListNode* node = CERT_LIST_HEAD(filteredCerts.get());
        !CERT_LIST_END(node, filteredCerts.get());
        node = CERT_LIST_NEXT(node)) {
     if (!node->cert) {
       continue;
     }
 
-    ScopedCERTCertList certChain;
+    UniqueCERTCertList certChain;
     SECStatus srv = certVerifier->VerifyCert(node->cert,
                                              certificateUsageEmailRecipient,
                                              mozilla::pkix::Now(), ctx,
                                              nullptr, certChain);
     if (srv != SECSuccess) {
       nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
       DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow, locker);
       continue;
@@ -681,17 +681,17 @@ nsNSSCertificateDB::ImportValidCACertsIn
   }
 
   // Iterate through the filtered cert list and import verified certs into
   // permanent storage.
   // Note: We verify the certs in order to prevent DoS attacks. See Bug 249004.
   for (CERTCertListNode* node = CERT_LIST_HEAD(filteredCerts.get());
        !CERT_LIST_END(node, filteredCerts.get());
        node = CERT_LIST_NEXT(node)) {
-    ScopedCERTCertList certChain;
+    UniqueCERTCertList certChain;
     SECStatus rv = certVerifier->VerifyCert(node->cert,
                                             certificateUsageVerifyCA,
                                             mozilla::pkix::Now(), ctx,
                                             nullptr, certChain);
     if (rv != SECSuccess) {
       nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
       DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow, proofOfLock);
       continue;
@@ -1137,34 +1137,34 @@ nsNSSCertificateDB::FindCertByEmailAddre
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
   NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
 
-  ScopedCERTCertList certlist(
+  UniqueCERTCertList certlist(
       PK11_FindCertsFromEmailAddress(aEmailAddress, nullptr));
   if (!certlist)
     return NS_ERROR_FAILURE;
 
   // certlist now contains certificates with the right email address,
   // but they might not have the correct usage or might even be invalid
 
   if (CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist))
     return NS_ERROR_FAILURE; // no certs found
 
   CERTCertListNode *node;
   // search for a valid certificate
   for (node = CERT_LIST_HEAD(certlist);
        !CERT_LIST_END(node, certlist);
        node = CERT_LIST_NEXT(node)) {
 
-    ScopedCERTCertList unusedCertChain;
+    UniqueCERTCertList unusedCertChain;
     SECStatus srv = certVerifier->VerifyCert(node->cert,
                                              certificateUsageEmailRecipient,
                                              mozilla::pkix::Now(),
                                              nullptr /*XXX pinarg*/,
                                              nullptr /*hostname*/,
                                              unusedCertChain);
     if (srv == SECSuccess) {
       break;
@@ -1466,25 +1466,25 @@ nsNSSCertificateDB::SetCertTrustFromStri
 }
 
 NS_IMETHODIMP 
 nsNSSCertificateDB::GetCerts(nsIX509CertList **_retval)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
-  }  
+  }
 
   nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
   nsCOMPtr<nsIX509CertList> nssCertList;
-  ScopedCERTCertList certList(PK11_ListCerts(PK11CertListUnique, ctx));
+  UniqueCERTCertList certList(PK11_ListCerts(PK11CertListUnique, ctx));
 
   // nsNSSCertList 1) adopts certList, and 2) handles the nullptr case fine.
   // (returns an empty list) 
-  nssCertList = new nsNSSCertList(certList, locker);
+  nssCertList = new nsNSSCertList(Move(certList), locker);
 
   nssCertList.forget(_retval);
   return NS_OK;
 }
 
 nsresult
 VerifyCertAtTime(nsIX509Cert* aCert,
                  int64_t /*SECCertificateUsage*/ aUsage,
@@ -1512,17 +1512,17 @@ VerifyCertAtTime(nsIX509Cert* aCert,
   UniqueCERTCertificate nssCert(aCert->GetCert());
   if (!nssCert) {
     return NS_ERROR_INVALID_ARG;
   }
 
   RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
   NS_ENSURE_TRUE(certVerifier, NS_ERROR_FAILURE);
 
-  ScopedCERTCertList resultChain;
+  UniqueCERTCertList resultChain;
   SECOidTag evOidPolicy;
   SECStatus srv;
 
   if (aHostname && aUsage == certificateUsageSSLServer) {
     srv = certVerifier->VerifySSLServerCert(nssCert,
                                             nullptr, // stapledOCSPResponse
                                             aTime,
                                             nullptr, // Assume no context
@@ -1540,17 +1540,17 @@ VerifyCertAtTime(nsIX509Cert* aCert,
                                    nullptr, // stapledOCSPResponse
                                    &evOidPolicy);
   }
 
   PRErrorCode error = PR_GetError();
 
   nsCOMPtr<nsIX509CertList> nssCertList;
   // This adopts the list
-  nssCertList = new nsNSSCertList(resultChain, locker);
+  nssCertList = new nsNSSCertList(Move(resultChain), locker);
   NS_ENSURE_TRUE(nssCertList, NS_ERROR_FAILURE);
 
   if (srv == SECSuccess) {
     if (evOidPolicy != SEC_OID_UNKNOWN) {
       *aHasEVPolicy = true;
     }
     *_retval = 0;
   } else {
--- a/security/manager/ssl/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/nsNSSIOLayer.cpp
@@ -368,17 +368,17 @@ nsNSSSocketInfo::IsAcceptableForHost(con
   // can associate the correct certificate chain with the HTTP transactions it
   // is trying to join onto this connection.
   RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
   if (!certVerifier) {
     return NS_OK;
   }
   nsAutoCString hostnameFlat(PromiseFlatCString(hostname));
   CertVerifier::Flags flags = CertVerifier::FLAG_LOCAL_ONLY;
-  ScopedCERTCertList unusedBuiltChain;
+  UniqueCERTCertList unusedBuiltChain;
   SECStatus rv = certVerifier->VerifySSLServerCert(nssCert, nullptr,
                                                    mozilla::pkix::Now(),
                                                    nullptr, hostnameFlat.get(),
                                                    unusedBuiltChain, false, flags);
   if (rv != SECSuccess) {
     return NS_OK;
   }
 
@@ -2084,17 +2084,17 @@ ClientAuthDataRunnable::RunOnTargetThrea
   // We check the value of a pref in this runnable, so this runnable should only
   // be run on the main thread.
   MOZ_ASSERT(NS_IsMainThread());
 
   UniquePLArenaPool arena;
   char** caNameStrings;
   UniqueCERTCertificate cert;
   UniqueSECKEYPrivateKey privKey;
-  ScopedCERTCertList certList;
+  UniqueCERTCertList certList;
   CERTCertListNode* node;
   UniqueCERTCertNicknames nicknames;
   int keyError = 0; // used for private key retrieval error
   int32_t NumberOfCerts = 0;
   void* wincx = mSocketInfo;
   nsresult rv;
 
   nsCOMPtr<nsIX509Cert> socketClientCert;
@@ -2137,19 +2137,19 @@ ClientAuthDataRunnable::RunOnTargetThrea
     goto loser;
   }
 
   // find valid user cert and key pair
   if (nsGetUserCertChoice() == UserCertChoice::Auto) {
     // automatically find the right cert
 
     // find all user certs that are valid and for SSL
-    certList = CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
-                                         certUsageSSLClient, false,
-                                         true, wincx);
+    certList.reset(CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
+                                             certUsageSSLClient, false, true,
+                                             wincx));
     if (!certList) {
       goto noCert;
     }
 
     // filter the list to those issued by CAs supported by the server
     mRV = CERT_FilterCertListByCANames(certList.get(), mCANames->nnames,
                                        caNameStrings, certUsageSSLClient);
     if (mRV != SECSuccess) {
@@ -2251,19 +2251,19 @@ ClientAuthDataRunnable::RunOnTargetThrea
       // user selects a cert to present
       nsCOMPtr<nsIClientAuthDialogs> dialogs;
       int32_t selectedIndex = -1;
       char16_t** certNicknameList = nullptr;
       char16_t** certDetailsList = nullptr;
 
       // find all user certs that are for SSL
       // note that we are allowing expired certs in this list
-      certList = CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
-        certUsageSSLClient, false,
-        false, wincx);
+      certList.reset(CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
+                                               certUsageSSLClient, false,
+                                               false, wincx));
       if (!certList) {
         goto noCert;
       }
 
       if (mCANames->nnames != 0) {
         // filter the list to those issued by CAs supported by the server
         mRV = CERT_FilterCertListByCANames(certList.get(),
                                            mCANames->nnames,
@@ -2284,17 +2284,17 @@ ClientAuthDataRunnable::RunOnTargetThrea
       while (!CERT_LIST_END(node, certList.get())) {
         ++NumberOfCerts;
         node = CERT_LIST_NEXT(node);
       }
       if (CERT_LIST_END(CERT_LIST_HEAD(certList.get()), certList.get())) {
         goto noCert;
       }
 
-      nicknames.reset(getNSSCertNicknamesFromCertList(certList.get()));
+      nicknames.reset(getNSSCertNicknamesFromCertList(certList));
 
       if (!nicknames) {
         goto loser;
       }
 
       NS_ASSERTION(nicknames->numnicknames == NumberOfCerts, "nicknames->numnicknames != NumberOfCerts");
 
       // Get CN and O of the subject and O of the issuer
--- a/security/manager/ssl/nsSiteSecurityService.cpp
+++ b/security/manager/ssl/nsSiteSecurityService.cpp
@@ -694,17 +694,17 @@ nsSiteSecurityService::ProcessPKPHeader(
   nsCOMPtr<nsIX509Cert> cert;
   rv = aSSLStatus->GetServerCert(getter_AddRefs(cert));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(cert, NS_ERROR_FAILURE);
   UniqueCERTCertificate nssCert(cert->GetCert());
   NS_ENSURE_TRUE(nssCert, NS_ERROR_FAILURE);
 
   mozilla::pkix::Time now(mozilla::pkix::Now());
-  ScopedCERTCertList certList;
+  UniqueCERTCertList certList;
   RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
   NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
   if (certVerifier->VerifySSLServerCert(nssCert, nullptr, // stapled ocsp
                                         now, nullptr, // pinarg
                                         host.get(), // hostname
                                         certList,
                                         false, // don't store intermediates
                                         CertVerifier::FLAG_LOCAL_ONLY)
--- a/security/manager/ssl/nsUsageArrayHelper.cpp
+++ b/security/manager/ssl/nsUsageArrayHelper.cpp
@@ -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 "nsUsageArrayHelper.h"
 
+#include "ScopedNSSTypes.h"
 #include "mozilla/Assertions.h"
 #include "nsCOMPtr.h"
 #include "nsComponentManagerUtils.h"
 #include "nsDateTimeFormatCID.h"
 #include "nsIDateTimeFormat.h"
 #include "nsNSSCertificate.h"
 #include "nsReadableUtils.h"
 #include "nsServiceManagerUtils.h"
@@ -98,17 +99,17 @@ nsUsageArrayHelper::check(uint32_t previ
     break;
   case certificateUsageStatusResponder:
     typestr = "VerifyStatusResponder";
     break;
   default:
     MOZ_CRASH("unknown cert usage passed to check()");
   }
 
-  ScopedCERTCertList unusedBuiltChain;
+  UniqueCERTCertList unusedBuiltChain;
   SECStatus rv = certVerifier->VerifyCert(mCert, aCertUsage, time,
                                           nullptr /*XXX:wincx*/,
                                           nullptr /*hostname*/,
                                           unusedBuiltChain, flags);
 
   if (rv == SECSuccess) {
     typestr.Append(suffix);
     nsAutoString verifyDesc;