11use crate :: chain_verifier:: ChainVerificationFailureReason :: {
2- CertificateExpired , InvalidCertificate , InvalidChainLength , InvalidEffectiveDate ,
2+ CertificateExpired , InvalidCertificate , InvalidEffectiveDate ,
33} ;
44use thiserror:: Error ;
55
@@ -47,148 +47,144 @@ pub enum ChainVerificationFailureReason {
4747 CertificateRevoked ,
4848}
4949
50- const EXPECTED_CHAIN_LENGTH : usize = 3 ;
51-
52- /// Verifies a certificate chain.
53- ///
54- /// This function verifies a certificate chain consisting of multiple certificates. It performs various
55- /// checks to ensure the validity and integrity of the chain.
56- ///
57- /// # Arguments
58- ///
59- /// * `certificates`: A vector of byte slices containing the certificates in the chain.
60- /// * `root_certificates`: A vector of byte slices containing the root certificates.
61- /// * `effective_date`: An optional Unix timestamp representing the effective date for the chain validation.
62- ///
63- /// # Returns
64- ///
65- /// * `Ok(Vec<u8>)`: If the certificate chain is valid, it returns the public key data from the leaf certificate.
66- /// * `Err(ChainVerifierError)`: If the chain verification fails for any reason, it returns a `ChainVerifierError` enum.
50+ /// A structure for verifying certificate chains.
6751///
68- /// # Example
69- ///
70- /// ```rust
71- /// use app_store_server_library::chain_verifier::{verify_chain, ChainVerifierError};
72- ///
73- /// fn main() {
74- /// let certificates: Vec<Vec<u8>> = vec![]; // Load your certificates here
75- /// let root_certificates: Vec<Vec<u8>> = vec![]; // Load your root certificates here
76- /// let effective_date: Option<u64> = None; // Provide an effective date if needed
77- ///
78- /// match verify_chain(&certificates, &root_certificates, effective_date) {
79- /// Ok(public_key) => println!("Certificate chain is valid. Public key: {:?}", public_key),
80- /// Err(err) => eprintln!("Certificate chain verification failed: {}", err),
81- /// }
82- /// }
83- /// ```
84- ///
85- /// TODO: Implement issuer checking
86- pub fn verify_chain (
87- certificates : & Vec < Vec < u8 > > ,
88- root_certificates : & Vec < Vec < u8 > > ,
89- effective_date : Option < u64 > ,
90- ) -> Result < Vec < u8 > , ChainVerifierError > {
91- if root_certificates. is_empty ( ) {
92- return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
93- }
52+ /// This struct holds the root certificates and provides methods to verify certificate chains.
53+ pub struct ChainVerifier {
54+ root_certificates : Vec < Vec < u8 > > ,
55+ }
9456
95- if certificates. len ( ) != EXPECTED_CHAIN_LENGTH {
96- return Err ( ChainVerifierError :: VerificationFailure ( InvalidChainLength ) ) ;
57+ impl ChainVerifier {
58+ /// Creates a new `ChainVerifier` with the provided root certificates.
59+ ///
60+ /// # Arguments
61+ ///
62+ /// * `root_certificates`: A vector of byte slices containing the root certificates.
63+ ///
64+ /// # Returns
65+ ///
66+ /// A new instance of `ChainVerifier`.
67+ pub fn new ( root_certificates : Vec < Vec < u8 > > ) -> Self {
68+ ChainVerifier { root_certificates }
9769 }
9870
99- let leaf_certificate = & certificates[ 0 ] ;
100- let Ok ( leaf_certificate) = X509Certificate :: from_der ( leaf_certificate. as_slice ( ) ) else {
101- return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
102- } ;
103- let leaf_certificate = leaf_certificate. 1 ;
104-
105- let Some ( _) = leaf_certificate. get_extension_unique ( & oid ! ( 1.2 . 840.113635 . 100.6 . 11.1 ) ) ? else {
106- return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
107- } ;
108-
109- let intermediate_certificate = & certificates[ 1 ] ;
110- let Ok ( intermediate_certificate) = X509Certificate :: from_der ( intermediate_certificate. as_slice ( ) ) else {
111- return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
112- } ;
113- let intermediate_certificate = intermediate_certificate. 1 ;
71+ /// Verifies a certificate pair (leaf and intermediate).
72+ ///
73+ /// This method verifies a leaf certificate against an intermediate certificate. It performs various
74+ /// checks to ensure the validity and integrity of the certificates.
75+ ///
76+ /// # Arguments
77+ ///
78+ /// * `leaf_certificate`: The leaf certificate as a byte slice.
79+ /// * `intermediate_certificate`: The intermediate certificate as a byte slice.
80+ /// * `effective_date`: An optional Unix timestamp representing the effective date for the chain validation.
81+ ///
82+ /// # Returns
83+ ///
84+ /// * `Ok(Vec<u8>)`: If the certificates are valid, it returns the public key data from the leaf certificate.
85+ /// * `Err(ChainVerifierError)`: If the verification fails for any reason, it returns a `ChainVerifierError` enum.
86+ /// TODO: Implement issuer checking
87+ pub fn verify (
88+ & self ,
89+ leaf_certificate : & Vec < u8 > ,
90+ intermediate_certificate : & Vec < u8 > ,
91+ effective_date : Option < u64 > ,
92+ ) -> Result < Vec < u8 > , ChainVerifierError > {
93+ if self . root_certificates . is_empty ( ) {
94+ return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
95+ }
96+ let Ok ( leaf_certificate) = X509Certificate :: from_der ( leaf_certificate. as_slice ( ) ) else {
97+ return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
98+ } ;
99+ let leaf_certificate = leaf_certificate. 1 ;
114100
115- let Some ( _) = intermediate_certificate . get_extension_unique ( & oid ! ( 1.2 . 840.113635 . 100.6 . 2 .1) ) ? else {
116- return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
117- } ;
101+ let Some ( _) = leaf_certificate . get_extension_unique ( & oid ! ( 1.2 . 840.113635 . 100.6 . 11 .1) ) ? else {
102+ return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
103+ } ;
118104
119- let mut root_certificate: Option < X509Certificate > = None ;
105+ let Ok ( intermediate_certificate) = X509Certificate :: from_der ( intermediate_certificate. as_slice ( ) ) else {
106+ return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
107+ } ;
108+ let intermediate_certificate = intermediate_certificate. 1 ;
120109
121- for cert in root_certificates {
122- let Ok ( cert) = X509Certificate :: from_der ( & cert) else {
110+ let Some ( _) = intermediate_certificate. get_extension_unique ( & oid ! ( 1.2 . 840.113635 . 100.6 . 2.1 ) ) ? else {
123111 return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
124112 } ;
125113
126- match intermediate_certificate. verify_signature ( Some ( cert. 1 . public_key ( ) ) ) {
127- Ok ( _) => ( ) ,
128- Err ( _) => continue ,
129- }
114+ let mut root_certificate: Option < X509Certificate > = None ;
130115
131- root_certificate = Some ( cert. 1 )
132- }
116+ for cert in & self . root_certificates {
117+ let Ok ( cert) = X509Certificate :: from_der ( & cert) else {
118+ return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
119+ } ;
133120
134- let Some ( root_certificate) = root_certificate else {
135- return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
136- } ;
121+ match intermediate_certificate. verify_signature ( Some ( cert. 1 . public_key ( ) ) ) {
122+ Ok ( _) => ( ) ,
123+ Err ( _) => continue ,
124+ }
137125
138- verify_chain_impl (
139- & leaf_certificate,
140- & intermediate_certificate,
141- & root_certificate,
142- effective_date,
143- )
144- }
126+ root_certificate = Some ( cert. 1 )
127+ }
145128
146- fn verify_chain_impl (
147- leaf : & X509Certificate ,
148- intermediate : & X509Certificate ,
149- root_certificate : & X509Certificate ,
150- effective_date : Option < u64 > ,
151- ) -> Result < Vec < u8 > , ChainVerifierError > {
152- leaf. verify_signature ( Some ( intermediate. public_key ( ) ) ) ?;
153-
154- if let Some ( date) = effective_date {
155- let Ok ( time) = ASN1Time :: from_timestamp ( i64:: try_from ( date) . unwrap ( ) ) else {
156- return Err ( ChainVerifierError :: VerificationFailure (
157- InvalidEffectiveDate ,
158- ) ) ;
129+ let Some ( root_certificate) = root_certificate else {
130+ return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
159131 } ;
160132
161- if ! ( root_certificate . validity . is_valid_at ( time ) &&
162- leaf . validity . is_valid_at ( time ) &&
163- intermediate . validity . is_valid_at ( time ) )
164- {
165- return Err ( ChainVerifierError :: VerificationFailure ( CertificateExpired ) ) ;
166- }
133+ self . verify_chain (
134+ & leaf_certificate ,
135+ & intermediate_certificate ,
136+ & root_certificate ,
137+ effective_date ,
138+ )
167139 }
168140
169- let k = leaf. public_key ( ) . raw . to_vec ( ) ;
170-
171- // Make online verification as additional step if ocsp flag enabled
172- #[ cfg( all( feature = "ocsp" ) ) ]
173- {
174- use crate :: chain_verifier_ocsp:: check_ocsp_status;
175- // Perform OCSP check - this is best-effort, so we don't fail on OCSP errors
176- match check_ocsp_status ( leaf, intermediate) {
177- Ok ( ( ) ) => {
178- // Certificate is valid according to OCSP
179- }
180- Err ( ChainVerifierError :: VerificationFailure ( ChainVerificationFailureReason :: CertificateRevoked ) ) => {
181- // Certificate is revoked - this should fail
141+ fn verify_chain (
142+ & self ,
143+ leaf : & X509Certificate ,
144+ intermediate : & X509Certificate ,
145+ root_certificate : & X509Certificate ,
146+ effective_date : Option < u64 > ,
147+ ) -> Result < Vec < u8 > , ChainVerifierError > {
148+ leaf. verify_signature ( Some ( intermediate. public_key ( ) ) ) ?;
149+
150+ if let Some ( date) = effective_date {
151+ let Ok ( time) = ASN1Time :: from_timestamp ( i64:: try_from ( date) . unwrap ( ) ) else {
182152 return Err ( ChainVerifierError :: VerificationFailure (
183- ChainVerificationFailureReason :: CertificateRevoked ,
153+ InvalidEffectiveDate ,
184154 ) ) ;
185- }
186- Err ( e) => {
187- // Other OCSP errors (network, parsing, etc.) - log but don't fail
188- eprintln ! ( "OCSP check failed (non-fatal): {:?}" , e) ;
155+ } ;
156+
157+ if !( root_certificate. validity . is_valid_at ( time) &&
158+ leaf. validity . is_valid_at ( time) &&
159+ intermediate. validity . is_valid_at ( time) )
160+ {
161+ return Err ( ChainVerifierError :: VerificationFailure ( CertificateExpired ) ) ;
189162 }
190163 }
191- } ;
192164
193- Ok ( k)
194- }
165+ let k = leaf. public_key ( ) . raw . to_vec ( ) ;
166+
167+ // Make online verification as additional step if ocsp flag enabled
168+ #[ cfg( all( feature = "ocsp" ) ) ]
169+ {
170+ // Perform OCSP check - this is best-effort, so we don't fail on OCSP errors
171+ match self . check_ocsp_status ( leaf, intermediate) {
172+ Ok ( ( ) ) => {
173+ // Certificate is valid according to OCSP
174+ }
175+ Err ( ChainVerifierError :: VerificationFailure ( ChainVerificationFailureReason :: CertificateRevoked ) ) => {
176+ // Certificate is revoked - this should fail
177+ return Err ( ChainVerifierError :: VerificationFailure (
178+ ChainVerificationFailureReason :: CertificateRevoked ,
179+ ) ) ;
180+ }
181+ Err ( e) => {
182+ // Other OCSP errors (network, parsing, etc.) - log but don't fail
183+ eprintln ! ( "OCSP check failed (non-fatal): {:?}" , e) ;
184+ }
185+ }
186+ } ;
187+
188+ Ok ( k)
189+ }
190+ }
0 commit comments