Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions crates/mtc_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use x509_cert::{
time::Validity,
Certificate, TbsCertificate,
};
use x509_util::{validate_chain_lax, CertPool};
use x509_util::{validate_chain_lax, CertPool, ValidationOptions};

// The OID to use for experimentaion. Eventually, we'll switch to "1.3.6.1.5.5.7.TBD1.TBD2"
// as described in <https://www.ietf.org/archive/id/draft-davidben-tls-merkle-tree-certs-05.html#name-log-ids>.
Expand Down Expand Up @@ -639,7 +639,17 @@ pub fn validate_correspondence(
// Run the validation logic with the above validation hook. We do
// not give `validate_chain_lax` a window for the `not_after` validity,
// since validity is checked within the validator hook.
validate_chain_lax(raw_chain, roots, None, None, validator_hook).map_err(|e| match e {
validate_chain_lax(
raw_chain,
roots,
&ValidationOptions {
stop_on_first_trusted_cert: true,
not_after_start: None,
not_after_end: None,
},
validator_hook,
)
.map_err(|e| match e {
x509_util::HookOrValidationError::Validation(ve) => ve.into(),
x509_util::HookOrValidationError::Hook(he) => he,
})
Expand Down Expand Up @@ -742,7 +752,16 @@ pub fn validate_chain(
// Run the validation and return the hook-constructed pending entry. We do
// not give `validate_chain_lax` a window for the `not_after` validity,
// since validity is checked within the validator hook.
let pending_entry = validate_chain_lax(raw_chain, roots, None, None, validator_hook);
let pending_entry = validate_chain_lax(
raw_chain,
roots,
&ValidationOptions {
stop_on_first_trusted_cert: true,
not_after_start: None,
not_after_end: None,
},
validator_hook,
);
pending_entry.map_err(|e| match e {
x509_util::HookOrValidationError::Validation(ve) => ve.into(),
x509_util::HookOrValidationError::Hook(he) => he,
Expand Down
2 changes: 2 additions & 0 deletions crates/static_ct_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ pub enum StaticCTError {
UnknownType,
#[error("trailing data")]
TrailingData,
#[error("invalid certificate chain per CT")]
InvalidChain,
#[error("invalid leaf certificate per CT")]
InvalidLeaf,
#[error("CT poison extension is not critical or invalid")]
Expand Down
24 changes: 13 additions & 11 deletions crates/static_ct_api/src/rfc6962.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use x509_cert::{
},
impl_newtype, Certificate, TbsCertificate,
};
use x509_util::{validate_chain_lax, CertPool};
use x509_util::{validate_chain_lax, CertPool, ValidationOptions};

// Data structures for the [Static CT Submission APIs](https://github.com/C2SP/C2SP/blob/main/static-ct-api.md#submission-apis),
// a subset of the APIs from [RFC 6962](https://datatracker.ietf.org/doc/html/rfc6962).
Expand Down Expand Up @@ -164,8 +164,11 @@ pub fn partially_validate_chain(
let pending_entry = validate_chain_lax(
raw_chain,
roots,
not_after_start,
not_after_end,
&ValidationOptions {
stop_on_first_trusted_cert: false,
not_after_start,
not_after_end,
},
validator_hook,
);
pending_entry.map_err(|e| match e {
Expand Down Expand Up @@ -352,14 +355,8 @@ mod tests {
($name:ident; $($root_file:expr),+; $($chain_file:expr),+; $not_after_start:expr; $not_after_end:expr; $expect_precert:expr; $require_server_auth_eku:expr; $want_err:expr; $want_chain_len:expr) => {
#[test]
fn $name() {
let mut roots = Vec::new();
$(
roots.append(&mut Certificate::load_pem_chain(include_bytes!($root_file)).unwrap());
)*
let mut chain = Vec::new();
$(
chain.append(&mut Certificate::load_pem_chain(include_bytes!($chain_file)).unwrap());
)*
let roots = x509_util::build_chain!($($root_file),*);
let chain = x509_util::build_chain!($($chain_file),*);

let result = partially_validate_chain(
&x509_util::certs_to_bytes(&chain).unwrap(),
Expand Down Expand Up @@ -400,6 +397,11 @@ mod tests {

test_validate_chain!(leaf_as_accepted_root; "../tests/leaf-signed-by-fake-intermediate-cert.pem"; "../tests/leaf-signed-by-fake-intermediate-cert.pem"; None; None; false; true; false; 0);

test_validate_chain!(valid_chain_inc_root; "../../static_ct_api/tests/fake-ca-cert.pem"; "../tests/leaf-signed-by-fake-intermediate-cert.pem", "../tests/fake-intermediate-cert.pem", "../tests/fake-ca-cert.pem"; None; None; false; true; false; 2);

// CT does not allow extra certs at the end of the chain.
test_validate_chain!(unrelated_cert_after_chain_inc_root; "../../static_ct_api/tests/fake-ca-cert.pem"; "../tests/leaf-signed-by-fake-intermediate-cert.pem", "../tests/fake-intermediate-cert.pem", "../tests/fake-ca-cert.pem", "../tests/test-cert.pem"; None; None; false; true; true; 0);

#[test]
fn test_build_precert_tbs() {
let precert_chain =
Expand Down
74 changes: 74 additions & 0 deletions crates/static_ct_api/tests/cloudflare.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
Certificate chain
0 s:CN=26d54cff.sni.cloudflaressl.com
i:C=US, O=Google Trust Services, CN=WE1
a:PKEY: EC, (prime256v1); sigalg: ecdsa-with-SHA256
v:NotBefore: Sep 10 18:11:56 2025 GMT; NotAfter: Dec 9 19:11:41 2025 GMT
-----BEGIN CERTIFICATE-----
MIIDyTCCA3CgAwIBAgIQQOWg2Nc9XhAT1toRzArhVzAKBggqhkjOPQQDAjA7MQsw
CQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZpY2VzMQwwCgYD
VQQDEwNXRTEwHhcNMjUwOTEwMTgxMTU2WhcNMjUxMjA5MTkxMTQxWjApMScwJQYD
VQQDEx4yNmQ1NGNmZi5zbmkuY2xvdWRmbGFyZXNzbC5jb20wWTATBgcqhkjOPQIB
BggqhkjOPQMBBwNCAATucLtnF8oOVucAgsWa82hdrSAkYJwy19iZTdlBeqTZQUvE
3VabmY4/xxWQ3womrnpQE6F2dul51ilAalRqTLGOo4ICZjCCAmIwDgYDVR0PAQH/
BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHQYDVR0O
BBYEFPgeK75wrmRIIvqJyzwf/y2QzmHdMB8GA1UdIwQYMBaAFJB3kjVnxP+ozKnm
e9mAeXvMk/k4MF4GCCsGAQUFBwEBBFIwUDAnBggrBgEFBQcwAYYbaHR0cDovL28u
cGtpLmdvb2cvcy93ZTEvUU9VMCUGCCsGAQUFBzAChhlodHRwOi8vaS5wa2kuZ29v
Zy93ZTEuY3J0MDkGA1UdEQQyMDCCHjI2ZDU0Y2ZmLnNuaS5jbG91ZGZsYXJlc3Ns
LmNvbYIOY2xvdWRmbGFyZS5jb20wEwYDVR0gBAwwCjAIBgZngQwBAgEwNgYDVR0f
BC8wLTAroCmgJ4YlaHR0cDovL2MucGtpLmdvb2cvd2UxL1h3N2s5OTVCdlZnLmNy
bDCCAQMGCisGAQQB1nkCBAIEgfQEgfEA7wB1AN3cyjSV1+EWBeeVMvrHn/g9HFDf
2wA6FBJ2Ciysu8gqAAABmTUKsOAAAAQDAEYwRAIgSbCq102Ac0iSU6uTmAw1JcUj
uLjCUKbHfX1jUi+4E0gCIDc2CklQ/04aH+En9ItnhzQ/zbKLEMkkkPshMYyQsLPx
AHYAzPsPaoVxCWX+lZtTzumyfCLphVwNl422qX5UwP5MDbAAAAGZNQqw9AAABAMA
RzBFAiBHdDICfuFVofCodDiC+VQ39Nw+EQVrohHSg7o8qyTPugIhAKh0/D8fcasn
8KaxEDLhxlQilBzQW9gP/iOlL4LasCAKMAoGCCqGSM49BAMCA0cAMEQCIFCuCbXl
cBlfWavWj7O0lN4aoxYVIsbbtF5VJqCEJfv5AiBLkdTa3bls3f8PbF0PZiec3QnQ
51nWenFitQt3t0xyUA==
-----END CERTIFICATE-----
1 s:C=US, O=Google Trust Services, CN=WE1
i:C=US, O=Google Trust Services LLC, CN=GTS Root R4
a:PKEY: EC, (prime256v1); sigalg: ecdsa-with-SHA384
v:NotBefore: Dec 13 09:00:00 2023 GMT; NotAfter: Feb 20 14:00:00 2029 GMT
-----BEGIN CERTIFICATE-----
MIICnzCCAiWgAwIBAgIQf/MZd5csIkp2FV0TttaF4zAKBggqhkjOPQQDAzBHMQsw
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIwMTQw
MDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZp
Y2VzMQwwCgYDVQQDEwNXRTEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARvzTr+
Z1dHTCEDhUDCR127WEcPQMFcF4XGGTfn1XzthkubgdnXGhOlCgP4mMTG6J7/EFmP
LCaY9eYmJbsPAvpWo4H+MIH7MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggr
BgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU
kHeSNWfE/6jMqeZ72YB5e8yT+TgwHwYDVR0jBBgwFoAUgEzW63T/STaj1dj8tT7F
avCUHYwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzAChhhodHRwOi8vaS5wa2ku
Z29vZy9yNC5jcnQwKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2MucGtpLmdvb2cv
ci9yNC5jcmwwEwYDVR0gBAwwCjAIBgZngQwBAgEwCgYIKoZIzj0EAwMDaAAwZQIx
AOcCq1HW90OVznX+0RGU1cxAQXomvtgM8zItPZCuFQ8jSBJSjz5keROv9aYsAm5V
sQIwJonMaAFi54mrfhfoFNZEfuNMSQ6/bIBiNLiyoX46FohQvKeIoJ99cx7sUkFN
7uJW
-----END CERTIFICATE-----
2 s:C=US, O=Google Trust Services LLC, CN=GTS Root R4
i:C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
a:PKEY: EC, (secp384r1); sigalg: sha256WithRSAEncryption
v:NotBefore: Nov 15 03:43:21 2023 GMT; NotAfter: Jan 28 00:00:42 2028 GMT
-----BEGIN CERTIFICATE-----
MIIDejCCAmKgAwIBAgIQf+UwvzMTQ77dghYQST2KGzANBgkqhkiG9w0BAQsFADBX
MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UE
CxMHUm9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTIzMTEx
NTAzNDMyMVoXDTI4MDEyODAwMDA0MlowRzELMAkGA1UEBhMCVVMxIjAgBgNVBAoT
GUdvb2dsZSBUcnVzdCBTZXJ2aWNlcyBMTEMxFDASBgNVBAMTC0dUUyBSb290IFI0
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE83Rzp2iLYK5DuDXFgTB7S0md+8Fhzube
Rr1r1WEYNa5A3XP3iZEwWus87oV8okB2O6nGuEfYKueSkWpz6bFyOZ8pn6KY019e
WIZlD6GEZQbR3IvJx3PIjGov5cSr0R2Ko4H/MIH8MA4GA1UdDwEB/wQEAwIBhjAd
BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAd
BgNVHQ4EFgQUgEzW63T/STaj1dj8tT7FavCUHYwwHwYDVR0jBBgwFoAUYHtmGkUN
l8qJUC99BM00qP/8/UswNgYIKwYBBQUHAQEEKjAoMCYGCCsGAQUFBzAChhpodHRw
Oi8vaS5wa2kuZ29vZy9nc3IxLmNydDAtBgNVHR8EJjAkMCKgIKAehhxodHRwOi8v
Yy5wa2kuZ29vZy9yL2dzcjEuY3JsMBMGA1UdIAQMMAowCAYGZ4EMAQIBMA0GCSqG
SIb3DQEBCwUAA4IBAQAYQrsPBtYDh5bjP2OBDwmkoWhIDDkic574y04tfzHpn+cJ
odI2D4SseesQ6bDrarZ7C30ddLibZatoKiws3UL9xnELz4ct92vID24FfVbiI1hY
+SW6FoVHkNeWIP0GCbaM4C6uVdF5dTUsMVs/ZbzNnIdCp5Gxmx5ejvEau8otR/Cs
kGN+hr/W5GvT1tMBjgWKZ1i4//emhA1JG1BbPzoLJQvyEotc03lXjTaCzv8mEbep
8RqZ7a2CPsgRbuvTPBwcOMBBmuFeU88+FSBX6+7iP0il8b4Z0QFqIwwMHfs/L6K1
vepuoxtGzi4CZ68zJpiq1UvSqTbFJjtbD4seiMHl
-----END CERTIFICATE-----
13 changes: 13 additions & 0 deletions crates/static_ct_api/tests/google-gts-root-r4.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQsw
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQA
IgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu
hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/l
xKvRHYqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
DgQWBBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0
CMRw3J5QdCHojXohw0+WbhXRIjVhLfoIN+4Zba3bssx9BzT1YBkstTTZbyACMANx
sbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11xzPKwTdb+mciUqXWi4w==
-----END CERTIFICATE-----
Loading