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