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