• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     ContextSpecificConstructed0 = CONTEXT_SPECIFIC | CONSTRUCTED | 0,
39     ContextSpecificConstructed1 = CONTEXT_SPECIFIC | CONSTRUCTED | 1,
40     ContextSpecificConstructed3 = CONTEXT_SPECIFIC | CONSTRUCTED | 3,
41 }
42 
43 impl From<Tag> for usize {
from(tag: Tag) -> Self44     fn from(tag: Tag) -> Self {
45         tag as Self
46     }
47 }
48 
49 impl From<Tag> for u8 {
from(tag: Tag) -> Self50     fn from(tag: Tag) -> Self {
51         tag as Self
52     } // XXX: narrowing conversion.
53 }
54 
expect_tag_and_get_value<'a>( input: &mut untrusted::Reader<'a>, tag: Tag, ) -> Result<untrusted::Input<'a>, error::Unspecified>55 pub fn expect_tag_and_get_value<'a>(
56     input: &mut untrusted::Reader<'a>,
57     tag: Tag,
58 ) -> Result<untrusted::Input<'a>, error::Unspecified> {
59     let (actual_tag, inner) = read_tag_and_get_value(input)?;
60     if usize::from(tag) != usize::from(actual_tag) {
61         return Err(error::Unspecified);
62     }
63     Ok(inner)
64 }
65 
read_tag_and_get_value<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<(u8, untrusted::Input<'a>), error::Unspecified>66 pub fn read_tag_and_get_value<'a>(
67     input: &mut untrusted::Reader<'a>,
68 ) -> Result<(u8, untrusted::Input<'a>), error::Unspecified> {
69     let tag = input.read_byte()?;
70     if (tag & 0x1F) == 0x1F {
71         return Err(error::Unspecified); // High tag number form is not allowed.
72     }
73 
74     // If the high order bit of the first byte is set to zero then the length
75     // is encoded in the seven remaining bits of that byte. Otherwise, those
76     // seven bits represent the number of bytes used to encode the length.
77     let length = match input.read_byte()? {
78         n if (n & 0x80) == 0 => usize::from(n),
79         0x81 => {
80             let second_byte = input.read_byte()?;
81             if second_byte < 128 {
82                 return Err(error::Unspecified); // Not the canonical encoding.
83             }
84             usize::from(second_byte)
85         }
86         0x82 => {
87             let second_byte = usize::from(input.read_byte()?);
88             let third_byte = usize::from(input.read_byte()?);
89             let combined = (second_byte << 8) | third_byte;
90             if combined < 256 {
91                 return Err(error::Unspecified); // Not the canonical encoding.
92             }
93             combined
94         }
95         _ => {
96             return Err(error::Unspecified); // We don't support longer lengths.
97         }
98     };
99 
100     let inner = input.read_bytes(length)?;
101     Ok((tag, inner))
102 }
103 
bit_string_with_no_unused_bits<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<untrusted::Input<'a>, error::Unspecified>104 pub fn bit_string_with_no_unused_bits<'a>(
105     input: &mut untrusted::Reader<'a>,
106 ) -> Result<untrusted::Input<'a>, error::Unspecified> {
107     nested(input, Tag::BitString, error::Unspecified, |value| {
108         let unused_bits_at_end = value.read_byte().map_err(|_| error::Unspecified)?;
109         if unused_bits_at_end != 0 {
110             return Err(error::Unspecified);
111         }
112         Ok(value.read_bytes_to_end())
113     })
114 }
115 
116 // TODO: investigate taking decoder as a reference to reduce generated code
117 // 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>,118 pub fn nested<'a, F, R, E: Copy>(
119     input: &mut untrusted::Reader<'a>,
120     tag: Tag,
121     error: E,
122     decoder: F,
123 ) -> Result<R, E>
124 where
125     F: FnOnce(&mut untrusted::Reader<'a>) -> Result<R, E>,
126 {
127     let inner = expect_tag_and_get_value(input, tag).map_err(|_| error)?;
128     inner.read_all(error, decoder)
129 }
130 
nonnegative_integer<'a>( input: &mut untrusted::Reader<'a>, min_value: u8, ) -> Result<untrusted::Input<'a>, error::Unspecified>131 pub(crate) fn nonnegative_integer<'a>(
132     input: &mut untrusted::Reader<'a>,
133     min_value: u8,
134 ) -> Result<untrusted::Input<'a>, error::Unspecified> {
135     // Verify that |input|, which has had any leading zero stripped off, is the
136     // encoding of a value of at least |min_value|.
137     fn check_minimum(input: untrusted::Input, min_value: u8) -> Result<(), error::Unspecified> {
138         input.read_all(error::Unspecified, |input| {
139             let first_byte = input.read_byte()?;
140             if input.at_end() && first_byte < min_value {
141                 return Err(error::Unspecified);
142             }
143             input.skip_to_end();
144             Ok(())
145         })
146     }
147 
148     let value = expect_tag_and_get_value(input, Tag::Integer)?;
149 
150     value.read_all(error::Unspecified, |input| {
151         // Empty encodings are not allowed.
152         let first_byte = input.read_byte()?;
153 
154         if first_byte == 0 {
155             if input.at_end() {
156                 // |value| is the legal encoding of zero.
157                 if min_value > 0 {
158                     return Err(error::Unspecified);
159                 }
160                 return Ok(value);
161             }
162 
163             let r = input.read_bytes_to_end();
164             r.read_all(error::Unspecified, |input| {
165                 let second_byte = input.read_byte()?;
166                 if (second_byte & 0x80) == 0 {
167                     // A leading zero is only allowed when the value's high bit
168                     // is set.
169                     return Err(error::Unspecified);
170                 }
171                 input.skip_to_end();
172                 Ok(())
173             })?;
174             check_minimum(r, min_value)?;
175             return Ok(r);
176         }
177 
178         // Negative values are not allowed.
179         if (first_byte & 0x80) != 0 {
180             return Err(error::Unspecified);
181         }
182 
183         input.skip_to_end();
184         check_minimum(value, min_value)?;
185         Ok(value)
186     })
187 }
188 
189 /// Parse as integer with a value in the in the range [0, 255], returning its
190 /// numeric value. This is typically used for parsing version numbers.
191 #[inline]
small_nonnegative_integer(input: &mut untrusted::Reader) -> Result<u8, error::Unspecified>192 pub fn small_nonnegative_integer(input: &mut untrusted::Reader) -> Result<u8, error::Unspecified> {
193     let value = nonnegative_integer(input, 0)?;
194     value.read_all(error::Unspecified, |input| {
195         let r = input.read_byte()?;
196         Ok(r)
197     })
198 }
199 
200 /// Parses a positive DER integer, returning the big-endian-encoded value,
201 /// sans any leading zero byte.
positive_integer<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<Positive<'a>, error::Unspecified>202 pub fn positive_integer<'a>(
203     input: &mut untrusted::Reader<'a>,
204 ) -> Result<Positive<'a>, error::Unspecified> {
205     Positive::new_non_empty_without_leading_zeros(nonnegative_integer(input, 1)?)
206 }
207 
208 #[cfg(test)]
209 mod tests {
210     use super::*;
211     use crate::error;
212 
with_good_i<F, R>(value: &[u8], f: F) where F: FnOnce(&mut untrusted::Reader) -> Result<R, error::Unspecified>,213     fn with_good_i<F, R>(value: &[u8], f: F)
214     where
215         F: FnOnce(&mut untrusted::Reader) -> Result<R, error::Unspecified>,
216     {
217         let r = untrusted::Input::from(value).read_all(error::Unspecified, f);
218         assert!(r.is_ok());
219     }
220 
with_bad_i<F, R>(value: &[u8], f: F) where F: FnOnce(&mut untrusted::Reader) -> Result<R, error::Unspecified>,221     fn with_bad_i<F, R>(value: &[u8], f: F)
222     where
223         F: FnOnce(&mut untrusted::Reader) -> Result<R, error::Unspecified>,
224     {
225         let r = untrusted::Input::from(value).read_all(error::Unspecified, f);
226         assert!(r.is_err());
227     }
228 
229     static ZERO_INTEGER: &[u8] = &[0x02, 0x01, 0x00];
230 
231     static GOOD_POSITIVE_INTEGERS: &[(&[u8], u8)] = &[
232         (&[0x02, 0x01, 0x01], 0x01),
233         (&[0x02, 0x01, 0x02], 0x02),
234         (&[0x02, 0x01, 0x7e], 0x7e),
235         (&[0x02, 0x01, 0x7f], 0x7f),
236         // Values that need to have an 0x00 prefix to disambiguate them from
237         // them from negative values.
238         (&[0x02, 0x02, 0x00, 0x80], 0x80),
239         (&[0x02, 0x02, 0x00, 0x81], 0x81),
240         (&[0x02, 0x02, 0x00, 0xfe], 0xfe),
241         (&[0x02, 0x02, 0x00, 0xff], 0xff),
242     ];
243 
244     static BAD_NONNEGATIVE_INTEGERS: &[&[u8]] = &[
245         &[],           // At end of input
246         &[0x02],       // Tag only
247         &[0x02, 0x00], // Empty value
248         // Length mismatch
249         &[0x02, 0x00, 0x01],
250         &[0x02, 0x01],
251         &[0x02, 0x01, 0x00, 0x01],
252         &[0x02, 0x01, 0x01, 0x00], // Would be valid if last byte is ignored.
253         &[0x02, 0x02, 0x01],
254         // Negative values
255         &[0x02, 0x01, 0x80],
256         &[0x02, 0x01, 0xfe],
257         &[0x02, 0x01, 0xff],
258         // Values that have an unnecessary leading 0x00
259         &[0x02, 0x02, 0x00, 0x00],
260         &[0x02, 0x02, 0x00, 0x01],
261         &[0x02, 0x02, 0x00, 0x02],
262         &[0x02, 0x02, 0x00, 0x7e],
263         &[0x02, 0x02, 0x00, 0x7f],
264     ];
265 
266     #[test]
test_small_nonnegative_integer()267     fn test_small_nonnegative_integer() {
268         with_good_i(ZERO_INTEGER, |input| {
269             assert_eq!(small_nonnegative_integer(input)?, 0x00);
270             Ok(())
271         });
272         for &(test_in, test_out) in GOOD_POSITIVE_INTEGERS.iter() {
273             with_good_i(test_in, |input| {
274                 assert_eq!(small_nonnegative_integer(input)?, test_out);
275                 Ok(())
276             });
277         }
278         for &test_in in BAD_NONNEGATIVE_INTEGERS.iter() {
279             with_bad_i(test_in, |input| {
280                 let _ = small_nonnegative_integer(input)?;
281                 Ok(())
282             });
283         }
284     }
285 
286     #[test]
test_positive_integer()287     fn test_positive_integer() {
288         with_bad_i(ZERO_INTEGER, |input| {
289             let _ = positive_integer(input)?;
290             Ok(())
291         });
292         for &(test_in, test_out) in GOOD_POSITIVE_INTEGERS.iter() {
293             with_good_i(test_in, |input| {
294                 let test_out = [test_out];
295                 assert_eq!(
296                     positive_integer(input)?.big_endian_without_leading_zero_as_input(),
297                     untrusted::Input::from(&test_out[..])
298                 );
299                 Ok(())
300             });
301         }
302         for &test_in in BAD_NONNEGATIVE_INTEGERS.iter() {
303             with_bad_i(test_in, |input| {
304                 let _ = positive_integer(input)?;
305                 Ok(())
306             });
307         }
308     }
309 }
310