simple_asn1/
lib.rs

1//! A small ASN.1 parsing library for Rust. In particular, this library is used
2//! to translate the binary DER encoding of an ASN.1-formatted document into the
3//! core primitives of ASN.1. It is assumed that you can do what you need to
4//! from there.
5//!
6//! The critical items for this document are the traits `ToASN1` and `FromASN1`.
7//! The first takes your data type and encodes it into a `Vec` of simple ASN.1
8//! structures (`ASN1Block`s). The latter inverts the process.
9//!
10//! Items that implement `ToASN1` can be used with the function `der_encode`
11//! to provide single-step encoding of a data type to binary DER encoding.
12//! Similarly, items that are `FromASN` can be single-step decoded using
13//! the helper function `der_decode`.
14//!
15//! You can implement one or both traits, depending on your needs. If you do
16//! implement both, the obvious encode/decode quickcheck property is strongly
17//! advised.
18//!
19//! For decoding schemes that require the actual bytes associated with the
20//! binary representation, we also provide `FromASN1WithBody`. This can be
21//! used with the offset information in the primitive `ASN1Block`s to, for
22//! example, validate signatures in X509 documents.
23//!
24//! Finally, this library supports ASN.1 class information. I'm still not sure
25//! why it's useful, but there it is.
26//!
27//! Please send any bug reports, patches, and curses to the GitHub repository
28//! at <code>https://github.com/acw/simple_asn1</code>.
29pub use num_bigint::{BigInt, BigUint};
30use num_traits::{FromPrimitive, One, ToPrimitive, Zero};
31#[cfg(test)]
32use quickcheck::quickcheck;
33use std::convert::TryFrom;
34use std::iter::FromIterator;
35use std::mem::size_of;
36use std::str::Utf8Error;
37use thiserror::Error;
38use time::PrimitiveDateTime;
39
40/// An ASN.1 block class.
41///
42/// I'm not sure if/when these are used, but here they are in case you want
43/// to do something with them.
44#[derive(Clone, Copy, Debug, PartialEq)]
45pub enum ASN1Class {
46    Universal,
47    Application,
48    ContextSpecific,
49    Private,
50}
51
52/// A primitive block from ASN.1.
53///
54/// Primitive blocks all contain the offset from the beginning of the parsed
55/// document, followed by whatever data is associated with the block. The latter
56/// should be fairly self-explanatory, so let's discuss the offset.
57///
58/// The offset is only valid during the reading process. It is ignored for
59/// the purposes of encoding blocks into their binary form. It is also
60/// ignored for the purpose of comparisons via `==`. It is included entirely
61/// to support the parsing of things like X509 certificates, in which it is
62/// necessary to know when particular blocks end.
63///
64/// The [`ASN1Class`] of explicitly tagged blocks is either `Application`,
65/// `ContextSpecific` or `Private`. `Unknown` can have any class.
66/// The class of all other variants is `Universal`.
67///
68/// [`ASN1Class`]: enum.ASN1Class.html
69#[derive(Clone, Debug)]
70pub enum ASN1Block {
71    Boolean(usize, bool),
72    Integer(usize, BigInt),
73    BitString(usize, usize, Vec<u8>),
74    OctetString(usize, Vec<u8>),
75    Null(usize),
76    ObjectIdentifier(usize, OID),
77    UTF8String(usize, String),
78    PrintableString(usize, String),
79    TeletexString(usize, String),
80    IA5String(usize, String),
81    UTCTime(usize, PrimitiveDateTime),
82    GeneralizedTime(usize, PrimitiveDateTime),
83    UniversalString(usize, String),
84    BMPString(usize, String),
85    Sequence(usize, Vec<ASN1Block>),
86    Set(usize, Vec<ASN1Block>),
87    /// An explicitly tagged block.
88    ///
89    /// The class can be either `Application`, `ContextSpecific` or `Private`.
90    /// The other parameters are `offset`, `tag` and `content`.
91    ///
92    /// This block is always `constructed`.
93    Explicit(ASN1Class, usize, BigUint, Box<ASN1Block>),
94    /// An unkown block.
95    ///
96    /// The parameters are `class`, `constructed`, `offset`, `tag` and
97    /// `content`.
98    Unknown(ASN1Class, bool, usize, BigUint, Vec<u8>),
99}
100
101impl ASN1Block {
102    /// Get the class associated with the given ASN1Block, regardless of what
103    /// kind of block it is.
104    pub fn class(&self) -> ASN1Class {
105        match *self {
106            ASN1Block::Boolean(_, _) => ASN1Class::Universal,
107            ASN1Block::Integer(_, _) => ASN1Class::Universal,
108            ASN1Block::BitString(_, _, _) => ASN1Class::Universal,
109            ASN1Block::OctetString(_, _) => ASN1Class::Universal,
110            ASN1Block::Null(_) => ASN1Class::Universal,
111            ASN1Block::ObjectIdentifier(_, _) => ASN1Class::Universal,
112            ASN1Block::UTF8String(_, _) => ASN1Class::Universal,
113            ASN1Block::PrintableString(_, _) => ASN1Class::Universal,
114            ASN1Block::TeletexString(_, _) => ASN1Class::Universal,
115            ASN1Block::IA5String(_, _) => ASN1Class::Universal,
116            ASN1Block::UTCTime(_, _) => ASN1Class::Universal,
117            ASN1Block::GeneralizedTime(_, _) => ASN1Class::Universal,
118            ASN1Block::UniversalString(_, _) => ASN1Class::Universal,
119            ASN1Block::BMPString(_, _) => ASN1Class::Universal,
120            ASN1Block::Sequence(_, _) => ASN1Class::Universal,
121            ASN1Block::Set(_, _) => ASN1Class::Universal,
122            ASN1Block::Explicit(c, _, _, _) => c,
123            ASN1Block::Unknown(c, _, _, _, _) => c,
124        }
125    }
126    /// Get the starting offset associated with the given ASN1Block, regardless
127    /// of what kind of block it is.
128    pub fn offset(&self) -> usize {
129        match *self {
130            ASN1Block::Boolean(o, _) => o,
131            ASN1Block::Integer(o, _) => o,
132            ASN1Block::BitString(o, _, _) => o,
133            ASN1Block::OctetString(o, _) => o,
134            ASN1Block::Null(o) => o,
135            ASN1Block::ObjectIdentifier(o, _) => o,
136            ASN1Block::UTF8String(o, _) => o,
137            ASN1Block::PrintableString(o, _) => o,
138            ASN1Block::TeletexString(o, _) => o,
139            ASN1Block::IA5String(o, _) => o,
140            ASN1Block::UTCTime(o, _) => o,
141            ASN1Block::GeneralizedTime(o, _) => o,
142            ASN1Block::UniversalString(o, _) => o,
143            ASN1Block::BMPString(o, _) => o,
144            ASN1Block::Sequence(o, _) => o,
145            ASN1Block::Set(o, _) => o,
146            ASN1Block::Explicit(_, o, _, _) => o,
147            ASN1Block::Unknown(_, _, o, _, _) => o,
148        }
149    }
150}
151
152impl PartialEq for ASN1Block {
153    fn eq(&self, other: &ASN1Block) -> bool {
154        match (self, other) {
155            (&ASN1Block::Boolean(_, a1), &ASN1Block::Boolean(_, a2)) => a1 == a2,
156            (ASN1Block::Integer(_, ref a1), ASN1Block::Integer(_, ref a2)) => a1 == a2,
157            (&ASN1Block::BitString(_, a1, ref b1), &ASN1Block::BitString(_, a2, ref b2)) => {
158                (a1 == a2) && (b1 == b2)
159            }
160            (ASN1Block::OctetString(_, ref a1), ASN1Block::OctetString(_, ref a2)) => a1 == a2,
161            (ASN1Block::Null(_), &ASN1Block::Null(_)) => true,
162            (ASN1Block::ObjectIdentifier(_, ref a1), ASN1Block::ObjectIdentifier(_, ref a2)) => {
163                a1 == a2
164            }
165            (ASN1Block::UTF8String(_, ref a1), ASN1Block::UTF8String(_, ref a2)) => a1 == a2,
166            (ASN1Block::PrintableString(_, ref a1), ASN1Block::PrintableString(_, ref a2)) => {
167                a1 == a2
168            }
169            (ASN1Block::TeletexString(_, ref a1), ASN1Block::TeletexString(_, ref a2)) => a1 == a2,
170            (ASN1Block::IA5String(_, ref a1), ASN1Block::IA5String(_, ref a2)) => a1 == a2,
171            (ASN1Block::UTCTime(_, ref a1), ASN1Block::UTCTime(_, ref a2)) => a1 == a2,
172            (ASN1Block::GeneralizedTime(_, ref a1), ASN1Block::GeneralizedTime(_, ref a2)) => {
173                a1 == a2
174            }
175            (ASN1Block::UniversalString(_, ref a1), ASN1Block::UniversalString(_, ref a2)) => {
176                a1 == a2
177            }
178            (ASN1Block::BMPString(_, ref a1), ASN1Block::BMPString(_, ref a2)) => a1 == a2,
179            (ASN1Block::Sequence(_, ref a1), ASN1Block::Sequence(_, ref a2)) => a1 == a2,
180            (ASN1Block::Set(_, ref a1), ASN1Block::Set(_, ref a2)) => a1 == a2,
181            (
182                &ASN1Block::Explicit(a1, _, ref b1, ref c1),
183                &ASN1Block::Explicit(a2, _, ref b2, ref c2),
184            ) => (a1 == a2) && (b1 == b2) && (c1 == c2),
185            (
186                &ASN1Block::Unknown(a1, b1, _, ref c1, ref d1),
187                &ASN1Block::Unknown(a2, b2, _, ref c2, ref d2),
188            ) => (a1 == a2) && (b1 == b2) && (c1 == c2) && (d1 == d2),
189            _ => false,
190        }
191    }
192}
193
194/// An ASN.1 OID.
195#[derive(Clone, Debug, PartialEq, Eq)]
196pub struct OID(Vec<BigUint>);
197
198impl OID {
199    /// Generate an ASN.1. The vector should be in the obvious format,
200    /// with each component going left-to-right.
201    pub fn new(x: Vec<BigUint>) -> OID {
202        OID(x)
203    }
204
205    /// converts the
206    pub fn as_raw(&self) -> Result<Vec<u8>, ASN1EncodeErr> {
207        match (self.0.first(), self.0.get(1)) {
208            (Some(v1), Some(v2)) => {
209                let two = BigUint::from_u8(2).unwrap();
210
211                // first, validate that the first two items meet spec
212                if v1 > &two {
213                    return Err(ASN1EncodeErr::ObjectIdentVal1TooLarge);
214                }
215
216                let u175 = BigUint::from_u8(175).unwrap();
217                let u39 = BigUint::from_u8(39).unwrap();
218                let bound = if v1 == &two { u175 } else { u39 };
219
220                if v2 > &bound {
221                    return Err(ASN1EncodeErr::ObjectIdentVal2TooLarge);
222                }
223
224                // the following unwraps must be safe, based on the
225                // validation above.
226                let value1 = v1.to_u8().unwrap();
227                let value2 = v2.to_u8().unwrap();
228                let byte1 = (value1 * 40) + value2;
229
230                // now we can build all the rest of the body
231                let mut body = vec![byte1];
232                for num in self.0.iter().skip(2) {
233                    let mut local = encode_base127(num);
234                    body.append(&mut local);
235                }
236
237                Ok(body)
238            }
239            _ => Err(ASN1EncodeErr::ObjectIdentHasTooFewFields),
240        }
241    }
242
243    pub fn as_vec<'a, T: TryFrom<&'a BigUint>>(&'a self) -> Result<Vec<T>, ASN1DecodeErr> {
244        let mut vec = Vec::new();
245        for val in self.0.iter() {
246            let ul = match T::try_from(val) {
247                Ok(a) => a,
248                Err(_) => return Err(ASN1DecodeErr::Overflow),
249            };
250            vec.push(ul);
251        }
252
253        Ok(vec)
254    }
255}
256
257impl PartialEq<OID> for &OID {
258    fn eq(&self, v2: &OID) -> bool {
259        let OID(ref vec1) = self;
260        let OID(ref vec2) = v2;
261
262        if vec1.len() != vec2.len() {
263            return false;
264        }
265
266        for i in 0..vec1.len() {
267            if vec1[i] != vec2[i] {
268                return false;
269            }
270        }
271
272        true
273    }
274}
275
276/// A handy macro for generating OIDs from a sequence of `u64`s.
277///
278/// Usage: oid!(1,2,840,113549,1,1,1) creates an OID that matches
279/// 1.2.840.113549.1.1.1. (Coincidentally, this is RSA.)
280#[macro_export]
281macro_rules! oid {
282    ( $( $e: expr ),* ) => {{
283        $crate::OID::new(vec![$($crate::BigUint::from($e as u64)),*])
284    }};
285}
286
287const PRINTABLE_CHARS: &str =
288    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()+,-./:=? ";
289
290#[cfg(test)]
291const KNOWN_TAGS: &[u8] = &[
292    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0c, 0x10, 0x11, 0x13, 0x14, 0x16, 0x17, 0x18, 0x1c, 0x1e,
293];
294
295/// An error that can arise decoding ASN.1 primitive blocks.
296#[derive(Clone, Debug, Error, PartialEq)]
297pub enum ASN1DecodeErr {
298    #[error("Encountered an empty buffer decoding ASN1 block.")]
299    EmptyBuffer,
300    #[error("Bad length field in boolean block: {0}")]
301    BadBooleanLength(usize),
302    #[error("Length field too large for object type: {0}")]
303    LengthTooLarge(usize),
304    #[error("UTF8 string failed to properly decode: {0}")]
305    UTF8DecodeFailure(Utf8Error),
306    #[error("Printable string failed to properly decode.")]
307    PrintableStringDecodeFailure,
308    #[error("Invalid date value: {0}")]
309    InvalidDateValue(String),
310    #[error("Invalid length of bit string: {0}")]
311    InvalidBitStringLength(isize),
312    /// Not a valid ASN.1 class
313    #[error("Invalid class value: {0}")]
314    InvalidClass(u8),
315    /// Expected more input
316    ///
317    /// Invalid ASN.1 input can lead to this error.
318    #[error("Incomplete data or invalid ASN1")]
319    Incomplete,
320    #[error("Value overflow")]
321    Overflow,
322}
323
324/// An error that can arise encoding ASN.1 primitive blocks.
325#[derive(Clone, Debug, Error, PartialEq)]
326pub enum ASN1EncodeErr {
327    #[error("ASN1 object identifier has too few fields.")]
328    ObjectIdentHasTooFewFields,
329    #[error("First value in ASN1 OID is too big.")]
330    ObjectIdentVal1TooLarge,
331    #[error("Second value in ASN1 OID is too big.")]
332    ObjectIdentVal2TooLarge,
333}
334
335/// Translate a binary blob into a series of `ASN1Block`s, or provide an
336/// error if it didn't work.
337pub fn from_der(i: &[u8]) -> Result<Vec<ASN1Block>, ASN1DecodeErr> {
338    from_der_(i, 0)
339}
340
341fn from_der_(i: &[u8], start_offset: usize) -> Result<Vec<ASN1Block>, ASN1DecodeErr> {
342    let mut result: Vec<ASN1Block> = Vec::new();
343    let mut index: usize = 0;
344    let len = i.len();
345
346    while index < len {
347        let soff = start_offset + index;
348        let (tag, constructed, class) = decode_tag(i, &mut index)?;
349        let len = decode_length(i, &mut index)?;
350        let checklen = index
351            .checked_add(len)
352            .ok_or(ASN1DecodeErr::LengthTooLarge(len))?;
353        if checklen > i.len() {
354            return Err(ASN1DecodeErr::Incomplete);
355        }
356        let body = &i[index..(index + len)];
357
358        if class != ASN1Class::Universal {
359            if constructed {
360                // Try to read as explicitly tagged
361                if let Ok(mut items) = from_der_(body, start_offset + index) {
362                    if items.len() == 1 {
363                        result.push(ASN1Block::Explicit(
364                            class,
365                            soff,
366                            tag,
367                            Box::new(items.remove(0)),
368                        ));
369                        index += len;
370                        continue;
371                    }
372                }
373            }
374            result.push(ASN1Block::Unknown(
375                class,
376                constructed,
377                soff,
378                tag,
379                body.to_vec(),
380            ));
381            index += len;
382            continue;
383        }
384
385        // Universal class
386        match tag.to_u8() {
387            // BOOLEAN
388            Some(0x01) => {
389                if len != 1 {
390                    return Err(ASN1DecodeErr::BadBooleanLength(len));
391                }
392                result.push(ASN1Block::Boolean(soff, body[0] != 0));
393            }
394            // INTEGER
395            Some(0x02) => {
396                let res = BigInt::from_signed_bytes_be(body);
397                result.push(ASN1Block::Integer(soff, res));
398            }
399            // BIT STRING
400            Some(0x03) if body.is_empty() => result.push(ASN1Block::BitString(soff, 0, Vec::new())),
401            Some(0x03) => {
402                let bits = (body[1..]).to_vec();
403                let bitcount = bits.len() * 8;
404                let rest = body[0] as usize;
405                if bitcount < rest {
406                    return Err(ASN1DecodeErr::InvalidBitStringLength(
407                        bitcount as isize - rest as isize,
408                    ));
409                }
410
411                let nbits = bitcount - (body[0] as usize);
412                result.push(ASN1Block::BitString(soff, nbits, bits))
413            }
414            // OCTET STRING
415            Some(0x04) => result.push(ASN1Block::OctetString(soff, body.to_vec())),
416            // NULL
417            Some(0x05) => {
418                result.push(ASN1Block::Null(soff));
419            }
420            // OBJECT IDENTIFIER
421            Some(0x06) => {
422                let mut value1 = BigUint::zero();
423                if body.is_empty() {
424                    return Err(ASN1DecodeErr::Incomplete);
425                }
426                let mut value2 = BigUint::from_u8(body[0]).unwrap();
427                let mut oidres = Vec::new();
428                let mut bindex = 1;
429
430                if body[0] >= 40 {
431                    if body[0] < 80 {
432                        value1 = BigUint::one();
433                        value2 -= BigUint::from_u8(40).unwrap();
434                    } else {
435                        value1 = BigUint::from_u8(2).unwrap();
436                        value2 -= BigUint::from_u8(80).unwrap();
437                    }
438                }
439
440                oidres.push(value1);
441                oidres.push(value2);
442                while bindex < body.len() {
443                    oidres.push(decode_base127(body, &mut bindex)?);
444                }
445                let res = OID(oidres);
446
447                result.push(ASN1Block::ObjectIdentifier(soff, res))
448            }
449            // UTF8STRING
450            Some(0x0C) => match String::from_utf8(body.to_vec()) {
451                Ok(v) => result.push(ASN1Block::UTF8String(soff, v)),
452                Err(e) => return Err(ASN1DecodeErr::UTF8DecodeFailure(e.utf8_error())),
453            },
454            // SEQUENCE
455            Some(0x10) => match from_der_(body, start_offset + index) {
456                Ok(items) => result.push(ASN1Block::Sequence(soff, items)),
457                Err(e) => return Err(e),
458            },
459            // SET
460            Some(0x11) => match from_der_(body, start_offset + index) {
461                Ok(items) => result.push(ASN1Block::Set(soff, items)),
462                Err(e) => return Err(e),
463            },
464            // PRINTABLE STRING
465            Some(0x13) => {
466                let mut res = String::new();
467                let val = body.iter().map(|x| *x as char);
468
469                for c in val {
470                    if PRINTABLE_CHARS.contains(c) {
471                        res.push(c);
472                    } else {
473                        return Err(ASN1DecodeErr::PrintableStringDecodeFailure);
474                    }
475                }
476                result.push(ASN1Block::PrintableString(soff, res));
477            }
478            // TELETEX STRINGS
479            Some(0x14) => match String::from_utf8(body.to_vec()) {
480                Ok(v) => result.push(ASN1Block::TeletexString(soff, v)),
481                Err(e) => return Err(ASN1DecodeErr::UTF8DecodeFailure(e.utf8_error())),
482            },
483            // IA5 (ASCII) STRING
484            Some(0x16) => {
485                let val = body.iter().map(|x| *x as char);
486                let res = String::from_iter(val);
487                result.push(ASN1Block::IA5String(soff, res))
488            }
489            // UTCTime
490            Some(0x17) => {
491                if body.len() != 13 {
492                    return Err(ASN1DecodeErr::InvalidDateValue(format!("{}", body.len())));
493                }
494
495                let v = String::from_iter(body.iter().map(|x| *x as char));
496
497                let y = match v.get(0..2) {
498                    Some(yy) => yy,
499                    None => {
500                        // This wasn't a valid character boundrary.
501                        return Err(ASN1DecodeErr::InvalidDateValue(v));
502                    }
503                };
504
505                let y_prefix = match y.parse::<u8>() {
506                    Err(_) => return Err(ASN1DecodeErr::InvalidDateValue(v)),
507                    Ok(y) => {
508                        if y >= 50 {
509                            "19"
510                        } else {
511                            "20"
512                        }
513                    }
514                };
515
516                let v = format!("{}{}", y_prefix, v);
517
518                let format = time::format_description::parse(
519                    "[year][month][day][hour repr:24][minute][second]Z",
520                )
521                .unwrap();
522
523                match PrimitiveDateTime::parse(&v, &format) {
524                    Err(_) => return Err(ASN1DecodeErr::InvalidDateValue(v)),
525                    Ok(t) => result.push(ASN1Block::UTCTime(soff, t)),
526                }
527            }
528            // GeneralizedTime
529            Some(0x18) => {
530                if body.len() < 15 {
531                    return Err(ASN1DecodeErr::InvalidDateValue(format!("{}", body.len())));
532                }
533
534                let mut v: String = String::from_utf8(body.to_vec())
535                    .map_err(|e| ASN1DecodeErr::UTF8DecodeFailure(e.utf8_error()))?;
536                // Make sure the string is ascii, otherwise we cannot insert
537                // chars at specific bytes.
538                if !v.is_ascii() {
539                    return Err(ASN1DecodeErr::InvalidDateValue(v));
540                }
541
542                // We need to add padding back to the string if it's not there.
543                if !v.contains('.') {
544                    v.insert(14, '.')
545                }
546                while v.len() < 25 {
547                    let idx = v.len() - 1;
548                    v.insert(idx, '0');
549                }
550
551                let format = time::format_description::parse(
552                    "[year][month][day][hour repr:24][minute][second].[subsecond]Z",
553                )
554                .unwrap();
555
556                match PrimitiveDateTime::parse(&v, &format) {
557                    Err(_) => return Err(ASN1DecodeErr::InvalidDateValue(v)),
558                    Ok(t) => result.push(ASN1Block::GeneralizedTime(soff, t)),
559                }
560            }
561            // UNIVERSAL STRINGS
562            Some(0x1C) => match String::from_utf8(body.to_vec()) {
563                Ok(v) => result.push(ASN1Block::UniversalString(soff, v)),
564                Err(e) => return Err(ASN1DecodeErr::UTF8DecodeFailure(e.utf8_error())),
565            },
566            // UNIVERSAL STRINGS
567            Some(0x1E) => match String::from_utf8(body.to_vec()) {
568                Ok(v) => result.push(ASN1Block::BMPString(soff, v)),
569                Err(e) => return Err(ASN1DecodeErr::UTF8DecodeFailure(e.utf8_error())),
570            },
571            // Dunno.
572            _ => {
573                result.push(ASN1Block::Unknown(
574                    class,
575                    constructed,
576                    soff,
577                    tag,
578                    body.to_vec(),
579                ));
580            }
581        }
582        index += len;
583    }
584
585    if result.is_empty() {
586        Err(ASN1DecodeErr::EmptyBuffer)
587    } else {
588        Ok(result)
589    }
590}
591
592/// Returns the tag, if the type is constructed and the class.
593fn decode_tag(i: &[u8], index: &mut usize) -> Result<(BigUint, bool, ASN1Class), ASN1DecodeErr> {
594    if *index >= i.len() {
595        return Err(ASN1DecodeErr::Incomplete);
596    }
597    let tagbyte = i[*index];
598    let constructed = (tagbyte & 0b0010_0000) != 0;
599    let class = decode_class(tagbyte)?;
600    let basetag = tagbyte & 0b1_1111;
601
602    *index += 1;
603
604    if basetag == 0b1_1111 {
605        let res = decode_base127(i, index)?;
606        Ok((res, constructed, class))
607    } else {
608        Ok((BigUint::from(basetag), constructed, class))
609    }
610}
611
612fn decode_base127(i: &[u8], index: &mut usize) -> Result<BigUint, ASN1DecodeErr> {
613    let mut res = BigUint::zero();
614
615    loop {
616        if *index >= i.len() {
617            return Err(ASN1DecodeErr::Incomplete);
618        }
619
620        let nextbyte = i[*index];
621
622        *index += 1;
623        res = (res << 7) + BigUint::from(nextbyte & 0x7f);
624        if (nextbyte & 0x80) == 0 {
625            return Ok(res);
626        }
627    }
628}
629
630fn decode_class(i: u8) -> Result<ASN1Class, ASN1DecodeErr> {
631    match i >> 6 {
632        0b00 => Ok(ASN1Class::Universal),
633        0b01 => Ok(ASN1Class::Application),
634        0b10 => Ok(ASN1Class::ContextSpecific),
635        0b11 => Ok(ASN1Class::Private),
636        _ => Err(ASN1DecodeErr::InvalidClass(i)),
637    }
638}
639
640fn decode_length(i: &[u8], index: &mut usize) -> Result<usize, ASN1DecodeErr> {
641    if *index >= i.len() {
642        return Err(ASN1DecodeErr::Incomplete);
643    }
644    let startbyte = i[*index];
645
646    // NOTE: Technically, this size can be much larger than a usize.
647    // However, our whole universe starts to break down if we get
648    // things that big. So we're boring, and only accept lengths
649    // that fit within a usize.
650    *index += 1;
651    if startbyte >= 0x80 {
652        let mut lenlen = (startbyte & 0x7f) as usize;
653        let mut res = 0;
654
655        if lenlen > size_of::<usize>() {
656            return Err(ASN1DecodeErr::LengthTooLarge(lenlen));
657        }
658
659        while lenlen > 0 {
660            if *index >= i.len() {
661                return Err(ASN1DecodeErr::Incomplete);
662            }
663
664            res = (res << 8) + (i[*index] as usize);
665
666            *index += 1;
667            lenlen -= 1;
668        }
669
670        Ok(res)
671    } else {
672        Ok(startbyte as usize)
673    }
674}
675
676/// Given an `ASN1Block`, covert it to its DER encoding, or return an error
677/// if something broke along the way.
678pub fn to_der(i: &ASN1Block) -> Result<Vec<u8>, ASN1EncodeErr> {
679    match *i {
680        // BOOLEAN
681        ASN1Block::Boolean(_, val) => {
682            let inttag = BigUint::one();
683            let mut tagbytes = encode_tag(ASN1Class::Universal, false, &inttag);
684            tagbytes.push(1);
685            tagbytes.push(if val { 0xFF } else { 0x00 });
686            Ok(tagbytes)
687        }
688        // INTEGER
689        ASN1Block::Integer(_, ref int) => {
690            let mut base = int.to_signed_bytes_be();
691            let mut lenbytes = encode_len(base.len());
692            let inttag = BigUint::from_u8(0x02).unwrap();
693            let mut tagbytes = encode_tag(ASN1Class::Universal, false, &inttag);
694
695            let mut result = Vec::new();
696            result.append(&mut tagbytes);
697            result.append(&mut lenbytes);
698            result.append(&mut base);
699            Ok(result)
700        }
701        // BIT STRING
702        ASN1Block::BitString(_, bits, ref vs) => {
703            let inttag = BigUint::from_u8(0x03).unwrap();
704            let mut tagbytes = encode_tag(ASN1Class::Universal, false, &inttag);
705
706            if bits == 0 {
707                tagbytes.push(0);
708                Ok(tagbytes)
709            } else {
710                let mut lenbytes = encode_len(vs.len() + 1);
711                let nbits = (vs.len() * 8) - bits;
712
713                let mut result = Vec::new();
714                result.append(&mut tagbytes);
715                result.append(&mut lenbytes);
716                result.push(nbits as u8);
717                result.extend_from_slice(vs);
718                Ok(result)
719            }
720        }
721        // OCTET STRING
722        ASN1Block::OctetString(_, ref bytes) => {
723            let inttag = BigUint::from_u8(0x04).unwrap();
724            let mut tagbytes = encode_tag(ASN1Class::Universal, false, &inttag);
725            let mut lenbytes = encode_len(bytes.len());
726
727            let mut result = Vec::new();
728            result.append(&mut tagbytes);
729            result.append(&mut lenbytes);
730            result.extend_from_slice(bytes);
731            Ok(result)
732        }
733        // NULL
734        ASN1Block::Null(_) => {
735            let inttag = BigUint::from_u8(0x05).unwrap();
736            let mut result = encode_tag(ASN1Class::Universal, false, &inttag);
737            result.push(0);
738            Ok(result)
739        }
740        // OBJECT IDENTIFIER
741        ASN1Block::ObjectIdentifier(_, OID(ref nums)) => {
742            match (nums.first(), nums.get(1)) {
743                (Some(v1), Some(v2)) => {
744                    let two = BigUint::from_u8(2).unwrap();
745
746                    // first, validate that the first two items meet spec
747                    if v1 > &two {
748                        return Err(ASN1EncodeErr::ObjectIdentVal1TooLarge);
749                    }
750
751                    let u175 = BigUint::from_u8(175).unwrap();
752                    let u39 = BigUint::from_u8(39).unwrap();
753                    let bound = if v1 == &two { u175 } else { u39 };
754
755                    if v2 > &bound {
756                        return Err(ASN1EncodeErr::ObjectIdentVal2TooLarge);
757                    }
758
759                    // the following unwraps must be safe, based on the
760                    // validation above.
761                    let value1 = v1.to_u8().unwrap();
762                    let value2 = v2.to_u8().unwrap();
763                    let byte1 = (value1 * 40) + value2;
764
765                    // now we can build all the rest of the body
766                    let mut body = vec![byte1];
767                    for num in nums.iter().skip(2) {
768                        let mut local = encode_base127(num);
769                        body.append(&mut local);
770                    }
771
772                    // now that we have the body, we can build the header
773                    let inttag = BigUint::from_u8(0x06).unwrap();
774                    let mut result = encode_tag(ASN1Class::Universal, false, &inttag);
775                    let mut lenbytes = encode_len(body.len());
776
777                    result.append(&mut lenbytes);
778                    result.append(&mut body);
779
780                    Ok(result)
781                }
782                _ => Err(ASN1EncodeErr::ObjectIdentHasTooFewFields),
783            }
784        }
785        // SEQUENCE
786        ASN1Block::Sequence(_, ref items) => {
787            let mut body = Vec::new();
788
789            // put all the subsequences into a block
790            for x in items.iter() {
791                let mut bytes = to_der(x)?;
792                body.append(&mut bytes);
793            }
794
795            let inttag = BigUint::from_u8(0x10).unwrap();
796            let mut lenbytes = encode_len(body.len());
797            // SEQUENCE and SET mut have the constructed encoding form (bit 5) set
798            // See: https://docs.microsoft.com/en-us/windows/desktop/seccertenroll/about-encoded-tag-bytes
799            let mut tagbytes = encode_tag(ASN1Class::Universal, true, &inttag);
800
801            let mut res = Vec::new();
802            res.append(&mut tagbytes);
803            res.append(&mut lenbytes);
804            res.append(&mut body);
805            Ok(res)
806        }
807        // SET
808        ASN1Block::Set(_, ref items) => {
809            let mut body = Vec::new();
810
811            // put all the subsequences into a block
812            for x in items.iter() {
813                let mut bytes = to_der(x)?;
814                body.append(&mut bytes);
815            }
816
817            let inttag = BigUint::from_u8(0x11).unwrap();
818            let mut lenbytes = encode_len(body.len());
819            // SEQUENCE and SET mut have the constructed encoding form (bit 5) set
820            // See: https://docs.microsoft.com/en-us/windows/desktop/seccertenroll/about-encoded-tag-bytes
821            let mut tagbytes = encode_tag(ASN1Class::Universal, true, &inttag);
822
823            let mut res = Vec::new();
824            res.append(&mut tagbytes);
825            res.append(&mut lenbytes);
826            res.append(&mut body);
827            Ok(res)
828        }
829        ASN1Block::UTCTime(_, ref time) => {
830            let format = time::format_description::parse(
831                "[year][month][day][hour repr:24][minute][second]Z",
832            )
833            .unwrap();
834            let mut body = time.format(&format).unwrap().into_bytes();
835            body.drain(0..2);
836            let inttag = BigUint::from_u8(0x17).unwrap();
837            let mut lenbytes = encode_len(body.len());
838            let mut tagbytes = encode_tag(ASN1Class::Universal, false, &inttag);
839
840            let mut res = Vec::new();
841            res.append(&mut tagbytes);
842            res.append(&mut lenbytes);
843            res.append(&mut body);
844            Ok(res)
845        }
846        ASN1Block::GeneralizedTime(_, ref time) => {
847            let format = time::format_description::parse(
848                "[year][month][day][hour repr:24][minute][second].[subsecond]",
849            )
850            .unwrap();
851            let base = time.format(&format).unwrap();
852            let zclear = base.trim_end_matches('0');
853            let dclear = zclear.trim_end_matches('.');
854            let mut body = format!("{}Z", dclear).into_bytes();
855
856            let inttag = BigUint::from_u8(0x18).unwrap();
857            let mut lenbytes = encode_len(body.len());
858            let mut tagbytes = encode_tag(ASN1Class::Universal, false, &inttag);
859
860            let mut res = Vec::new();
861            res.append(&mut tagbytes);
862            res.append(&mut lenbytes);
863            res.append(&mut body);
864            Ok(res)
865        }
866        ASN1Block::UTF8String(_, ref str) => {
867            encode_asn1_string(0x0c, false, ASN1Class::Universal, str)
868        }
869        ASN1Block::PrintableString(_, ref str) => {
870            encode_asn1_string(0x13, true, ASN1Class::Universal, str)
871        }
872        ASN1Block::TeletexString(_, ref str) => {
873            encode_asn1_string(0x14, false, ASN1Class::Universal, str)
874        }
875        ASN1Block::UniversalString(_, ref str) => {
876            encode_asn1_string(0x1c, false, ASN1Class::Universal, str)
877        }
878        ASN1Block::IA5String(_, ref str) => {
879            encode_asn1_string(0x16, true, ASN1Class::Universal, str)
880        }
881        ASN1Block::BMPString(_, ref str) => {
882            encode_asn1_string(0x1e, false, ASN1Class::Universal, str)
883        }
884        ASN1Block::Explicit(class, _, ref tag, ref item) => {
885            let mut tagbytes = encode_tag(class, true, tag);
886            let mut bytes = to_der(item)?;
887            let mut lenbytes = encode_len(bytes.len());
888
889            let mut res = Vec::new();
890            res.append(&mut tagbytes);
891            res.append(&mut lenbytes);
892            res.append(&mut bytes);
893            Ok(res)
894        }
895        // Unknown blocks
896        ASN1Block::Unknown(class, c, _, ref tag, ref bytes) => {
897            let mut tagbytes = encode_tag(class, c, tag);
898            let mut lenbytes = encode_len(bytes.len());
899
900            let mut res = Vec::new();
901            res.append(&mut tagbytes);
902            res.append(&mut lenbytes);
903            res.extend_from_slice(bytes);
904            Ok(res)
905        }
906    }
907}
908
909fn encode_asn1_string(
910    tag: u8,
911    force_chars: bool,
912    c: ASN1Class,
913    s: &str,
914) -> Result<Vec<u8>, ASN1EncodeErr> {
915    let mut body = {
916        if force_chars {
917            let mut out = Vec::new();
918
919            for c in s.chars() {
920                out.push(c as u8);
921            }
922            out
923        } else {
924            s.to_string().into_bytes()
925        }
926    };
927    let inttag = BigUint::from_u8(tag).unwrap();
928    let mut lenbytes = encode_len(body.len());
929    let mut tagbytes = encode_tag(c, false, &inttag);
930
931    let mut res = Vec::new();
932    res.append(&mut tagbytes);
933    res.append(&mut lenbytes);
934    res.append(&mut body);
935    Ok(res)
936}
937
938fn encode_tag(c: ASN1Class, constructed: bool, t: &BigUint) -> Vec<u8> {
939    let cbyte = encode_class(c);
940
941    match t.to_u8() {
942        Some(mut x) if x < 31 => {
943            if constructed {
944                x |= 0b0010_0000;
945            }
946            vec![cbyte | x]
947        }
948        _ => {
949            let mut res = encode_base127(t);
950            let mut x = cbyte | 0b0001_1111;
951            if constructed {
952                x |= 0b0010_0000;
953            }
954            res.insert(0, x);
955            res
956        }
957    }
958}
959
960fn encode_base127(v: &BigUint) -> Vec<u8> {
961    let mut acc = v.clone();
962    let mut res = Vec::new();
963    let u128 = BigUint::from_u8(128).unwrap();
964    let zero = BigUint::zero();
965
966    if acc == zero {
967        res.push(0);
968        return res;
969    }
970
971    while acc > zero {
972        // we build this vector backwards
973        let digit = &acc % &u128;
974        acc >>= 7;
975
976        match digit.to_u8() {
977            None => panic!("7 bits don't fit into 8, cause ..."),
978            Some(x) if res.is_empty() => res.push(x),
979            Some(x) => res.push(x | 0x80),
980        }
981    }
982
983    res.reverse();
984    res
985}
986
987fn encode_class(c: ASN1Class) -> u8 {
988    match c {
989        ASN1Class::Universal => 0b0000_0000,
990        ASN1Class::Application => 0b0100_0000,
991        ASN1Class::ContextSpecific => 0b1000_0000,
992        ASN1Class::Private => 0b1100_0000,
993    }
994}
995
996fn encode_len(x: usize) -> Vec<u8> {
997    if x < 128 {
998        vec![x as u8]
999    } else {
1000        let mut bstr = Vec::new();
1001        let mut work = x;
1002
1003        // convert this into bytes, backwards
1004        while work > 0 {
1005            bstr.push(work as u8);
1006            work >>= 8;
1007        }
1008
1009        // encode the front of the length
1010        let len = bstr.len() as u8;
1011        bstr.push(len | 0x80);
1012
1013        // and then reverse it into the right order
1014        bstr.reverse();
1015        bstr
1016    }
1017}
1018
1019// ----------------------------------------------------------------------------
1020
1021/// A trait defining types that can be decoded from an `ASN1Block` stream,
1022/// assuming they also have access to the underlying bytes making up the
1023/// stream.
1024pub trait FromASN1WithBody: Sized {
1025    type Error: From<ASN1DecodeErr>;
1026
1027    fn from_asn1_with_body<'a>(
1028        v: &'a [ASN1Block],
1029        _b: &[u8],
1030    ) -> Result<(Self, &'a [ASN1Block]), Self::Error>;
1031}
1032
1033/// A trait defining types that can be decoded from an `ASN1Block` stream.
1034/// Any member of this trait is also automatically a member of
1035/// `FromASN1WithBody`, as it can obviously just ignore the body.
1036pub trait FromASN1: Sized {
1037    type Error: From<ASN1DecodeErr>;
1038
1039    fn from_asn1(v: &[ASN1Block]) -> Result<(Self, &[ASN1Block]), Self::Error>;
1040}
1041
1042impl<T: FromASN1> FromASN1WithBody for T {
1043    type Error = T::Error;
1044
1045    fn from_asn1_with_body<'a>(
1046        v: &'a [ASN1Block],
1047        _b: &[u8],
1048    ) -> Result<(T, &'a [ASN1Block]), T::Error> {
1049        T::from_asn1(v)
1050    }
1051}
1052
1053/// Automatically decode a type via DER encoding, assuming that the type
1054/// is a member of `FromASN1` or `FromASN1WithBody`.
1055pub fn der_decode<T: FromASN1WithBody>(v: &[u8]) -> Result<T, T::Error> {
1056    let vs = from_der(v)?;
1057    T::from_asn1_with_body(&vs, v).map(|(a, _)| a)
1058}
1059
1060/// The set of types that can automatically converted into a sequence
1061/// of `ASN1Block`s. You should probably use to_asn1() but implement
1062/// to_asn1_class(). The former has a default implementation that passes
1063/// `ASN1Class::Universal` as the tag to use, which should be good for
1064/// most people.
1065pub trait ToASN1 {
1066    type Error: From<ASN1EncodeErr>;
1067
1068    fn to_asn1(&self) -> Result<Vec<ASN1Block>, Self::Error> {
1069        self.to_asn1_class(ASN1Class::Universal)
1070    }
1071    fn to_asn1_class(&self, c: ASN1Class) -> Result<Vec<ASN1Block>, Self::Error>;
1072}
1073
1074/// Automatically encode a type into binary via DER encoding, assuming
1075/// that the type is a member of `ToASN1`.
1076pub fn der_encode<T: ToASN1>(v: &T) -> Result<Vec<u8>, T::Error> {
1077    let blocks = T::to_asn1(v)?;
1078    let mut res = Vec::new();
1079
1080    for block in blocks {
1081        let mut x = to_der(&block)?;
1082        res.append(&mut x);
1083    }
1084
1085    Ok(res)
1086}
1087
1088// ----------------------------------------------------------------------------
1089
1090#[cfg(test)]
1091mod tests {
1092    use super::*;
1093    use quickcheck::{Arbitrary, Gen};
1094    use std::fs::File;
1095    use std::io::Read;
1096    use time::{Date, Month, Time};
1097
1098    impl Arbitrary for ASN1Class {
1099        fn arbitrary(g: &mut Gen) -> ASN1Class {
1100            match u8::arbitrary(g) % 4 {
1101                0 => ASN1Class::Private,
1102                1 => ASN1Class::ContextSpecific,
1103                2 => ASN1Class::Universal,
1104                3 => ASN1Class::Application,
1105                _ => panic!("I weep for a broken life."),
1106            }
1107        }
1108    }
1109
1110    quickcheck! {
1111        fn class_encdec_roundtrips(c: ASN1Class) -> bool {
1112            c == decode_class(encode_class(c.clone())).unwrap()
1113        }
1114
1115        fn class_decenc_roundtrips(v: u8) -> bool {
1116            (v & 0b11000000) == encode_class(decode_class(v).unwrap())
1117        }
1118    }
1119
1120    #[derive(Clone, Debug)]
1121    struct RandomUint {
1122        x: BigUint,
1123    }
1124
1125    impl Arbitrary for RandomUint {
1126        fn arbitrary(g: &mut Gen) -> RandomUint {
1127            let v = BigUint::from_u32(u32::arbitrary(g)).unwrap();
1128            RandomUint { x: v }
1129        }
1130    }
1131
1132    quickcheck! {
1133        fn tags_encdec_roundtrips(c: ASN1Class, con: bool, t: RandomUint) -> bool {
1134            let bytes = encode_tag(c, con, &t.x);
1135            let mut zero = 0;
1136            let (t2, con2, c2) = decode_tag(&bytes[..], &mut zero).unwrap();
1137            (c == c2) && (con == con2) && (t.x == t2)
1138        }
1139
1140        fn len_encdec_roundtrips(l: usize) -> bool {
1141            let bytes = encode_len(l);
1142            let mut zero = 0;
1143            match decode_length(&bytes[..], &mut zero) {
1144                Err(_) => false,
1145                Ok(l2) => l == l2
1146            }
1147        }
1148    }
1149
1150    #[derive(Clone, Debug)]
1151    struct RandomInt {
1152        x: BigInt,
1153    }
1154
1155    impl Arbitrary for RandomInt {
1156        fn arbitrary(g: &mut Gen) -> RandomInt {
1157            let v = BigInt::from_i64(i64::arbitrary(g)).unwrap();
1158            RandomInt { x: v }
1159        }
1160    }
1161
1162    #[allow(type_alias_bounds)]
1163    type ASN1BlockGen = fn(&mut Gen, usize) -> ASN1Block;
1164
1165    fn arb_boolean(g: &mut Gen, _d: usize) -> ASN1Block {
1166        let v = bool::arbitrary(g);
1167        ASN1Block::Boolean(0, v)
1168    }
1169
1170    fn arb_integer(g: &mut Gen, _d: usize) -> ASN1Block {
1171        let d = RandomInt::arbitrary(g);
1172        ASN1Block::Integer(0, d.x)
1173    }
1174
1175    fn arb_bitstr(g: &mut Gen, _d: usize) -> ASN1Block {
1176        let size = u16::arbitrary(g) as usize % 16;
1177        let maxbits = (size as usize) * 8;
1178        let modbits = u8::arbitrary(g) as usize % 8;
1179        let nbits = if modbits > maxbits {
1180            maxbits
1181        } else {
1182            maxbits - modbits
1183        };
1184
1185        let mut bytes = Vec::with_capacity(size);
1186        while bytes.len() < size {
1187            bytes.push(u8::arbitrary(g));
1188        }
1189
1190        ASN1Block::BitString(0, nbits, bytes)
1191    }
1192
1193    fn arb_octstr(g: &mut Gen, _d: usize) -> ASN1Block {
1194        let size = usize::arbitrary(g) % 16;
1195        let mut bytes = Vec::with_capacity(size);
1196
1197        while bytes.len() < size {
1198            bytes.push(u8::arbitrary(g));
1199        }
1200
1201        ASN1Block::OctetString(0, bytes)
1202    }
1203
1204    fn arb_null(_g: &mut Gen, _d: usize) -> ASN1Block {
1205        ASN1Block::Null(0)
1206    }
1207
1208    impl Arbitrary for OID {
1209        fn arbitrary(g: &mut Gen) -> OID {
1210            let count = usize::arbitrary(g) % 40;
1211            let val1 = u8::arbitrary(g) % 3;
1212            let v2mod = if val1 == 2 { 176 } else { 40 };
1213            let val2 = u8::arbitrary(g) % v2mod;
1214            let v1 = BigUint::from_u8(val1).unwrap();
1215            let v2 = BigUint::from_u8(val2).unwrap();
1216            let mut nums = vec![v1, v2];
1217
1218            for _ in 0..count {
1219                let num = RandomUint::arbitrary(g);
1220                nums.push(num.x);
1221            }
1222
1223            OID(nums)
1224        }
1225    }
1226
1227    fn arb_objid(g: &mut Gen, _d: usize) -> ASN1Block {
1228        let oid = OID::arbitrary(g);
1229        ASN1Block::ObjectIdentifier(0, oid)
1230    }
1231
1232    fn arb_seq(g: &mut Gen, d: usize) -> ASN1Block {
1233        let count = usize::arbitrary(g) % 63 + 1;
1234        let mut items = Vec::new();
1235
1236        for _ in 0..count {
1237            items.push(limited_arbitrary(g, d - 1));
1238        }
1239
1240        ASN1Block::Sequence(0, items)
1241    }
1242
1243    fn arb_set(g: &mut Gen, d: usize) -> ASN1Block {
1244        let count = usize::arbitrary(g) % 63 + 1;
1245        let mut items = Vec::new();
1246
1247        for _ in 0..count {
1248            items.push(limited_arbitrary(g, d - 1));
1249        }
1250
1251        ASN1Block::Set(0, items)
1252    }
1253
1254    fn arb_print(g: &mut Gen, _d: usize) -> ASN1Block {
1255        let count = usize::arbitrary(g) % 384;
1256        let mut items = Vec::new();
1257
1258        for _ in 0..count {
1259            let v = g.choose(PRINTABLE_CHARS.as_bytes());
1260            items.push(*v.unwrap() as char);
1261        }
1262
1263        ASN1Block::PrintableString(0, String::from_iter(items.iter()))
1264    }
1265
1266    fn arb_ia5(g: &mut Gen, _d: usize) -> ASN1Block {
1267        let count = usize::arbitrary(g) % 384;
1268        let mut items = Vec::new();
1269
1270        for _ in 0..count {
1271            items.push(u8::arbitrary(g) as char);
1272        }
1273
1274        ASN1Block::IA5String(0, String::from_iter(items.iter()))
1275    }
1276
1277    fn arb_utf8(g: &mut Gen, _d: usize) -> ASN1Block {
1278        let val = String::arbitrary(g);
1279        ASN1Block::UTF8String(0, val)
1280    }
1281
1282    fn arb_tele(g: &mut Gen, _d: usize) -> ASN1Block {
1283        let val = String::arbitrary(g);
1284        ASN1Block::TeletexString(0, val)
1285    }
1286
1287    fn arb_uni(g: &mut Gen, _d: usize) -> ASN1Block {
1288        let val = String::arbitrary(g);
1289        ASN1Block::UniversalString(0, val)
1290    }
1291
1292    fn arb_bmp(g: &mut Gen, _d: usize) -> ASN1Block {
1293        let val = String::arbitrary(g);
1294        ASN1Block::BMPString(0, val)
1295    }
1296
1297    fn arb_utc(g: &mut Gen, _d: usize) -> ASN1Block {
1298        let min = Date::from_calendar_date(1950, Month::January, 01)
1299            .unwrap()
1300            .to_julian_day();
1301        let max = Date::from_calendar_date(2049, Month::December, 31)
1302            .unwrap()
1303            .to_julian_day();
1304        let date =
1305            Date::from_julian_day(i32::arbitrary(g).rem_euclid(max - min + 1) + min).unwrap();
1306
1307        let h = u8::arbitrary(g).rem_euclid(24);
1308        let m = u8::arbitrary(g).rem_euclid(60);
1309        let s = u8::arbitrary(g).rem_euclid(60);
1310        let time = Time::from_hms(h, m, s).unwrap();
1311
1312        let t = PrimitiveDateTime::new(date, time);
1313        ASN1Block::UTCTime(0, t)
1314    }
1315
1316    fn arb_time(g: &mut Gen, _d: usize) -> ASN1Block {
1317        let min = Date::from_calendar_date(0, Month::January, 01)
1318            .unwrap()
1319            .to_julian_day();
1320        let max = Date::from_calendar_date(9999, Month::December, 31)
1321            .unwrap()
1322            .to_julian_day();
1323        let date =
1324            Date::from_julian_day(i32::arbitrary(g).rem_euclid(max - min + 1) + min).unwrap();
1325
1326        let time = Time::arbitrary(g);
1327
1328        let t = PrimitiveDateTime::new(date, time);
1329        ASN1Block::GeneralizedTime(0, t)
1330    }
1331
1332    fn arb_explicit(g: &mut Gen, d: usize) -> ASN1Block {
1333        let mut class = ASN1Class::arbitrary(g);
1334        if class == ASN1Class::Universal {
1335            // Universal is invalid for an explicitly tagged block
1336            class = ASN1Class::ContextSpecific;
1337        }
1338        let tag = RandomUint::arbitrary(g);
1339        let item = limited_arbitrary(g, d - 1);
1340
1341        ASN1Block::Explicit(class, 0, tag.x, Box::new(item))
1342    }
1343
1344    fn arb_unknown(g: &mut Gen, _d: usize) -> ASN1Block {
1345        let class = ASN1Class::arbitrary(g);
1346        let tag = loop {
1347            let potential = RandomUint::arbitrary(g);
1348            match potential.x.to_u8() {
1349                None => break potential,
1350                Some(x) if KNOWN_TAGS.contains(&x) => {}
1351                Some(_) => break potential,
1352            }
1353        };
1354        let size = usize::arbitrary(g) % 128;
1355        let mut items = Vec::with_capacity(size);
1356
1357        while items.len() < size {
1358            items.push(u8::arbitrary(g));
1359        }
1360
1361        ASN1Block::Unknown(class, false, 0, tag.x, items)
1362    }
1363
1364    fn limited_arbitrary(g: &mut Gen, d: usize) -> ASN1Block {
1365        let mut possibles: Vec<ASN1BlockGen> = vec![
1366            arb_boolean,
1367            arb_integer,
1368            arb_bitstr,
1369            arb_octstr,
1370            arb_null,
1371            arb_objid,
1372            arb_utf8,
1373            arb_print,
1374            arb_tele,
1375            arb_uni,
1376            arb_ia5,
1377            arb_utc,
1378            arb_time,
1379            arb_bmp,
1380            arb_unknown,
1381        ];
1382
1383        if d > 0 {
1384            possibles.push(arb_seq);
1385            possibles.push(arb_set);
1386            possibles.push(arb_explicit);
1387        }
1388
1389        match g.choose(&possibles[..]) {
1390            Some(f) => f(g, d),
1391            None => panic!("Couldn't generate arbitrary value."),
1392        }
1393    }
1394
1395    impl Arbitrary for ASN1Block {
1396        fn arbitrary(g: &mut Gen) -> ASN1Block {
1397            limited_arbitrary(g, 2)
1398        }
1399    }
1400
1401    quickcheck! {
1402        fn encode_decode_roundtrips(v: ASN1Block) -> bool {
1403            match to_der(&v) {
1404                Err(e) => {
1405                    println!("Serialization error: {:?}", e);
1406                    false
1407                }
1408                Ok(bytes) =>
1409                    match from_der(&bytes[..]) {
1410                        Err(e) => {
1411                            println!("Parse error: {:?}", e);
1412                            false
1413                        }
1414                        Ok(ref rvec) if rvec.len() == 1 => {
1415                            let v2 = rvec.get(0).unwrap();
1416                            if &v != v2 {
1417                                println!("Original: {:?}", v);
1418                                println!("Constructed: {:?}", v2);
1419                            }
1420                            &v == v2
1421                        }
1422                        Ok(_) => {
1423                            println!("Too many results returned.");
1424                            false
1425                        }
1426                    }
1427            }
1428        }
1429    }
1430
1431    fn result_int(v: i16) -> Result<Vec<ASN1Block>, ASN1DecodeErr> {
1432        let val = BigInt::from(v);
1433        Ok(vec![ASN1Block::Integer(0, val)])
1434    }
1435
1436    #[test]
1437    fn utc_time_tests() {
1438        // Check for a regression against issue #27, in which this would
1439        // cause a panic.
1440        let input = [
1441            55, 13, 13, 133, 13, 13, 50, 13, 13, 133, 13, 13, 50, 13, 133,
1442        ];
1443        let output = from_der(&input);
1444        assert!(output.is_err());
1445    }
1446
1447    #[test]
1448    fn generalized_time_tests() {
1449        check_spec(
1450            &PrimitiveDateTime::new(
1451                Date::from_calendar_date(1992, Month::May, 21).unwrap(),
1452                Time::from_hms(0, 0, 0).unwrap(),
1453            ),
1454            "19920521000000Z".to_string(),
1455        );
1456        check_spec(
1457            &PrimitiveDateTime::new(
1458                Date::from_calendar_date(1992, Month::June, 22).unwrap(),
1459                Time::from_hms(12, 34, 21).unwrap(),
1460            ),
1461            "19920622123421Z".to_string(),
1462        );
1463        check_spec(
1464            &PrimitiveDateTime::new(
1465                Date::from_calendar_date(1992, Month::July, 22).unwrap(),
1466                Time::from_hms_milli(13, 21, 00, 300).unwrap(),
1467            ),
1468            "19920722132100.3Z".to_string(),
1469        );
1470    }
1471
1472    fn check_spec(d: &PrimitiveDateTime, s: String) {
1473        let b = ASN1Block::GeneralizedTime(0, d.clone());
1474        match to_der(&b) {
1475            Err(_) => assert_eq!(format!("Broken: {}", d), s),
1476            Ok(ref vec) => {
1477                let mut resvec = vec.clone();
1478                resvec.remove(0);
1479                resvec.remove(0);
1480                assert_eq!(String::from_utf8(resvec).unwrap(), s);
1481                match from_der_(vec, 0) {
1482                    Err(_) => assert_eq!(format!("Broken [reparse]: {}", d), s),
1483                    Ok(mut vec) => {
1484                        assert_eq!(vec.len(), 1);
1485                        match vec.pop() {
1486                            None => assert!(false, "The world's gone mad again."),
1487                            Some(ASN1Block::GeneralizedTime(_, d2)) => assert_eq!(&d2, d),
1488                            Some(_) => assert!(false, "Bad reparse of GeneralizedTime."),
1489                        }
1490                    }
1491                }
1492            }
1493        }
1494    }
1495
1496    #[test]
1497    fn base_integer_tests() {
1498        assert_eq!(from_der(&vec![0x02, 0x01, 0x00]), result_int(0));
1499        assert_eq!(from_der(&vec![0x02, 0x01, 0x7F]), result_int(127));
1500        assert_eq!(from_der(&vec![0x02, 0x02, 0x00, 0x80]), result_int(128));
1501        assert_eq!(from_der(&vec![0x02, 0x02, 0x01, 0x00]), result_int(256));
1502        assert_eq!(from_der(&vec![0x02, 0x01, 0x80]), result_int(-128));
1503        assert_eq!(from_der(&vec![0x02, 0x02, 0xFF, 0x7F]), result_int(-129));
1504    }
1505
1506    fn can_parse(f: &str) -> Result<Vec<ASN1Block>, ASN1DecodeErr> {
1507        let mut fd = File::open(f).unwrap();
1508        let mut buffer = Vec::new();
1509        let _amt = fd.read_to_end(&mut buffer);
1510        from_der(&buffer[..])
1511    }
1512
1513    #[test]
1514    fn x509_tests() {
1515        can_parse("test/server.bin").unwrap();
1516        can_parse("test/key.bin").unwrap();
1517    }
1518
1519    #[test]
1520    fn encode_base127_zero() {
1521        let zero = BigUint::from(0 as u64);
1522        let encoded = encode_base127(&zero);
1523        let expected: Vec<u8> = vec![0x0];
1524        assert_eq!(expected, encoded);
1525    }
1526
1527    #[test]
1528    fn raw_oid_eq() {
1529        // data taken from https://tools.ietf.org/html/rfc4880
1530        // ( OID as vector of unsigned integers , asn1 encoded block)
1531
1532        // comparision is not done against the full length, but only for
1533        // the actually encoded OID part (see the expect statement further down)
1534        let md5 = (
1535            oid!(1, 2, 840, 113549, 2, 5),
1536            vec![
1537                0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05,
1538                0x05, 0x00, 0x04, 0x10,
1539            ],
1540        );
1541
1542        let ripmed160 = (
1543            oid!(1, 3, 36, 3, 2, 1),
1544            vec![
1545                0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04,
1546                0x14,
1547            ],
1548        );
1549
1550        let sha1 = (
1551            oid!(1, 3, 14, 3, 2, 26),
1552            vec![
1553                0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04,
1554                0x14,
1555            ],
1556        );
1557
1558        let sha224 = (
1559            oid!(2, 16, 840, 1, 101, 3, 4, 2, 4),
1560            vec![
1561                0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
1562                0x04, 0x05, 0x00, 0x04, 0x1C,
1563            ],
1564        );
1565
1566        let sha256 = (
1567            oid!(2, 16, 840, 1, 101, 3, 4, 2, 1),
1568            vec![
1569                0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
1570                0x01, 0x05, 0x00, 0x04, 0x20,
1571            ],
1572        );
1573
1574        let sha384 = (
1575            oid!(2, 16, 840, 1, 101, 3, 4, 2, 2),
1576            vec![
1577                0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
1578                0x02, 0x05, 0x00, 0x04, 0x30,
1579            ],
1580        );
1581
1582        let sha512 = (
1583            oid!(2, 16, 840, 1, 101, 3, 4, 2, 3),
1584            vec![
1585                0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
1586                0x03, 0x05, 0x00, 0x04, 0x40,
1587            ],
1588        );
1589
1590        let tests: Vec<(OID, Vec<u8>)> = vec![md5, ripmed160, sha1, sha224, sha256, sha384, sha512];
1591
1592        for test in tests {
1593            let expected = test.1;
1594            let raw_oid = test.0.as_raw().expect("Failed to convert OID to raw");
1595            assert_eq!(raw_oid, &expected[6..(expected.len() - 4)]);
1596        }
1597    }
1598
1599    #[test]
1600    fn vec_oid() {
1601        let vec_u64: Vec<u64> = vec![1, 2, 840, 10045, 4, 3, 2];
1602        let vec_i64: Vec<i64> = vec![1, 2, 840, 10045, 4, 3, 2];
1603        let vec_usize: Vec<usize> = vec![1, 2, 840, 10045, 4, 3, 2];
1604
1605        let mut o = Vec::new();
1606        for val in vec_u64.iter() {
1607            o.push(BigUint::from(*val));
1608        }
1609
1610        let oid = OID::new(o);
1611
1612        assert_eq!(Ok(vec_u64), oid.as_vec());
1613        assert_eq!(Ok(vec_i64), oid.as_vec());
1614        assert_eq!(Ok(vec_usize), oid.as_vec());
1615        assert_eq!(Err(ASN1DecodeErr::Overflow), oid.as_vec::<u8>());
1616    }
1617}