Bug 1492414 - Modify CertBlocklist interface to a form that should work with Rust XPCom bindings r=keeler

Differential Revision: https://phabricator.services.mozilla.com/D6260

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Mark Goodwin 2018-09-21 13:10:40 +00:00
parent 6d86e85fe6
commit 41b314b255
6 changed files with 150 additions and 85 deletions

View File

@ -206,16 +206,20 @@ NSSCertDBTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
// certificates.
if (mCertDBTrustType == trustSSL) {
bool isCertRevoked;
nsresult nsrv = mCertBlocklist->IsCertRevoked(
candidateCert->derIssuer.data,
candidateCert->derIssuer.len,
candidateCert->serialNumber.data,
candidateCert->serialNumber.len,
candidateCert->derSubject.data,
candidateCert->derSubject.len,
candidateCert->derPublicKey.data,
candidateCert->derPublicKey.len,
&isCertRevoked);
nsAutoCString encIssuer;
nsAutoCString encSerial;
nsAutoCString encSubject;
nsAutoCString encPubKey;
nsresult nsrv = BuildRevocationCheckStrings(candidateCert.get(), encIssuer, encSerial, encSubject, encPubKey);
if (NS_FAILED(nsrv)) {
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}
nsrv = mCertBlocklist->IsCertRevoked(
encIssuer, encSerial, encSubject, encPubKey, &isCertRevoked);
if (NS_FAILED(nsrv)) {
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}
@ -1285,6 +1289,47 @@ DefaultServerNicknameForCert(const CERTCertificate* cert,
return NS_ERROR_FAILURE;
}
nsresult
BuildRevocationCheckStrings(const CERTCertificate* cert,
/*out*/ nsCString& encIssuer,
/*out*/ nsCString& encSerial,
/*out*/ nsCString& encSubject,
/*out*/ nsCString& encPubKey)
{
// Convert issuer, serial, subject and pubKey data to Base64 encoded DER
nsDependentCSubstring issuerString(
BitwiseCast<char*, uint8_t*>(cert->derIssuer.data),
cert->derIssuer.len);
nsDependentCSubstring serialString(
BitwiseCast<char*, uint8_t*>(cert->serialNumber.data),
cert->serialNumber.len);
nsDependentCSubstring subjectString(
BitwiseCast<char*, uint8_t*>(cert->derSubject.data),
cert->derSubject.len);
nsDependentCSubstring pubKeyString(
BitwiseCast<char*, uint8_t*>(cert->derPublicKey.data),
cert->derPublicKey.len);
nsresult rv = Base64Encode(issuerString, encIssuer);
if (NS_FAILED(rv)) {
return rv;
}
rv = Base64Encode(serialString, encSerial);
if (NS_FAILED(rv)) {
return rv;
}
rv = Base64Encode(subjectString, encSubject);
if (NS_FAILED(rv)) {
return rv;
}
rv = Base64Encode(pubKeyString, encPubKey);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
/**
* Given a list of certificates representing a verified certificate path from an
* end-entity certificate to a trust anchor, imports the intermediate

View File

@ -58,6 +58,30 @@ void UnloadLoadableRoots();
nsresult DefaultServerNicknameForCert(const CERTCertificate* cert,
/*out*/ nsCString& nickname);
/**
* Build strings of base64 encoded issuer, serial, subject and public key data
* from the supplied certificate for use in revocation checks.
*
* @param cert
* The CERTCertificate* from which to extract the data.
* @param out encIssuer
* The string to populate with base64 encoded issuer data.
* @param out encSerial
* The string to populate with base64 encoded serial number data.
* @param out encSubject
* The string to populate with base64 encoded subject data.
* @param out encPubKey
* The string to populate with base64 encoded public key data.
* @return
* NS_OK, unless there's a Base64 encoding problem, in which case
* NS_ERROR_FAILURE.
*/
nsresult BuildRevocationCheckStrings(const CERTCertificate* cert,
/*out*/ nsCString& encIssuer,
/*out*/ nsCString& encSerial,
/*out*/ nsCString& encSubject,
/*out*/ nsCString& encPubKey);
void SaveIntermediateCerts(const UniqueCERTCertList& certList);
class NSSCertDBTrustDomain : public mozilla::pkix::TrustDomain

View File

@ -9,6 +9,7 @@
#include "mozilla/Preferences.h"
#include "nsNSSCertificate.h"
#include "nsNSSComponent.h"
#include "NSSCertDBTrustDomain.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "pkix/pkixnss.h"
@ -44,17 +45,19 @@ CSTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
return MapPRErrorCodeToResult(PR_GetError());
}
nsAutoCString encIssuer;
nsAutoCString encSerial;
nsAutoCString encSubject;
nsAutoCString encPubKey;
nsresult nsrv = BuildRevocationCheckStrings(candidateCert.get(), encIssuer, encSerial, encSubject, encPubKey);
if (NS_FAILED(nsrv)) {
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}
bool isCertRevoked;
nsresult nsrv = mCertBlocklist->IsCertRevoked(
candidateCert->derIssuer.data,
candidateCert->derIssuer.len,
candidateCert->serialNumber.data,
candidateCert->serialNumber.len,
candidateCert->derSubject.data,
candidateCert->derSubject.len,
candidateCert->derPublicKey.data,
candidateCert->derPublicKey.len,
&isCertRevoked);
nsrv = mCertBlocklist->IsCertRevoked(
encIssuer, encSerial, encSubject, encPubKey, &isCertRevoked);
if (NS_FAILED(nsrv)) {
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}

View File

@ -508,48 +508,54 @@ CertBlocklist::SaveEntries()
}
NS_IMETHODIMP
CertBlocklist::IsCertRevoked(const uint8_t* aIssuer,
uint32_t aIssuerLength,
const uint8_t* aSerial,
uint32_t aSerialLength,
const uint8_t* aSubject,
uint32_t aSubjectLength,
const uint8_t* aPubKey,
uint32_t aPubKeyLength,
CertBlocklist::IsCertRevoked(const nsACString& aIssuerString,
const nsACString& aSerialNumberString,
const nsACString& aSubjectString,
const nsACString& aPubKeyString,
bool* _retval)
{
MutexAutoLock lock(mMutex);
MOZ_LOG(gCertBlockPRLog, LogLevel::Warning, ("CertBlocklist::IsCertRevoked"));
MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
("CertBlocklist::IsCertRevoked?"));
nsresult rv = EnsureBackingFileInitialized(lock);
nsCString decodedIssuer;
nsCString decodedSerial;
nsCString decodedSubject;
nsCString decodedPubKey;
nsresult rv = Base64Decode(aIssuerString, decodedIssuer);
if (NS_FAILED(rv)) {
return rv;
}
rv = Base64Decode(aSerialNumberString, decodedSerial);
if (NS_FAILED(rv)) {
return rv;
}
rv = Base64Decode(aSubjectString, decodedSubject);
if (NS_FAILED(rv)) {
return rv;
}
rv = Base64Decode(aPubKeyString, decodedPubKey);
if (NS_FAILED(rv)) {
return rv;
}
Input issuer;
Input serial;
if (issuer.Init(aIssuer, aIssuerLength) != Success) {
return NS_ERROR_FAILURE;
}
if (serial.Init(aSerial, aSerialLength) != Success) {
return NS_ERROR_FAILURE;
}
CertBlocklistItem issuerSerial(aIssuer, aIssuerLength, aSerial, aSerialLength,
BlockByIssuerAndSerial);
nsAutoCString encDN;
nsAutoCString encOther;
issuerSerial.ToBase64(encDN, encOther);
rv = EnsureBackingFileInitialized(lock);
if (NS_FAILED(rv)) {
return rv;
}
MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
CertBlocklistItem issuerSerial(
BitwiseCast<const uint8_t*, const char*>(decodedIssuer.get()),
decodedIssuer.Length(),
BitwiseCast<const uint8_t*, const char*>(decodedSerial.get()),
decodedSerial.Length(),
BlockByIssuerAndSerial);
MOZ_LOG(gCertBlockPRLog,
LogLevel::Warning,
("CertBlocklist::IsCertRevoked issuer %s - serial %s",
encDN.get(), encOther.get()));
PromiseFlatCString(aIssuerString).get(),
PromiseFlatCString(aSerialNumberString).get()));
*_retval = mBlocklist.Contains(issuerSerial);
@ -567,7 +573,9 @@ CertBlocklist::IsCertRevoked(const uint8_t* aIssuer,
return rv;
}
rv = crypto->Update(aPubKey, aPubKeyLength);
rv = crypto->Update(
BitwiseCast<const uint8_t*, const char*>(decodedPubKey.get()),
decodedPubKey.Length());
if (NS_FAILED(rv)) {
return rv;
}
@ -579,20 +587,24 @@ CertBlocklist::IsCertRevoked(const uint8_t* aIssuer,
}
CertBlocklistItem subjectPubKey(
aSubject,
static_cast<size_t>(aSubjectLength),
BitwiseCast<const uint8_t*, const char*>(decodedSubject.get()),
decodedSubject.Length(),
BitwiseCast<const uint8_t*, const char*>(hashString.get()),
hashString.Length(),
BlockBySubjectAndPubKey);
rv = subjectPubKey.ToBase64(encDN, encOther);
nsCString encodedHash;
rv = Base64Encode(hashString, encodedHash);
if (NS_FAILED(rv)) {
return rv;
}
MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,
("CertBlocklist::IsCertRevoked subject %s - pubKey hash %s",
encDN.get(), encOther.get()));
MOZ_LOG(gCertBlockPRLog,
LogLevel::Warning,
("CertBlocklist::IsCertRevoked subject %s - pubKeyHash %s (pubKey %s)",
PromiseFlatCString(aSubjectString).get(),
PromiseFlatCString(encodedHash).get(),
PromiseFlatCString(aPubKeyString).get()));
*_retval = mBlocklist.Contains(subjectPubKey);
MOZ_LOG(gCertBlockPRLog, LogLevel::Warning,

View File

@ -42,20 +42,16 @@ interface nsICertBlocklist : nsISupports {
/**
* Check if a certificate is blocked.
* issuer - issuer name, DER encoded
* serial - serial number, DER encoded
* subject - subject name, DER encoded
* pubkey - public key, DER encoded
* issuer - issuer name, DER, Base64 encoded
* serial - serial number, DER, BAse64 encoded
* subject - subject name, DER, Base64 encoded
* pubkey - public key, DER, Base64 encoded
*/
[must_use]
boolean isCertRevoked([const, array, size_is(issuer_length)] in octet issuer,
in unsigned long issuer_length,
[const, array, size_is(serial_length)] in octet serial,
in unsigned long serial_length,
[const, array, size_is(subject_length)] in octet subject,
in unsigned long subject_length,
[const, array, size_is(pubkey_length)] in octet pubkey,
in unsigned long pubkey_length);
boolean isCertRevoked(in ACString issuer,
in ACString serial,
in ACString subject,
in ACString pubkey);
/**
* Check that the blocklist data is current. Specifically, that the current

View File

@ -162,10 +162,6 @@ var addonManager = Cc["@mozilla.org/addons/integration;1"]
.QueryInterface(Ci.nsITimerCallback);
addonManager.observe(null, "addons-startup", null);
var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
function verify_cert(file, expectedError) {
let ee = constructCertFromFile(file);
return checkCertErrorGeneric(certDB, ee, expectedError,
@ -190,19 +186,8 @@ function load_cert(cert, trust) {
function test_is_revoked(certList, issuerString, serialString, subjectString,
pubKeyString) {
let issuer = converter.convertToByteArray(issuerString || "", {});
let serial = converter.convertToByteArray(serialString || "", {});
let subject = converter.convertToByteArray(subjectString || "", {});
let pubKey = converter.convertToByteArray(pubKeyString || "", {});
return certList.isCertRevoked(issuer,
issuerString ? issuerString.length : 0,
serial,
serialString ? serialString.length : 0,
subject,
subjectString ? subjectString.length : 0,
pubKey,
pubKeyString ? pubKeyString.length : 0);
return certList.isCertRevoked(btoa(issuerString), btoa(serialString),
btoa(subjectString), btoa(pubKeyString));
}
function fetch_blocklist() {