33use crate :: { name:: Name , serial_number:: SerialNumber , time:: Validity } ;
44use alloc:: vec:: Vec ;
55use const_oid:: AssociatedOid ;
6- use core:: cmp:: Ordering ;
6+ use core:: { cmp:: Ordering , fmt :: Debug , marker :: PhantomData } ;
77use der:: asn1:: BitString ;
88use der:: { Decode , Enumerated , Error , ErrorKind , Sequence , ValueOrd } ;
99use spki:: { AlgorithmIdentifierOwned , SubjectPublicKeyInfoOwned } ;
1010
1111#[ cfg( feature = "pem" ) ]
1212use der:: pem:: PemLabel ;
1313
14+ /// [`ParsingProfile`] allows the consumer of this crate to customize the behavior when parsing
15+ /// certificates.
16+ /// By default, parsing will be made in a rfc5280-compliant manner.
17+ pub trait ParsingProfile : PartialEq + Debug + Eq + Clone {
18+ /// Checks to run when parsing serial numbers
19+ fn check_serial_number ( serial : & SerialNumber < Self > ) -> der:: Result < ( ) > {
20+ // See the note in `SerialNumber::new`: we permit lengths of 21 bytes here,
21+ // since some X.509 implementations interpret the limit of 20 bytes to refer
22+ // to the pre-encoded value.
23+ if serial. inner . len ( ) > SerialNumber :: < Self > :: MAX_DECODE_LEN {
24+ Err ( ErrorKind :: Overlength . into ( ) )
25+ } else {
26+ Ok ( ( ) )
27+ }
28+ }
29+ }
30+
31+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
32+ /// Parse certificates with rfc5280-compliant checks
33+ pub struct Rfc5280 ;
34+
35+ impl ParsingProfile for Rfc5280 { }
36+
37+ #[ cfg( feature = "hazmat" ) ]
38+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
39+ /// Parse raw x509 certificate and disable all the checks
40+ pub struct Raw ;
41+
42+ #[ cfg( feature = "hazmat" ) ]
43+ impl ParsingProfile for Raw {
44+ fn check_serial_number ( _serial : & SerialNumber < Self > ) -> der:: Result < ( ) > {
45+ Ok ( ( ) )
46+ }
47+ }
48+
1449/// Certificate `Version` as defined in [RFC 5280 Section 4.1].
1550///
1651/// ```text
@@ -73,7 +108,7 @@ impl Default for Version {
73108#[ cfg_attr( feature = "arbitrary" , derive( arbitrary:: Arbitrary ) ) ]
74109#[ derive( Clone , Debug , Eq , PartialEq , Sequence , ValueOrd ) ]
75110#[ allow( missing_docs) ]
76- pub struct TbsCertificate {
111+ pub struct TbsCertificate < PP : ParsingProfile = Rfc5280 > {
77112 /// The certificate version
78113 ///
79114 /// Note that this value defaults to Version 1 per the RFC. However,
@@ -83,7 +118,7 @@ pub struct TbsCertificate {
83118 #[ asn1( context_specific = "0" , default = "Default::default" ) ]
84119 pub version : Version ,
85120
86- pub serial_number : SerialNumber ,
121+ pub serial_number : SerialNumber < PP > ,
87122 pub signature : AlgorithmIdentifierOwned ,
88123 pub issuer : Name ,
89124 pub validity : Validity ,
@@ -98,9 +133,12 @@ pub struct TbsCertificate {
98133
99134 #[ asn1( context_specific = "3" , tag_mode = "EXPLICIT" , optional = "true" ) ]
100135 pub extensions : Option < crate :: ext:: Extensions > ,
136+
137+ #[ asn1( skipped = "Default::default" ) ]
138+ _profile : PhantomData < PP > ,
101139}
102140
103- impl TbsCertificate {
141+ impl < PP : ParsingProfile > TbsCertificate < PP > {
104142 /// Decodes a single extension
105143 ///
106144 /// Returns an error if multiple of these extensions is present. Returns
@@ -146,14 +184,14 @@ impl TbsCertificate {
146184#[ cfg_attr( feature = "arbitrary" , derive( arbitrary:: Arbitrary ) ) ]
147185#[ derive( Clone , Debug , Eq , PartialEq , Sequence , ValueOrd ) ]
148186#[ allow( missing_docs) ]
149- pub struct Certificate {
150- pub tbs_certificate : TbsCertificate ,
187+ pub struct Certificate < PP : ParsingProfile = Rfc5280 > {
188+ pub tbs_certificate : TbsCertificate < PP > ,
151189 pub signature_algorithm : AlgorithmIdentifierOwned ,
152190 pub signature : BitString ,
153191}
154192
155193#[ cfg( feature = "pem" ) ]
156- impl PemLabel for Certificate {
194+ impl < PP : ParsingProfile > PemLabel for Certificate < PP > {
157195 const PEM_LABEL : & ' static str = "CERTIFICATE" ;
158196}
159197
0 commit comments