Bug 1911005 - certificate transparency: note log states and timestamps r=jschanck

This patch uses the log state information in the known CT log list to
differentiate qualified, usable, and readonly (collectively now referred to as
"admissible") logs from retired logs. This patch also takes the opportunity to
update the language in the implementation from "disqualified" to "retired" to
match the current terminology from the source data.

Differential Revision: https://phabricator.services.mozilla.com/D218266
This commit is contained in:
Dana Keeler 2024-08-02 23:13:18 +00:00
Родитель b7f7ca3512
Коммит f1fe9ebab5
18 изменённых файлов: 531 добавлений и 463 удалений

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

@ -257,11 +257,10 @@ void CertVerifier::LoadKnownCTLogs() {
continue;
}
CTLogVerifier logVerifier;
const CTLogOperatorInfo& logOperator =
kCTLogOperatorList[log.operatorIndex];
rv = logVerifier.Init(publicKey, logOperator.id, log.status,
log.disqualificationTime);
CTLogVerifier logVerifier(logOperator.id, log.state, log.timestamp);
rv = logVerifier.Init(publicKey);
if (rv != Success) {
MOZ_ASSERT_UNREACHABLE("Failed initializing a known CT Log");
continue;
@ -364,40 +363,25 @@ Result CertVerifier::VerifyCertificateTransparencyPolicy(
if (MOZ_LOG_TEST(gCertVerifierLog, LogLevel::Debug)) {
size_t validCount = 0;
size_t unknownLogCount = 0;
size_t disqualifiedLogCount = 0;
size_t invalidSignatureCount = 0;
size_t invalidTimestampCount = 0;
size_t retiredLogCount = 0;
for (const VerifiedSCT& verifiedSct : result.verifiedScts) {
switch (verifiedSct.status) {
case VerifiedSCT::Status::Valid:
switch (verifiedSct.logState) {
case CTLogState::Admissible:
validCount++;
break;
case VerifiedSCT::Status::ValidFromDisqualifiedLog:
disqualifiedLogCount++;
case CTLogState::Retired:
retiredLogCount++;
break;
case VerifiedSCT::Status::UnknownLog:
unknownLogCount++;
break;
case VerifiedSCT::Status::InvalidSignature:
invalidSignatureCount++;
break;
case VerifiedSCT::Status::InvalidTimestamp:
invalidTimestampCount++;
break;
case VerifiedSCT::Status::None:
default:
MOZ_ASSERT_UNREACHABLE("Unexpected SCT verification status");
}
}
MOZ_LOG(
gCertVerifierLog, LogLevel::Debug,
("SCT verification result: "
"valid=%zu unknownLog=%zu disqualifiedLog=%zu "
"invalidSignature=%zu invalidTimestamp=%zu "
"decodingErrors=%zu\n",
validCount, unknownLogCount, disqualifiedLogCount,
invalidSignatureCount, invalidTimestampCount, result.decodingErrors));
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
("SCT verification result: "
"valid=%zu unknownLog=%zu retiredLog=%zu "
"invalidSignature=%zu invalidTimestamp=%zu "
"decodingErrors=%zu\n",
validCount, result.sctsFromUnknownLogs, retiredLogCount,
result.sctsWithInvalidSignatures, result.sctsWithInvalidTimestamps,
result.decodingErrors));
}
BackCert endEntityBackCert(endEntityInput, EndEntityOrCA::MustBeEndEntity,

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

@ -14,16 +14,21 @@
#include <stddef.h>
static const PRTime kCTExpirationTime = INT64_C(1729551936000000);
static const PRTime kCTExpirationTime = INT64_C(1729883443000000);
namespace mozilla::ct {
enum class CTLogState {
Admissible, // Qualified, Usable, or ReadOnly
Retired,
};
struct CTLogInfo {
// See bug 1338873 about making these fields const.
const char* name;
CTLogState state;
uint64_t timestamp;
// Index within kCTLogOperatorList.
mozilla::ct::CTLogStatus status;
// 0 for qualified logs, disqualification time for disqualified logs
// (in milliseconds, measured since the epoch, ignoring leap seconds).
uint64_t disqualificationTime;
size_t operatorIndex;
const char* key;
size_t keyLength;
@ -36,9 +41,9 @@ struct CTLogOperatorInfo {
};
const CTLogInfo kCTLogList[] = {
{"Google 'Argon2024' log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
0, // operated by Google
{"Google 'Argon2024' log", CTLogState::Admissible,
1667328840000, // 2022-11-01T18:54:00Z
0, // operated by Google
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x1d\xb9\x6c\xa9\xcb\x69\x94\xc5\x5c"
"\xe6\xb6\xa6\x03\xbb\xd2\xb8\xdc\x54\x43\x17\x28\x99\x0c\x06\x01\x50\x1d"
@ -46,9 +51,9 @@ const CTLogInfo kCTLogList[] = {
"\xed\x04\xfb\xe5\x57\xba\x26\x04\xf6\x11\x52\xce\x14\x65\x3b\x2f\x76\x2b"
"\xc0",
91},
{"Google 'Argon2025h1' log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
0, // operated by Google
{"Google 'Argon2025h1' log", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
0, // operated by Google
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x20\x82\xa1\xf9\x67\x68\xa8\xe4\xdb"
"\x94\x98\xe2\xe1\x68\x87\xe4\x09\x6d\x20\x35\x33\x38\x3c\xaf\x14\xaa\xd7"
@ -56,9 +61,9 @@ const CTLogInfo kCTLogList[] = {
"\xfb\xae\xbe\xc8\x23\x52\x20\x2b\xaa\x44\x05\xfe\x54\xf9\xd5\xf1\x1d\x45"
"\x9a",
91},
{"Google 'Argon2025h2' log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
0, // operated by Google
{"Google 'Argon2025h2' log", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
0, // operated by Google
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xaf\xe4\xf3\x94\x2c\xdf\xa6\x27\xb5"
"\xfe\xb2\x61\x83\x19\xc8\x21\x3a\x23\xa8\xa9\x3d\x54\xaf\xbc\x31\x9a\x1c"
@ -66,9 +71,9 @@ const CTLogInfo kCTLogList[] = {
"\x56\x4e\x98\xe8\xaa\x26\x29\x36\x1e\x28\x60\x6f\xeb\x15\x6e\xf7\x7c\xd0"
"\xba",
91},
{"Google 'Argon2026h1' log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
0, // operated by Google
{"Google 'Argon2026h1' log", CTLogState::Admissible,
1721666666000, // 2024-07-22T16:44:26Z
0, // operated by Google
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x07\xfc\x1e\xe8\x63\x8e\xff\x1c\x31"
"\x8a\xfc\xb8\x1e\x19\x2b\x60\x50\x00\x3e\x8e\x9e\xda\x77\x37\xe3\xa5\xa8"
@ -76,9 +81,9 @@ const CTLogInfo kCTLogList[] = {
"\x06\x4f\x64\x58\x75\x14\x5d\x56\x52\xe6\x6a\x2b\x14\x4c\xec\x81\xd1\xea"
"\x3e",
91},
{"Google 'Argon2026h2' log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
0, // operated by Google
{"Google 'Argon2026h2' log", CTLogState::Admissible,
1721666666000, // 2024-07-22T16:44:26Z
0, // operated by Google
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x2a\x3a\x67\x8b\xfe\xba\x0c\x86\x2b"
"\x4a\x51\x8a\xe9\x17\xfe\x7b\xa1\x76\x73\xfd\xbc\x65\x4b\xc3\x27\xbf\x4d"
@ -86,9 +91,9 @@ const CTLogInfo kCTLogList[] = {
"\xf5\x35\x50\x9c\xa1\xd3\x49\x4d\x13\xd5\x3b\x6a\x0e\xea\x45\x9d\x24\x13"
"\x22",
91},
{"Google 'Xenon2024' log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
0, // operated by Google
{"Google 'Xenon2024' log", CTLogState::Admissible,
1667328840000, // 2022-11-01T18:54:00Z
0, // operated by Google
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xb9\x60\xe0\x34\x1e\x35\xe4\x65\x00"
"\x93\x4f\x90\x09\xbd\x5a\xec\x44\xdd\x8c\x0f\xce\xed\x11\x3e\x2a\x59\x46"
@ -96,9 +101,9 @@ const CTLogInfo kCTLogList[] = {
"\xba\xbb\xf2\x54\xe2\xa8\x0c\x83\x08\x51\x06\xde\x21\x6d\x36\x50\x8e\x38"
"\x4d",
91},
{"Google 'Xenon2025h1' log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
0, // operated by Google
{"Google 'Xenon2025h1' log", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
0, // operated by Google
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x82\xe2\xce\x90\x40\x3f\x81\x0e\xdf"
"\xea\xe1\x20\x2b\x5e\x2e\x30\x54\x46\x81\xb9\x58\xed\xaf\xbd\xff\x36\xa7"
@ -106,9 +111,9 @@ const CTLogInfo kCTLogList[] = {
"\x12\xe6\x54\x78\x50\xdc\xff\x6d\xfd\x1c\xa7\xb6\x3a\x1f\xf9\x26\xa9\x1b"
"\xbd",
91},
{"Google 'Xenon2025h2' log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
0, // operated by Google
{"Google 'Xenon2025h2' log", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
0, // operated by Google
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x6b\xe0\xaf\xed\x06\x7c\x3d\xef\xd9"
"\x0e\xe4\x58\x4b\x04\xd8\x2a\x47\x99\x90\x89\x7a\xb9\x36\xa5\x75\xc8\x04"
@ -116,9 +121,9 @@ const CTLogInfo kCTLogList[] = {
"\xa0\x3e\x9d\x94\x1c\xb2\xb7\x4a\xf2\x51\xec\x40\xed\x62\x47\xa4\x03\x49"
"\x86",
91},
{"Google 'Xenon2026h1' log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
0, // operated by Google
{"Google 'Xenon2026h1' log", CTLogState::Admissible,
1721666666000, // 2024-07-22T16:44:26Z
0, // operated by Google
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x3a\x1f\xc8\xbb\xce\xd5\x90\x47\x34"
"\xca\xca\x01\x04\x27\x21\x1c\xe2\x29\x3d\x92\xbb\x91\x45\xc7\x5a\x3e\xa5"
@ -126,9 +131,9 @@ const CTLogInfo kCTLogList[] = {
"\xeb\x03\x0a\x30\xcc\x63\x6c\xd9\x3c\xbe\xf5\x7b\x94\xba\x94\xd3\xbf\x88"
"\x4c",
91},
{"Google 'Xenon2026h2' log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
0, // operated by Google
{"Google 'Xenon2026h2' log", CTLogState::Admissible,
1721666666000, // 2024-07-22T16:44:26Z
0, // operated by Google
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xe5\x77\x78\x95\x71\x28\xb3\x95\xc9"
"\xa5\xcc\x7a\x4c\xe8\x32\x03\x96\x7b\xfc\x2e\x1d\xb9\xa4\xdb\x43\xa0\xbd"
@ -136,9 +141,9 @@ const CTLogInfo kCTLogList[] = {
"\x8a\x72\x30\x65\x86\x43\x53\xdc\x11\x44\x18\x49\x98\x25\x68\xa7\x3c\x05"
"\xbf",
91},
{"Cloudflare 'Nimbus2024' Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
1, // operated by Cloudflare
{"Cloudflare 'Nimbus2024' Log", CTLogState::Admissible,
1669827600000, // 2022-11-30T17:00:00Z
1, // operated by Cloudflare
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x77\xb1\x9b\x7b\x8f\xe6\x8b\x35\xfe"
"\x3a\x92\x29\x2d\xac\x8a\x8d\x51\x8a\x25\xfc\x93\xb6\xd7\xa0\x8b\x29\x37"
@ -146,9 +151,9 @@ const CTLogInfo kCTLogList[] = {
"\xf6\x9e\x94\x25\xdd\x36\x81\xd1\xeb\x5d\x29\xc3\x2b\x44\xf1\x5b\xca\x15"
"\x48",
91},
{"Cloudflare 'Nimbus2025'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
1, // operated by Cloudflare
{"Cloudflare 'Nimbus2025'", CTLogState::Admissible,
1702969200000, // 2023-12-19T07:00:00Z
1, // operated by Cloudflare
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x1a\x80\x1a\x15\x19\x19\x23\x79\xb4"
"\xfa\xa0\x79\x8e\x8d\xd5\xc1\xdc\xc2\xb5\x96\x92\x7e\x94\xe0\xc3\x7e\x14"
@ -156,9 +161,9 @@ const CTLogInfo kCTLogList[] = {
"\x81\x5b\x4a\x14\x41\xec\xaf\xa9\x5d\x0e\xab\x12\x19\x71\xcd\x43\xef\xbb"
"\x97",
91},
{"DigiCert Yeti2024 Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
2, // operated by DigiCert
{"DigiCert Yeti2024 Log", CTLogState::Admissible,
1667328840000, // 2022-11-01T18:54:00Z
2, // operated by DigiCert
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x57\xb8\xc1\x6f\x30\xa4\x7f\x2e\xe4"
"\xf0\xd0\xd9\x60\x62\x13\x95\xe3\x7a\xe3\x4e\x53\xc3\xb3\xb8\x73\x85\xc1"
@ -166,9 +171,9 @@ const CTLogInfo kCTLogList[] = {
"\x1b\x19\x44\x58\xb7\x00\x77\x60\x20\x1a\x72\xd8\x82\xde\xae\x9e\xb1\xc6"
"\x4b",
91},
{"DigiCert Yeti2025 Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
2, // operated by DigiCert
{"DigiCert Yeti2025 Log", CTLogState::Admissible,
1667328840000, // 2022-11-01T18:54:00Z
2, // operated by DigiCert
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xdf\x95\x00\x5e\x10\xc1\x01\xf7\x37"
"\xe3\x10\x74\xd1\xff\xb2\xca\x90\xed\x32\x99\x5f\x0c\x39\xfe\xa1\xd1\x13"
@ -176,9 +181,9 @@ const CTLogInfo kCTLogList[] = {
"\x95\x24\x7c\xd8\x91\x98\x48\x3b\xf0\xf0\xdf\x21\xf1\xb0\x81\x5a\x59\x25"
"\x43",
91},
{"DigiCert Nessie2024 Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
2, // operated by DigiCert
{"DigiCert Nessie2024 Log", CTLogState::Retired,
1685404800000, // 2023-05-30T00:00:00Z
2, // operated by DigiCert
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x2d\xfc\xa2\x7b\x36\xbf\x56\x91\xe9"
"\xfe\x3f\xe8\x3d\xfc\xc3\xa7\xe0\x61\x52\xea\x2c\xe9\x05\xa3\x9f\x27\x17"
@ -186,9 +191,9 @@ const CTLogInfo kCTLogList[] = {
"\x21\xfc\x41\x54\x84\xa3\x54\xd5\x2e\xb2\x7a\x16\x4b\x2a\x1f\x2b\x66\x04"
"\x2b",
91},
{"DigiCert Nessie2025 Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
2, // operated by DigiCert
{"DigiCert Nessie2025 Log", CTLogState::Admissible,
1667328840000, // 2022-11-01T18:54:00Z
2, // operated by DigiCert
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xf2\xf0\xf0\xa7\x8b\x81\x2e\x09\x39"
"\x3b\x9f\x42\xda\x38\x44\x5f\xb4\xcc\xed\x36\xbb\xd8\x43\x7f\x16\x49\x57"
@ -196,9 +201,9 @@ const CTLogInfo kCTLogList[] = {
"\x75\x80\xb7\x53\xa7\x85\xd5\xbc\xab\x47\x06\x55\xdb\xb5\xdf\x88\xa1\x6f"
"\x38",
91},
{"DigiCert 'Wyvern2024h1' Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
2, // operated by DigiCert
{"DigiCert 'Wyvern2024h1' Log", CTLogState::Admissible,
1718500000000, // 2024-06-16T01:06:40Z
2, // operated by DigiCert
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x68\xa6\x79\x14\xd1\x58\xe7\xab\xaa"
"\x29\x69\x7f\x60\xed\x68\xe8\x10\xf6\x07\x84\xc0\xfb\x59\x04\x5a\x09\xc9"
@ -206,9 +211,9 @@ const CTLogInfo kCTLogList[] = {
"\x35\xc1\x8e\xfc\x9f\xb4\x20\x24\xd7\x15\xac\x87\xf7\x1e\xc1\x0b\x3c\x76"
"\x1a",
91},
{"DigiCert 'Wyvern2024h2' Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
2, // operated by DigiCert
{"DigiCert 'Wyvern2024h2' Log", CTLogState::Admissible,
1718500000000, // 2024-06-16T01:06:40Z
2, // operated by DigiCert
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xa8\x73\x12\x9c\x54\xd0\x7a\x7d\xc5"
"\xb5\x17\x2b\x71\x52\x89\x04\x90\xbb\x42\xf1\x9d\xf8\x1c\xde\x4c\xcf\x82"
@ -216,9 +221,9 @@ const CTLogInfo kCTLogList[] = {
"\x98\x84\xce\x1c\xbe\xcf\x4f\x7a\xef\x15\xfa\xd0\xee\xed\xed\x07\xad\x71"
"\x6d",
91},
{"DigiCert 'Wyvern2025h1' Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
2, // operated by DigiCert
{"DigiCert 'Wyvern2025h1' Log", CTLogState::Admissible,
1718500000000, // 2024-06-16T01:06:40Z
2, // operated by DigiCert
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xa7\xcb\x80\x61\x86\x1b\x1f\xb5\xab"
"\x2b\x20\x76\x59\x83\x66\x0e\xce\xae\xb8\x6f\x3b\x88\x02\xeb\x43\xf4\x87"
@ -226,9 +231,9 @@ const CTLogInfo kCTLogList[] = {
"\x0d\x96\x58\x44\x9d\x3b\x8a\x80\xc5\xc8\xbe\xe1\x89\x46\x6b\x48\x4c\xd6"
"\x09",
91},
{"DigiCert 'Wyvern2025h2' Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
2, // operated by DigiCert
{"DigiCert 'Wyvern2025h2' Log", CTLogState::Admissible,
1718500000000, // 2024-06-16T01:06:40Z
2, // operated by DigiCert
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xe0\xdb\x41\xef\xe4\x04\xbd\xcb\x6b"
"\x2e\x4c\xcc\xf1\x6c\xde\x41\x58\x7f\xfe\x94\xf6\x7a\xf6\x60\xed\x8b\x76"
@ -236,9 +241,9 @@ const CTLogInfo kCTLogList[] = {
"\x1c\x63\xde\x95\xe2\x81\x69\x97\x8d\x1e\xa8\xb7\x66\x51\x25\x75\x4d\x78"
"\x2e",
91},
{"DigiCert 'Sphinx2024h1' Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
2, // operated by DigiCert
{"DigiCert 'Sphinx2024h1' Log", CTLogState::Admissible,
1718500000000, // 2024-06-16T01:06:40Z
2, // operated by DigiCert
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xc6\xe4\x29\x69\x98\xfe\x28\x92\x57"
"\x12\x4d\x9e\xed\x0e\xe7\x32\xa2\xe6\x9c\x27\x78\xa4\x29\x7c\x99\xd5\xdb"
@ -246,9 +251,9 @@ const CTLogInfo kCTLogList[] = {
"\x1d\xd8\x22\xa8\xd3\xeb\xc9\x22\x8e\x36\xfb\x4a\xb1\x70\x9c\x5d\xc1\xe8"
"\x33",
91},
{"DigiCert 'Sphinx2024h2' Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
2, // operated by DigiCert
{"DigiCert 'Sphinx2024h2' Log", CTLogState::Admissible,
1718500000000, // 2024-06-16T01:06:40Z
2, // operated by DigiCert
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xdb\x09\x41\x84\xe7\xd1\xf1\x5b\x25"
"\x09\x7b\xe8\xc6\x98\x51\x5e\x29\x85\xfd\x81\xde\x89\xd7\xd0\x86\xa4\xb0"
@ -256,9 +261,9 @@ const CTLogInfo kCTLogList[] = {
"\x3f\xd1\xe9\xd4\x09\x84\x81\xbe\xb6\xc1\xed\x1b\x17\xea\x26\x97\xba\xe9"
"\x9a",
91},
{"DigiCert 'Sphinx2025h1' Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
2, // operated by DigiCert
{"DigiCert 'Sphinx2025h1' Log", CTLogState::Admissible,
1718500000000, // 2024-06-16T01:06:40Z
2, // operated by DigiCert
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xe3\x2f\x1f\x4d\x89\x05\x75\x29\x78"
"\xbb\x22\x3d\x07\x62\x51\x14\x70\x94\xe7\x3c\xea\xf5\xee\xae\xa6\x48\x9a"
@ -266,9 +271,9 @@ const CTLogInfo kCTLogList[] = {
"\x45\x31\x17\xd3\x8d\xf2\xe7\xce\x18\x11\x58\x98\x2c\x60\x6f\x58\x20\x36"
"\x6e",
91},
{"DigiCert 'Sphinx2025h2' Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
2, // operated by DigiCert
{"DigiCert 'Sphinx2025h2' Log", CTLogState::Admissible,
1718500000000, // 2024-06-16T01:06:40Z
2, // operated by DigiCert
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x41\x8c\x50\x13\x54\xb1\x19\x05\xb7"
"\x7f\x4a\x20\x6e\xa3\x75\x63\xca\x34\xf4\xcc\x74\xea\x32\x3b\xb6\x8b\x03"
@ -276,9 +281,9 @@ const CTLogInfo kCTLogList[] = {
"\x1a\x27\x54\x85\x5d\xc1\x7b\x24\xa8\x34\xe3\xcd\x88\xce\xd4\x50\x1b\xbe"
"\x69",
91},
{"Sectigo 'Sabre' CT log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
3, // operated by Sectigo
{"Sectigo 'Sabre' CT log", CTLogState::Admissible,
1715000000000, // 2024-05-06T12:53:20Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xf2\x6f\xd2\x89\x0f\x3f\xc5\xf8\x87"
"\x1e\xab\x65\xb3\xd9\xbb\x17\x23\x8c\x06\x0e\x09\x55\x96\x3d\x0a\x08\xa2"
@ -286,9 +291,9 @@ const CTLogInfo kCTLogList[] = {
"\xe1\x98\x80\xd0\xce\x24\x6d\x3e\x67\x9a\xe9\x37\x23\xce\x52\x93\x86\xda"
"\x80",
91},
{"Sectigo 'Sabre2024h1'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
3, // operated by Sectigo
{"Sectigo 'Sabre2024h1'", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x2c\x01\xf6\xce\x31\xbc\xaa\x14\x61"
"\x51\xfe\x6b\x7a\x87\xae\xa6\xd3\x9b\xc7\x87\x2d\x0a\x5a\xc8\x4f\xb5\x54"
@ -296,9 +301,9 @@ const CTLogInfo kCTLogList[] = {
"\x16\x1c\x70\x2e\xc8\xec\x53\x5a\x4c\x21\x4c\x7e\x27\x0b\x13\x14\x5e\xfc"
"\x85",
91},
{"Sectigo 'Sabre2024h2'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
3, // operated by Sectigo
{"Sectigo 'Sabre2024h2'", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x7a\x10\x4c\x8a\xe7\x22\x7b\x6d\x2a"
"\xba\x8e\xfa\x6b\x4a\x81\xd5\x85\xae\x03\xef\xff\x4b\xfc\x4d\x53\x3d\xb7"
@ -306,9 +311,9 @@ const CTLogInfo kCTLogList[] = {
"\xe1\x88\x37\xdf\xd4\xf3\x60\x65\xfc\xa0\x75\xf0\x20\x66\x8e\x4a\xcc\x19"
"\xda",
91},
{"Sectigo 'Sabre2025h1'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
3, // operated by Sectigo
{"Sectigo 'Sabre2025h1'", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x7e\x2f\x39\xf1\xe8\x23\x8e\xb3\x32"
"\x04\xaf\x4d\x57\xf6\xdb\xc5\x74\xa4\x7a\x6d\x3b\x07\x51\x0c\x5a\xfb\x80"
@ -316,9 +321,9 @@ const CTLogInfo kCTLogList[] = {
"\x41\xae\x70\xb3\x31\xa2\xe3\xfa\x3d\x5f\x2c\x5d\x04\xcd\xb4\x9d\x55\xab"
"\x41",
91},
{"Sectigo 'Sabre2025h2'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
3, // operated by Sectigo
{"Sectigo 'Sabre2025h2'", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x85\x13\x11\x2d\x7b\xf3\x93\x81\xe4"
"\xb9\x7c\xd9\x64\x3b\xe7\xb5\x83\x99\x66\x79\x59\x47\x6a\x42\x5e\xd6\xbd"
@ -326,9 +331,9 @@ const CTLogInfo kCTLogList[] = {
"\xaf\x89\x8b\xf5\x58\xd8\xba\xeb\x7b\x83\x52\xe9\xf4\xe0\xa5\xcd\xcd\x92"
"\xcc",
91},
{"Sectigo 'Mammoth2024h1'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
3, // operated by Sectigo
{"Sectigo 'Mammoth2024h1'", CTLogState::Retired,
1706486400000, // 2024-01-29T00:00:00Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xa4\x59\x90\xf3\x71\x24\x24\xf7\xc3"
"\x55\x27\x56\x9c\xa3\x59\x1e\xf7\xb7\x9f\xce\xab\x4e\x19\x66\x4d\xd0\x8a"
@ -336,9 +341,9 @@ const CTLogInfo kCTLogList[] = {
"\x38\x54\x5a\xcf\x9f\x6b\x07\x90\xd0\x0e\x7e\x3d\x4c\x87\xb2\xe8\x3f\x07"
"\xcc",
91},
{"Sectigo 'Mammoth2024h1b'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
3, // operated by Sectigo
{"Sectigo 'Mammoth2024h1b'", CTLogState::Admissible,
1714320000000, // 2024-04-28T16:00:00Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xa3\xd5\x07\x28\x7a\x04\x34\xae\xca"
"\xbe\x80\x79\x4f\x3e\xf6\x41\xf4\x24\x04\xe1\xd6\x36\x5a\x1a\x09\xf2\xd1"
@ -346,9 +351,9 @@ const CTLogInfo kCTLogList[] = {
"\x10\xe1\x8c\xec\xb2\x8a\x8c\xc8\xe7\xdd\xcd\xe2\x07\xf0\x4e\x16\x02\x57"
"\x37",
91},
{"Sectigo 'Mammoth2024h2'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
3, // operated by Sectigo
{"Sectigo 'Mammoth2024h2'", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x85\x66\x22\x24\x6e\xbe\x52\x62\x0a"
"\xa0\xaf\xc3\x25\x1a\x36\x2e\xa7\x60\x89\xa2\x65\xbf\xa4\x5f\xbd\x85\x6a"
@ -356,9 +361,9 @@ const CTLogInfo kCTLogList[] = {
"\x57\x8b\x63\x1a\x81\xc1\x41\x9d\x7d\xec\x01\x3a\xdb\xb9\xc1\x27\xf4\x65"
"\x1e",
91},
{"Sectigo 'Mammoth2025h1'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
3, // operated by Sectigo
{"Sectigo 'Mammoth2025h1'", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x13\x3c\x41\xb5\x30\x7d\x2e\x4a\xa1"
"\xa8\x6b\xd2\xc5\x57\x6b\x98\xfe\x7e\xef\xd5\x21\xe2\xba\x5d\xb0\xba\x85"
@ -366,9 +371,9 @@ const CTLogInfo kCTLogList[] = {
"\x9b\x4e\x72\x62\x4b\x3c\x0c\x32\xdd\x86\xfb\xeb\x3e\x66\xcd\x77\x58\x5b"
"\xe5",
91},
{"Sectigo 'Mammoth2025h2'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
3, // operated by Sectigo
{"Sectigo 'Mammoth2025h2'", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x88\xe2\xc7\xb3\xd7\x37\xa3\x91\xd7"
"\xb3\xc5\xda\x07\x51\x04\x2b\x81\xed\xc2\x44\x3b\x75\xa0\xe6\x65\xe1\x4a"
@ -376,9 +381,49 @@ const CTLogInfo kCTLogList[] = {
"\xb1\x15\x67\x66\xa0\x7c\x0b\x5b\x62\x7f\x6c\x9a\x6a\x30\x9b\x68\x02\x16"
"\x6f",
91},
{"Let's Encrypt 'Oak2024H1' log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
4, // operated by Let's Encrypt
{"Sectigo 'Mammoth2026h1'", CTLogState::Admissible,
1722312000000, // 2024-07-30T04:00:00Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x9e\xcb\x0c\x8a\x51\xcc\x8a\xe2\x0b"
"\xce\x85\xe6\xaf\x4d\x31\xdb\x1b\x6a\x4c\xfd\xb0\x79\x6b\x99\x97\xc0\x5d"
"\xfb\x6e\x45\x50\x1d\x62\xaa\xc6\x9f\x9b\x6b\x05\x3d\xa2\xab\x2b\x5d\x88"
"\x9b\x50\x28\xe2\x9e\x58\xa5\xa5\xfa\xf9\xe3\xfa\x15\x25\xe3\x14\x13\x32"
"\xc4",
91},
{"Sectigo 'Mammoth2026h2'", CTLogState::Admissible,
1722312000000, // 2024-07-30T04:00:00Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xec\x83\x61\xf2\xd7\xb4\xbb\xe4\xe4"
"\x3b\xeb\xc8\x63\x75\x98\xcf\x61\x90\x63\x14\x3d\x5f\x22\xdf\x74\xba\x50"
"\xa7\x58\x9b\x69\x7d\xe6\x63\x89\x6d\xd9\xd7\x51\x84\x3f\xf8\x02\xd8\xc8"
"\xff\xc2\x97\x71\xe5\x7e\x27\xf5\x72\xb1\x8f\x24\x27\x57\x0a\x0d\x74\xc0"
"\xb6",
91},
{"Sectigo 'Sabre2026h1'", CTLogState::Admissible,
1722312000000, // 2024-07-30T04:00:00Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x84\x26\xbc\x36\xbd\xd8\x8d\x3c\x87"
"\x9e\xe0\x10\xaf\xcd\x94\xd9\xd7\xb9\x51\x80\x34\x7e\xf7\x58\x5c\x73\xea"
"\xeb\x09\x93\xb8\x10\x7b\x90\x9c\x7d\xc7\xcd\x96\x43\xed\x53\x6e\x95\x21"
"\x46\x67\x51\xf0\xde\xb6\xc9\x9e\xaa\xe2\x80\x6d\xce\x25\x81\x34\xd7\x6a"
"\x60",
91},
{"Sectigo 'Sabre2026h2'", CTLogState::Admissible,
1722312000000, // 2024-07-30T04:00:00Z
3, // operated by Sectigo
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xce\x35\xca\xec\x39\x07\x82\xda\x77"
"\x27\x86\xe4\xf2\x7e\xc5\xdc\x38\xf2\x9b\xa9\xab\x8c\xa7\xc0\xed\x83\x1e"
"\x3e\x6a\x1b\xc0\xf0\x95\x56\xba\x32\x33\x4c\x75\x7c\x09\x07\xe9\xe1\x3e"
"\x65\x35\x63\xf0\x49\xbe\x72\xd1\xaa\x9d\xaf\x7d\x08\xc4\xb4\x8d\x59\x3d"
"\x73",
91},
{"Let's Encrypt 'Oak2024H1' log", CTLogState::Admissible,
1669827600000, // 2022-11-30T17:00:00Z
4, // operated by Let's Encrypt
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x56\x43\xd7\x7e\x7b\xd4\x72\xb7\xba"
"\xa9\x51\xbd\x36\x93\xb7\xe9\xb5\x92\x0f\xea\x5e\xb7\x45\xa3\x92\xfd\xc9"
@ -386,9 +431,9 @@ const CTLogInfo kCTLogList[] = {
"\xe6\xeb\xa4\xe2\x7d\x24\x63\x9f\x46\xbf\x94\x73\x52\x8d\x96\xae\xa9\x26"
"\xfd",
91},
{"Let's Encrypt 'Oak2024H2' log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
4, // operated by Let's Encrypt
{"Let's Encrypt 'Oak2024H2' log", CTLogState::Admissible,
1669827600000, // 2022-11-30T17:00:00Z
4, // operated by Let's Encrypt
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xd7\x73\xd6\x53\x47\xe9\xf3\xc9\xd5"
"\x7c\x16\xc2\xd6\x8f\x70\x65\xfa\xf2\x51\x36\xa9\x13\x80\x2f\xed\xf9\x94"
@ -396,9 +441,9 @@ const CTLogInfo kCTLogList[] = {
"\x71\xcb\xca\xbb\x9f\x9f\xf3\x5c\x2d\x1e\xa3\x81\x59\xaf\x92\xb3\x6d\x30"
"\x68",
91},
{"Let's Encrypt 'Oak2025h1'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
4, // operated by Let's Encrypt
{"Let's Encrypt 'Oak2025h1'", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
4, // operated by Let's Encrypt
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x29\xe0\x69\x53\xd7\xa3\x9c\x26\x88"
"\x65\xe5\xf7\xf4\x4b\x1d\x17\x9b\xc3\xbd\xff\x04\x2d\x31\xdd\x2c\xfc\x62"
@ -406,9 +451,9 @@ const CTLogInfo kCTLogList[] = {
"\xf9\x3c\x58\x54\x5b\x37\x10\xb1\xab\xd8\x83\xfb\x84\xf1\x95\x3f\x2e\x2f"
"\x1c",
91},
{"Let's Encrypt 'Oak2025h2'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
4, // operated by Let's Encrypt
{"Let's Encrypt 'Oak2025h2'", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
4, // operated by Let's Encrypt
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xb5\x76\x30\x07\xad\xc6\xc8\xd2\xe4"
"\x4b\xd2\xf5\xbe\xa2\x8d\x9c\xfd\x74\xfa\x3a\xd6\xfa\x59\x5d\xb6\x1c\x60"
@ -416,9 +461,9 @@ const CTLogInfo kCTLogList[] = {
"\xc9\xd7\x3d\xbb\xc1\xf7\x71\x86\x69\xf4\xb3\x5f\x90\x09\xaa\xae\xbd\x8d"
"\xa9",
91},
{"Trust Asia Log2024-2", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
5, // operated by TrustAsia
{"Trust Asia Log2024-2", CTLogState::Admissible,
1675411200000, // 2023-02-03T08:00:00Z
5, // operated by TrustAsia
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xa7\x64\xe2\x79\x81\x3f\x61\xd7\xec"
"\xc6\xf8\x65\x28\x1d\xa0\xb4\x66\x33\xc3\x25\xd5\x0a\x95\x78\x9c\x8f\xfe"
@ -426,9 +471,9 @@ const CTLogInfo kCTLogList[] = {
"\x0d\x2f\x8c\xab\xd7\x7f\x7a\x1e\xd9\x84\x33\x39\xe8\xfd\x89\x5f\x96\x48"
"\x08",
91},
{"TrustAsia Log2025a", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
5, // operated by TrustAsia
{"TrustAsia Log2025a", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
5, // operated by TrustAsia
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x70\xe5\xb1\xa4\x09\x79\x2b\x9d\xf8"
"\xa3\xa0\xdf\x18\xef\x95\x5d\x03\x6c\x7b\xa1\x91\xa9\xb8\x80\x7d\xec\x5c"
@ -436,9 +481,9 @@ const CTLogInfo kCTLogList[] = {
"\x90\x58\xba\x22\xd5\xf9\xf5\x69\x54\xb7\xa8\x94\x4e\x32\x09\xae\x26\x11"
"\x4d",
91},
{"TrustAsia Log2025b", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
5, // operated by TrustAsia
{"TrustAsia Log2025b", CTLogState::Admissible,
1701000000000, // 2023-11-26T12:00:00Z
5, // operated by TrustAsia
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xaa\xa0\x8b\xdb\x67\x14\x5d\x97\x89"
"\x1d\x08\x8d\x06\xd7\xc1\x94\x8e\xb0\xfa\x4c\x46\xd5\x53\x08\x78\x2b\x04"
@ -446,9 +491,9 @@ const CTLogInfo kCTLogList[] = {
"\xbd\x2f\xa9\xcf\xe8\x7b\x5e\xe1\x4b\x60\xe5\x38\x43\x60\x97\xc1\x5b\x2f"
"\x65",
91},
{"TrustAsia 'log2026a'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
5, // operated by TrustAsia
{"TrustAsia 'log2026a'", CTLogState::Admissible,
1719964800000, // 2024-07-03T00:00:00Z
5, // operated by TrustAsia
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xa7\x4e\x7a\xc9\xa6\x07\xf9\xff\x74"
"\xec\x98\xcb\x49\xe1\x00\x24\xb3\x59\x2e\x83\xfd\xc0\x70\x35\x33\x4c\x63"
@ -456,9 +501,9 @@ const CTLogInfo kCTLogList[] = {
"\x89\x17\xe8\x5b\x2e\xc5\xac\x00\x05\xc9\x76\x37\x45\x97\x03\x15\xff\x60"
"\x59",
91},
{"TrustAsia 'log2026b'", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
5, // operated by TrustAsia
{"TrustAsia 'log2026b'", CTLogState::Admissible,
1719964800000, // 2024-07-03T00:00:00Z
5, // operated by TrustAsia
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x0f\x12\x8c\xa9\xe6\xe3\xec\x62\xee"
"\xdf\x58\xc8\x50\xe6\x26\x70\x76\x10\xb7\x04\x39\xb3\xa7\xf8\x4c\x73\x3b"
@ -467,9 +512,9 @@ const CTLogInfo kCTLogList[] = {
"\x85",
91},
#ifdef DEBUG
{"Mozilla Test RSA Log 1", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
6, // operated by Mozilla Test Org 1
{"Mozilla Test RSA Log 1", CTLogState::Admissible,
1721666666000, // 2024-07-22T16:44:26Z
6, // operated by Mozilla Test Org 1
"\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05"
"\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xba\x88\x51"
"\xa8\x44\x8e\x16\xd6\x41\xfd\x6e\xb6\x88\x06\x36\x10\x3d\x3c\x13\xd9\xea"
@ -490,9 +535,9 @@ const CTLogInfo kCTLogList[] = {
294},
#endif // DEBUG
#ifdef DEBUG
{"Mozilla Test EC Log", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
6, // operated by Mozilla Test Org 1
{"Mozilla Test EC Log", CTLogState::Admissible,
1721666666000, // 2024-07-22T16:44:26Z
6, // operated by Mozilla Test Org 1
"\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x4f\xbf\xbb\xbb\x61\xe0\xf8\xf9\xb1"
"\xa6\x0a\x59\xac\x87\x04\xe2\xec\x05\x0b\x42\x3e\x3c\xf7\x2e\x92\x3f\x2c"
@ -502,9 +547,9 @@ const CTLogInfo kCTLogList[] = {
91},
#endif // DEBUG
#ifdef DEBUG
{"Mozilla Test RSA Log 2", mozilla::ct::CTLogStatus::Included,
0, // no disqualification time
7, // operated by Mozilla Test Org 2
{"Mozilla Test RSA Log 2", CTLogState::Admissible,
1721666666000, // 2024-07-22T16:44:26Z
7, // operated by Mozilla Test Org 2
"\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05"
"\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xc1\x75\xc6"
"\x52\x66\x09\x9f\x77\x08\x2a\x67\x91\xf1\xb8\x76\xc3\x7f\x5c\xe5\x38\xb0"
@ -541,4 +586,6 @@ const CTLogOperatorInfo kCTLogOperatorList[] = {
#endif // DEBUG
};
} // namespace mozilla::ct
#endif // CTKnownLogs_h

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

@ -13,25 +13,13 @@
namespace mozilla {
namespace ct {
// Signed integer sufficient to store the numeric ID of CT log operators
// as assigned at https://www.certificate-transparency.org/known-logs .
// Signed integer sufficient to store the numeric ID of CT log operators.
// The assigned IDs are 0-based positive integers, so you can use special
// values (such as -1) to indicate a "null" or unknown log ID.
typedef int16_t CTLogOperatorId;
typedef std::vector<CTLogOperatorId> CTLogOperatorList;
// Current status of a CT log in regard to its inclusion in the
// Known Logs List such as https://www.certificate-transparency.org/known-logs
enum class CTLogStatus {
// Status unknown or unavailable.
Unknown,
// Included in the list of known logs.
Included,
// Previously included, but disqualified at some point of time.
Disqualified,
};
} // namespace ct
} // namespace mozilla

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

@ -105,30 +105,14 @@ class SignatureParamsTrustDomain final : public TrustDomain {
DigitallySigned::SignatureAlgorithm mSignatureAlgorithm;
};
CTLogVerifier::CTLogVerifier()
CTLogVerifier::CTLogVerifier(CTLogOperatorId operatorId, CTLogState state,
uint64_t timestamp)
: mSignatureAlgorithm(DigitallySigned::SignatureAlgorithm::Anonymous),
mOperatorId(-1),
mDisqualified(false),
mDisqualificationTime(UINT64_MAX) {}
Result CTLogVerifier::Init(Input subjectPublicKeyInfo,
CTLogOperatorId operatorId, CTLogStatus logStatus,
uint64_t disqualificationTime) {
switch (logStatus) {
case CTLogStatus::Included:
mDisqualified = false;
mDisqualificationTime = UINT64_MAX;
break;
case CTLogStatus::Disqualified:
mDisqualified = true;
mDisqualificationTime = disqualificationTime;
break;
case CTLogStatus::Unknown:
default:
assert(false);
return Result::FATAL_ERROR_INVALID_ARGS;
}
mOperatorId(operatorId),
mState(state),
mTimestamp(timestamp) {}
Result CTLogVerifier::Init(Input subjectPublicKeyInfo) {
SignatureParamsTrustDomain trustDomain;
Result rv = CheckSubjectPublicKeyInfo(subjectPublicKeyInfo, trustDomain,
EndEntityOrCA::MustBeEndEntity);
@ -172,7 +156,6 @@ Result CTLogVerifier::Init(Input subjectPublicKeyInfo,
return rv;
}
mOperatorId = operatorId;
return Success;
}

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

@ -9,6 +9,7 @@
#include <memory>
#include "CTKnownLogs.h"
#include "CTLog.h"
#include "CTUtils.h"
#include "SignedCertificateTimestamp.h"
@ -28,28 +29,25 @@ namespace ct {
// on error.
class CTLogVerifier {
public:
CTLogVerifier();
// |operatorId| The numeric ID of the log operator.
// |logState| "Qualified", "Usable", "ReadOnly", or "Retired".
// |timestamp| timestamp associated with logState.
CTLogVerifier(CTLogOperatorId operatorId, CTLogState logState,
uint64_t timestamp);
// Initializes the verifier with log-specific information. Only the public
// key is used for verification, other parameters are purely informational.
// Initializes the verifier with the given subjectPublicKeyInfo.
// |subjectPublicKeyInfo| is a DER-encoded SubjectPublicKeyInfo.
// |operatorId| The numeric ID of the log operator as assigned at
// https://www.certificate-transparency.org/known-logs .
// |logStatus| Either "Included" or "Disqualified".
// |disqualificationTime| Disqualification timestamp (for disqualified logs).
// An error is returned if |subjectPublicKeyInfo| refers to an unsupported
// public key.
pkix::Result Init(pkix::Input subjectPublicKeyInfo,
CTLogOperatorId operatorId, CTLogStatus logStatus,
uint64_t disqualificationTime);
pkix::Result Init(pkix::Input subjectPublicKeyInfo);
// Returns the log's key ID, which is a SHA256 hash of its public key.
// See RFC 6962, Section 3.2.
const Buffer& keyId() const { return mKeyId; }
CTLogOperatorId operatorId() const { return mOperatorId; }
bool isDisqualified() const { return mDisqualified; }
uint64_t disqualificationTime() const { return mDisqualificationTime; }
CTLogState state() const { return mState; }
uint64_t timestamp() const { return mTimestamp; }
// Verifies that |sct| contains a valid signature for |entry|.
// |sct| must be signed by the verifier's log.
@ -78,8 +76,8 @@ class CTLogVerifier {
Buffer mKeyId;
DigitallySigned::SignatureAlgorithm mSignatureAlgorithm;
CTLogOperatorId mOperatorId;
bool mDisqualified;
uint64_t mDisqualificationTime;
CTLogState mState;
uint64_t mTimestamp;
};
} // namespace ct

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

@ -29,8 +29,8 @@ static size_t GetRequiredEmbeddedSctsCount(
// Whether a valid embedded SCT is present in the list.
static bool HasValidEmbeddedSct(const VerifiedSCTList& verifiedScts) {
for (const VerifiedSCT& verifiedSct : verifiedScts) {
if (verifiedSct.status == VerifiedSCT::Status::Valid &&
verifiedSct.origin == VerifiedSCT::Origin::Embedded) {
if (verifiedSct.logState == CTLogState::Admissible &&
verifiedSct.origin == SCTOrigin::Embedded) {
return true;
}
}
@ -40,9 +40,9 @@ static bool HasValidEmbeddedSct(const VerifiedSCTList& verifiedScts) {
// Whether a valid non-embedded SCT is present in the list.
static bool HasValidNonEmbeddedSct(const VerifiedSCTList& verifiedScts) {
for (const VerifiedSCT& verifiedSct : verifiedScts) {
if (verifiedSct.status == VerifiedSCT::Status::Valid &&
(verifiedSct.origin == VerifiedSCT::Origin::TLSExtension ||
verifiedSct.origin == VerifiedSCT::Origin::OCSPResponse)) {
if (verifiedSct.logState == CTLogState::Admissible &&
(verifiedSct.origin == SCTOrigin::TLSExtension ||
verifiedSct.origin == SCTOrigin::OCSPResponse)) {
return true;
}
}
@ -133,7 +133,7 @@ static uint64_t GetEffectiveCertIssuanceTime(
const VerifiedSCTList& verifiedScts) {
uint64_t result = UINT64_MAX;
for (const VerifiedSCT& verifiedSct : verifiedScts) {
if (verifiedSct.status == VerifiedSCT::Status::Valid) {
if (verifiedSct.logState == CTLogState::Admissible) {
result = std::min(result, verifiedSct.sct.timestamp);
}
}
@ -142,17 +142,19 @@ static uint64_t GetEffectiveCertIssuanceTime(
// Checks if the log that issued the given SCT is "once or currently qualified"
// (i.e. was qualified at the time of the certificate issuance). In addition,
// makes sure the SCT is before the disqualification.
// makes sure the SCT is before the retirement timestamp.
static bool LogWasQualifiedForSct(const VerifiedSCT& verifiedSct,
uint64_t certIssuanceTime) {
if (verifiedSct.status == VerifiedSCT::Status::Valid) {
return true;
}
if (verifiedSct.status == VerifiedSCT::Status::ValidFromDisqualifiedLog) {
uint64_t logDisqualificationTime = verifiedSct.logDisqualificationTime;
return certIssuanceTime < logDisqualificationTime &&
verifiedSct.sct.timestamp < logDisqualificationTime;
switch (verifiedSct.logState) {
case CTLogState::Admissible:
return true;
case CTLogState::Retired: {
uint64_t logRetirementTime = verifiedSct.logTimestamp;
return certIssuanceTime < logRetirementTime &&
verifiedSct.sct.timestamp < logRetirementTime;
}
}
MOZ_ASSERT_UNREACHABLE("verifiedSct.logState must be Admissible or Retired");
return false;
}
@ -198,7 +200,7 @@ static void CheckNonEmbeddedCompliance(const VerifiedSCTList& verifiedScts,
size_t validSctsCount;
CountLogsForSelectedScts(
verifiedScts, validSctsCount, [](const VerifiedSCT& verifiedSct) -> bool {
return verifiedSct.status == VerifiedSCT::Status::Valid;
return verifiedSct.logState == CTLogState::Admissible;
});
compliant = validSctsCount >= 2;
@ -227,7 +229,7 @@ static void CheckEmbeddedCompliance(const VerifiedSCTList& verifiedScts,
CountLogsForSelectedScts(
verifiedScts, embeddedSctsCount,
[certIssuanceTime](const VerifiedSCT& verifiedSct) -> bool {
return verifiedSct.origin == VerifiedSCT::Origin::Embedded &&
return verifiedSct.origin == SCTOrigin::Embedded &&
LogWasQualifiedForSct(verifiedSct, certIssuanceTime);
});

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

@ -11,15 +11,24 @@
namespace mozilla {
namespace ct {
VerifiedSCT::VerifiedSCT()
: status(Status::None),
origin(Origin::Unknown),
logOperatorId(-1),
logDisqualificationTime(UINT64_MAX) {}
VerifiedSCT::VerifiedSCT(SignedCertificateTimestamp&& sct, SCTOrigin origin,
CTLogOperatorId logOperatorId, CTLogState logState,
uint64_t logTimestamp)
: sct(std::move(sct)),
origin(origin),
logOperatorId(logOperatorId),
logState(logState),
logTimestamp(logTimestamp) {}
void CTVerifyResult::Reset() {
verifiedScts.clear();
decodingErrors = 0;
sctsFromUnknownLogs = 0;
sctsWithInvalidSignatures = 0;
sctsWithInvalidTimestamps = 0;
embeddedSCTs = 0;
sctsFromTLSHandshake = 0;
sctsFromOCSP = 0;
}
} // namespace ct

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

@ -9,48 +9,33 @@
#include <vector>
#include "CTKnownLogs.h"
#include "CTLog.h"
#include "SignedCertificateTimestamp.h"
namespace mozilla {
namespace ct {
enum class SCTOrigin {
Embedded,
TLSExtension,
OCSPResponse,
};
// Holds a verified Signed Certificate Timestamp along with the verification
// status (e.g. valid/invalid) and additional information related to the
// verification.
struct VerifiedSCT {
VerifiedSCT();
VerifiedSCT(SignedCertificateTimestamp&& sct, SCTOrigin origin,
CTLogOperatorId logOperatorId, CTLogState logState,
uint64_t logTimestamp);
// The original SCT.
SignedCertificateTimestamp sct;
enum class Status {
None,
// The SCT is from a known log, and the signature is valid.
Valid,
// The SCT is from a known disqualified log, and the signature is valid.
// For the disqualification time of the log see |logDisqualificationTime|.
ValidFromDisqualifiedLog,
// The SCT is from an unknown log and can not be verified.
UnknownLog,
// The SCT is from a known log, but the signature is invalid.
InvalidSignature,
// The SCT signature is valid, but the timestamp is in the future.
// Such SCTs are considered invalid (see RFC 6962, Section 5.2).
InvalidTimestamp,
};
enum class Origin {
Unknown,
Embedded,
TLSExtension,
OCSPResponse,
};
Status status;
Origin origin;
SCTOrigin origin;
CTLogOperatorId logOperatorId;
uint64_t logDisqualificationTime;
CTLogState logState;
uint64_t logTimestamp;
};
typedef std::vector<VerifiedSCT> VerifiedSCTList;
@ -74,6 +59,19 @@ class CTVerifyResult {
// standard.
// |decodingErrors| field counts the errors of the above kind.
size_t decodingErrors;
// The number of SCTs encountered from unknown logs.
size_t sctsFromUnknownLogs;
// The number of SCTs encountered with invalid signatures.
size_t sctsWithInvalidSignatures;
// The number of SCTs encountered with timestamps in the future.
size_t sctsWithInvalidTimestamps;
// The number of SCTs that were embedded in the certificate.
size_t embeddedSCTs;
// The number of SCTs included in the TLS handshake.
size_t sctsFromTLSHandshake;
// The number of SCTs delivered via OCSP.
size_t sctsFromOCSP;
void Reset();
};

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

@ -14,13 +14,6 @@ namespace ct {
using namespace mozilla::pkix;
// Note: this moves |verifiedSct| to the target list in |result|.
static void StoreVerifiedSct(CTVerifyResult& result, VerifiedSCT&& verifiedSct,
VerifiedSCT::Status status) {
verifiedSct.status = status;
result.verifiedScts.push_back(std::move(verifiedSct));
}
void MultiLogCTVerifier::AddLog(CTLogVerifier&& log) {
mLogs.push_back(std::move(log));
}
@ -43,8 +36,8 @@ Result MultiLogCTVerifier::Verify(Input cert, Input issuerSubjectPublicKeyInfo,
if (rv != Success) {
return rv;
}
rv = VerifySCTs(sctListFromCert, precertEntry,
VerifiedSCT::Origin::Embedded, time, result);
rv = VerifySCTs(sctListFromCert, precertEntry, SCTOrigin::Embedded, time,
result);
if (rv != Success) {
return rv;
}
@ -55,8 +48,8 @@ Result MultiLogCTVerifier::Verify(Input cert, Input issuerSubjectPublicKeyInfo,
// Verify SCTs from a stapled OCSP response
if (sctListFromOCSPResponse.GetLength() > 0) {
rv = VerifySCTs(sctListFromOCSPResponse, x509Entry,
VerifiedSCT::Origin::OCSPResponse, time, result);
rv = VerifySCTs(sctListFromOCSPResponse, x509Entry, SCTOrigin::OCSPResponse,
time, result);
if (rv != Success) {
return rv;
}
@ -64,8 +57,8 @@ Result MultiLogCTVerifier::Verify(Input cert, Input issuerSubjectPublicKeyInfo,
// Verify SCTs from a TLS extension
if (sctListFromTLSExtension.GetLength() > 0) {
rv = VerifySCTs(sctListFromTLSExtension, x509Entry,
VerifiedSCT::Origin::TLSExtension, time, result);
rv = VerifySCTs(sctListFromTLSExtension, x509Entry, SCTOrigin::TLSExtension,
time, result);
if (rv != Success) {
return rv;
}
@ -106,7 +99,7 @@ void DecodeSCTs(Input encodedSctList,
Result MultiLogCTVerifier::VerifySCTs(Input encodedSctList,
const LogEntry& expectedEntry,
VerifiedSCT::Origin origin, Time time,
SCTOrigin origin, Time time,
CTVerifyResult& result) {
std::vector<SignedCertificateTimestamp> decodedSCTs;
DecodeSCTs(encodedSctList, decodedSCTs, result.decodingErrors);
@ -122,15 +115,23 @@ Result MultiLogCTVerifier::VerifySCTs(Input encodedSctList,
Result MultiLogCTVerifier::VerifySingleSCT(SignedCertificateTimestamp&& sct,
const LogEntry& expectedEntry,
VerifiedSCT::Origin origin,
Time time, CTVerifyResult& result) {
VerifiedSCT verifiedSct;
verifiedSct.origin = origin;
verifiedSct.sct = std::move(sct);
SCTOrigin origin, Time time,
CTVerifyResult& result) {
switch (origin) {
case SCTOrigin::Embedded:
result.embeddedSCTs++;
break;
case SCTOrigin::TLSExtension:
result.sctsFromTLSHandshake++;
break;
case SCTOrigin::OCSPResponse:
result.sctsFromOCSP++;
break;
}
CTLogVerifier* matchingLog = nullptr;
for (auto& log : mLogs) {
if (log.keyId() == verifiedSct.sct.logId) {
if (log.keyId() == sct.logId) {
matchingLog = &log;
break;
}
@ -138,25 +139,20 @@ Result MultiLogCTVerifier::VerifySingleSCT(SignedCertificateTimestamp&& sct,
if (!matchingLog) {
// SCT does not match any known log.
StoreVerifiedSct(result, std::move(verifiedSct),
VerifiedSCT::Status::UnknownLog);
result.sctsFromUnknownLogs++;
return Success;
}
verifiedSct.logOperatorId = matchingLog->operatorId();
if (!matchingLog->SignatureParametersMatch(verifiedSct.sct.signature)) {
if (!matchingLog->SignatureParametersMatch(sct.signature)) {
// SCT signature parameters do not match the log's.
StoreVerifiedSct(result, std::move(verifiedSct),
VerifiedSCT::Status::InvalidSignature);
result.sctsWithInvalidSignatures++;
return Success;
}
Result rv = matchingLog->Verify(expectedEntry, verifiedSct.sct);
Result rv = matchingLog->Verify(expectedEntry, sct);
if (rv != Success) {
if (rv == Result::ERROR_BAD_SIGNATURE) {
StoreVerifiedSct(result, std::move(verifiedSct),
VerifiedSCT::Status::InvalidSignature);
result.sctsWithInvalidSignatures++;
return Success;
}
return rv;
@ -168,25 +164,15 @@ Result MultiLogCTVerifier::VerifySingleSCT(SignedCertificateTimestamp&& sct,
// pkix::Time, we need to round it either up or down. In our case, rounding up
// (towards the future) is more "secure", although practically
// it does not matter.
Time sctTime =
TimeFromEpochInSeconds((verifiedSct.sct.timestamp + 999u) / 1000u);
Time sctTime = TimeFromEpochInSeconds((sct.timestamp + 999u) / 1000u);
if (sctTime > time) {
StoreVerifiedSct(result, std::move(verifiedSct),
VerifiedSCT::Status::InvalidTimestamp);
result.sctsWithInvalidTimestamps++;
return Success;
}
// SCT verified ok, see if the log is qualified. Since SCTs from
// disqualified logs are treated as valid under certain circumstances (see
// the CT Policy), the log qualification check must be the last one we do.
if (matchingLog->isDisqualified()) {
verifiedSct.logDisqualificationTime = matchingLog->disqualificationTime();
StoreVerifiedSct(result, std::move(verifiedSct),
VerifiedSCT::Status::ValidFromDisqualifiedLog);
return Success;
}
StoreVerifiedSct(result, std::move(verifiedSct), VerifiedSCT::Status::Valid);
VerifiedSCT verifiedSct(std::move(sct), origin, matchingLog->operatorId(),
matchingLog->state(), matchingLog->timestamp());
result.verifiedScts.push_back(std::move(verifiedSct));
return Success;
}

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

@ -68,15 +68,14 @@ class MultiLogCTVerifier {
// placing the verification results in |result|. The SCTs in the list
// come from |origin| (as will be reflected in the origin field of each SCT).
pkix::Result VerifySCTs(pkix::Input encodedSctList,
const LogEntry& expectedEntry,
VerifiedSCT::Origin origin, pkix::Time time,
CTVerifyResult& result);
const LogEntry& expectedEntry, SCTOrigin origin,
pkix::Time time, CTVerifyResult& result);
// Verifies a single, parsed SCT against all known logs.
// Note: moves |sct| to the target list in |result|, invalidating |sct|.
pkix::Result VerifySingleSCT(SignedCertificateTimestamp&& sct,
const ct::LogEntry& expectedEntry,
VerifiedSCT::Origin origin, pkix::Time time,
SCTOrigin origin, pkix::Time time,
CTVerifyResult& result);
// The list of known logs.

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

@ -11,6 +11,7 @@ EXPORTS += [
"BTTypes.h",
"BTVerifier.h",
"Buffer.h",
"CTKnownLogs.h",
"CTLog.h",
"CTPolicyEnforcer.h",
"CTVerifyResult.h",

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

@ -23,14 +23,12 @@ class CTLogVerifierTest : public ::testing::Test {
abort();
}
ASSERT_EQ(Success,
mLog.Init(InputForBuffer(GetTestPublicKey()), -1 /*operator id*/,
CTLogStatus::Included, 0 /*disqualification time*/));
ASSERT_EQ(Success, mLog.Init(InputForBuffer(GetTestPublicKey())));
ASSERT_EQ(GetTestPublicKeyId(), mLog.keyId());
}
protected:
CTLogVerifier mLog;
CTLogVerifier mLog = CTLogVerifier(-1, CTLogState::Admissible, 0);
};
TEST_F(CTLogVerifierTest, VerifiesCertSCT) {
@ -108,10 +106,8 @@ TEST_F(CTLogVerifierTest, ExcessDataInPublicKey) {
std::string extra = "extra";
key.insert(key.end(), extra.begin(), extra.end());
CTLogVerifier log;
EXPECT_NE(Success,
log.Init(InputForBuffer(key), -1 /*operator id*/,
CTLogStatus::Included, 0 /*disqualification time*/));
CTLogVerifier log(-1, CTLogState::Admissible, 0);
EXPECT_NE(Success, log.Init(InputForBuffer(key)));
}
} // namespace ct

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

@ -30,9 +30,7 @@ class CTObjectsExtractorTest : public ::testing::Test {
mCaCertSPKI = ExtractCertSPKI(mCaCert);
Buffer logPublicKey = GetTestPublicKey();
ASSERT_EQ(Success,
mLog.Init(InputForBuffer(logPublicKey), -1 /*operator id*/,
CTLogStatus::Included, 0 /*disqualification time*/));
ASSERT_EQ(Success, mLog.Init(InputForBuffer(logPublicKey)));
}
protected:
@ -40,7 +38,7 @@ class CTObjectsExtractorTest : public ::testing::Test {
Buffer mEmbeddedCert;
Buffer mCaCert;
Buffer mCaCertSPKI;
CTLogVerifier mLog;
CTLogVerifier mLog = CTLogVerifier(-1, CTLogState::Admissible, 0);
};
TEST_F(CTObjectsExtractorTest, ExtractPrecert) {

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

@ -44,32 +44,26 @@ class CTPolicyEnforcerTest : public ::testing::Test {
}
void AddSct(VerifiedSCTList& verifiedScts, size_t logNo,
CTLogOperatorId operatorId, VerifiedSCT::Origin origin,
uint64_t timestamp,
VerifiedSCT::Status status = VerifiedSCT::Status::Valid) {
VerifiedSCT verifiedSct;
verifiedSct.status = status;
verifiedSct.origin = origin;
verifiedSct.logOperatorId = operatorId;
verifiedSct.logDisqualificationTime =
status == VerifiedSCT::Status::ValidFromDisqualifiedLog
? DISQUALIFIED_AT
: UINT64_MAX;
verifiedSct.sct.version = SignedCertificateTimestamp::Version::V1;
verifiedSct.sct.timestamp = timestamp;
CTLogOperatorId operatorId, SCTOrigin origin, uint64_t timestamp,
CTLogState logState = CTLogState::Admissible) {
SignedCertificateTimestamp sct;
sct.version = SignedCertificateTimestamp::Version::V1;
sct.timestamp = timestamp;
Buffer logId;
GetLogId(logId, logNo);
verifiedSct.sct.logId = std::move(logId);
sct.logId = std::move(logId);
VerifiedSCT verifiedSct(std::move(sct), origin, operatorId, logState,
LOG_TIMESTAMP);
verifiedScts.push_back(std::move(verifiedSct));
}
void AddMultipleScts(
VerifiedSCTList& verifiedScts, size_t logsCount, uint8_t operatorsCount,
VerifiedSCT::Origin origin, uint64_t timestamp,
VerifiedSCT::Status status = VerifiedSCT::Status::Valid) {
void AddMultipleScts(VerifiedSCTList& verifiedScts, size_t logsCount,
uint8_t operatorsCount, SCTOrigin origin,
uint64_t timestamp,
CTLogState logState = CTLogState::Admissible) {
for (size_t logNo = 0; logNo < logsCount; logNo++) {
CTLogOperatorId operatorId = logNo % operatorsCount;
AddSct(verifiedScts, logNo, operatorId, origin, timestamp, status);
AddSct(verifiedScts, logNo, operatorId, origin, timestamp, logState);
}
}
@ -99,9 +93,9 @@ class CTPolicyEnforcerTest : public ::testing::Test {
CTLogOperatorList NO_OPERATORS;
CTLogOperatorList OPERATORS_1_AND_2;
const VerifiedSCT::Origin ORIGIN_EMBEDDED = VerifiedSCT::Origin::Embedded;
const VerifiedSCT::Origin ORIGIN_TLS = VerifiedSCT::Origin::TLSExtension;
const VerifiedSCT::Origin ORIGIN_OCSP = VerifiedSCT::Origin::OCSPResponse;
const SCTOrigin ORIGIN_EMBEDDED = SCTOrigin::Embedded;
const SCTOrigin ORIGIN_TLS = SCTOrigin::TLSExtension;
const SCTOrigin ORIGIN_OCSP = SCTOrigin::OCSPResponse;
// 4 years of cert lifetime requires 5 SCTs for the embedded case.
const size_t DEFAULT_MONTHS = 4 * 12L;
@ -110,10 +104,10 @@ class CTPolicyEnforcerTest : public ::testing::Test {
const uint64_t TIMESTAMP_1 = 1439596800000L;
// Date.parse("2016-04-15T00:00:00Z")
const uint64_t DISQUALIFIED_AT = 1460678400000L;
const uint64_t LOG_TIMESTAMP = 1460678400000L;
// Date.parse("2016-04-01T00:00:00Z")
const uint64_t BEFORE_DISQUALIFIED = 1459468800000L;
const uint64_t BEFORE_RETIREMENT = 1459468800000L;
// Date.parse("2016-04-16T00:00:00Z")
const uint64_t AFTER_DISQUALIFIED = 1460764800000L;
@ -206,23 +200,23 @@ TEST_F(CTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughFreshSCTs) {
// SCT from before disqualification.
scts.clear();
AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1);
AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_TLS, BEFORE_DISQUALIFIED,
VerifiedSCT::Status::ValidFromDisqualifiedLog);
AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_TLS, BEFORE_RETIREMENT,
CTLogState::Retired);
CheckCompliance(scts, DEFAULT_MONTHS, NO_OPERATORS,
CTPolicyCompliance::NotEnoughScts);
// SCT from after disqualification.
scts.clear();
AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1);
AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_TLS, AFTER_DISQUALIFIED,
VerifiedSCT::Status::ValidFromDisqualifiedLog);
CTLogState::Retired);
CheckCompliance(scts, DEFAULT_MONTHS, NO_OPERATORS,
CTPolicyCompliance::NotEnoughScts);
// Embedded SCT from before disqualification.
scts.clear();
AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1);
AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_EMBEDDED, BEFORE_DISQUALIFIED,
VerifiedSCT::Status::ValidFromDisqualifiedLog);
AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_EMBEDDED, BEFORE_RETIREMENT,
CTLogState::Retired);
CheckCompliance(scts, DEFAULT_MONTHS, NO_OPERATORS,
CTPolicyCompliance::NotEnoughScts);
@ -230,7 +224,7 @@ TEST_F(CTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughFreshSCTs) {
scts.clear();
AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1);
AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_EMBEDDED, AFTER_DISQUALIFIED,
VerifiedSCT::Status::ValidFromDisqualifiedLog);
CTLogState::Retired);
CheckCompliance(scts, DEFAULT_MONTHS, NO_OPERATORS,
CTPolicyCompliance::NotEnoughScts);
}
@ -244,8 +238,8 @@ TEST_F(CTPolicyEnforcerTest,
AddSct(scts, LOG_2, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
AddSct(scts, LOG_3, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
AddSct(scts, LOG_4, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
AddSct(scts, LOG_5, OPERATOR_2, ORIGIN_EMBEDDED, BEFORE_DISQUALIFIED,
VerifiedSCT::Status::ValidFromDisqualifiedLog);
AddSct(scts, LOG_5, OPERATOR_2, ORIGIN_EMBEDDED, BEFORE_RETIREMENT,
CTLogState::Retired);
CheckCompliance(scts, DEFAULT_MONTHS, NO_OPERATORS,
CTPolicyCompliance::Compliant);
@ -261,7 +255,7 @@ TEST_F(CTPolicyEnforcerTest,
AddSct(scts, LOG_3, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
AddSct(scts, LOG_4, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
AddSct(scts, LOG_5, OPERATOR_2, ORIGIN_EMBEDDED, AFTER_DISQUALIFIED,
VerifiedSCT::Status::ValidFromDisqualifiedLog);
CTLogState::Retired);
CheckCompliance(scts, DEFAULT_MONTHS, NO_OPERATORS,
CTPolicyCompliance::NotEnoughScts);
@ -273,7 +267,7 @@ TEST_F(CTPolicyEnforcerTest,
// 5 embedded SCTs required for DEFAULT_MONTHS.
AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_EMBEDDED, AFTER_DISQUALIFIED,
VerifiedSCT::Status::ValidFromDisqualifiedLog);
CTLogState::Retired);
AddSct(scts, LOG_2, OPERATOR_1, ORIGIN_EMBEDDED, AFTER_DISQUALIFIED);
AddSct(scts, LOG_3, OPERATOR_1, ORIGIN_EMBEDDED, AFTER_DISQUALIFIED);
AddSct(scts, LOG_4, OPERATOR_1, ORIGIN_EMBEDDED, AFTER_DISQUALIFIED);

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

@ -30,10 +30,9 @@ class MultiLogCTVerifierTest : public ::testing::Test {
abort();
}
CTLogVerifier log;
ASSERT_EQ(Success,
log.Init(InputForBuffer(GetTestPublicKey()), mLogOperatorID,
CTLogStatus::Included, 0 /*disqualification time*/));
CTLogVerifier log(mLogOperatorID, CTLogState::Admissible, 0);
;
ASSERT_EQ(Success, log.Init(InputForBuffer(GetTestPublicKey())));
mVerifier.AddLog(std::move(log));
mTestCert = GetDEREncodedX509Cert();
@ -49,10 +48,10 @@ class MultiLogCTVerifierTest : public ::testing::Test {
}
void CheckForSingleValidSCTInResult(const CTVerifyResult& result,
VerifiedSCT::Origin origin) {
SCTOrigin origin) {
EXPECT_EQ(0U, result.decodingErrors);
ASSERT_EQ(1U, result.verifiedScts.size());
EXPECT_EQ(VerifiedSCT::Status::Valid, result.verifiedScts[0].status);
EXPECT_EQ(CTLogState::Admissible, result.verifiedScts[0].logState);
EXPECT_EQ(origin, result.verifiedScts[0].origin);
EXPECT_EQ(mLogOperatorID, result.verifiedScts[0].logOperatorId);
}
@ -83,7 +82,7 @@ class MultiLogCTVerifierTest : public ::testing::Test {
mVerifier.Verify(InputForBuffer(cert), InputForBuffer(issuerSPKI),
InputForBuffer(sctList), Input(), Input(), mNow,
result));
CheckForSingleValidSCTInResult(result, VerifiedSCT::Origin::Embedded);
CheckForSingleValidSCTInResult(result, SCTOrigin::Embedded);
}
protected:
@ -157,7 +156,7 @@ TEST_F(MultiLogCTVerifierTest, VerifiesSCTFromOCSP) {
mVerifier.Verify(InputForBuffer(mTestCert), Input(), Input(),
InputForBuffer(sctList), Input(), mNow, result));
CheckForSingleValidSCTInResult(result, VerifiedSCT::Origin::OCSPResponse);
CheckForSingleValidSCTInResult(result, SCTOrigin::OCSPResponse);
}
TEST_F(MultiLogCTVerifierTest, VerifiesSCTFromTLS) {
@ -170,7 +169,7 @@ TEST_F(MultiLogCTVerifierTest, VerifiesSCTFromTLS) {
mVerifier.Verify(InputForBuffer(mTestCert), Input(), Input(),
Input(), InputForBuffer(sctList), mNow, result));
CheckForSingleValidSCTInResult(result, VerifiedSCT::Origin::TLSExtension);
CheckForSingleValidSCTInResult(result, SCTOrigin::TLSExtension);
}
TEST_F(MultiLogCTVerifierTest, VerifiesSCTFromMultipleSources) {
@ -188,20 +187,17 @@ TEST_F(MultiLogCTVerifierTest, VerifiesSCTFromMultipleSources) {
size_t tlsExtensionCount = 0;
size_t ocspResponseCount = 0;
for (const VerifiedSCT& verifiedSct : result.verifiedScts) {
EXPECT_EQ(VerifiedSCT::Status::Valid, verifiedSct.status);
EXPECT_EQ(CTLogState::Admissible, verifiedSct.logState);
switch (verifiedSct.origin) {
case VerifiedSCT::Origin::Embedded:
case SCTOrigin::Embedded:
embeddedCount++;
break;
case VerifiedSCT::Origin::TLSExtension:
case SCTOrigin::TLSExtension:
tlsExtensionCount++;
break;
case VerifiedSCT::Origin::OCSPResponse:
case SCTOrigin::OCSPResponse:
ocspResponseCount++;
break;
case VerifiedSCT::Origin::Unknown:
default:
ASSERT_TRUE(false);
}
}
EXPECT_EQ(embeddedCount, 0u);
@ -219,17 +215,15 @@ TEST_F(MultiLogCTVerifierTest, IdentifiesSCTFromUnknownLog) {
Input(), InputForBuffer(sctList), mNow, result));
EXPECT_EQ(0U, result.decodingErrors);
ASSERT_EQ(1U, result.verifiedScts.size());
EXPECT_EQ(VerifiedSCT::Status::UnknownLog, result.verifiedScts[0].status);
EXPECT_EQ(0U, result.verifiedScts.size());
EXPECT_EQ(1U, result.sctsFromUnknownLogs);
}
TEST_F(MultiLogCTVerifierTest, IdentifiesSCTFromDisqualifiedLog) {
MultiLogCTVerifier verifier;
CTLogVerifier log;
const uint64_t disqualificationTime = 12345u;
ASSERT_EQ(Success,
log.Init(InputForBuffer(GetTestPublicKey()), mLogOperatorID,
CTLogStatus::Disqualified, disqualificationTime));
const uint64_t retiredTime = 12345u;
CTLogVerifier log(mLogOperatorID, CTLogState::Retired, retiredTime);
ASSERT_EQ(Success, log.Init(InputForBuffer(GetTestPublicKey())));
verifier.AddLog(std::move(log));
Buffer sct(GetTestSignedCertificateTimestamp());
@ -243,10 +237,8 @@ TEST_F(MultiLogCTVerifierTest, IdentifiesSCTFromDisqualifiedLog) {
EXPECT_EQ(0U, result.decodingErrors);
ASSERT_EQ(1U, result.verifiedScts.size());
EXPECT_EQ(VerifiedSCT::Status::ValidFromDisqualifiedLog,
result.verifiedScts[0].status);
EXPECT_EQ(disqualificationTime,
result.verifiedScts[0].logDisqualificationTime);
EXPECT_EQ(CTLogState::Retired, result.verifiedScts[0].logState);
EXPECT_EQ(retiredTime, result.verifiedScts[0].logTimestamp);
EXPECT_EQ(mLogOperatorID, result.verifiedScts[0].logOperatorId);
}

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

@ -438,43 +438,15 @@ static SECStatus BlockServerCertChangeForSpdy(
}
void GatherTelemetryForSingleSCT(const ct::VerifiedSCT& verifiedSct) {
// See SSL_SCTS_ORIGIN in Histograms.json.
uint32_t origin = 0;
switch (verifiedSct.origin) {
case ct::VerifiedSCT::Origin::Embedded:
origin = 1;
break;
case ct::VerifiedSCT::Origin::TLSExtension:
origin = 2;
break;
case ct::VerifiedSCT::Origin::OCSPResponse:
origin = 3;
break;
default:
MOZ_ASSERT_UNREACHABLE("Unexpected VerifiedSCT::Origin type");
}
Telemetry::Accumulate(Telemetry::SSL_SCTS_ORIGIN, origin);
// See SSL_SCTS_VERIFICATION_STATUS in Histograms.json.
uint32_t verificationStatus = 0;
switch (verifiedSct.status) {
case ct::VerifiedSCT::Status::Valid:
switch (verifiedSct.logState) {
case ct::CTLogState::Admissible:
verificationStatus = 1;
break;
case ct::VerifiedSCT::Status::UnknownLog:
verificationStatus = 2;
break;
case ct::VerifiedSCT::Status::InvalidSignature:
verificationStatus = 3;
break;
case ct::VerifiedSCT::Status::InvalidTimestamp:
verificationStatus = 4;
break;
case ct::VerifiedSCT::Status::ValidFromDisqualifiedLog:
case ct::CTLogState::Retired:
verificationStatus = 5;
break;
default:
MOZ_ASSERT_UNREACHABLE("Unexpected VerifiedSCT::Status type");
}
Telemetry::Accumulate(Telemetry::SSL_SCTS_VERIFICATION_STATUS,
verificationStatus);
@ -492,11 +464,30 @@ void GatherCertificateTransparencyTelemetry(
GatherTelemetryForSingleSCT(sct);
}
// Decoding errors are reported to the 0th bucket
// of the SSL_SCTS_VERIFICATION_STATUS enumerated probe.
// See SSL_SCTS_VERIFICATION_STATUS in Histograms.json.
for (size_t i = 0; i < info.verifyResult.decodingErrors; ++i) {
Telemetry::Accumulate(Telemetry::SSL_SCTS_VERIFICATION_STATUS, 0);
}
for (size_t i = 0; i < info.verifyResult.sctsFromUnknownLogs; ++i) {
Telemetry::Accumulate(Telemetry::SSL_SCTS_VERIFICATION_STATUS, 2);
}
for (size_t i = 0; i < info.verifyResult.sctsWithInvalidSignatures; ++i) {
Telemetry::Accumulate(Telemetry::SSL_SCTS_VERIFICATION_STATUS, 3);
}
for (size_t i = 0; i < info.verifyResult.sctsWithInvalidTimestamps; ++i) {
Telemetry::Accumulate(Telemetry::SSL_SCTS_VERIFICATION_STATUS, 4);
}
// See SSL_SCTS_ORIGIN in Histograms.json.
for (size_t i = 0; i < info.verifyResult.embeddedSCTs; ++i) {
Telemetry::Accumulate(Telemetry::SSL_SCTS_ORIGIN, 1);
}
for (size_t i = 0; i < info.verifyResult.sctsFromTLSHandshake; ++i) {
Telemetry::Accumulate(Telemetry::SSL_SCTS_ORIGIN, 2);
}
for (size_t i = 0; i < info.verifyResult.sctsFromOCSP; ++i) {
Telemetry::Accumulate(Telemetry::SSL_SCTS_ORIGIN, 3);
}
// Handle the histogram of SCTs counts.
uint32_t sctsCount =

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

@ -51,14 +51,19 @@ OUTPUT_TEMPLATE = """\
static const PRTime kCTExpirationTime = INT64_C($expiration_time);
namespace mozilla::ct {
enum class CTLogState {
Admissible, // Qualified, Usable, or ReadOnly
Retired,
};
struct CTLogInfo {
// See bug 1338873 about making these fields const.
const char* name;
CTLogState state;
uint64_t timestamp;
// Index within kCTLogOperatorList.
mozilla::ct::CTLogStatus status;
// 0 for qualified logs, disqualification time for disqualified logs
// (in milliseconds, measured since the epoch, ignoring leap seconds).
uint64_t disqualificationTime;
size_t operatorIndex;
const char* key;
size_t keyLength;
@ -78,11 +83,13 @@ const CTLogOperatorInfo kCTLogOperatorList[] = {
$operators
};
} // namespace mozilla::ct
#endif // $include_guard
"""
def get_disqualification_time(time_str):
def get_timestamp(time_str):
"""
Convert a time string such as "2017-01-01T00:00:00Z" to an integer
representing milliseconds since the epoch.
@ -117,13 +124,34 @@ def get_operator_index(json_data, target_name):
LOG_INFO_TEMPLATE = """\
{$description, $status,
$disqualification_time, // $disqualification_time_comment
$operator_index, // $operator_comment
{$description, $state,
$timestamp, // $timestamp_comment
$operator_index,$spaces // $operator_comment
$indented_log_key,
$log_key_len}"""
class UnhandledLogStateException(Exception):
pass
def map_state(state):
"""
Maps a log state string to the appropriate CTLogState enum value or None,
if the log state indicates that the log should not be included. Valid
states to be included are 'qualified', 'usable', 'readonly', or 'retired'.
Valid states that are not to be included are 'pending' or 'rejected'.
"""
if state == "qualified" or state == "usable" or state == "readonly":
return "CTLogState::Admissible"
elif state == "retired":
return "CTLogState::Retired"
elif state == "pending" or state == "rejected":
return None
else:
raise UnhandledLogStateException("unhandled log state '%s'" % state)
def get_log_info_structs(json_data):
"""Return array of CTLogInfo initializers for the known logs."""
tmpl = Template(LOG_INFO_TEMPLATE)
@ -133,24 +161,20 @@ def get_log_info_structs(json_data):
for log in operator["logs"]:
log_key = base64.b64decode(log["key"])
operator_index = get_operator_index(json_data, operator_name)
if "disqualification_time" in log:
status = "mozilla::ct::CTLogStatus::Disqualified"
disqualification_time = get_disqualification_time(
log["disqualification_time"]
)
disqualification_time_comment = 'Date.parse("{0}")'.format(
log["disqualification_time"]
)
else:
status = "mozilla::ct::CTLogStatus::Included"
disqualification_time = 0
disqualification_time_comment = "no disqualification time"
state = list(log["state"].keys())[0]
timestamp_comment = log["state"][state]["timestamp"]
timestamp = get_timestamp(timestamp_comment)
state = map_state(state)
if state is None:
continue
is_test_log = "test_only" in operator and operator["test_only"]
prefix = ""
suffix = ","
if is_test_log:
prefix = "#ifdef DEBUG\n"
suffix = ",\n#endif // DEBUG"
num_spaces = len(str(timestamp)) - len(str(operator_index))
spaces = " " * num_spaces
toappend = tmpl.substitute(
# Use json.dumps for C-escaping strings.
# Not perfect but close enough.
@ -159,9 +183,10 @@ def get_log_info_structs(json_data):
operator_comment="operated by {0}".
# The comment must not contain "/".
format(operator_name).replace("/", "|"),
status=status,
disqualification_time=disqualification_time,
disqualification_time_comment=disqualification_time_comment,
state=state,
timestamp=timestamp,
spaces=spaces,
timestamp_comment=timestamp_comment,
# Maximum line width is 80.
indented_log_key="\n".join(
[' "{0}"'.format(l) for l in get_hex_lines(log_key, 74)]
@ -234,7 +259,11 @@ def patch_in_test_logs(json_data):
tIqVYR3uJtYlnauRCE42yxwkBCy/Fosv5fGPmRcxuLP+SSP6clHEMdUDrNoYCjXt
jQIDAQAB
""",
"operated_by": [max_id + 1],
"state": {
"qualified": {
"timestamp": "2024-07-22T16:44:26Z",
},
},
},
{
"description": "Mozilla Test EC Log",
@ -243,7 +272,11 @@ def patch_in_test_logs(json_data):
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAET7+7u2Hg+PmxpgpZrIcE4uwFC0I+
PPcukj8sT3lLRVwqadIzRWw2xBGdBwbgDu3I0ZOQ15kbey0HowTqoEqmwA==
""",
"operated_by": [max_id + 1],
"state": {
"qualified": {
"timestamp": "2024-07-22T16:44:26Z",
},
},
},
],
}
@ -264,7 +297,11 @@ def patch_in_test_logs(json_data):
gys1uJMPdLqQqovHYWckKrH9bWIUDRjEwLjGj8N0hFcyStfehuZVLx0eGR1xIWjT
uwIDAQAB
""",
"operated_by": [max_id + 2],
"state": {
"qualified": {
"timestamp": "2024-07-22T16:44:26Z",
},
},
}
],
}
@ -303,7 +340,11 @@ def run(args):
Load the input JSON file and generate the C++ header according to the
command line arguments.
"""
if args.url:
if args.json_file:
print("Reading file: ", args.json_file)
with open(args.json_file, "rb") as json_file:
json_text = json_file.read()
else:
json_text = get_content_at(args.url)
signature = get_content_at(args.signature_url)
key = read_rsa_key(args.key_file)
@ -316,10 +357,6 @@ def run(args):
print("Writing output: ", args.json_file_out)
with open(args.json_file_out, "wb") as json_file_out:
json_file_out.write(json_text)
else:
print("Reading file: ", args.json_file)
with open(args.json_file, "rb") as json_file:
json_text = json_file.read()
json_data = json.loads(json_text)
patch_in_test_logs(json_data)
@ -362,10 +399,11 @@ def parse_arguments_and_run():
)
arg_parser.add_argument(
"--json-file",
default=mozpath.join(
nargs="?",
const=mozpath.join(
buildconfig.topsrcdir, "security", "manager", "tools", "log_list.json"
),
help="read the known CT logs JSON data from the specified file (default: %(default)s)",
help="read the known CT logs JSON data from the specified file (default: %(const)s)",
)
arg_parser.add_argument(
"--json-file-out",

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

@ -1,6 +1,6 @@
{
"version": "39.9",
"log_list_timestamp": "2024-07-29T12:55:53Z",
"version": "40.3",
"log_list_timestamp": "2024-08-02T12:55:10Z",
"operators": [
{
"name": "Google",
@ -578,6 +578,70 @@
"start_inclusive": "2025-07-01T00:00:00Z",
"end_exclusive": "2026-01-01T00:00:00Z"
}
},
{
"description": "Sectigo 'Mammoth2026h1'",
"log_id": "JS+Uwisp6W6fQRpyBytpXFtS/5epDSVAu/zcUexN7gs=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnssMilHMiuILzoXmr00x2xtqTP2weWuZl8Bd+25FUB1iqsafm2sFPaKrK12Im1Ao4p5YpaX6+eP6FSXjFBMyxA==",
"url": "https://mammoth2026h1.ct.sectigo.com/",
"mmd": 86400,
"state": {
"qualified": {
"timestamp": "2024-07-30T04:00:00Z"
}
},
"temporal_interval": {
"start_inclusive": "2026-01-01T00:00:00Z",
"end_exclusive": "2026-07-01T00:00:00Z"
}
},
{
"description": "Sectigo 'Mammoth2026h2'",
"log_id": "lLHBirDQV8R74KwEDh8svI3DdXJ7yVHyClJhJoY7pzw=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7INh8te0u+TkO+vIY3WYz2GQYxQ9XyLfdLpQp1ibaX3mY4lt2ddRhD/4AtjI/8KXceV+J/VysY8kJ1cKDXTAtg==",
"url": "https://mammoth2026h2.ct.sectigo.com/",
"mmd": 86400,
"state": {
"qualified": {
"timestamp": "2024-07-30T04:00:00Z"
}
},
"temporal_interval": {
"start_inclusive": "2026-07-01T00:00:00Z",
"end_exclusive": "2027-01-01T00:00:00Z"
}
},
{
"description": "Sectigo 'Sabre2026h1'",
"log_id": "VmzVo3a+g9/jQrZ1xJwjJJinabrDgsurSaOHfZqzLQE=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhCa8Nr3YjTyHnuAQr82U2de5UYA0fvdYXHPq6wmTuBB7kJx9x82WQ+1TbpUhRmdR8N62yZ6q4oBtziWBNNdqYA==",
"url": "https://sabre2026h1.ct.sectigo.com/",
"mmd": 86400,
"state": {
"qualified": {
"timestamp": "2024-07-30T04:00:00Z"
}
},
"temporal_interval": {
"start_inclusive": "2026-01-01T00:00:00Z",
"end_exclusive": "2026-07-01T00:00:00Z"
}
},
{
"description": "Sectigo 'Sabre2026h2'",
"log_id": "H1bRq5RwSkHdP+r99GmTVTAsFDG/5hNGCJ//rnldzC8=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzjXK7DkHgtp3J4bk8n7F3Djym6mrjKfA7YMePmobwPCVVroyM0x1fAkH6eE+ZTVj8Em+ctGqna99CMS0jVk9cw==",
"url": "https://sabre2026h2.ct.sectigo.com/",
"mmd": 86400,
"state": {
"qualified": {
"timestamp": "2024-07-30T04:00:00Z"
}
},
"temporal_interval": {
"start_inclusive": "2026-07-01T00:00:00Z",
"end_exclusive": "2027-01-01T00:00:00Z"
}
}
]
},