3
3
use crate :: { name:: Name , serial_number:: SerialNumber , time:: Validity } ;
4
4
use alloc:: vec:: Vec ;
5
5
use const_oid:: AssociatedOid ;
6
- use core:: cmp:: Ordering ;
6
+ use core:: { cmp:: Ordering , fmt :: Debug , marker :: PhantomData } ;
7
7
use der:: asn1:: BitString ;
8
8
use der:: { Decode , Enumerated , Error , ErrorKind , Sequence , ValueOrd } ;
9
9
use spki:: { AlgorithmIdentifierOwned , SubjectPublicKeyInfoOwned } ;
10
10
11
11
#[ cfg( feature = "pem" ) ]
12
12
use der:: pem:: PemLabel ;
13
13
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
+
14
49
/// Certificate `Version` as defined in [RFC 5280 Section 4.1].
15
50
///
16
51
/// ```text
@@ -73,7 +108,7 @@ impl Default for Version {
73
108
#[ cfg_attr( feature = "arbitrary" , derive( arbitrary:: Arbitrary ) ) ]
74
109
#[ derive( Clone , Debug , Eq , PartialEq , Sequence , ValueOrd ) ]
75
110
#[ allow( missing_docs) ]
76
- pub struct TbsCertificate {
111
+ pub struct TbsCertificate < PP : ParsingProfile = Rfc5280 > {
77
112
/// The certificate version
78
113
///
79
114
/// Note that this value defaults to Version 1 per the RFC. However,
@@ -83,7 +118,7 @@ pub struct TbsCertificate {
83
118
#[ asn1( context_specific = "0" , default = "Default::default" ) ]
84
119
pub version : Version ,
85
120
86
- pub serial_number : SerialNumber ,
121
+ pub serial_number : SerialNumber < PP > ,
87
122
pub signature : AlgorithmIdentifierOwned ,
88
123
pub issuer : Name ,
89
124
pub validity : Validity ,
@@ -98,9 +133,12 @@ pub struct TbsCertificate {
98
133
99
134
#[ asn1( context_specific = "3" , tag_mode = "EXPLICIT" , optional = "true" ) ]
100
135
pub extensions : Option < crate :: ext:: Extensions > ,
136
+
137
+ #[ asn1( skipped = "Default::default" ) ]
138
+ _profile : PhantomData < PP > ,
101
139
}
102
140
103
- impl TbsCertificate {
141
+ impl < PP : ParsingProfile > TbsCertificate < PP > {
104
142
/// Decodes a single extension
105
143
///
106
144
/// Returns an error if multiple of these extensions is present. Returns
@@ -146,14 +184,14 @@ impl TbsCertificate {
146
184
#[ cfg_attr( feature = "arbitrary" , derive( arbitrary:: Arbitrary ) ) ]
147
185
#[ derive( Clone , Debug , Eq , PartialEq , Sequence , ValueOrd ) ]
148
186
#[ 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 > ,
151
189
pub signature_algorithm : AlgorithmIdentifierOwned ,
152
190
pub signature : BitString ,
153
191
}
154
192
155
193
#[ cfg( feature = "pem" ) ]
156
- impl PemLabel for Certificate {
194
+ impl < PP : ParsingProfile > PemLabel for Certificate < PP > {
157
195
const PEM_LABEL : & ' static str = "CERTIFICATE" ;
158
196
}
159
197
0 commit comments