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