1+ use crate :: x509:: x509:: X509Error ;
12use crate :: chain_verifier:: ChainVerificationFailureReason :: {
23 CertificateExpired , InvalidCertificate , InvalidEffectiveDate ,
34} ;
45use thiserror:: Error ;
56
6- use x509_parser:: certificate:: X509Certificate ;
7- use x509_parser:: der_parser:: asn1_rs:: oid;
8- use x509_parser:: error:: X509Error ;
9- use x509_parser:: prelude:: { ASN1Time , FromDer } ;
7+ use x509_cert:: Certificate ;
8+ use const_oid:: ObjectIdentifier ;
9+ use crate :: x509:: x509;
1010
1111#[ derive( Error , Debug , PartialEq ) ]
1212pub enum ChainVerifierError {
1313 #[ error( "VerificationFailure: [{0}]" ) ]
1414 VerificationFailure ( ChainVerificationFailureReason ) ,
1515
1616 #[ error( "InternalX509Error: [{0}]" ) ]
17- InternalX509Error ( # [ from ] X509Error ) ,
17+ InternalX509Error ( String ) ,
1818
1919 #[ error( "InternalDecodeError: [{0}]" ) ]
2020 InternalDecodeError ( #[ from] base64:: DecodeError ) ,
2121}
2222
23+ impl From < X509Error > for ChainVerifierError {
24+ fn from ( err : X509Error ) -> Self {
25+ ChainVerifierError :: InternalX509Error ( err. to_string ( ) )
26+ }
27+ }
28+
2329#[ derive( Error , Debug , PartialEq ) ]
2430pub enum ChainVerificationFailureReason {
2531 #[ error( "InvalidAppIdentifier" ) ]
@@ -96,37 +102,39 @@ impl ChainVerifier {
96102 if self . root_certificates . is_empty ( ) {
97103 return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
98104 }
99- let Ok ( leaf_certificate) = X509Certificate :: from_der ( leaf_certificate. as_slice ( ) ) else {
100- return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
101- } ;
102- let leaf_certificate = leaf_certificate. 1 ;
103105
104- let Some ( _) = leaf_certificate. get_extension_unique ( & oid ! ( 1.2 . 840.113635 . 100.6 . 11.1 ) ) ? else {
105- return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
106- } ;
106+ let leaf_certificate = x509:: parse_certificate ( leaf_certificate. as_slice ( ) )
107+ . map_err ( |_| ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ?;
108+
109+ // Check for Apple-specific leaf certificate extension (1.2.840.113635.100.6.11.1)
110+ let leaf_oid = ObjectIdentifier :: new ( "1.2.840.113635.100.6.11.1" )
111+ . map_err ( |_| ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ?;
107112
108- let Ok ( intermediate_certificate ) = X509Certificate :: from_der ( intermediate_certificate . as_slice ( ) ) else {
113+ if !x509 :: has_extension ( & leaf_certificate , & leaf_oid ) {
109114 return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
110- } ;
111- let intermediate_certificate = intermediate_certificate. 1 ;
115+ }
116+
117+ let intermediate_certificate = x509:: parse_certificate ( intermediate_certificate. as_slice ( ) )
118+ . map_err ( |_| ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ?;
119+
120+ // Check for Apple-specific intermediate certificate extension (1.2.840.113635.100.6.2.1)
121+ let intermediate_oid = ObjectIdentifier :: new ( "1.2.840.113635.100.6.2.1" )
122+ . map_err ( |_| ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ?;
112123
113- let Some ( _ ) = intermediate_certificate. get_extension_unique ( & oid ! ( 1.2 . 840.113635 . 100.6 . 2.1 ) ) ? else {
124+ if !x509 :: has_extension ( & intermediate_certificate, & intermediate_oid ) {
114125 return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
115- } ;
126+ }
116127
117- let mut root_certificate: Option < X509Certificate > = None ;
128+ let mut root_certificate: Option < Certificate > = None ;
118129
119130 for cert in & self . root_certificates {
120- let Ok ( cert) = X509Certificate :: from_der ( & cert) else {
121- return Err ( ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ;
122- } ;
131+ let cert = x509:: parse_certificate ( & cert)
132+ . map_err ( |_| ChainVerifierError :: VerificationFailure ( InvalidCertificate ) ) ?;
123133
124- match intermediate_certificate . verify_signature ( Some ( cert. 1 . public_key ( ) ) ) {
125- Ok ( _ ) => ( ) ,
126- Err ( _ ) => continue ,
134+ if x509 :: verify_signature ( & intermediate_certificate , & cert) . is_ok ( ) {
135+ root_certificate = Some ( cert ) ;
136+ break ;
127137 }
128-
129- root_certificate = Some ( cert. 1 )
130138 }
131139
132140 let Some ( root_certificate) = root_certificate else {
@@ -143,31 +151,27 @@ impl ChainVerifier {
143151
144152 fn verify_chain (
145153 & self ,
146- leaf : & X509Certificate ,
147- intermediate : & X509Certificate ,
148- root_certificate : & X509Certificate ,
154+ leaf : & Certificate ,
155+ intermediate : & Certificate ,
156+ root_certificate : & Certificate ,
149157 effective_date : Option < u64 > ,
150158 ) -> Result < Vec < u8 > , ChainVerifierError > {
151- leaf . verify_signature ( Some ( intermediate. public_key ( ) ) ) ?;
159+ x509 :: verify_signature ( leaf , intermediate) ?;
152160
153161 if let Some ( date) = effective_date {
154- let Ok ( time) = ASN1Time :: from_timestamp ( i64:: try_from ( date) . unwrap ( ) ) else {
155- return Err ( ChainVerifierError :: VerificationFailure (
156- InvalidEffectiveDate ,
157- ) ) ;
158- } ;
159-
160- if !( root_certificate. validity . is_valid_at ( time) &&
161- leaf. validity . is_valid_at ( time) &&
162- intermediate. validity . is_valid_at ( time) )
162+ let timestamp = i64:: try_from ( date)
163+ . map_err ( |_| ChainVerifierError :: VerificationFailure ( InvalidEffectiveDate ) ) ?;
164+
165+ if !x509:: is_valid_at ( leaf, timestamp) ||
166+ !x509:: is_valid_at ( intermediate, timestamp) ||
167+ !x509:: is_valid_at ( root_certificate, timestamp)
163168 {
164169 return Err ( ChainVerifierError :: VerificationFailure ( CertificateExpired ) ) ;
165170 }
166171 }
167172
168- let k = leaf . public_key ( ) . raw . to_vec ( ) ;
173+ let public_key_bytes = x509 :: public_key_bytes ( leaf ) ;
169174
170- // Make online verification as additional step if ocsp flag enabled
171175 #[ cfg( all( feature = "ocsp" ) ) ]
172176 {
173177 // Perform OCSP check - this is best-effort, so we don't fail on OCSP errors
@@ -188,6 +192,6 @@ impl ChainVerifier {
188192 }
189193 } ;
190194
191- Ok ( k )
195+ Ok ( public_key_bytes )
192196 }
193197}
0 commit comments