Bug 1753071 - Add a "confirm revocations" mode to CRLite. r=keeler

Differential Revision: https://phabricator.services.mozilla.com/D137553
This commit is contained in:
John Schanck 2022-02-14 18:55:21 +00:00
Родитель 5043e17baf
Коммит 2654fbb629
6 изменённых файлов: 119 добавлений и 7 удалений

Просмотреть файл

@ -156,9 +156,10 @@ pref("security.webauth.webauthn_enable_softtoken", false);
pref("security.xfocsp.errorReporting.enabled", true);
pref("security.xfocsp.errorReporting.automatic", false);
// 0: Disable CRLite entirely
// 1: Enable and check revocations via CRLite, but only collect telemetry
// 2: Enable and enforce revocations via CRLite
// 0: Disable CRLite entirely.
// 1: Consult CRLite but only collect telemetry.
// 2: Consult CRLite and enforce both "Revoked" and "Not Revoked" results.
// 3: Consult CRLite and enforce "Not Revoked" results, but defer to OCSP for "Revoked".
pref("security.pki.crlite_mode", 1);
// Issuer we use to detect MitM proxies. Set to the issuer of the cert of the

Просмотреть файл

@ -76,6 +76,7 @@ enum class CRLiteMode {
Disabled = 0,
TelemetryOnly = 1,
Enforce = 2,
ConfirmRevocations = 3,
};
enum class NetscapeStepUpPolicy : uint32_t;

Просмотреть файл

@ -757,10 +757,16 @@ Result NSSCertDBTrustDomain::CheckRevocation(
crliteResult != Result::ERROR_REVOKED_CERTIFICATE) {
return crliteResult;
}
// Always return the result of CheckCRLite if CRLite is being enforced and
// the certificate is covered by the CRLite filter.
if (mCRLiteMode == CRLiteMode::Enforce && crliteFilterCoversCertificate) {
return crliteResult;
if (crliteFilterCoversCertificate) {
// If we don't return here we will consult OCSP.
// In CRLiteMode::Enforce we can return "Revoked" or "Not Revoked"
// without consulting OCSP. In CRLiteMode::ConfirmRevocations we can
// only return "Not Revoked" without consulting OCSP.
if (mCRLiteMode == CRLiteMode::Enforce ||
(mCRLiteMode == CRLiteMode::ConfirmRevocations &&
crliteResult == Success)) {
return crliteResult;
}
}
}
}

Просмотреть файл

@ -1541,6 +1541,7 @@ void nsNSSComponent::setValidationOptions(
case CRLiteMode::Disabled:
case CRLiteMode::TelemetryOnly:
case CRLiteMode::Enforce:
case CRLiteMode::ConfirmRevocations:
break;
default:
crliteMode = defaultCRLiteMode;

Просмотреть файл

@ -129,6 +129,7 @@ const NO_FLAGS = 0;
const CRLiteModeDisabledPrefValue = 0;
const CRLiteModeTelemetryOnlyPrefValue = 1;
const CRLiteModeEnforcePrefValue = 2;
const CRLiteModeConfirmRevocationsValue = 3;
// Convert a string to an array of bytes consisting of the char code at each
// index.

Просмотреть файл

@ -366,6 +366,108 @@ function getCRLiteEnrollmentRecordFor(nsCert) {
};
}
add_task(async function test_crlite_confirm_revocations_mode() {
Services.prefs.setBoolPref(CRLITE_FILTERS_ENABLED_PREF, true);
Services.prefs.setIntPref(
"security.pki.crlite_mode",
CRLiteModeConfirmRevocationsValue
);
Services.prefs.setBoolPref(INTERMEDIATES_ENABLED_PREF, true);
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
let issuerCert = constructCertFromFile("test_crlite_filters/issuer.pem");
let noSCTCertIssuer = constructCertFromFile(
"test_crlite_filters/no-sct-issuer.pem"
);
let crliteEnrollmentRecords = [
getCRLiteEnrollmentRecordFor(issuerCert),
getCRLiteEnrollmentRecordFor(noSCTCertIssuer),
];
await IntermediatePreloadsClient.onSync({
data: {
current: crliteEnrollmentRecords,
created: crliteEnrollmentRecords,
updated: [],
deleted: [],
},
});
let result = await syncAndDownload([
{
timestamp: "2020-10-17T00:00:00Z",
type: "full",
id: "0000",
coverage: [
{
logID: "9lyUL9F3MCIUVBgIMJRWjuNNExkzv98MLyALzE7xZOM=",
minTimestamp: 0,
maxTimestamp: 9999999999999,
},
{
logID: "pLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BA=",
minTimestamp: 0,
maxTimestamp: 9999999999999,
},
],
},
]);
equal(
result,
"finished;2020-10-17T00:00:00Z-full",
"CRLite filter download should have run"
);
// The CRLite result should be enforced for this certificate and
// OCSP should not be consulted.
let validCert = constructCertFromFile("test_crlite_filters/valid.pem");
await checkCertErrorGenericAtTime(
certdb,
validCert,
PRErrorCodeSuccess,
certificateUsageSSLServer,
new Date("2020-10-20T00:00:00Z").getTime() / 1000,
undefined,
"vpn.worldofspeed.org",
0
);
// OCSP should be consulted for this certificate, but OCSP is disabled by
// Ci.nsIX509CertDB.FLAG_LOCAL_ONLY so this will return Success.
let revokedCert = constructCertFromFile("test_crlite_filters/revoked.pem");
await checkCertErrorGenericAtTime(
certdb,
revokedCert,
PRErrorCodeSuccess,
certificateUsageSSLServer,
new Date("2020-10-20T00:00:00Z").getTime() / 1000,
undefined,
"us-datarecovery.com",
Ci.nsIX509CertDB.FLAG_LOCAL_ONLY
);
// Switch back to enforcement to confirm that it was the security.pki.crlite_mode
// that caused us to return Success for revokedCert.
Services.prefs.setIntPref(
"security.pki.crlite_mode",
CRLiteModeEnforcePrefValue
);
await checkCertErrorGenericAtTime(
certdb,
revokedCert,
SEC_ERROR_REVOKED_CERTIFICATE,
certificateUsageSSLServer,
new Date("2020-10-20T00:00:00Z").getTime() / 1000,
undefined,
"us-datarecovery.com",
0
);
});
add_task(async function test_crlite_filters_and_check_revocation() {
Services.prefs.setBoolPref(CRLITE_FILTERS_ENABLED_PREF, true);
Services.prefs.setIntPref(