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