1
1
//! X.509 serial number
2
2
3
- use core:: fmt:: Display ;
3
+ use core:: { fmt:: Display , marker :: PhantomData } ;
4
4
5
5
use der:: {
6
6
asn1:: { self , Int } ,
7
7
DecodeValue , EncodeValue , ErrorKind , FixedTag , Header , Length , Reader , Result , Tag , ValueOrd ,
8
8
Writer ,
9
9
} ;
10
10
11
+ use crate :: certificate:: { Profile , Rfc5280 } ;
12
+
11
13
/// [RFC 5280 Section 4.1.2.2.] Serial Number
12
14
///
13
15
/// The serial number MUST be a positive integer assigned by the CA to
@@ -25,16 +27,17 @@ use der::{
25
27
/// that are negative or zero. Certificate users SHOULD be prepared to
26
28
/// gracefully handle such certificates.
27
29
#[ derive( Clone , Debug , Eq , PartialEq , ValueOrd , PartialOrd , Ord ) ]
28
- pub struct SerialNumber {
29
- inner : Int ,
30
+ pub struct SerialNumber < P : Profile = Rfc5280 > {
31
+ pub ( crate ) inner : Int ,
32
+ _profile : PhantomData < P > ,
30
33
}
31
34
32
- impl SerialNumber {
35
+ impl < P : Profile > SerialNumber < P > {
33
36
/// Maximum length in bytes for a [`SerialNumber`]
34
37
pub const MAX_LEN : Length = Length :: new ( 20 ) ;
35
38
36
39
/// See notes in `SerialNumber::new` and `SerialNumber::decode_value`.
37
- const MAX_DECODE_LEN : Length = Length :: new ( 21 ) ;
40
+ pub ( crate ) const MAX_DECODE_LEN : Length = Length :: new ( 21 ) ;
38
41
39
42
/// Create a new [`SerialNumber`] from a byte slice.
40
43
///
@@ -47,12 +50,13 @@ impl SerialNumber {
47
50
// RFC 5280 is ambiguous about whether this is valid, so we limit
48
51
// `SerialNumber` *encodings* to 20 bytes or fewer while permitting
49
52
// `SerialNumber` *decodings* to have up to 21 bytes below.
50
- if inner. value_len ( ) ? > SerialNumber :: MAX_LEN {
53
+ if inner. value_len ( ) ? > Self :: MAX_LEN {
51
54
return Err ( ErrorKind :: Overlength . into ( ) ) ;
52
55
}
53
56
54
57
Ok ( Self {
55
58
inner : inner. into ( ) ,
59
+ _profile : PhantomData ,
56
60
} )
57
61
}
58
62
@@ -63,7 +67,7 @@ impl SerialNumber {
63
67
}
64
68
}
65
69
66
- impl EncodeValue for SerialNumber {
70
+ impl < P : Profile > EncodeValue for SerialNumber < P > {
67
71
fn value_len ( & self ) -> Result < Length > {
68
72
self . inner . value_len ( )
69
73
}
@@ -73,22 +77,21 @@ impl EncodeValue for SerialNumber {
73
77
}
74
78
}
75
79
76
- impl < ' a > DecodeValue < ' a > for SerialNumber {
80
+ impl < ' a , P : Profile > DecodeValue < ' a > for SerialNumber < P > {
77
81
fn decode_value < R : Reader < ' a > > ( reader : & mut R , header : Header ) -> Result < Self > {
78
82
let inner = Int :: decode_value ( reader, header) ?;
83
+ let serial = Self {
84
+ inner,
85
+ _profile : PhantomData ,
86
+ } ;
79
87
80
- // See the note in `SerialNumber::new`: we permit lengths of 21 bytes here,
81
- // since some X.509 implementations interpret the limit of 20 bytes to refer
82
- // to the pre-encoded value.
83
- if inner. len ( ) > SerialNumber :: MAX_DECODE_LEN {
84
- return Err ( Tag :: Integer . value_error ( ) ) ;
85
- }
88
+ P :: check_serial_number ( & serial) ?;
86
89
87
- Ok ( Self { inner } )
90
+ Ok ( serial )
88
91
}
89
92
}
90
93
91
- impl FixedTag for SerialNumber {
94
+ impl < P : Profile > FixedTag for SerialNumber < P > {
92
95
const TAG : Tag = <Int as FixedTag >:: TAG ;
93
96
}
94
97
@@ -131,7 +134,7 @@ impl_from!(usize);
131
134
// Implement by hand because the derive would create invalid values.
132
135
// Use the constructor to create a valid value.
133
136
#[ cfg( feature = "arbitrary" ) ]
134
- impl < ' a > arbitrary:: Arbitrary < ' a > for SerialNumber {
137
+ impl < ' a , P : Profile > arbitrary:: Arbitrary < ' a > for SerialNumber < P > {
135
138
fn arbitrary ( u : & mut arbitrary:: Unstructured < ' a > ) -> arbitrary:: Result < Self > {
136
139
let len = u. int_in_range ( 0u32 ..=Self :: MAX_LEN . into ( ) ) ?;
137
140
@@ -154,7 +157,7 @@ mod tests {
154
157
// Creating a new serial with an oversized encoding (due to high MSB) fails.
155
158
{
156
159
let too_big = [ 0x80 ; 20 ] ;
157
- assert ! ( SerialNumber :: new( & too_big) . is_err( ) ) ;
160
+ assert ! ( SerialNumber :: < Rfc5280 > :: new( & too_big) . is_err( ) ) ;
158
161
}
159
162
160
163
// Creating a new serial with the maximum encoding succeeds.
@@ -163,7 +166,7 @@ mod tests {
163
166
0x7F , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
164
167
0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
165
168
] ;
166
- assert ! ( SerialNumber :: new( & just_enough) . is_ok( ) ) ;
169
+ assert ! ( SerialNumber :: < Rfc5280 > :: new( & just_enough) . is_ok( ) ) ;
167
170
}
168
171
}
169
172
0 commit comments