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    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
45impl From<Tag> for usize {
46    fn from(tag: Tag) -> Self {
47        tag as Self
48    }
49}
50
51impl From<Tag> for u8 {
52    fn from(tag: Tag) -> Self {
53        tag as Self
54    } // XXX: narrowing conversion.
55}
56
57pub 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
68pub 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]
107pub 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
113pub(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.
128pub 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>
134where
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
141pub(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]
171pub 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.
181pub 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)]
189mod tests {
190    use super::*;
191    use crate::error;
192
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]
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]
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}