1 // Copyright 2015 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 //! Building blocks for parsing DER-encoded ASN.1 structures.
16 //!
17 //! This module contains the foundational parts of an ASN.1 DER parser.
18 
19 use super::Positive;
20 use crate::error;
21 
22 pub const CONSTRUCTED: u8 = 1 << 5;
23 pub const CONTEXT_SPECIFIC: u8 = 2 << 6;
24 
25 #[derive(Clone, Copy, PartialEq)]
26 #[repr(u8)]
27 pub enum Tag {
28     Boolean = 0x01,
29     Integer = 0x02,
30     BitString = 0x03,
31     OctetString = 0x04,
32     Null = 0x05,
33     OID = 0x06,
34     Sequence = CONSTRUCTED | 0x10, // 0x30
35     UTCTime = 0x17,
36     GeneralizedTime = 0x18,
37 
38     ContextSpecific1 = CONTEXT_SPECIFIC | 1,
39 
40     ContextSpecificConstructed0 = CONTEXT_SPECIFIC | CONSTRUCTED | 0,
41     ContextSpecificConstructed1 = CONTEXT_SPECIFIC | CONSTRUCTED | 1,
42     ContextSpecificConstructed3 = CONTEXT_SPECIFIC | CONSTRUCTED | 3,
43 }
44 
45 impl From<Tag> for usize {
from(tag: Tag) -> Self46     fn from(tag: Tag) -> Self {
47         tag as Self
48     }
49 }
50 
51 impl From<Tag> for u8 {
from(tag: Tag) -> Self52     fn from(tag: Tag) -> Self {
53         tag as Self
54     } // XXX: narrowing conversion.
55 }
56 
expect_tag_and_get_value<'a>( input: &mut untrusted::Reader<'a>, tag: Tag, ) -> Result<untrusted::Input<'a>, error::Unspecified>57 pub fn expect_tag_and_get_value<'a>(
58     input: &mut untrusted::Reader<'a>,
59     tag: Tag,
60 ) -> Result<untrusted::Input<'a>, error::Unspecified> {
61     let (actual_tag, inner) = read_tag_and_get_value(input)?;
62     if usize::from(tag) != usize::from(actual_tag) {
63         return Err(error::Unspecified);
64     }
65     Ok(inner)
66 }
67 
read_tag_and_get_value<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<(u8, untrusted::Input<'a>), error::Unspecified>68 pub fn read_tag_and_get_value<'a>(
69     input: &mut untrusted::Reader<'a>,
70 ) -> Result<(u8, untrusted::Input<'a>), error::Unspecified> {
71     let tag = input.read_byte()?;
72     if (tag & 0x1F) == 0x1F {
73         return Err(error::Unspecified); // High tag number form is not allowed.
74     }
75 
76     // If the high order bit of the first byte is set to zero then the length
77     // is encoded in the seven remaining bits of that byte. Otherwise, those
78     // seven bits represent the number of bytes used to encode the length.
79     let length = match input.read_byte()? {
80         n if (n & 0x80) == 0 => usize::from(n),
81         0x81 => {
82             let second_byte = input.read_byte()?;
83             if second_byte < 128 {
84                 return Err(error::Unspecified); // Not the canonical encoding.
85             }
86             usize::from(second_byte)
87         }
88         0x82 => {
89             let second_byte = usize::from(input.read_byte()?);
90             let third_byte = usize::from(input.read_byte()?);
91             let combined = (second_byte << 8) | third_byte;
92             if combined < 256 {
93                 return Err(error::Unspecified); // Not the canonical encoding.
94             }
95             combined
96         }
97         _ => {
98             return Err(error::Unspecified); // We don't support longer lengths.
99         }
100     };
101 
102     let inner = input.read_bytes(length)?;
103     Ok((tag, inner))
104 }
105 
106 #[inline]
bit_string_with_no_unused_bits<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<untrusted::Input<'a>, error::Unspecified>107 pub fn bit_string_with_no_unused_bits<'a>(
108     input: &mut untrusted::Reader<'a>,
109 ) -> Result<untrusted::Input<'a>, error::Unspecified> {
110     bit_string_tagged_with_no_unused_bits(Tag::BitString, input)
111 }
112 
bit_string_tagged_with_no_unused_bits<'a>( tag: Tag, input: &mut untrusted::Reader<'a>, ) -> Result<untrusted::Input<'a>, error::Unspecified>113 pub(crate) fn bit_string_tagged_with_no_unused_bits<'a>(
114     tag: Tag,
115     input: &mut untrusted::Reader<'a>,
116 ) -> Result<untrusted::Input<'a>, error::Unspecified> {
117     nested(input, tag, error::Unspecified, |value| {
118         let unused_bits_at_end = value.read_byte().map_err(|_| error::Unspecified)?;
119         if unused_bits_at_end != 0 {
120             return Err(error::Unspecified);
121         }
122         Ok(value.read_bytes_to_end())
123     })
124 }
125 
126 // TODO: investigate taking decoder as a reference to reduce generated code
127 // size.
nested<'a, F, R, E: Copy>( input: &mut untrusted::Reader<'a>, tag: Tag, error: E, decoder: F, ) -> Result<R, E> where F: FnOnce(&mut untrusted::Reader<'a>) -> Result<R, E>,128 pub fn nested<'a, F, R, E: Copy>(
129     input: &mut untrusted::Reader<'a>,
130     tag: Tag,
131     error: E,
132     decoder: F,
133 ) -> Result<R, E>
134 where
135     F: FnOnce(&mut untrusted::Reader<'a>) -> Result<R, E>,
136 {
137     let inner = expect_tag_and_get_value(input, tag).map_err(|_| error)?;
138     inner.read_all(error, decoder)
139 }
140 
nonnegative_integer<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<untrusted::Input<'a>, error::Unspecified>141 pub(crate) fn nonnegative_integer<'a>(
142     input: &mut untrusted::Reader<'a>,
143 ) -> Result<untrusted::Input<'a>, error::Unspecified> {
144     let value = expect_tag_and_get_value(input, Tag::Integer)?;
145     match value
146         .as_slice_less_safe()
147         .split_first()
148         .ok_or(error::Unspecified)?
149     {
150         // Zero or leading zero.
151         (0, rest) => {
152             match rest.first() {
153                 // Zero.
154                 None => Ok(value),
155                 // Necessary leading zero.
156                 Some(&second) if second & 0x80 == 0x80 => Ok(untrusted::Input::from(rest)),
157                 // Unnecessary leading zero.
158                 _ => Err(error::Unspecified),
159             }
160         }
161         // Positive value with no leading zero.
162         (first, _) if first & 0x80 == 0 => Ok(value),
163         // Negative value.
164         (_, _) => Err(error::Unspecified),
165     }
166 }
167 
168 /// Parse as integer with a value in the in the range [0, 255], returning its
169 /// numeric value. This is typically used for parsing version numbers.
170 #[inline]
small_nonnegative_integer(input: &mut untrusted::Reader) -> Result<u8, error::Unspecified>171 pub fn small_nonnegative_integer(input: &mut untrusted::Reader) -> Result<u8, error::Unspecified> {
172     let value = nonnegative_integer(input)?;
173     match *value.as_slice_less_safe() {
174         [b] => Ok(b),
175         _ => Err(error::Unspecified),
176     }
177 }
178 
179 /// Parses a positive DER integer, returning the big-endian-encoded value,
180 /// sans any leading zero byte.
positive_integer<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<Positive<'a>, error::Unspecified>181 pub fn positive_integer<'a>(
182     input: &mut untrusted::Reader<'a>,
183 ) -> Result<Positive<'a>, error::Unspecified> {
184     let value = nonnegative_integer(input)?;
185     Positive::from_be_bytes(value)
186 }
187 
188 #[cfg(test)]
189 mod tests {
190     use super::*;
191     use crate::error;
192 
with_i<'a, F, R>(value: &'a [u8], f: F) -> Result<R, error::Unspecified> where F: FnOnce(&mut untrusted::Reader<'a>) -> Result<R, error::Unspecified>,193     fn with_i<'a, F, R>(value: &'a [u8], f: F) -> Result<R, error::Unspecified>
194     where
195         F: FnOnce(&mut untrusted::Reader<'a>) -> Result<R, error::Unspecified>,
196     {
197         untrusted::Input::from(value).read_all(error::Unspecified, f)
198     }
199 
200     static ZERO_INTEGER: &[u8] = &[0x02, 0x01, 0x00];
201 
202     static GOOD_POSITIVE_INTEGERS_SMALL: &[(&[u8], u8)] = &[
203         (&[0x02, 0x01, 0x01], 0x01),
204         (&[0x02, 0x01, 0x02], 0x02),
205         (&[0x02, 0x01, 0x7e], 0x7e),
206         (&[0x02, 0x01, 0x7f], 0x7f),
207         // Values that need to have an 0x00 prefix to disambiguate them from
208         // them from negative values.
209         (&[0x02, 0x02, 0x00, 0x80], 0x80),
210         (&[0x02, 0x02, 0x00, 0x81], 0x81),
211         (&[0x02, 0x02, 0x00, 0xfe], 0xfe),
212         (&[0x02, 0x02, 0x00, 0xff], 0xff),
213     ];
214 
215     static GOOD_POSITIVE_INTEGERS_LARGE: &[(&[u8], &[u8])] = &[
216         (&[0x02, 0x02, 0x01, 0x00], &[0x01, 0x00]),
217         (&[0x02, 0x02, 0x02, 0x01], &[0x02, 0x01]),
218         (&[0x02, 0x02, 0x7e, 0xfe], &[0x7e, 0xfe]),
219         (&[0x02, 0x02, 0x7f, 0xff], &[0x7f, 0xff]),
220         // Values that need to have an 0x00 prefix to disambiguate them from
221         // them from negative values.
222         (&[0x02, 0x03, 0x00, 0x80, 0x00], &[0x80, 0x00]),
223         (&[0x02, 0x03, 0x00, 0x81, 0x01], &[0x81, 0x01]),
224         (&[0x02, 0x03, 0x00, 0xfe, 0xfe], &[0xfe, 0xfe]),
225         (&[0x02, 0x03, 0x00, 0xff, 0xff], &[0xff, 0xff]),
226     ];
227 
228     static BAD_NONNEGATIVE_INTEGERS: &[&[u8]] = &[
229         &[],           // At end of input
230         &[0x02],       // Tag only
231         &[0x02, 0x00], // Empty value
232         // Length mismatch
233         &[0x02, 0x00, 0x01],
234         &[0x02, 0x01],
235         // Would be valid if leading zero is ignored when comparing length.
236         &[0x02, 0x01, 0x00, 0x01],
237         &[0x02, 0x01, 0x01, 0x00], // Would be valid if last byte is ignored.
238         &[0x02, 0x02, 0x01],
239         // Values that are missing a necessary leading 0x00
240         &[0x02, 0x01, 0x80],
241         &[0x02, 0x01, 0x81],
242         &[0x02, 0x01, 0xfe],
243         &[0x02, 0x01, 0xff],
244         // Values that have an unnecessary leading 0x00
245         &[0x02, 0x02, 0x00, 0x00],
246         &[0x02, 0x02, 0x00, 0x01],
247         &[0x02, 0x02, 0x00, 0x02],
248         &[0x02, 0x02, 0x00, 0x7e],
249         &[0x02, 0x02, 0x00, 0x7f],
250     ];
251 
252     #[test]
test_small_nonnegative_integer()253     fn test_small_nonnegative_integer() {
254         let zero = (ZERO_INTEGER, 0x00);
255         for &(test_in, test_out) in
256             core::iter::once(&zero).chain(GOOD_POSITIVE_INTEGERS_SMALL.iter())
257         {
258             let result = with_i(test_in, |input| {
259                 assert_eq!(small_nonnegative_integer(input)?, test_out);
260                 Ok(())
261             });
262             assert_eq!(result, Ok(()));
263         }
264         for &test_in in BAD_NONNEGATIVE_INTEGERS
265             .iter()
266             .chain(GOOD_POSITIVE_INTEGERS_LARGE.iter().map(|(input, _)| input))
267         {
268             let result = with_i(test_in, small_nonnegative_integer);
269             assert_eq!(result, Err(error::Unspecified));
270         }
271     }
272 
273     #[test]
test_positive_integer()274     fn test_positive_integer() {
275         for (test_in, test_out) in GOOD_POSITIVE_INTEGERS_SMALL
276             .iter()
277             .map(|(test_in, test_out)| (*test_in, core::slice::from_ref(test_out)))
278             .chain(GOOD_POSITIVE_INTEGERS_LARGE.iter().copied())
279         {
280             let result = with_i(test_in, |input| {
281                 assert_eq!(
282                     positive_integer(input)?.big_endian_without_leading_zero(),
283                     test_out
284                 );
285                 Ok(())
286             });
287             assert_eq!(result, Ok(()))
288         }
289         for &test_in in core::iter::once(&ZERO_INTEGER).chain(BAD_NONNEGATIVE_INTEGERS.iter()) {
290             let result = with_i(test_in, positive_integer);
291             assert!(matches!(result, Err(error::Unspecified)));
292         }
293     }
294 }
295