ring/io/
der.rs

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
19use super::Positive;
20use crate::error;
21
22pub const CONSTRUCTED: u8 = 1 << 5;
23pub const CONTEXT_SPECIFIC: u8 = 2 << 6;
24
25#[derive(Clone, Copy, PartialEq)]
26#[repr(u8)]
27pub 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
43impl From<Tag> for usize {
44    fn from(tag: Tag) -> Self {
45        tag as Self
46    }
47}
48
49impl From<Tag> for u8 {
50    fn from(tag: Tag) -> Self {
51        tag as Self
52    } // XXX: narrowing conversion.
53}
54
55pub 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
66pub 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
104pub 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.
118pub 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>
124where
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
131fn 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]
192pub 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.
202pub 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)]
211mod tests {
212    use super::*;
213    use crate::error;
214
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
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]
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]
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}