ocsp/common/
asn1.rs

1//! Common components in ASN.1  
2//! For ASN.1 universal tags list, see [here](https://www.obj-sys.com/asn1tutorial/node124.html)
3
4use asn1_der::{
5    typed::{DerDecodable, Sequence},
6    DerObject,
7};
8use chrono::{Datelike, Timelike};
9use tracing::{error, trace};
10
11use crate::err::OcspError;
12use crate::oid::{b2i_oid, d2i_oid, i2b_oid};
13
14/// Aliasing `Vec<u8>` with Bytes
15pub type Bytes = Vec<u8>;
16
17/// ASN.1 explicit tag 0
18pub(crate) const ASN1_EXPLICIT_0: u8 = 0xa0;
19/// ASN.1 explicit tag 1
20pub(crate) const ASN1_EXPLICIT_1: u8 = 0xa1;
21/// ASN.1 explicit tag 1
22pub(crate) const ASN1_EXPLICIT_2: u8 = 0xa2;
23/// ASN.1 null
24pub(crate) const ASN1_NULL: u8 = 0x05;
25/// ASN.1 oid
26pub(crate) const ASN1_OID: u8 = 0x06;
27/// ASN.1 oid followed by NULL
28pub(crate) const ASN1_OID_PADDING: [u8; 2] = [0x05, 0x00];
29/// ASN.1 sequence
30pub(crate) const ASN1_SEQUENCE: u8 = 0x30;
31/// ASN.1 octet
32pub(crate) const ASN1_OCTET: u8 = 0x04;
33/// ASN.1 integer
34pub(crate) const ASN1_INTEGER: u8 = 0x02;
35/// ASN.1 ia5string
36pub(crate) const ASN1_IA5STRING: u8 = 0x16;
37/// ASN.1 generalized time
38pub(crate) const ASN1_GENERALIZED_TIME: u8 = 0x18;
39/// ASN.1 enumerated
40pub(crate) const ASN1_ENUMERATED: u8 = 0x0a;
41/// ASN.1 bit string
42pub(crate) const ASN1_BIT_STRING: u8 = 0x03;
43
44/// Allowing byte data to be converted to [Sequence](https://docs.rs/asn1_der/0.7.2/asn1_der/typed/struct.Sequence.html)
45pub trait TryIntoSequence<'d> {
46    /// Converting asn1_der::err
47    type Error;
48    /// Try converting to Sequence
49    fn try_into(&'d self) -> Result<Sequence<'d>, Self::Error>;
50}
51
52impl<'d> TryIntoSequence<'d> for DerObject<'d> {
53    type Error = OcspError;
54    fn try_into(&self) -> Result<Sequence<'d>, Self::Error> {
55        Sequence::decode(self.raw()).map_err(OcspError::Asn1DecodingError)
56    }
57}
58
59impl<'d> TryIntoSequence<'d> for Bytes {
60    type Error = OcspError;
61    fn try_into(&'d self) -> Result<Sequence<'d>, Self::Error> {
62        Sequence::decode(self).map_err(OcspError::Asn1DecodingError)
63    }
64}
65
66impl<'d> TryIntoSequence<'d> for &[u8] {
67    type Error = OcspError;
68    fn try_into(&'d self) -> Result<Sequence<'d>, Self::Error> {
69        Sequence::decode(self).map_err(OcspError::Asn1DecodingError)
70    }
71}
72
73/// Determining ASN.1 length  
74/// For details, check ASN.1 encoding rules at [here](https://docs.microsoft.com/en-us/windows/win32/seccertenroll/about-encoded-length-and-value-bytes)
75pub(crate) fn asn1_encode_length(len: usize) -> Result<Bytes, OcspError> {
76    match len {
77        0..=127 => Ok(vec![len as u8]),
78        _ => {
79            let v = len.to_be_bytes().to_vec();
80            // removing leading zero in usize
81            let v: Bytes = v.into_iter().skip_while(|n| *n == 0).collect();
82
83            // safety check
84            if v.len() > 127 {
85                return Err(OcspError::Asn1LengthOverflow(v.len()));
86            }
87            let l = 0x80 + v.len() as u8;
88            let l = vec![l];
89            Ok(l.into_iter().chain(v.into_iter()).collect())
90        }
91    }
92}
93
94/// Packing octet into ASN.1 DER
95pub(crate) fn asn1_encode_octet(data: &[u8]) -> Result<Bytes, OcspError> {
96    let mut tlv = vec![ASN1_OCTET];
97    let len = asn1_encode_length(data.len())?;
98    tlv.extend(len);
99    tlv.extend(data);
100    Ok(tlv)
101}
102
103/// Packing integer into ASN.1 DER
104pub(crate) fn asn1_encode_integer(data: &[u8]) -> Result<Bytes, OcspError> {
105    let mut tlv = vec![ASN1_INTEGER];
106    let len = asn1_encode_length(data.len())?;
107    tlv.extend(len);
108    tlv.extend(data);
109    Ok(tlv)
110}
111
112/// Packing bit string into ASN.1 DER
113pub(crate) fn asn1_encode_bit_string(data: &[u8]) -> Result<Bytes, OcspError> {
114    let mut tlv = vec![ASN1_BIT_STRING];
115    let len = asn1_encode_length(data.len())?;
116    tlv.extend(len);
117    tlv.extend(data);
118    Ok(tlv)
119}
120
121/// Represents a ASN.1 GeneralizedTime  
122/// Only support UTC
123#[derive(Debug, Copy, Clone)]
124pub struct GeneralizedTime {
125    year: i32,
126    month: u32,
127    day: u32,
128    hour: u32,
129    min: u32,
130    sec: u32,
131    //millis: u32,
132}
133
134impl GeneralizedTime {
135    /// Create a generalized time at specified time
136    pub fn new(
137        year: i32,
138        month: u32,
139        day: u32,
140        hour: u32,
141        min: u32,
142        sec: u32,
143    ) -> Result<Self, OcspError> {
144        // lazy check if date time is valid
145        // turn it into chrono
146        let dt = chrono::NaiveDate::from_ymd_opt(year, month, day)
147            .ok_or(OcspError::GenInvalidDate(year, month, day))?;
148        let _ = dt
149            .and_hms_opt(hour, min, sec)
150            .ok_or(OcspError::GenInvalidTime(hour, min, sec))?;
151
152        Ok(GeneralizedTime {
153            year,
154            month,
155            day,
156            hour,
157            min,
158            sec,
159        })
160    }
161
162    /// Create a generalized time **now** in UTC
163    pub fn now() -> Self {
164        let now = chrono::offset::Utc::now();
165
166        GeneralizedTime {
167            year: now.year(),
168            month: now.month(),
169            day: now.day(),
170            hour: now.hour(),
171            min: now.minute(),
172            sec: now.second(),
173            //millis: mi,
174        }
175    }
176
177    /// Serialize to DER encoding  
178    /// see [html](https://www.obj-sys.com/asn1tutorial/node14.html)
179    pub fn to_der_utc(&self) -> Result<Bytes, OcspError> {
180        let v = format!(
181            "{}{:02}{:02}{:02}{:02}{:02}Z",
182            self.year, self.month, self.day, self.hour, self.min, self.sec
183        )
184        .as_bytes()
185        .to_vec();
186        let l = asn1_encode_length(v.len())?;
187        let mut t = vec![ASN1_GENERALIZED_TIME];
188        t.extend(l);
189        t.extend(v);
190        Ok(t)
191    }
192}
193
194/// Oid represents a 0x06 OID type in ASN.1  
195/// In OpenSSL ocsp request, OID is followed by NULL 0x05  
196/// REVIEW 0x05
197#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
198pub struct Oid {
199    pub(crate) index: usize,
200}
201
202impl Oid {
203    /// get oid from raw bytes
204    pub fn parse(oid: &[u8]) -> Result<Self, OcspError> {
205        let oid_hex = hex::encode(oid);
206        trace!("Parsing oid {}", oid_hex);
207        let s = oid.try_into()?;
208
209        if s.len() != 2 {
210            error!(
211                "Provided oid contains {} items in sequence, expecting 2",
212                s.len()
213            );
214            return Err(OcspError::Asn1LengthError("OID"));
215        }
216
217        let id = s.get(0).map_err(OcspError::Asn1DecodingError)?;
218        let nil = s.get(1).map_err(OcspError::Asn1DecodingError)?;
219        if id.tag() != ASN1_OID || nil.tag() != ASN1_NULL {
220            error!(
221                "Provided oid sequence tags are {} and {}, expecting 0x06 and 0x05",
222                id.tag(),
223                nil.tag()
224            );
225            return Err(OcspError::Asn1MismatchError("OID"));
226        }
227
228        let u = match b2i_oid(id.value()) {
229            None => return Err(OcspError::Asn1OidUnknown),
230            Some(u) => u,
231        };
232
233        trace!("Oid {} successfully decoded to internal {}", oid_hex, u);
234        Ok(Oid { index: u })
235    }
236
237    /// return new oid from dot notation
238    pub fn new_from_dot(name_dot_notation: &str) -> Result<Self, OcspError> {
239        // ignoring logging here, trace if logged in d2i_oid
240        d2i_oid(name_dot_notation).ok_or(OcspError::Asn1OidUnknown)
241    }
242
243    /// encode to ASN.1 DER with tailing NULL
244    pub fn to_der_with_null(&self) -> Result<Bytes, OcspError> {
245        trace!("Encoding oid index {}", self.index);
246        let val_oid = i2b_oid(self)?;
247        let len_oid = asn1_encode_length(val_oid.len())?;
248        let mut tlv_oid = vec![ASN1_OID];
249        tlv_oid.extend(len_oid);
250        tlv_oid.extend(val_oid);
251        tlv_oid.extend(ASN1_OID_PADDING);
252        let len_seq = asn1_encode_length(tlv_oid.len())?;
253        let mut tlv_seq_oid = vec![ASN1_SEQUENCE];
254        tlv_seq_oid.extend(len_seq);
255        tlv_seq_oid.extend(tlv_oid);
256
257        trace!("Internal oid {} successfully encoded", self.index);
258        Ok(tlv_seq_oid)
259    }
260
261    /// encode to ASN.1 DER
262    /// - without sequence header
263    /// - without tailing NULL
264    pub fn to_der_raw(&self) -> Result<Bytes, OcspError> {
265        trace!("Encoding oid without sequence index {}", self.index);
266        let val_oid = i2b_oid(self)?;
267        let len_oid = asn1_encode_length(val_oid.len())?;
268        let mut tlv_oid = vec![ASN1_OID];
269        tlv_oid.extend(len_oid);
270        tlv_oid.extend(val_oid);
271
272        trace!(
273            "Internal oid {} successfully encoded without padding",
274            self.index
275        );
276        Ok(tlv_oid)
277    }
278}
279
280/// RFC 6960 CertID or cid
281#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
282pub struct CertId {
283    /// hash algo oid
284    pub hash_algo: Oid,
285    /// issuer name hash in byte
286    pub issuer_name_hash: Bytes,
287    /// issuer key hash in byte
288    pub issuer_key_hash: Bytes,
289    /// certificate serial number in byte
290    pub serial_num: Bytes,
291}
292
293impl CertId {
294    /// get cid from raw bytes
295    pub fn parse(cid: &[u8]) -> Result<Self, OcspError> {
296        let cid_hex = hex::encode(cid);
297        trace!("Parsing cid {}", cid_hex);
298        let s = cid.try_into()?;
299
300        if s.len() != 4 {
301            error!(
302                "Provided cid contains {} items in sequence, expecting 4",
303                s.len()
304            );
305            return Err(OcspError::Asn1LengthError("CID"));
306        }
307
308        let oid = s.get(0).map_err(OcspError::Asn1DecodingError)?;
309        let name_hash = s.get(1).map_err(OcspError::Asn1DecodingError)?;
310        let key_hash = s.get(2).map_err(OcspError::Asn1DecodingError)?;
311        let sn = s.get(3).map_err(OcspError::Asn1DecodingError)?;
312
313        if oid.tag() != ASN1_SEQUENCE
314            || name_hash.tag() != ASN1_OCTET
315            || key_hash.tag() != ASN1_OCTET
316            || sn.tag() != ASN1_INTEGER
317        {
318            error!(
319                "Provided cid sequence tags are {}, {}, {} and {}, expecting 0x30, 0x04, 0x04, 0x02", 
320                oid.tag(),
321                name_hash.tag(),
322                key_hash.tag(),
323                sn.tag()
324            );
325            return Err(OcspError::Asn1MismatchError("CID"));
326        }
327
328        let oid = Oid::parse(oid.raw())?;
329        let name_hash = name_hash.value().to_vec();
330        let key_hash = key_hash.value().to_vec();
331        let sn = sn.value().to_vec();
332
333        trace!("Cid {} successfully decoded", cid_hex);
334        Ok(CertId {
335            hash_algo: oid,
336            issuer_name_hash: name_hash,
337            issuer_key_hash: key_hash,
338            serial_num: sn,
339        })
340    }
341
342    /// create new cid
343    pub fn new(oid: Oid, name_hash: &[u8], key_hash: &[u8], sn: &[u8]) -> Self {
344        CertId {
345            hash_algo: oid,
346            issuer_name_hash: name_hash.to_vec(),
347            issuer_key_hash: key_hash.to_vec(),
348            serial_num: sn.to_vec(),
349        }
350    }
351
352    /// encode cid to ASN.1 DER
353    pub fn to_der(&self) -> Result<Bytes, OcspError> {
354        trace!("Encoding cid with sn {}", hex::encode(&self.serial_num));
355
356        let mut oid = self.hash_algo.to_der_with_null()?;
357        let name = asn1_encode_octet(&self.issuer_name_hash)?;
358        let key = asn1_encode_octet(&self.issuer_key_hash)?;
359        let sn = asn1_encode_integer(&self.serial_num)?;
360        oid.extend(name);
361        oid.extend(key);
362        oid.extend(sn);
363        let len = asn1_encode_length(oid.len())?;
364        let mut tlv = vec![ASN1_SEQUENCE];
365        tlv.extend(len);
366        tlv.extend(oid);
367
368        trace!("Cid {:?} successfully encoded", self);
369        Ok(tlv)
370    }
371}
372#[cfg(test)]
373mod test {
374    use hex::FromHex;
375
376    use crate::oid::{ALGO_SHA1_DOT, OCSP_EXT_CRL_REASON_DOT, OCSP_EXT_CRL_REASON_ID};
377
378    use super::*;
379
380    // test encoding length
381    #[test]
382    fn encoding_length_over128() {
383        let v = asn1_encode_length(4934).unwrap();
384        let c = vec![0x82, 0x13, 0x46u8];
385        assert_eq!(c, v);
386
387        let v = asn1_encode_length(256).unwrap();
388        let c = vec![0x82, 0x01, 0x00u8];
389        assert_eq!(c, v);
390    }
391
392    // test encoding length
393    #[test]
394    fn encoding_length_under128() {
395        let v = asn1_encode_length(52).unwrap();
396        let c = vec![0x34u8];
397        assert_eq!(c, v);
398
399        let v = asn1_encode_length(127).unwrap();
400        let c = vec![0x7fu8];
401        assert_eq!(c, v);
402    }
403
404    // test encoding signature
405    #[test]
406    fn encode_bit_string() {
407        let sign = vec![
408            0x6du8, 0xdb, 0x51, 0x4f, 0x2c, 0x6a, 0x35, 0x49, 0x80, 0x1e, 0x40, 0x1e, 0x31, 0x45,
409            0xdd, 0x88, 0x4a, 0x6a, 0x47, 0x2c, 0x8a, 0x09, 0xa6, 0xf9, 0xa3, 0x18, 0x79, 0x85,
410            0xa3, 0x4e, 0xcb, 0x59, 0xa2, 0xbb, 0x49, 0x15, 0x40, 0x9b, 0x8d, 0x89, 0x25, 0x05,
411            0x5d, 0xa0, 0x6a, 0xb3, 0xb1, 0x07, 0x57, 0xde, 0x46, 0x43, 0x37, 0xd7, 0x0b, 0x29,
412            0x56, 0x67, 0xf9, 0x7a, 0xbb, 0x33, 0x78, 0x3d, 0x5f, 0x38, 0x5a, 0xb8, 0x77, 0x38,
413            0x1b, 0xac, 0x7c, 0x15, 0xdb, 0xcf, 0x85, 0xe9, 0x38, 0x51, 0x94, 0x39, 0x7d, 0x05,
414            0x34, 0x2e, 0x32, 0x64, 0xb7, 0x72, 0x49, 0x51, 0xbd, 0x61, 0xf6, 0x8c, 0x0b, 0x7f,
415            0xa1, 0x02, 0x97, 0xa2, 0xe0, 0x41, 0x35, 0xdc, 0xe5, 0x5c, 0x55, 0x74, 0xab, 0x02,
416            0xcf, 0x63, 0x76, 0x96, 0x98, 0xa6, 0xec, 0x0d, 0x94, 0xa3, 0xa2, 0xf5, 0xbe, 0xee,
417            0x0a, 0xdd, 0x0f, 0x5d, 0x9e, 0x96, 0x7a, 0x73, 0x6d, 0xb7, 0x45, 0xbd, 0xda, 0xa7,
418            0x90, 0xf7, 0x49, 0x16, 0x0f, 0x42, 0xf1, 0x03, 0x70, 0x3f, 0xec, 0xb4, 0xa8, 0x09,
419            0x55, 0xa0, 0x5c, 0x7a, 0x7a, 0x29, 0xac, 0xf6, 0x13, 0xd8, 0xac, 0x08, 0x15, 0x5c,
420            0xab, 0x2f, 0x59, 0xc0, 0xc3, 0xe3, 0x3d, 0x2d, 0x1b, 0xb0, 0x56, 0x0a, 0xde, 0x03,
421            0x94, 0x30, 0x86, 0xdf, 0x7d, 0xa7, 0x48, 0x4a, 0x8c, 0x7b, 0x6d, 0xca, 0x10, 0x79,
422            0x6d, 0x42, 0x69, 0x79, 0xbd, 0x02, 0x1d, 0x22, 0x00, 0x94, 0x98, 0x5f, 0x94, 0x89,
423            0x0b, 0xca, 0xdc, 0x03, 0x54, 0xb2, 0x89, 0x93, 0x1f, 0xf4, 0x56, 0x4c, 0x98, 0xdf,
424            0xf8, 0xe5, 0x32, 0x69, 0x5d, 0x21, 0xc8, 0x2f, 0x46, 0x18, 0xfd, 0x60, 0x98, 0x7d,
425            0x98, 0xee, 0x04, 0x09, 0xfb, 0xa4, 0x8a, 0xe4, 0x46, 0xdf, 0xfe, 0xc7, 0x1d, 0xb9,
426            0x57, 0x40, 0x69, 0xb4,
427        ];
428
429        let bit = asn1_encode_bit_string(&sign).unwrap();
430        let c = vec![
431            0x03, 0x82, 0x01, 0x00, 0x6d, 0xdb, 0x51, 0x4f, 0x2c, 0x6a, 0x35, 0x49, 0x80, 0x1e,
432            0x40, 0x1e, 0x31, 0x45, 0xdd, 0x88, 0x4a, 0x6a, 0x47, 0x2c, 0x8a, 0x09, 0xa6, 0xf9,
433            0xa3, 0x18, 0x79, 0x85, 0xa3, 0x4e, 0xcb, 0x59, 0xa2, 0xbb, 0x49, 0x15, 0x40, 0x9b,
434            0x8d, 0x89, 0x25, 0x05, 0x5d, 0xa0, 0x6a, 0xb3, 0xb1, 0x07, 0x57, 0xde, 0x46, 0x43,
435            0x37, 0xd7, 0x0b, 0x29, 0x56, 0x67, 0xf9, 0x7a, 0xbb, 0x33, 0x78, 0x3d, 0x5f, 0x38,
436            0x5a, 0xb8, 0x77, 0x38, 0x1b, 0xac, 0x7c, 0x15, 0xdb, 0xcf, 0x85, 0xe9, 0x38, 0x51,
437            0x94, 0x39, 0x7d, 0x05, 0x34, 0x2e, 0x32, 0x64, 0xb7, 0x72, 0x49, 0x51, 0xbd, 0x61,
438            0xf6, 0x8c, 0x0b, 0x7f, 0xa1, 0x02, 0x97, 0xa2, 0xe0, 0x41, 0x35, 0xdc, 0xe5, 0x5c,
439            0x55, 0x74, 0xab, 0x02, 0xcf, 0x63, 0x76, 0x96, 0x98, 0xa6, 0xec, 0x0d, 0x94, 0xa3,
440            0xa2, 0xf5, 0xbe, 0xee, 0x0a, 0xdd, 0x0f, 0x5d, 0x9e, 0x96, 0x7a, 0x73, 0x6d, 0xb7,
441            0x45, 0xbd, 0xda, 0xa7, 0x90, 0xf7, 0x49, 0x16, 0x0f, 0x42, 0xf1, 0x03, 0x70, 0x3f,
442            0xec, 0xb4, 0xa8, 0x09, 0x55, 0xa0, 0x5c, 0x7a, 0x7a, 0x29, 0xac, 0xf6, 0x13, 0xd8,
443            0xac, 0x08, 0x15, 0x5c, 0xab, 0x2f, 0x59, 0xc0, 0xc3, 0xe3, 0x3d, 0x2d, 0x1b, 0xb0,
444            0x56, 0x0a, 0xde, 0x03, 0x94, 0x30, 0x86, 0xdf, 0x7d, 0xa7, 0x48, 0x4a, 0x8c, 0x7b,
445            0x6d, 0xca, 0x10, 0x79, 0x6d, 0x42, 0x69, 0x79, 0xbd, 0x02, 0x1d, 0x22, 0x00, 0x94,
446            0x98, 0x5f, 0x94, 0x89, 0x0b, 0xca, 0xdc, 0x03, 0x54, 0xb2, 0x89, 0x93, 0x1f, 0xf4,
447            0x56, 0x4c, 0x98, 0xdf, 0xf8, 0xe5, 0x32, 0x69, 0x5d, 0x21, 0xc8, 0x2f, 0x46, 0x18,
448            0xfd, 0x60, 0x98, 0x7d, 0x98, 0xee, 0x04, 0x09, 0xfb, 0xa4, 0x8a, 0xe4, 0x46, 0xdf,
449            0xfe, 0xc7, 0x1d, 0xb9, 0x57, 0x40, 0x69, 0xb4,
450        ];
451
452        assert_eq!(c, bit);
453    }
454
455    /// test certid to ASN.1 DER
456    #[test]
457    fn certid_to_der() {
458        let oid = Oid::new_from_dot(ALGO_SHA1_DOT).unwrap();
459        let name = vec![
460            0x69, 0x4d, 0x18, 0xa9, 0xbe, 0x42, 0xf7, 0x80, 0x26, 0x14, 0xd4, 0x84, 0x4f, 0x23,
461            0x60, 0x14, 0x78, 0xb7, 0x88, 0x20,
462        ];
463        let key = vec![
464            0x39, 0x7b, 0xe0, 0x02, 0xa2, 0xf5, 0x71, 0xfd, 0x80, 0xdc, 0xeb, 0x52, 0xa1, 0x7a,
465            0x7f, 0x8b, 0x63, 0x2b, 0xe7, 0x55,
466        ];
467        let sn = vec![0x41, 0x30, 0x09, 0x83, 0x33, 0x1f, 0x9d, 0x4f];
468        let certid = CertId::new(oid, &name, &key, &sn);
469        let v = certid.to_der().unwrap();
470        let c = vec![
471            0x30, 0x41, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04,
472            0x14, 0x69, 0x4d, 0x18, 0xa9, 0xbe, 0x42, 0xf7, 0x80, 0x26, 0x14, 0xd4, 0x84, 0x4f,
473            0x23, 0x60, 0x14, 0x78, 0xb7, 0x88, 0x20, 0x04, 0x14, 0x39, 0x7b, 0xe0, 0x02, 0xa2,
474            0xf5, 0x71, 0xfd, 0x80, 0xdc, 0xeb, 0x52, 0xa1, 0x7a, 0x7f, 0x8b, 0x63, 0x2b, 0xe7,
475            0x55, 0x02, 0x08, 0x41, 0x30, 0x09, 0x83, 0x33, 0x1f, 0x9d, 0x4f,
476        ];
477
478        assert_eq!(c, v);
479    }
480
481    /// test oid to ASN.1 DER
482    #[test]
483    fn oid_to_der() {
484        let oid = Oid::new_from_dot(ALGO_SHA1_DOT).unwrap();
485        let v = oid.to_der_with_null().unwrap();
486        assert_eq!(
487            vec![0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00],
488            v
489        );
490    }
491
492    /// test oid dot notation to internal
493    #[test]
494    fn oid_dot_new() {
495        let dot = OCSP_EXT_CRL_REASON_DOT;
496        let d = Oid::new_from_dot(dot).unwrap().index;
497        assert_eq!(d, OCSP_EXT_CRL_REASON_ID);
498    }
499
500    /// test generalized time to der
501    #[test]
502    fn generalized_time_to_der_utc() {
503        let gt = GeneralizedTime {
504            year: 2021,
505            month: 1,
506            day: 13,
507            hour: 3,
508            min: 9,
509            sec: 25,
510        };
511
512        let der = gt.to_der_utc().unwrap();
513        assert_eq!(
514            vec![
515                0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x30, 0x31, 0x31, 0x33, 0x30, 0x33, 0x30, 0x39,
516                0x32, 0x35, 0x5a
517            ],
518            der
519        );
520    }
521
522    /// test asn1 encoding with length requires more than one byte
523    #[test]
524    fn asn1_length_4934() {
525        let v = asn1_encode_length(4934).unwrap();
526        assert_eq!(vec![0x82, 0x13, 0x46], v);
527    }
528
529    /// test asn1 encoding with one byte length
530    #[test]
531    fn asn1_length_127() {
532        let v = asn1_encode_length(52).unwrap();
533        assert_eq!(vec![0x34], v)
534    }
535
536    /// generalized time conversion
537    #[test]
538    fn num2hex() {
539        let num: u32 = 2021;
540        let hex = num.to_string();
541        let hex = hex.as_bytes();
542        assert_eq!(vec![0x32, 0x30, 0x32, 0x31], hex);
543    }
544
545    // generalized time conversion
546    #[test]
547    fn hex2time() {
548        let hex = "32303231303131333033303932355a";
549        let hex = Vec::from_hex(hex).unwrap();
550        let time = std::str::from_utf8(&hex).unwrap();
551        assert_eq!("20210113030925Z", time);
552    }
553}