1use crate::error::*;
6use crate::util::assert_nss_initialized;
7
8use nss_sys::PRErrorCode;
9
10const SEC_ERROR_BASE: i32 = -0x2000; const SEC_ERROR_EXPIRED_CERTIFICATE: i32 = SEC_ERROR_BASE + 11;
14const SEC_ERROR_UNKNOWN_ISSUER: i32 = SEC_ERROR_BASE + 13;
15const SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: i32 = SEC_ERROR_BASE + 30;
16
17const SSL_ERROR_BASE: i32 = -0x3000; const SSL_ERROR_BAD_CERT_DOMAIN: i32 = SSL_ERROR_BASE + 12;
21
22const PKIX_ERROR_BASE: i32 = -0x4000; const PKIX_ERROR_NOT_YET_VALID_CERTIFICATE: i32 = PKIX_ERROR_BASE + 5;
26const PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE: i32 = PKIX_ERROR_BASE + 6;
27
28const ROOT_HASH_LENGTH: usize = 32;
29
30pub fn verify_code_signing_certificate_chain(
31 certificates: Vec<&[u8]>,
32 seconds_since_epoch: u64,
33 root_sha256_hash: &[u8],
34 hostname: &str,
35) -> Result<()> {
36 assert_nss_initialized();
37
38 let mut cert_lens: Vec<u16> = vec![];
39 for certificate in &certificates {
40 match u16::try_from(certificate.len()) {
41 Ok(v) => cert_lens.push(v),
42 Err(e) => {
43 return Err(ErrorKind::InputError(format!(
44 "certificate length is more than 65536 bytes: {}",
45 e
46 ))
47 .into());
48 }
49 }
50 }
51
52 let mut p_certificates: Vec<_> = certificates.iter().map(|c| c.as_ptr()).collect();
53
54 if root_sha256_hash.len() != ROOT_HASH_LENGTH {
55 return Err(ErrorKind::InputError(format!(
56 "root hash contains {} bytes instead of {}",
57 root_sha256_hash.len(),
58 ROOT_HASH_LENGTH
59 ))
60 .into());
61 }
62
63 let mut out: PRErrorCode = 0;
64
65 let result = unsafe {
66 nss_sys::VerifyCodeSigningCertificateChain(
67 p_certificates.as_mut_ptr(), cert_lens.as_ptr(),
69 certificates.len(),
70 seconds_since_epoch,
71 root_sha256_hash.as_ptr(),
72 hostname.as_ptr(),
73 hostname.len(),
74 &mut out,
75 )
76 };
77
78 if !result {
79 let kind = match out {
80 SEC_ERROR_UNKNOWN_ISSUER => ErrorKind::CertificateIssuerError,
81 SEC_ERROR_EXPIRED_CERTIFICATE => ErrorKind::CertificateValidityError,
82 SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE => ErrorKind::CertificateValidityError,
83 PKIX_ERROR_NOT_YET_VALID_CERTIFICATE => ErrorKind::CertificateValidityError,
84 PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE => ErrorKind::CertificateValidityError,
85 SSL_ERROR_BAD_CERT_DOMAIN => ErrorKind::CertificateSubjectError,
86 _ => {
87 let msg = "invalid chain of trust".to_string();
88 if SSL_ERROR_BASE < out && out < SSL_ERROR_BASE + 1000 {
89 ErrorKind::SSLError(out, msg)
90 } else if PKIX_ERROR_BASE < out && out < PKIX_ERROR_BASE + 1000 {
91 ErrorKind::PKIXError(out, msg)
92 } else {
93 ErrorKind::NSSError(out, msg)
94 }
95 }
96 };
97 return Err(kind.into());
98 }
99
100 Ok(())
101}