mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 1028643: Convert nsISignatureVerifier to use CertVerifier (mozilla::pkix) and move nsISignatureVerifier functionality to nsIDataSignatureVerifier, r=keeler
--HG-- extra : rebase_source : 14f6f5dedd7145d574ac5b4c86b6ad42b6716ae8 extra : histedit_source : f891fbe80c4ca9fc62849bc2d6d8ffad372a6bf0
This commit is contained in:
parent
109e54dee4
commit
bd8f23ccd6
@ -6,8 +6,10 @@
|
||||
#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"
|
||||
|
||||
@ -555,8 +557,8 @@ nsJAR::ParseManifest()
|
||||
}
|
||||
|
||||
//-- 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;
|
||||
@ -569,9 +571,9 @@ nsJAR::ParseManifest()
|
||||
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;
|
||||
|
@ -24,13 +24,12 @@
|
||||
#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;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "AppTrustDomain.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDataSignatureVerifier.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIInputStream.h"
|
||||
@ -522,85 +523,23 @@ ParseMF(const char* filebuf, nsIZipReader * zip,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct VerifyCertificateContext {
|
||||
AppTrustedRoot trustedRoot;
|
||||
mozilla::pkix::ScopedCERTCertList& builtChain;
|
||||
};
|
||||
|
||||
nsresult
|
||||
VerifySignature(AppTrustedRoot trustedRoot,
|
||||
const SECItem& buffer, const SECItem& detachedDigest,
|
||||
/*out*/ mozilla::pkix::ScopedCERTCertList& builtChain)
|
||||
VerifyCertificate(CERTCertificate* signerCert, void* voidContext, void* pinArg)
|
||||
{
|
||||
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;
|
||||
// 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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(),
|
||||
@ -608,21 +547,23 @@ VerifySignature(AppTrustedRoot trustedRoot,
|
||||
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
|
||||
|
@ -32,7 +32,6 @@ XPIDL_SOURCES += [
|
||||
'nsIPKCS11Slot.idl',
|
||||
'nsIProtectedAuthThread.idl',
|
||||
'nsIRecentBadCertsService.idl',
|
||||
'nsISignatureVerifier.idl',
|
||||
'nsISSLErrorListener.idl',
|
||||
'nsISSLStatus.idl',
|
||||
'nsIStreamCipher.idl',
|
||||
|
@ -5,11 +5,14 @@
|
||||
|
||||
#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
|
||||
{
|
||||
/**
|
||||
@ -23,4 +26,16 @@ interface nsIDataSignatureVerifier : nsISupports
|
||||
* @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);
|
||||
|
||||
};
|
||||
|
@ -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"
|
||||
%}
|
@ -3,14 +3,22 @@
|
||||
* 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 "nssb64.h"
|
||||
#include "certt.h"
|
||||
#include "keyhi.h"
|
||||
#include "cms.h"
|
||||
#include "cryptohi.h"
|
||||
#include "keyhi.h"
|
||||
#include "nsCertificatePrincipal.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsNSSComponent.h"
|
||||
#include "nssb64.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)
|
||||
|
||||
@ -104,3 +112,221 @@ nsDataSignatureVerifier::VerifyData(const nsACString & aData,
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "keythi.h"
|
||||
|
||||
typedef struct CERTCertificateStr CERTCertificate;
|
||||
|
||||
// 296d76aa-275b-4f3c-af8a-30a4026c18fc
|
||||
#define NS_DATASIGNATUREVERIFIER_CID \
|
||||
{ 0x296d76aa, 0x275b, 0x4f3c, \
|
||||
@ -33,4 +35,14 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
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_
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "nsIDOMSmartCardEvent.h"
|
||||
#include "nsSmartCardMonitor.h"
|
||||
#include "nsIDOMCryptoLegacy.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#else
|
||||
#include "nsIDOMCrypto.h"
|
||||
#endif
|
||||
@ -44,7 +43,6 @@
|
||||
#include "nsIProperties.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsCertificatePrincipal.h"
|
||||
#include "nsIBufEntropyCollector.h"
|
||||
#include "nsITokenPasswordDialogs.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
@ -57,7 +55,6 @@
|
||||
#include "ssl.h"
|
||||
#include "sslproto.h"
|
||||
#include "secmod.h"
|
||||
#include "secmime.h"
|
||||
#include "secerr.h"
|
||||
#include "sslerr.h"
|
||||
|
||||
@ -1357,141 +1354,11 @@ nsNSSComponent::Init()
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISignatureVerifier.h"
|
||||
#include "nsIEntropyCollector.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIObserver.h"
|
||||
@ -113,8 +112,7 @@ 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
|
||||
@ -127,7 +125,6 @@ public:
|
||||
nsNSSComponent();
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSISIGNATUREVERIFIER
|
||||
NS_DECL_NSIENTROPYCOLLECTOR
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user