rpki/tests/test_crl_errors.rs

128 lines
6.0 KiB
Rust

use rpki::data_model::crl::{CrlDecodeError, CrlVerifyError, RpkixCrl};
use x509_parser::prelude::FromDer;
use x509_parser::prelude::X509Certificate;
const TEST_NO_CRLSIGN_CERT_DER_B64: &str = "MIIDATCCAemgAwIBAgIUCyQLQJn92+gyAzvIz22q1F/97OMwDQYJKoZIhvcNAQELBQAwGjEYMBYGA1UEAwwPVGVzdCBObyBDUkxTaWduMB4XDTI2MDEyNzAzNTk1OVoXDTM2MDEyNTAzNTk1OVowGjEYMBYGA1UEAwwPVGVzdCBObyBDUkxTaWduMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr/aoMU8J6cddkM2r6F2snd1rCdQPepgo2T2lrqWFcxnQJdcxBL1OYg3wFi95TJmZSeIHIOGauDaJ2abmjgyOUHOC4U68x66JRg4hLkmLxo1cf3uYHWl9Obph6g2qPRvN80ORq70JPuL6mAfUkNiO9hnwK6oQiTzc/rjCQGIFH8kTESBMXLfNCyUpGi+MNztYH6Ha6bKAQuXgd29OFwIkOlGQnYgGC2qBMvnp86eITvV1gTiuI8Ho9m9nZHCmaD7TylvkMDq8Hk5nkIpRcG0uO60SkR2BiMOYe/TNn5dTmHd6bsdbU2GOvgnq1SnqGq3FOWhKIe3ycUJde0uNfZOqRwIDAQABoz8wPTAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUFjyzfJCDNhFfKxVr06kjUkE23dMwDQYJKoZIhvcNAQELBQADggEBAK98n2gVlwKA3Ob1YeAm9f+8hm7pbvrt0tA8GW180CILjf09k7fKgiRlxqGdZ9ySXjU52+zCqu3MpBXVbI87ZC+zA6uK05n4y1F0n85MJ9hGR2UEiPcqou85X73LvioynnSOy/OV1PjKJXReUsqF3GgDtgcMyFssPJ9s/5DWuUCScUJY6pu0kuIGOLQ/oXUw4TvxUeyz73gOTiAJshVTQoLpHUhj0595S7lArjwi7oLI1b8m8guTknvhk0Sc3tJZmUqOcIvYIs0guHpaeC+sMoF4K+6UTrxxOBdX+fUEWNpUyYXWHjdZq25PbJdHwA/VAW2zYVojaVREligf0Qfo6F4=";
fn test_no_crlsign_cert_der() -> Vec<u8> {
use base64::{engine::general_purpose, Engine as _};
general_purpose::STANDARD
.decode(TEST_NO_CRLSIGN_CERT_DER_B64)
.expect("decode base64 cert")
}
#[test]
fn verify_errors_are_reported() {
let crl_der = std::fs::read(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.crl",
)
.expect("read CRL fixture");
let issuer_cert_der = std::fs::read(
"tests/fixtures/repository/rpki.apnic.net/repository/B527EF581D6611E2BB468F7C72FD1FF2/BfycW4hQb3wNP4YsiJW-1n6fjro.cer",
)
.expect("read issuer cert");
let mut crl = RpkixCrl::decode_der(&crl_der).expect("decode");
// IssuerSubjectMismatch.
crl.issuer_dn = "CN=Not The Issuer".to_string();
let err = crl
.verify_signature_with_issuer_certificate_der(&issuer_cert_der)
.unwrap_err();
assert!(matches!(err, CrlVerifyError::IssuerSubjectMismatch { .. }));
// AkiSkiMismatch (force issuer dn to match, then change AKI).
let (_rem, issuer_cert) = X509Certificate::from_der(&issuer_cert_der).unwrap();
crl.issuer_dn = issuer_cert.subject().to_string();
crl.extensions.authority_key_identifier = vec![0u8; 20];
let err = crl
.verify_signature_with_issuer_certificate_der(&issuer_cert_der)
.unwrap_err();
assert!(matches!(err, CrlVerifyError::AkiSkiMismatch));
// IssuerKeyUsageMissingCrlSign (use a cert with KeyUsage present but without CRLSign).
let no_crlsign_der = test_no_crlsign_cert_der();
let (_rem, no_crlsign_cert) = X509Certificate::from_der(&no_crlsign_der).unwrap();
crl.issuer_dn = no_crlsign_cert.subject().to_string();
let err = crl
.verify_signature_with_issuer_certificate_der(&no_crlsign_der)
.unwrap_err();
assert!(matches!(err, CrlVerifyError::IssuerKeyUsageMissingCrlSign));
// InvalidSignature: verify cryptographically with the wrong SPKI.
let no_crlsign_spki_der = no_crlsign_cert.public_key().raw.to_vec();
let err = crl
.verify_signature_with_issuer_spki_der(&no_crlsign_spki_der)
.unwrap_err();
assert!(matches!(err, CrlVerifyError::InvalidSignature(_)));
// IssuerCertificateParse / trailing bytes.
let err = crl
.verify_signature_with_issuer_certificate_der(b"not a cert")
.unwrap_err();
assert!(matches!(err, CrlVerifyError::IssuerCertificateParse(_)));
let mut bad = issuer_cert_der.clone();
bad.push(0);
let err = crl
.verify_signature_with_issuer_certificate_der(&bad)
.unwrap_err();
assert!(matches!(err, CrlVerifyError::IssuerCertificateTrailingBytes(1)));
}
#[test]
fn verify_signature_with_spki_der_paths() {
let crl_der = std::fs::read(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.crl",
)
.expect("read CRL fixture");
let issuer_cert_der = std::fs::read(
"tests/fixtures/repository/rpki.apnic.net/repository/B527EF581D6611E2BB468F7C72FD1FF2/BfycW4hQb3wNP4YsiJW-1n6fjro.cer",
)
.expect("read issuer cert");
let crl = RpkixCrl::decode_der(&crl_der).expect("decode");
let (_rem, issuer_cert) = X509Certificate::from_der(&issuer_cert_der).unwrap();
let spki_der = issuer_cert.public_key().raw.to_vec();
crl.verify_signature_with_issuer_spki_der(&spki_der)
.expect("verify with spki der");
let mut bad = spki_der;
bad.push(0);
let err = crl.verify_signature_with_issuer_spki_der(&bad).unwrap_err();
assert!(matches!(err, CrlVerifyError::IssuerSpkiTrailingBytes(1)));
}
#[test]
fn decode_rejects_trailing_bytes() {
let crl_der = std::fs::read(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.crl",
)
.expect("read CRL fixture");
let mut bad = crl_der.clone();
bad.push(0);
let err = RpkixCrl::decode_der(&bad).unwrap_err();
assert!(matches!(err, CrlDecodeError::TrailingBytes(1)));
}
#[test]
fn verify_rejects_crl_with_trailing_bytes_in_raw_der() {
let crl_der = std::fs::read(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.crl",
)
.expect("read CRL fixture");
let issuer_cert_der = std::fs::read(
"tests/fixtures/repository/rpki.apnic.net/repository/B527EF581D6611E2BB468F7C72FD1FF2/BfycW4hQb3wNP4YsiJW-1n6fjro.cer",
)
.expect("read issuer cert");
let mut crl = RpkixCrl::decode_der(&crl_der).expect("decode");
crl.raw_der.push(0);
let (_rem, issuer_cert) = X509Certificate::from_der(&issuer_cert_der).unwrap();
let spki_der = issuer_cert.public_key().raw.to_vec();
let err = crl.verify_signature_with_issuer_spki_der(&spki_der).unwrap_err();
assert!(matches!(err, CrlVerifyError::CrlTrailingBytes(1)));
}