// Perform a hash of the provided cert, then search in the RootHashes.inc data // structure for a matching bin number. int32_t RootCABinNumber(const SECItem* cert) { Digest digest; // Compute SHA256 hash of the certificate nsresult rv = digest.DigestBuf(SEC_OID_SHA256, cert->data, cert->len); if (NS_WARN_IF(NS_FAILED(rv))) { return HASH_FAILURE; } // Compare against list of stored hashes size_t idx; PR_LOG(PublicKeyPinningTelemetryLog(), PR_LOG_DEBUG, ("pkpinTelem: First bytes %02hx %02hx %02hx %02hx\n", digest.get().data[0], digest.get().data[1], digest.get().data[2], digest.get().data[3])); if (mozilla::BinarySearchIf(ROOT_TABLE, 0, ArrayLength(ROOT_TABLE), BinaryHashSearchArrayComparator( reinterpret_cast<const uint8_t*>(digest.get().data), digest.get().len), &idx)) { PR_LOG(PublicKeyPinningTelemetryLog(), PR_LOG_DEBUG, ("pkpinTelem: Telemetry index was %lu, bin is %d\n", idx, ROOT_TABLE[idx].binNumber)); return (int32_t) ROOT_TABLE[idx].binNumber; } // Didn't match. return UNKNOWN_ROOT; }
// Perform a hash of the provided cert, then search in the RootHashes.inc data // structure for a matching bin number. int32_t RootCABinNumber(const SECItem* cert) { Digest digest; // Compute SHA256 hash of the certificate nsresult rv = digest.DigestBuf(SEC_OID_SHA256, cert->data, cert->len); if (NS_WARN_IF(NS_FAILED(rv))) { return ROOT_CERTIFICATE_HASH_FAILURE; } // Compare against list of stored hashes size_t idx; MOZ_LOG(gPublicKeyPinningTelemetryLog, LogLevel::Debug, ("pkpinTelem: First bytes %02x %02x %02x %02x\n", digest.get().data[0], digest.get().data[1], digest.get().data[2], digest.get().data[3])); if (mozilla::BinarySearchIf(ROOT_TABLE, 0, ArrayLength(ROOT_TABLE), BinaryHashSearchArrayComparator(static_cast<uint8_t*>(digest.get().data), digest.get().len), &idx)) { MOZ_LOG(gPublicKeyPinningTelemetryLog, LogLevel::Debug, ("pkpinTelem: Telemetry index was %" PRIuSIZE ", bin is %d\n", idx, ROOT_TABLE[idx].binNumber)); return (int32_t) ROOT_TABLE[idx].binNumber; } // Didn't match. return ROOT_CERTIFICATE_UNKNOWN; }
nsresult nsNSSCertificate::GetCertificateHash(nsAString& aFingerprint, SECOidTag aHashAlg) { nsNSSShutDownPreventionLock locker; if (isAlreadyShutDown()) { return NS_ERROR_NOT_AVAILABLE; } aFingerprint.Truncate(); Digest digest; nsresult rv = digest.DigestBuf(aHashAlg, mCert->derCert.data, mCert->derCert.len); if (NS_FAILED(rv)) { return rv; } // CERT_Hexify's second argument is an int that is interpreted as a boolean char* fpStr = CERT_Hexify(const_cast<SECItem*>(&digest.get()), 1); if (!fpStr) { return NS_ERROR_FAILURE; } aFingerprint.AssignASCII(fpStr); PORT_Free(fpStr); return NS_OK; }
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; }
/** Computes in the location specified by base64Out the SHA256 digest of the DER Encoded subject Public Key Info for the given cert */ static nsresult GetBase64HashSPKI(const CERTCertificate* cert, nsACString& hashSPKIDigest) { hashSPKIDigest.Truncate(); Digest digest; nsresult rv = digest.DigestBuf(SEC_OID_SHA256, cert->derPublicKey.data, cert->derPublicKey.len); if (NS_FAILED(rv)) { return rv; } return Base64Encode(nsDependentCSubstring( reinterpret_cast<const char*>(digest.get().data), digest.get().len), hashSPKIDigest); }
/** Computes in the location specified by base64Out the SHA256 digest of the DER Encoded subject Public Key Info for the given cert */ static SECStatus GetBase64SHA256SPKI(const CERTCertificate* cert, nsACString& aSha256SPKIDigest){ aSha256SPKIDigest.Truncate(); Digest digest; nsresult rv = digest.DigestBuf(SEC_OID_SHA256, cert->derPublicKey.data, cert->derPublicKey.len); if (NS_WARN_IF(NS_FAILED(rv))) { return SECFailure; } rv = Base64Encode(nsDependentCSubstring( reinterpret_cast<const char*>(digest.get().data), digest.get().len), aSha256SPKIDigest); if (NS_WARN_IF(NS_FAILED(rv))) { return SECFailure; } return SECSuccess; }
NS_IMETHODIMP nsNSSCertificate::GetSha256SubjectPublicKeyInfoDigest(nsACString& aSha256SPKIDigest) { nsNSSShutDownPreventionLock locker; if (isAlreadyShutDown()) { return NS_ERROR_NOT_AVAILABLE; } aSha256SPKIDigest.Truncate(); Digest digest; nsresult rv = digest.DigestBuf(SEC_OID_SHA256, mCert->derPublicKey.data, mCert->derPublicKey.len); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } rv = Base64Encode(nsDependentCSubstring( reinterpret_cast<const char*> (digest.get().data), digest.get().len), aSha256SPKIDigest); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } return NS_OK; }