Bug 1028643: Convert nsISignatureVerifier to use CertVerifier (mozilla::pkix) and move nsISignatureVerifier functionality to nsIDataSignatureVerifier, r=keeler
authorBrian Smith <brian@briansmith.org>
Sun, 22 Jun 2014 18:50:22 -0700
changeset 190367 3a1aa8745a6fae5d8a7d994107e23d0570ef89dc
parent 190366 1dbdfb30254168353d2e47fe007aaa851ee87951
child 190368 35c8882a4028eb055c475f0dbd9ee700e02430a6
push id27004
push useremorley@mozilla.com
push dateTue, 24 Jun 2014 15:52:34 +0000
treeherdermozilla-central@7b174d47f3cc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler
bugs1028643
milestone33.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 1028643: Convert nsISignatureVerifier to use CertVerifier (mozilla::pkix) and move nsISignatureVerifier functionality to nsIDataSignatureVerifier, r=keeler
modules/libjar/nsJAR.cpp
modules/libjar/nsJAR.h
security/apps/AppSignatureVerification.cpp
security/manager/ssl/public/moz.build
security/manager/ssl/public/nsIDataSignatureVerifier.idl
security/manager/ssl/public/nsISignatureVerifier.idl
security/manager/ssl/src/nsDataSignatureVerifier.cpp
security/manager/ssl/src/nsDataSignatureVerifier.h
security/manager/ssl/src/nsNSSComponent.cpp
security/manager/ssl/src/nsNSSComponent.h
--- a/modules/libjar/nsJAR.cpp
+++ b/modules/libjar/nsJAR.cpp
@@ -1,18 +1,20 @@
 /* -*- 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/. */
 #include <string.h>
 #include "nsJARInputStream.h"
 #include "nsJAR.h"
 #include "nsIFile.h"
+#include "nsICertificatePrincipal.h"
 #include "nsIConsoleService.h"
 #include "nsICryptoHash.h"
+#include "nsIDataSignatureVerifier.h"
 #include "prprf.h"
 #include "mozilla/Omnijar.h"
 
 #ifdef XP_UNIX
   #include <sys/stat.h>
 #elif defined (XP_WIN)
   #include <io.h>
 #endif
@@ -550,33 +552,33 @@ nsJAR::ParseManifest()
   if (NS_FAILED(rv))
   {
     mGlobalStatus = JAR_NO_MANIFEST;
     mParsedManifest = true;
     return NS_OK;
   }
 
   //-- Get the signature verifier service
-  nsCOMPtr<nsISignatureVerifier> verifier =
-           do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
+  nsCOMPtr<nsIDataSignatureVerifier> verifier(
+    do_GetService("@mozilla.org/security/datasignatureverifier;1", &rv));
   if (NS_FAILED(rv)) // No signature verifier available
   {
     mGlobalStatus = JAR_NO_MANIFEST;
     mParsedManifest = true;
     return NS_OK;
   }
 
   //-- Verify that the signature file is a valid signature of the SF file
   int32_t verifyError;
   rv = verifier->VerifySignature(sigBuffer, sigLen, manifestBuffer, manifestLen,
                                  &verifyError, getter_AddRefs(mPrincipal));
   if (NS_FAILED(rv)) return rv;
-  if (mPrincipal && verifyError == 0)
+  if (mPrincipal && verifyError == nsIDataSignatureVerifier::VERIFY_OK)
     mGlobalStatus = JAR_VALID_MANIFEST;
-  else if (verifyError == nsISignatureVerifier::VERIFY_ERROR_UNKNOWN_CA)
+  else if (verifyError == nsIDataSignatureVerifier::VERIFY_ERROR_UNKNOWN_ISSUER)
     mGlobalStatus = JAR_INVALID_UNKNOWN_CA;
   else
     mGlobalStatus = JAR_INVALID_SIG;
 
   //-- Parse the SF file. If the verification above failed, principal
   // is null, and ParseOneFile will mark the relevant entries as invalid.
   // if ParseOneFile fails, then it has no effect, and we can safely
   // continue to the next SF file, or return.
--- a/modules/libjar/nsJAR.h
+++ b/modules/libjar/nsJAR.h
@@ -19,23 +19,22 @@
 #include "nsString.h"
 #include "nsIFile.h"
 #include "nsStringEnumerator.h"
 #include "nsHashKeys.h"
 #include "nsRefPtrHashtable.h"
 #include "nsTHashtable.h"
 #include "nsIZipReader.h"
 #include "nsZipArchive.h"
-#include "nsICertificatePrincipal.h"
-#include "nsISignatureVerifier.h"
 #include "nsIObserverService.h"
 #include "nsWeakReference.h"
 #include "nsIObserver.h"
 #include "mozilla/Attributes.h"
 
+class nsICertificatePrincipal;
 class nsIInputStream;
 class nsJARManifestItem;
 class nsZipReaderCache;
 
 /* For mManifestStatus */
 typedef enum
 {
   JAR_MANIFEST_NOT_PARSED = 0,
--- a/security/apps/AppSignatureVerification.cpp
+++ b/security/apps/AppSignatureVerification.cpp
@@ -11,16 +11,17 @@
 #include "nsNSSCertificateDB.h"
 
 #include "pkix/pkix.h"
 #include "mozilla/RefPtr.h"
 #include "CryptoTask.h"
 #include "AppTrustDomain.h"
 #include "nsComponentManagerUtils.h"
 #include "nsCOMPtr.h"
+#include "nsDataSignatureVerifier.h"
 #include "nsHashKeys.h"
 #include "nsIFile.h"
 #include "nsIInputStream.h"
 #include "nsIStringEnumerator.h"
 #include "nsIZipReader.h"
 #include "nsNSSCertificate.h"
 #include "nsProxyRelease.h"
 #include "nsString.h"
@@ -517,117 +518,57 @@ ParseMF(const char* filebuf, nsIZipReade
     }
 
     // unrecognized attributes must be ignored
   }
 
   return NS_OK;
 }
 
-nsresult
-VerifySignature(AppTrustedRoot trustedRoot,
-                const SECItem& buffer, const SECItem& detachedDigest,
-        /*out*/ mozilla::pkix::ScopedCERTCertList& builtChain)
-{
-  mozilla::pkix::ScopedPtr<NSSCMSMessage, NSS_CMSMessage_Destroy>
-    cmsMsg(NSS_CMSMessage_CreateFromDER(const_cast<SECItem*>(&buffer), nullptr,
-                                        nullptr, nullptr, nullptr, nullptr,
-                                        nullptr));
-  if (!cmsMsg) {
-    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
-  }
-
-  if (!NSS_CMSMessage_IsSigned(cmsMsg.get())) {
-    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CMS message isn't signed"));
-    return NS_ERROR_CMS_VERIFY_NOT_SIGNED;
-  }
-
-  NSSCMSContentInfo* cinfo = NSS_CMSMessage_ContentLevel(cmsMsg.get(), 0);
-  if (!cinfo) {
-    return NS_ERROR_CMS_VERIFY_NO_CONTENT_INFO;
-  }
-
-  // signedData is non-owning
-  NSSCMSSignedData* signedData =
-    reinterpret_cast<NSSCMSSignedData*>(NSS_CMSContentInfo_GetContent(cinfo));
-  if (!signedData) {
-    return NS_ERROR_CMS_VERIFY_NO_CONTENT_INFO;
-  }
-
-  // Set digest value.
-  if (NSS_CMSSignedData_SetDigestValue(signedData, SEC_OID_SHA1,
-                                       const_cast<SECItem*>(&detachedDigest))) {
-    return NS_ERROR_CMS_VERIFY_BAD_DIGEST;
-  }
+struct VerifyCertificateContext {
+  AppTrustedRoot trustedRoot;
+  mozilla::pkix::ScopedCERTCertList& builtChain;
+};
 
-  // Parse the certificates into CERTCertificate objects held in memory, so that
-  // AppTrustDomain will be able to find them during path building.
-  mozilla::pkix::ScopedCERTCertList certs(CERT_NewCertList());
-  if (!certs) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  if (signedData->rawCerts) {
-    for (size_t i = 0; signedData->rawCerts[i]; ++i) {
-      mozilla::pkix::ScopedCERTCertificate
-        cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
-                                     signedData->rawCerts[i], nullptr, false,
-                                     true));
-      // Skip certificates that fail to parse
-      if (cert) {
-        if (CERT_AddCertToListTail(certs.get(), cert.get()) == SECSuccess) {
-          cert.release(); // ownership transfered
-        } else {
-          return NS_ERROR_OUT_OF_MEMORY;
-        }
-      }
-    }
+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;
   }
+  const VerifyCertificateContext& context =
+    *reinterpret_cast<const VerifyCertificateContext*>(voidContext);
 
-  // Get the end-entity certificate.
-  int numSigners = NSS_CMSSignedData_SignerInfoCount(signedData);
-  if (NS_WARN_IF(numSigners != 1)) {
-    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
-  }
-  // signer is non-owning.
-  NSSCMSSignerInfo* signer = NSS_CMSSignedData_GetSignerInfo(signedData, 0);
-  if (NS_WARN_IF(!signer)) {
-    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
-  }
-  // cert is signerCert
-  CERTCertificate* signerCert =
-    NSS_CMSSignerInfo_GetSigningCertificate(signer, CERT_GetDefaultCertDB());
-  if (!signerCert) {
-    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
-  }
-
-  // Verify certificate.
-  AppTrustDomain trustDomain(nullptr); // TODO: null pinArg
-  if (trustDomain.SetTrustedRoot(trustedRoot) != SECSuccess) {
+  AppTrustDomain trustDomain(pinArg);
+  if (trustDomain.SetTrustedRoot(context.trustedRoot) != SECSuccess) {
     return MapSECStatus(SECFailure);
   }
   if (BuildCertChain(trustDomain, signerCert, PR_Now(),
                      EndEntityOrCA::MustBeEndEntity,
                      KeyUsage::digitalSignature,
                      KeyPurposeId::id_kp_codeSigning,
                      CertPolicyId::anyPolicy,
-                     nullptr, builtChain)
-        != SECSuccess) {
+                     nullptr, context.builtChain) != SECSuccess) {
     return MapSECStatus(SECFailure);
   }
 
-  // See NSS_CMSContentInfo_GetContentTypeOID, which isn't exported from NSS.
-  SECOidData* contentTypeOidData =
-    SECOID_FindOID(&signedData->contentInfo.contentType);
-  if (!contentTypeOidData) {
-    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
-  }
+  return NS_OK;
+}
 
-  return MapSECStatus(NSS_CMSSignerInfo_Verify(signer,
-                         const_cast<SECItem*>(&detachedDigest),
-                         &contentTypeOidData->oid));
+nsresult
+VerifySignature(AppTrustedRoot trustedRoot, const SECItem& buffer,
+                const SECItem& detachedDigest,
+                /*out*/ mozilla::pkix::ScopedCERTCertList& builtChain)
+{
+  VerifyCertificateContext context = { trustedRoot, builtChain };
+  // XXX: missing pinArg
+  return VerifyCMSDetachedSignatureIncludingCertificate(buffer, detachedDigest,
+                                                        VerifyCertificate,
+                                                        &context, nullptr);
 }
 
 NS_IMETHODIMP
 OpenSignedAppFile(AppTrustedRoot aTrustedRoot, nsIFile* aJarFile,
                   /*out, optional */ nsIZipReader** aZipReader,
                   /*out, optional */ nsIX509Cert3** aSignerCert)
 {
   NS_ENSURE_ARG_POINTER(aJarFile);
--- a/security/manager/ssl/public/moz.build
+++ b/security/manager/ssl/public/moz.build
@@ -27,17 +27,16 @@ XPIDL_SOURCES += [
     'nsIPK11Token.idl',
     'nsIPK11TokenDB.idl',
     'nsIPKCS11.idl',
     'nsIPKCS11Module.idl',
     'nsIPKCS11ModuleDB.idl',
     'nsIPKCS11Slot.idl',
     'nsIProtectedAuthThread.idl',
     'nsIRecentBadCertsService.idl',
-    'nsISignatureVerifier.idl',
     'nsISSLErrorListener.idl',
     'nsISSLStatus.idl',
     'nsIStreamCipher.idl',
     'nsITokenDialogs.idl',
     'nsITokenPasswordDialogs.idl',
     'nsIUserCertPicker.idl',
     'nsIX509Cert.idl',
     'nsIX509Cert2.idl',
--- a/security/manager/ssl/public/nsIDataSignatureVerifier.idl
+++ b/security/manager/ssl/public/nsIDataSignatureVerifier.idl
@@ -1,26 +1,41 @@
 /* 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 "nsISupports.idl"
 
+// NB: This isn't actually a principal at all. The naming is just historical.
+interface nsICertificatePrincipal;
+
 /**
  * An interface for verifying that a given string of data was signed by the
  * private key matching the given public key.
  */
-[scriptable, uuid(0a84b3d5-6ba9-432d-89da-4fbd0b0f2aec)]
+[scriptable, uuid(577f097f-15e4-4043-bc0e-6d2fadcacae2)]
 interface nsIDataSignatureVerifier : nsISupports
 {
   /**
    * Verifies that the data matches the data that was used to generate the
    * signature.
    *
    * @param aData      The data to be tested.
    * @param aSignature The signature of the data, base64 encoded.
    * @param aPublicKey The public part of the key used for signing, DER encoded
    *                   then base64 encoded.
    * @returns true if the signature matches the data, false if not.
    */
   boolean verifyData(in ACString aData, in ACString aSignature, in ACString aPublicKey);
+
+   /* Sig Verification Error Codes */
+  const long VERIFY_OK = 0;
+  const long VERIFY_ERROR_UNKNOWN_ISSUER = 1;
+  const long VERIFY_ERROR_OTHER = 2;
+
+  nsICertificatePrincipal verifySignature(in string aSignature,
+                                          in unsigned long aSignatureLen,
+                                          in string plaintext,
+                                          in unsigned long plaintextLen,
+                                          out long errorCode);
+
 };
deleted file mode 100644
--- a/security/manager/ssl/public/nsISignatureVerifier.idl
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* 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/. */
-
-/* An interface for verifying signatures */
-
-#include "nsISupports.idl"
-
-// NB: This isn't actually a principal at all. The naming is just historical.
-interface nsICertificatePrincipal;
-
-[uuid(22870b07-b5ef-481b-9f7f-d41787d4e617)]
-interface nsISignatureVerifier : nsISupports
-{
-   /* Sig Verification Error Codes */
-  const long VERIFY_OK = 0;
-  const long VERIFY_ERROR_UNKNOWN_CA  = -8172; /* -8172 is the error code returned by PSM */
-  
-  nsICertificatePrincipal verifySignature(in string aSignature,
-                                          in unsigned long aSignatureLen,
-                                          in string plaintext,
-                                          in unsigned long plaintextLen,
-                                          out long errorCode);
-};
-
-
-%{C++
-#define SIGNATURE_VERIFIER_CONTRACTID "@mozilla.org/psm;1"
-%}
--- a/security/manager/ssl/src/nsDataSignatureVerifier.cpp
+++ b/security/manager/ssl/src/nsDataSignatureVerifier.cpp
@@ -1,21 +1,29 @@
 /* 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 "nsDataSignatureVerifier.h"
-#include "nsCOMPtr.h"
-#include "nsString.h"
 
-#include "seccomon.h"
+#include "cms.h"
+#include "cryptohi.h"
+#include "keyhi.h"
+#include "nsCertificatePrincipal.h"
+#include "nsCOMPtr.h"
+#include "nsNSSComponent.h"
 #include "nssb64.h"
-#include "certt.h"
-#include "keyhi.h"
-#include "cryptohi.h"
+#include "pkix/pkixtypes.h"
+#include "ScopedNSSTypes.h"
+#include "secerr.h"
+#include "SharedCertVerifier.h"
+
+using namespace mozilla;
+using namespace mozilla::pkix;
+using namespace mozilla::psm;
 
 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
 
 NS_IMPL_ISUPPORTS(nsDataSignatureVerifier, nsIDataSignatureVerifier)
 
 const SEC_ASN1Template CERT_SignatureDataTemplate[] =
 {
     { SEC_ASN1_SEQUENCE,
@@ -99,8 +107,226 @@ nsDataSignatureVerifier::VerifyData(cons
     // Clean up remaining objects
     SECKEY_DestroyPublicKey(publicKey);
     PORT_FreeArena(arena, false);
     
     *_retval = (ss == SECSuccess);
 
     return NS_OK;
 }
+
+namespace mozilla {
+
+nsresult
+VerifyCMSDetachedSignatureIncludingCertificate(
+  const SECItem& buffer, const SECItem& detachedDigest,
+  nsresult (*verifyCertificate)(CERTCertificate* cert, void* context,
+                                void* pinArg),
+  void *verifyCertificateContext, void* pinArg)
+{
+  // XXX: missing pinArg is tolerated.
+  if (NS_WARN_IF(!buffer.data && buffer.len > 0) ||
+      NS_WARN_IF(!detachedDigest.data && detachedDigest.len > 0) ||
+      (!verifyCertificate) ||
+      NS_WARN_IF(!verifyCertificateContext)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  ScopedPtr<NSSCMSMessage, NSS_CMSMessage_Destroy>
+    cmsMsg(NSS_CMSMessage_CreateFromDER(const_cast<SECItem*>(&buffer), nullptr,
+                                        nullptr, nullptr, nullptr, nullptr,
+                                        nullptr));
+  if (!cmsMsg) {
+    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
+  }
+
+  if (!NSS_CMSMessage_IsSigned(cmsMsg.get())) {
+    return NS_ERROR_CMS_VERIFY_NOT_SIGNED;
+  }
+
+  NSSCMSContentInfo* cinfo = NSS_CMSMessage_ContentLevel(cmsMsg.get(), 0);
+  if (!cinfo) {
+    return NS_ERROR_CMS_VERIFY_NO_CONTENT_INFO;
+  }
+
+  // signedData is non-owning
+  NSSCMSSignedData* signedData =
+    reinterpret_cast<NSSCMSSignedData*>(NSS_CMSContentInfo_GetContent(cinfo));
+  if (!signedData) {
+    return NS_ERROR_CMS_VERIFY_NO_CONTENT_INFO;
+  }
+
+  // Set digest value.
+  if (NSS_CMSSignedData_SetDigestValue(signedData, SEC_OID_SHA1,
+                                       const_cast<SECItem*>(&detachedDigest))) {
+    return NS_ERROR_CMS_VERIFY_BAD_DIGEST;
+  }
+
+  // Parse the certificates into CERTCertificate objects held in memory so
+  // verifyCertificate will be able to find them during path building.
+  mozilla::pkix::ScopedCERTCertList certs(CERT_NewCertList());
+  if (!certs) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  if (signedData->rawCerts) {
+    for (size_t i = 0; signedData->rawCerts[i]; ++i) {
+      mozilla::pkix::ScopedCERTCertificate
+        cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
+                                     signedData->rawCerts[i], nullptr, false,
+                                     true));
+      // Skip certificates that fail to parse
+      if (cert) {
+        if (CERT_AddCertToListTail(certs.get(), cert.get()) == SECSuccess) {
+          cert.release(); // ownership transfered
+        } else {
+          return NS_ERROR_OUT_OF_MEMORY;
+        }
+      }
+    }
+  }
+
+  // Get the end-entity certificate.
+  int numSigners = NSS_CMSSignedData_SignerInfoCount(signedData);
+  if (NS_WARN_IF(numSigners != 1)) {
+    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
+  }
+  // signer is non-owning.
+  NSSCMSSignerInfo* signer = NSS_CMSSignedData_GetSignerInfo(signedData, 0);
+  if (NS_WARN_IF(!signer)) {
+    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
+  }
+  CERTCertificate* signerCert =
+    NSS_CMSSignerInfo_GetSigningCertificate(signer, CERT_GetDefaultCertDB());
+  if (!signerCert) {
+    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
+  }
+
+  nsresult rv = verifyCertificate(signerCert, verifyCertificateContext, pinArg);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  // See NSS_CMSContentInfo_GetContentTypeOID, which isn't exported from NSS.
+  SECOidData* contentTypeOidData =
+    SECOID_FindOID(&signedData->contentInfo.contentType);
+  if (!contentTypeOidData) {
+    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
+  }
+
+  return MapSECStatus(NSS_CMSSignerInfo_Verify(signer,
+                         const_cast<SECItem*>(&detachedDigest),
+                         &contentTypeOidData->oid));
+}
+
+} // namespace mozilla
+
+namespace {
+
+struct VerifyCertificateContext
+{
+  nsCOMPtr<nsICertificatePrincipal> principal;
+  mozilla::pkix::ScopedCERTCertList 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;
+  }
+
+  VerifyCertificateContext* context =
+    reinterpret_cast<VerifyCertificateContext*>(voidContext);
+
+  nsCOMPtr<nsIX509Cert> xpcomCert(nsNSSCertificate::Create(cert));
+  if (!xpcomCert) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  nsAutoString fingerprint;
+  nsresult rv = xpcomCert->GetSha1Fingerprint(fingerprint);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  nsAutoString orgName;
+  rv = xpcomCert->GetOrganization(orgName);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  nsAutoString subjectName;
+  rv = xpcomCert->GetSubjectName(subjectName);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  context->principal =
+    new nsCertificatePrincipal(NS_ConvertUTF16toUTF8(fingerprint),
+                               NS_ConvertUTF16toUTF8(subjectName),
+                               NS_ConvertUTF16toUTF8(orgName),
+                               xpcomCert);
+
+  RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
+  NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
+
+  return MapSECStatus(certVerifier->VerifyCert(cert,
+                                               certificateUsageObjectSigner,
+                                               PR_Now(), pinArg,
+                                               nullptr, // hostname
+                                               0, // flags
+                                               nullptr, // stapledOCSPResponse
+                                               &context->builtChain));
+}
+
+} // unnamed namespcae
+
+NS_IMETHODIMP
+nsDataSignatureVerifier::VerifySignature(const char* aRSABuf,
+                                         uint32_t aRSABufLen,
+                                         const char* aPlaintext,
+                                         uint32_t aPlaintextLen,
+                                         int32_t* aErrorCode,
+                                         nsICertificatePrincipal** aPrincipal)
+{
+  if (!aPlaintext || !aPrincipal || !aErrorCode) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  *aErrorCode = VERIFY_ERROR_OTHER;
+  *aPrincipal = nullptr;
+
+  nsNSSShutDownPreventionLock locker;
+
+  Digest digest;
+  nsresult rv = digest.DigestBuf(SEC_OID_SHA1,
+                                 reinterpret_cast<const uint8_t*>(aPlaintext),
+                                 aPlaintextLen);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  SECItem buffer = {
+    siBuffer,
+    reinterpret_cast<uint8_t*>(const_cast<char*>(aRSABuf)),
+    aRSABufLen
+  };
+
+  VerifyCertificateContext context;
+  // XXX: pinArg is missing
+  rv = VerifyCMSDetachedSignatureIncludingCertificate(buffer, digest.get(),
+                                                      VerifyCertificate,
+                                                      &context, nullptr);
+  if (NS_SUCCEEDED(rv)) {
+    *aErrorCode = VERIFY_OK;
+  } else if (NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_SECURITY) {
+    if (rv == GetXPCOMFromNSSError(SEC_ERROR_UNKNOWN_ISSUER)) {
+      *aErrorCode = VERIFY_ERROR_UNKNOWN_ISSUER;
+    } else {
+      *aErrorCode = VERIFY_ERROR_OTHER;
+    }
+    rv = NS_OK;
+  }
+  if (rv == NS_OK) {
+    context.principal.forget(aPrincipal);
+  }
+
+  return rv;
+}
--- a/security/manager/ssl/src/nsDataSignatureVerifier.h
+++ b/security/manager/ssl/src/nsDataSignatureVerifier.h
@@ -5,16 +5,18 @@
 #ifndef _NS_DATASIGNATUREVERIFIER_H_
 #define _NS_DATASIGNATUREVERIFIER_H_
 
 #include "nsIDataSignatureVerifier.h"
 #include "mozilla/Attributes.h"
 
 #include "keythi.h"
 
+typedef struct CERTCertificateStr CERTCertificate;
+
 // 296d76aa-275b-4f3c-af8a-30a4026c18fc
 #define NS_DATASIGNATUREVERIFIER_CID \
     { 0x296d76aa, 0x275b, 0x4f3c, \
     { 0xaf, 0x8a, 0x30, 0xa4, 0x02, 0x6c, 0x18, 0xfc } }
 #define NS_DATASIGNATUREVERIFIER_CONTRACTID \
     "@mozilla.org/security/datasignatureverifier;1"
 
 class nsDataSignatureVerifier MOZ_FINAL : public nsIDataSignatureVerifier
@@ -28,9 +30,19 @@ public:
   }
 
 private:
   ~nsDataSignatureVerifier()
   {
   }
 };
 
+namespace mozilla {
+
+nsresult VerifyCMSDetachedSignatureIncludingCertificate(
+  const SECItem& buffer, const SECItem& detachedDigest,
+  nsresult (*verifyCertificate)(CERTCertificate* cert, void* context,
+                                void* pinArg),
+  void* verifyCertificateContext, void* pinArg);
+
+} // namespace mozilla
+
 #endif // _NS_DATASIGNATUREVERIFIER_H_
--- a/security/manager/ssl/src/nsNSSComponent.cpp
+++ b/security/manager/ssl/src/nsNSSComponent.cpp
@@ -28,41 +28,38 @@
 #include "nsIDOMEvent.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMWindowCollection.h"
 #include "nsIDocument.h"
 #include "nsIDOMSmartCardEvent.h"
 #include "nsSmartCardMonitor.h"
 #include "nsIDOMCryptoLegacy.h"
-#include "nsIPrincipal.h"
 #else
 #include "nsIDOMCrypto.h"
 #endif
 
 #include "nsCRT.h"
 #include "nsNTLMAuthModule.h"
 #include "nsIFile.h"
 #include "nsIProperties.h"
 #include "nsIWindowWatcher.h"
 #include "nsIPrompt.h"
-#include "nsCertificatePrincipal.h"
 #include "nsIBufEntropyCollector.h"
 #include "nsITokenPasswordDialogs.h"
 #include "nsServiceManagerUtils.h"
 #include "nsNSSShutDown.h"
 #include "GeneratedEvents.h"
 #include "SharedSSLState.h"
 #include "NSSErrorsService.h"
 
 #include "nss.h"
 #include "ssl.h"
 #include "sslproto.h"
 #include "secmod.h"
-#include "secmime.h"
 #include "secerr.h"
 #include "sslerr.h"
 
 #include "nsXULAppAPI.h"
 
 #ifdef XP_WIN
 #include "nsILocalFileWin.h"
 #endif
@@ -1352,151 +1349,21 @@ nsNSSComponent::Init()
     bec->ForwardTo(this);
   }
 
   return rv;
 }
 
 // nsISupports Implementation for the class
 NS_IMPL_ISUPPORTS(nsNSSComponent,
-                  nsISignatureVerifier,
                   nsIEntropyCollector,
                   nsINSSComponent,
                   nsIObserver,
                   nsISupportsWeakReference)
 
-
-// Callback functions for decoder. For now, use empty/default functions.
-static void
-ContentCallback(void* arg, const char* buf, unsigned long len)
-{
-}
-
-static PK11SymKey*
-GetDecryptKeyCallback(void* arg, SECAlgorithmID* algid)
-{
-  return nullptr;
-}
-
-static PRBool
-DecryptionAllowedCallback(SECAlgorithmID* algid, PK11SymKey* bulkkey)
-{
-  return SECMIME_DecryptionAllowed(algid, bulkkey);
-}
-
-static void*
-GetPasswordKeyCallback(void* arg, void* handle)
-{
-  return nullptr;
-}
-
-NS_IMETHODIMP
-nsNSSComponent::VerifySignature(const char* aRSABuf, uint32_t aRSABufLen,
-                                const char* aPlaintext, uint32_t aPlaintextLen,
-                                int32_t* aErrorCode,
-                                nsICertificatePrincipal** aPrincipal)
-{
-  if (!aPrincipal || !aErrorCode) {
-    return NS_ERROR_NULL_POINTER;
-  }
-
-  *aErrorCode = 0;
-  *aPrincipal = nullptr;
-
-  nsNSSShutDownPreventionLock locker;
-  ScopedSEC_PKCS7ContentInfo p7_info;
-  unsigned char hash[SHA1_LENGTH];
-
-  SECItem item;
-  item.type = siEncodedCertBuffer;
-  item.data = (unsigned char*)aRSABuf;
-  item.len = aRSABufLen;
-  p7_info = SEC_PKCS7DecodeItem(&item,
-                                ContentCallback, nullptr,
-                                GetPasswordKeyCallback, nullptr,
-                                GetDecryptKeyCallback, nullptr,
-                                DecryptionAllowedCallback);
-
-  if (!p7_info) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Make sure we call SEC_PKCS7DestroyContentInfo after this point;
-  // otherwise we leak data in p7_info
-
-  //-- If a plaintext was provided, hash it.
-  SECItem digest;
-  digest.data = nullptr;
-  digest.len = 0;
-
-  if (aPlaintext) {
-    HASHContext* hash_ctxt;
-    uint32_t hashLen = 0;
-
-    hash_ctxt = HASH_Create(HASH_AlgSHA1);
-    HASH_Begin(hash_ctxt);
-    HASH_Update(hash_ctxt,(const unsigned char*)aPlaintext, aPlaintextLen);
-    HASH_End(hash_ctxt, hash, &hashLen, SHA1_LENGTH);
-    HASH_Destroy(hash_ctxt);
-
-    digest.data = hash;
-    digest.len = SHA1_LENGTH;
-  }
-
-  //-- Verify signature
-  bool rv = SEC_PKCS7VerifyDetachedSignature(p7_info, certUsageObjectSigner,
-                                               &digest, HASH_AlgSHA1, false);
-  if (!rv) {
-    *aErrorCode = PR_GetError();
-  }
-
-  // Get the signing cert //
-  CERTCertificate* cert = p7_info->content.signedData->signerInfos[0]->cert;
-  nsresult rv2 = NS_OK;
-  if (cert) {
-    // Use |do { } while (0);| as a "more C++-ish" thing than goto;
-    // this way we don't have to worry about goto across variable
-    // declarations.  We have no loops in this code, so it's OK.
-    do {
-      nsCOMPtr<nsIX509Cert> pCert = nsNSSCertificate::Create(cert);
-      if (!pCert) {
-        rv2 = NS_ERROR_OUT_OF_MEMORY;
-        break;
-      }
-
-      //-- Create a certificate principal with id and organization data
-      nsAutoString fingerprint;
-      rv2 = pCert->GetSha1Fingerprint(fingerprint);
-      if (NS_FAILED(rv2)) {
-        break;
-      }
-      nsAutoString orgName;
-      rv2 = pCert->GetOrganization(orgName);
-      if (NS_FAILED(rv2)) {
-        break;
-      }
-      nsAutoString subjectName;
-      rv2 = pCert->GetSubjectName(subjectName);
-      if (NS_FAILED(rv2)) {
-        break;
-      }
-
-      nsCOMPtr<nsICertificatePrincipal> certPrincipal =
-        new nsCertificatePrincipal(NS_ConvertUTF16toUTF8(fingerprint),
-                                   NS_ConvertUTF16toUTF8(subjectName),
-                                   NS_ConvertUTF16toUTF8(orgName),
-                                   pCert);
-
-      certPrincipal.swap(*aPrincipal);
-    } while (0);
-  }
-
-  return rv2;
-}
-
 NS_IMETHODIMP
 nsNSSComponent::RandomUpdate(void* entropy, int32_t bufLen)
 {
   nsNSSShutDownPreventionLock locker;
 
   // Asynchronous event happening often,
   // must not interfere with initialization or profile switch.
 
--- a/security/manager/ssl/src/nsNSSComponent.h
+++ b/security/manager/ssl/src/nsNSSComponent.h
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef _nsNSSComponent_h_
 #define _nsNSSComponent_h_
 
 #include "mozilla/Mutex.h"
 #include "mozilla/RefPtr.h"
 #include "nsCOMPtr.h"
-#include "nsISignatureVerifier.h"
 #include "nsIEntropyCollector.h"
 #include "nsIStringBundle.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
 #endif
 #include "nsINSSErrorsService.h"
 #include "nsNSSCallbacks.h"
@@ -108,31 +107,29 @@ class NS_NO_VTABLE nsINSSComponent : pub
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsINSSComponent, NS_INSSCOMPONENT_IID)
 
 class nsNSSShutDownList;
 class nsCertVerificationThread;
 
 // Implementation of the PSM component interface.
-class nsNSSComponent : public nsISignatureVerifier,
-                       public nsIEntropyCollector,
+class nsNSSComponent : public nsIEntropyCollector,
                        public nsINSSComponent,
                        public nsIObserver,
                        public nsSupportsWeakReference
 {
   typedef mozilla::Mutex Mutex;
 
 public:
   NS_DEFINE_STATIC_CID_ACCESSOR( NS_NSSCOMPONENT_CID )
 
   nsNSSComponent();
 
   NS_DECL_THREADSAFE_ISUPPORTS
-  NS_DECL_NSISIGNATUREVERIFIER
   NS_DECL_NSIENTROPYCOLLECTOR
   NS_DECL_NSIOBSERVER
 
   NS_METHOD Init();
 
   static nsresult GetNewPrompter(nsIPrompt** result);
   static nsresult ShowAlertWithConstructedString(const nsString& message);
   NS_IMETHOD ShowAlertFromStringBundle(const char* messageID);