Bug 1640316 - Add tests for corrupted CRLite information. r=keeler

Differential Revision: https://phabricator.services.mozilla.com/D136284
This commit is contained in:
John Schanck 2022-01-20 18:09:24 +00:00
Родитель 211bff8723
Коммит a60cfaa300
15 изменённых файлов: 340 добавлений и 0 удалений

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

@ -0,0 +1,116 @@
// -*- indent-tabs-mode: nil; js-indent-level: 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/.
// Helper file for tests that initialize CRLite with corrupted `security_state`
// files.
//
// Usage:
// Define nsILocalFile variables for the `crlite.filter`, `crlite.coverage`,
// and `data.safe.bin` files that should be copied to the new profile, and
// then load this file. The variables should be called `filter`, `coverage`,
// and `enrollment`, respectively. To omit a file, leave the corresponding
// variable `undefined`.
//
// Example:
// let filter = do_get_file("some_test_dir/crlite.filter");
// let coverage = undefined;
// let enrollment = do_get_file("some_test_dir/data.safe.bin");
// load("./corrupted_crlite_helper.js");
//
// Note:
// The cert_storage library only attempts to read security_state once. So
// this task can only be included once per test file.
"use strict";
/* eslint-disable no-undef */
add_task(async function test_crlite_corrupted() {
let securityStateDirectory = do_get_profile();
securityStateDirectory.append("security_state");
Services.prefs.setIntPref(
"security.pki.crlite_mode",
CRLiteModeEnforcePrefValue
);
if (coverage != undefined) {
coverage.copyTo(securityStateDirectory, "crlite.coverage");
}
if (enrollment != undefined) {
enrollment.copyTo(securityStateDirectory, "data.safe.bin");
}
if (filter != undefined) {
filter.copyTo(securityStateDirectory, "crlite.filter");
}
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
let certStorage = Cc["@mozilla.org/security/certstorage;1"].getService(
Ci.nsICertStorage
);
// This certificate is revoked according to `test_crlite_filters/20201017-0-filter`.
// Its issuer is enrolled according to `test_crlite_preexisting/data.safe.bin`,
// and it is covered according to `test_crlite_preexisting/crlite.coverage`.
let revokedCert = constructCertFromFile("test_crlite_filters/revoked.pem");
// The issuer's certificate needs to be available for path building.
let issuerCert = constructCertFromFile("test_crlite_filters/issuer.pem");
ok(issuerCert, "issuer certificate should decode successfully");
// If we copied a corrupted file to security_state, then CRLite should not be
// initialized, and we should fall back to OCSP. By setting
// Ci.nsIX509CertDB.FLAG_LOCAL_ONLY here we skip the OCSP test, so there's no
// revocation checking, and the revoked certificate should pass inspection.
await checkCertErrorGenericAtTime(
certdb,
revokedCert,
PRErrorCodeSuccess,
certificateUsageSSLServer,
new Date("2020-10-20T00:00:00Z").getTime() / 1000,
undefined,
"us-datarecovery.com",
Ci.nsIX509CertDB.FLAG_LOCAL_ONLY
);
// The attempted revocation check should have at least partially initialized
// CRLite. We should have a database (an empty one is created if
// `data.safe.bin` is corrupted). But we should not have a filter or a stash.
let hasDB = await new Promise(resolve => {
certStorage.hasPriorData(
Ci.nsICertStorage.DATA_TYPE_CRLITE,
(rv, result) => {
Assert.equal(rv, Cr.NS_OK, "hasPriorData should succeed");
resolve(result);
}
);
});
Assert.equal(hasDB, true, "CRLite should have a database");
let hasFilter = await new Promise(resolve => {
certStorage.hasPriorData(
Ci.nsICertStorage.DATA_TYPE_CRLITE_FILTER_FULL,
(rv, result) => {
Assert.equal(rv, Cr.NS_OK, "hasPriorData should succeed");
resolve(result);
}
);
});
Assert.equal(hasFilter, false, "CRLite should not have a filter");
let hasStash = await new Promise(resolve => {
certStorage.hasPriorData(
Ci.nsICertStorage.DATA_TYPE_CRLITE_FILTER_INCREMENTAL,
(rv, result) => {
Assert.equal(rv, Cr.NS_OK, "hasPriorData should succeed");
resolve(result);
}
);
});
Assert.equal(hasStash, false, "CRLite should not have a stash");
});

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

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>

Двоичный файл не отображается.

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

@ -0,0 +1,2 @@



Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичный файл не отображается.

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

@ -0,0 +1,17 @@
// -*- indent-tabs-mode: nil; js-indent-level: 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/.
// Tests that CRLite is left in the uninitialized state when the profile
// contains a corrupted coverage file. Specifically, this handles the case
// where the coverage file is missing.
"use strict";
/* eslint-disable no-unused-vars */
let coverage = undefined;
let enrollment = do_get_file("test_crlite_preexisting/data.safe.bin");
let filter = do_get_file("test_crlite_filters/20201017-0-filter");
load("./corrupted_crlite_helper.js");

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

@ -0,0 +1,17 @@
// -*- indent-tabs-mode: nil; js-indent-level: 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/.
// Tests that CRLite is left in the uninitialized state when the profile
// contains a corrupted coverage file. Specifically, this handles the case
// where the coverage file is truncated in a LogID field.
"use strict";
/* eslint-disable no-unused-vars */
let coverage = do_get_file("test_crlite_corrupted/trunc-log-id.coverage");
let enrollment = do_get_file("test_crlite_preexisting/data.safe.bin");
let filter = do_get_file("test_crlite_filters/20201017-0-filter");
load("./corrupted_crlite_helper.js");

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

@ -0,0 +1,19 @@
// -*- indent-tabs-mode: nil; js-indent-level: 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/.
// Tests that CRLite is left in the uninitialized state when the profile
// contains a corrupted coverage file. Specifically, this handles the case
// where the coverage file is truncated in a MinTimestamp field.
"use strict";
/* eslint-disable no-unused-vars */
let coverage = do_get_file(
"test_crlite_corrupted/trunc-min-timestamp.coverage"
);
let enrollment = do_get_file("test_crlite_preexisting/data.safe.bin");
let filter = do_get_file("test_crlite_filters/20201017-0-filter");
load("./corrupted_crlite_helper.js");

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

@ -0,0 +1,19 @@
// -*- indent-tabs-mode: nil; js-indent-level: 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/.
// Tests that CRLite is left in the uninitialized state when the profile
// contains a corrupted coverage file. Specifically, this handles the case
// where the coverage file is truncated in a MaxTimestamp field.
"use strict";
/* eslint-disable no-unused-vars */
let coverage = do_get_file(
"test_crlite_corrupted/trunc-max-timestamp.coverage"
);
let enrollment = do_get_file("test_crlite_preexisting/data.safe.bin");
let filter = do_get_file("test_crlite_filters/20201017-0-filter");
load("./corrupted_crlite_helper.js");

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

@ -0,0 +1,17 @@
// -*- indent-tabs-mode: nil; js-indent-level: 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/.
// Tests that CRLite is left in the uninitialized state when the profile
// contains a corrupted coverage file. Specifically, this handles the case
// where the coverage file's version is not recognized.
"use strict";
/* eslint-disable no-unused-vars */
let coverage = do_get_file("test_crlite_corrupted/version-0.coverage");
let enrollment = do_get_file("test_crlite_preexisting/data.safe.bin");
let filter = do_get_file("test_crlite_filters/20201017-0-filter");
load("./corrupted_crlite_helper.js");

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

@ -0,0 +1,21 @@
// -*- indent-tabs-mode: nil; js-indent-level: 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/.
// Tests that CRLite is left in the uninitialized state when the profile
// contains a corrupted filter file.
//
// There are many ways that a filter file could be corrupted, but the parsing
// is done in rust-cascade, not cert_storage, so it is sufficient for us to
// test any form of corruption here. For simplicity we just try to load a
// single \x00 byte as the filter.
"use strict";
/* eslint-disable no-unused-vars */
let coverage = do_get_file("test_crlite_preexisting/crlite.coverage");
let enrollment = do_get_file("test_crlite_preexisting/data.safe.bin");
let filter = do_get_file("test_crlite_corrupted/hash-alg-0.filter");
load("./corrupted_crlite_helper.js");

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

@ -0,0 +1,102 @@
// -*- indent-tabs-mode: nil; js-indent-level: 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/.
// Tests that CRLite is left in the uninitialized state when the profile
// contains a corrupted stash file.
"use strict";
add_task(async function test_crlite_stash_corrupted() {
let securityStateDirectory = do_get_profile();
securityStateDirectory.append("security_state");
Services.prefs.setIntPref(
"security.pki.crlite_mode",
CRLiteModeEnforcePrefValue
);
let coverage = do_get_file("test_crlite_preexisting/crlite.coverage");
coverage.copyTo(securityStateDirectory, "crlite.coverage");
let enrollment = do_get_file("test_crlite_preexisting/data.safe.bin");
enrollment.copyTo(securityStateDirectory, "data.safe.bin");
let filter = do_get_file("test_crlite_filters/20201017-0-filter");
filter.copyTo(securityStateDirectory, "crlite.filter");
let stash = do_get_file("test_crlite_corrupted/bad.stash");
stash.copyTo(securityStateDirectory, "crlite.stash");
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
let certStorage = Cc["@mozilla.org/security/certstorage;1"].getService(
Ci.nsICertStorage
);
// Await a task that ensures the stash loading task has completed.
await new Promise(resolve => {
certStorage.hasPriorData(Ci.nsICertStorage.DATA_TYPE_CRLITE, (rv, _) => {
Assert.equal(rv, Cr.NS_OK, "hasPriorData should succeed");
resolve();
});
});
// This certificate is revoked according to `test_crlite_filters/20201017-0-filter`.
// Its issuer is enrolled according to `test_crlite_preexisting/data.safe.bin`,
// and it is covered according to `test_crlite_preexisting/crlite.coverage`.
let revokedCert = constructCertFromFile("test_crlite_filters/revoked.pem");
// The issuer's certificate needs to be available for path building.
let issuerCert = constructCertFromFile("test_crlite_filters/issuer.pem");
ok(issuerCert, "issuer certificate should decode successfully");
// Loading the stash should not have caused any problems, and `revokedCert`
// should be marked as revoked.
await checkCertErrorGenericAtTime(
certdb,
revokedCert,
SEC_ERROR_REVOKED_CERTIFICATE,
certificateUsageSSLServer,
new Date("2020-10-20T00:00:00Z").getTime() / 1000,
undefined,
"us-datarecovery.com",
0
);
let hasDB = await new Promise(resolve => {
certStorage.hasPriorData(
Ci.nsICertStorage.DATA_TYPE_CRLITE,
(rv, result) => {
Assert.equal(rv, Cr.NS_OK, "hasPriorData should succeed");
resolve(result);
}
);
});
Assert.equal(hasDB, true, "CRLite should have a database");
let hasFilter = await new Promise(resolve => {
certStorage.hasPriorData(
Ci.nsICertStorage.DATA_TYPE_CRLITE_FILTER_FULL,
(rv, result) => {
Assert.equal(rv, Cr.NS_OK, "hasPriorData should succeed");
resolve(result);
}
);
});
Assert.equal(hasFilter, true, "CRLite should have a filter");
let hasStash = await new Promise(resolve => {
certStorage.hasPriorData(
Ci.nsICertStorage.DATA_TYPE_CRLITE_FILTER_INCREMENTAL,
(rv, result) => {
Assert.equal(rv, Cr.NS_OK, "hasPriorData should succeed");
resolve(result);
}
);
});
Assert.equal(hasStash, false, "CRLite should not have a stash");
});

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

@ -3,6 +3,7 @@ head = head_psm.js
tags = psm
firefox-appdir = browser
support-files =
corrupted_crlite_helper.js
bad_certs/**
ocsp_certs/**
test_baseline_requirements/**
@ -24,6 +25,7 @@ support-files =
test_content_signing/**
test_crlite_filters/**
test_crlite_preexisting/**
test_crlite_corrupted/**
test_ct/**
test_delegated_credentials/**
test_encrypted_client_hello/**
@ -102,6 +104,13 @@ skip-if = toolkit == 'android' && processor == 'x86_64'
[test_crlite_filters.js]
tags = remote-settings psm
[test_crlite_preexisting.js]
[test_crlite_filter_corrupted.js]
[test_crlite_stash_corrupted.js]
[test_crlite_coverage_version.js]
[test_crlite_coverage_trunc1.js]
[test_crlite_coverage_trunc2.js]
[test_crlite_coverage_trunc3.js]
[test_crlite_coverage_missing.js]
[test_ct.js]
# Requires hard-coded debug-only data
skip-if = !debug