use c2pa_raw_crypto::OpenSslMutex;
use openssl::{
stack::Stack,
x509::{verify::X509VerifyFlags, X509StoreContext, X509},
};
use crate::crypto::cose::{CertificateTrustError, CertificateTrustPolicy, TrustAnchorType};
pub(crate) fn check_certificate_trust(
ctp: &CertificateTrustPolicy,
chain_der: &[Vec<u8>],
cert_der: &[u8],
signing_time_epoch: Option<i64>,
) -> Result<(TrustAnchorType, String), CertificateTrustError> {
let _openssl = OpenSslMutex::acquire()?;
if ctp.anchor_sets().count() == 0 {
return Err(CertificateTrustError::CertificateNotTrusted);
}
for anchor_set in ctp.anchor_sets() {
let mut cert_chain = Stack::new()?;
for cert_der in chain_der {
let x509_cert = X509::from_der(cert_der)?;
cert_chain.push(x509_cert)?;
}
let cert = X509::from_der(cert_der)?;
let mut builder = openssl::x509::store::X509StoreBuilder::new()?;
builder.set_flags(X509VerifyFlags::X509_STRICT)?;
let mut verify_param = openssl::x509::verify::X509VerifyParam::new()?;
verify_param.set_flags(X509VerifyFlags::X509_STRICT)?;
verify_param.set_flags(X509VerifyFlags::PARTIAL_CHAIN)?;
if let Some(st) = signing_time_epoch {
verify_param.set_time(st);
}
builder.set_param(&verify_param)?;
for der in &anchor_set.trust_anchor_ders {
let root_cert = X509::from_der(der)?;
builder.add_cert(root_cert)?;
}
let store = builder.build();
let mut store_ctx = X509StoreContext::new()?;
if store_ctx.init(&store, cert.as_ref(), &cert_chain, |f| f.verify_cert())? {
return Ok((
anchor_set.trust_anchor_type,
anchor_set.trust_anchor_uri.clone(),
));
}
}
Err(CertificateTrustError::CertificateNotTrusted)
}