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 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 let _ = input.read_bytes_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 let _ = input.read_bytes_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 let _ = input.read_bytes_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 Ok(Positive::new_non_empty_without_leading_zeros(
206 nonnegative_integer(input, 1)?,
207 ))
208 }
209
210 #[cfg(test)]
211 mod tests {
212 use super::*;
213 use crate::error;
214
with_good_i<F, R>(value: &[u8], f: F) where F: FnOnce(&mut untrusted::Reader) -> Result<R, error::Unspecified>,215 fn with_good_i<F, R>(value: &[u8], f: F)
216 where
217 F: FnOnce(&mut untrusted::Reader) -> Result<R, error::Unspecified>,
218 {
219 let r = untrusted::Input::from(value).read_all(error::Unspecified, f);
220 assert!(r.is_ok());
221 }
222
with_bad_i<F, R>(value: &[u8], f: F) where F: FnOnce(&mut untrusted::Reader) -> Result<R, error::Unspecified>,223 fn with_bad_i<F, R>(value: &[u8], f: F)
224 where
225 F: FnOnce(&mut untrusted::Reader) -> Result<R, error::Unspecified>,
226 {
227 let r = untrusted::Input::from(value).read_all(error::Unspecified, f);
228 assert!(r.is_err());
229 }
230
231 static ZERO_INTEGER: &[u8] = &[0x02, 0x01, 0x00];
232
233 static GOOD_POSITIVE_INTEGERS: &[(&[u8], u8)] = &[
234 (&[0x02, 0x01, 0x01], 0x01),
235 (&[0x02, 0x01, 0x02], 0x02),
236 (&[0x02, 0x01, 0x7e], 0x7e),
237 (&[0x02, 0x01, 0x7f], 0x7f),
238 // Values that need to have an 0x00 prefix to disambiguate them from
239 // them from negative values.
240 (&[0x02, 0x02, 0x00, 0x80], 0x80),
241 (&[0x02, 0x02, 0x00, 0x81], 0x81),
242 (&[0x02, 0x02, 0x00, 0xfe], 0xfe),
243 (&[0x02, 0x02, 0x00, 0xff], 0xff),
244 ];
245
246 static BAD_NONNEGATIVE_INTEGERS: &[&[u8]] = &[
247 &[], // At end of input
248 &[0x02], // Tag only
249 &[0x02, 0x00], // Empty value
250 // Length mismatch
251 &[0x02, 0x00, 0x01],
252 &[0x02, 0x01],
253 &[0x02, 0x01, 0x00, 0x01],
254 &[0x02, 0x01, 0x01, 0x00], // Would be valid if last byte is ignored.
255 &[0x02, 0x02, 0x01],
256 // Negative values
257 &[0x02, 0x01, 0x80],
258 &[0x02, 0x01, 0xfe],
259 &[0x02, 0x01, 0xff],
260 // Values that have an unnecessary leading 0x00
261 &[0x02, 0x02, 0x00, 0x00],
262 &[0x02, 0x02, 0x00, 0x01],
263 &[0x02, 0x02, 0x00, 0x02],
264 &[0x02, 0x02, 0x00, 0x7e],
265 &[0x02, 0x02, 0x00, 0x7f],
266 ];
267
268 #[test]
test_small_nonnegative_integer()269 fn test_small_nonnegative_integer() {
270 with_good_i(ZERO_INTEGER, |input| {
271 assert_eq!(small_nonnegative_integer(input)?, 0x00);
272 Ok(())
273 });
274 for &(test_in, test_out) in GOOD_POSITIVE_INTEGERS.iter() {
275 with_good_i(test_in, |input| {
276 assert_eq!(small_nonnegative_integer(input)?, test_out);
277 Ok(())
278 });
279 }
280 for &test_in in BAD_NONNEGATIVE_INTEGERS.iter() {
281 with_bad_i(test_in, |input| {
282 let _ = small_nonnegative_integer(input)?;
283 Ok(())
284 });
285 }
286 }
287
288 #[test]
test_positive_integer()289 fn test_positive_integer() {
290 with_bad_i(ZERO_INTEGER, |input| {
291 let _ = positive_integer(input)?;
292 Ok(())
293 });
294 for &(test_in, test_out) in GOOD_POSITIVE_INTEGERS.iter() {
295 with_good_i(test_in, |input| {
296 let test_out = [test_out];
297 assert_eq!(
298 positive_integer(input)?.big_endian_without_leading_zero_as_input(),
299 untrusted::Input::from(&test_out[..])
300 );
301 Ok(())
302 });
303 }
304 for &test_in in BAD_NONNEGATIVE_INTEGERS.iter() {
305 with_bad_i(test_in, |input| {
306 let _ = positive_integer(input)?;
307 Ok(())
308 });
309 }
310 }
311 }
312