use der::{DateTime, Encode}; use mc_attestation_verifier::{CertificateChainVerifier, CertificateChainVerifierError}; use x509_cert::{crl::CertificateList, Certificate}; use x509_parser::parse_x509_certificate; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq)] pub struct TlsCertificateChainVerifier; impl TlsCertificateChainVerifier { pub fn new(_root_ca: &str) -> Self { // FIXME(hu55a1n1) Self } } impl CertificateChainVerifier for TlsCertificateChainVerifier { fn verify_certificate_chain<'a, 'b>( &self, certificate_chain: impl IntoIterator, _crls: impl IntoIterator, _time: impl Into>, ) -> Result<(), CertificateChainVerifierError> { let enc_certs = certificate_chain .into_iter() .map(|cert| cert.to_der()) .collect::, _>>() .map_err(|_| CertificateChainVerifierError::GeneralCertificateError)?; let cert_chain = enc_certs .iter() .map(|der| parse_x509_certificate(der)) .collect::, _>>() .map_err(|_| CertificateChainVerifierError::GeneralCertificateError)?; // Skip applying the Certificate Revocation List entirely /* let enc_crls = crls .into_iter() .map(|crl| der_encode(crl)) .collect::, _>>() .map_err(|_| CertificateChainVerifierError::GeneralCertificateError)?; let _crls = enc_crls .iter() .map(|enc_crl| parse_x509_crl(enc_crl.as_ref())) .collect::, _>>(); .map_err(|_| CertificateChainVerifierError::GeneralCertificateError)?; */ let v: Vec<_> = cert_chain.to_vec(); let mut issuers: Vec = (1..v.len()).collect(); issuers.push(v.len() - 1); let subjects: Vec = (0..v.len()).collect(); for (i, s) in core::iter::zip(issuers, subjects) { let r = v[s].1.verify_signature(Some(v[i].1.public_key())); r.map_err(|_| CertificateChainVerifierError::SignatureVerification)? } Ok(()) } } #[cfg(test)] mod test { use der::{Decode, DecodePem}; use super::*; const LEAF_CERT: &str = include_str!("../../../data/leaf_cert.pem"); const PROCESSOR_CA: &str = include_str!("../../../data/processor_ca.pem"); const ROOT_CA: &str = include_str!("../../../data/root_ca.pem"); const PROCESSOR_CRL: &[u8] = include_bytes!("../../../data/processor_crl.der"); const ROOT_CRL: &[u8] = include_bytes!("../../../data/root_crl.der"); #[test] fn verify_valid_cert_chain() { let chain = [LEAF_CERT, PROCESSOR_CA, ROOT_CA] .iter() .map(|cert| Certificate::from_pem(cert).expect("failed to parse cert")) .collect::>(); let crls = [ROOT_CRL, PROCESSOR_CRL] .iter() .map(|crl| CertificateList::from_der(crl).expect("failed to parse CRL")) .collect::>(); let verifier = TlsCertificateChainVerifier::new(ROOT_CA); assert!(verifier .verify_certificate_chain(chain.iter(), crls.iter(), None) .is_ok()); } #[test] fn invalid_cert_chain() { let chain = [LEAF_CERT, ROOT_CA] .iter() .map(|cert| Certificate::from_pem(cert).expect("failed to parse cert")) .collect::>(); let crls = [ROOT_CRL, PROCESSOR_CRL] .iter() .map(|crl| CertificateList::from_der(crl).expect("failed to parse CRL")) .collect::>(); let verifier = TlsCertificateChainVerifier::new(ROOT_CA); assert_eq!( verifier.verify_certificate_chain(chain.iter(), crls.iter(), None), Err(CertificateChainVerifierError::SignatureVerification) ); } #[test] #[ignore] fn unordered_cert_chain_succeeds() { let chain = [PROCESSOR_CA, ROOT_CA, LEAF_CERT] .iter() .map(|cert| Certificate::from_pem(cert).expect("failed to parse cert")) .collect::>(); let crls = [ROOT_CRL, PROCESSOR_CRL] .iter() .map(|crl| CertificateList::from_der(crl).expect("failed to parse CRL")) .collect::>(); let verifier = TlsCertificateChainVerifier::new(ROOT_CA); assert!(verifier .verify_certificate_chain(chain.iter(), crls.iter(), None) .is_ok()); } // TODO(hu55a1n1) - add [PKITS tests](https://csrc.nist.gov/projects/pki-testing) }