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
10 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 use crate::{calendar, time, Error};
16 pub use ring::io::{
17     der::{nested, Tag, CONSTRUCTED},
18     Positive,
19 };
20 
21 #[inline(always)]
expect_tag_and_get_value<'a>( input: &mut untrusted::Reader<'a>, tag: Tag, ) -> Result<untrusted::Input<'a>, Error>22 pub fn expect_tag_and_get_value<'a>(
23     input: &mut untrusted::Reader<'a>, tag: Tag,
24 ) -> Result<untrusted::Input<'a>, Error> {
25     ring::io::der::expect_tag_and_get_value(input, tag).map_err(|_| Error::BadDER)
26 }
27 
28 pub struct Value<'a> {
29     tlv: untrusted::Input<'a>,
30     value: untrusted::Input<'a>,
31 }
32 
33 impl<'a> Value<'a> {
34     #[allow(dead_code)] // TODO: remove this.
tlv(&self) -> untrusted::Input<'a>35     pub fn tlv(&self) -> untrusted::Input<'a> { self.tlv }
36 
value(&self) -> untrusted::Input<'a>37     pub fn value(&self) -> untrusted::Input<'a> { self.value }
38 }
39 
expect_tag<'a>(input: &mut untrusted::Reader<'a>, tag: Tag) -> Result<Value<'a>, Error>40 pub fn expect_tag<'a>(input: &mut untrusted::Reader<'a>, tag: Tag) -> Result<Value<'a>, Error> {
41     let start = input.mark();
42 
43     let (actual_tag, value) = read_tag_and_get_value(input)?;
44     if usize::from(tag) != usize::from(actual_tag) {
45         return Err(Error::BadDER);
46     }
47 
48     let end = input.mark();
49 
50     let tlv = input
51         .get_input_between_marks(start, end)
52         .map_err(|untrusted::EndOfInput| Error::BadDER)?;
53 
54     Ok(Value { tlv, value })
55 }
56 
57 #[inline(always)]
read_tag_and_get_value<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<(u8, untrusted::Input<'a>), Error>58 pub fn read_tag_and_get_value<'a>(
59     input: &mut untrusted::Reader<'a>,
60 ) -> Result<(u8, untrusted::Input<'a>), Error> {
61     ring::io::der::read_tag_and_get_value(input).map_err(|_| Error::BadDER)
62 }
63 
64 // TODO: investigate taking decoder as a reference to reduce generated code
65 // size.
66 #[inline(always)]
nested_mut<'a, F, R, E: Copy>( input: &mut untrusted::Reader<'a>, tag: Tag, error: E, decoder: F, ) -> Result<R, E> where F: FnMut(&mut untrusted::Reader<'a>) -> Result<R, E>,67 pub fn nested_mut<'a, F, R, E: Copy>(
68     input: &mut untrusted::Reader<'a>, tag: Tag, error: E, decoder: F,
69 ) -> Result<R, E>
70 where
71     F: FnMut(&mut untrusted::Reader<'a>) -> Result<R, E>,
72 {
73     let inner = expect_tag_and_get_value(input, tag).map_err(|_| error)?;
74     inner.read_all(error, decoder).map_err(|_| error)
75 }
76 
77 // TODO: investigate taking decoder as a reference to reduce generated code
78 // size.
nested_of_mut<'a, F, E: Copy>( input: &mut untrusted::Reader<'a>, outer_tag: Tag, inner_tag: Tag, error: E, mut decoder: F, ) -> Result<(), E> where F: FnMut(&mut untrusted::Reader<'a>) -> Result<(), E>,79 pub fn nested_of_mut<'a, F, E: Copy>(
80     input: &mut untrusted::Reader<'a>, outer_tag: Tag, inner_tag: Tag, error: E, mut decoder: F,
81 ) -> Result<(), E>
82 where
83     F: FnMut(&mut untrusted::Reader<'a>) -> Result<(), E>,
84 {
85     nested_mut(input, outer_tag, error, |outer| {
86         loop {
87             nested_mut(outer, inner_tag, error, |inner| decoder(inner))?;
88             if outer.at_end() {
89                 break;
90             }
91         }
92         Ok(())
93     })
94 }
95 
bit_string_with_no_unused_bits<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<untrusted::Input<'a>, Error>96 pub fn bit_string_with_no_unused_bits<'a>(
97     input: &mut untrusted::Reader<'a>,
98 ) -> Result<untrusted::Input<'a>, Error> {
99     nested(input, Tag::BitString, Error::BadDER, |value| {
100         let unused_bits_at_end = value.read_byte().map_err(|_| Error::BadDER)?;
101         if unused_bits_at_end != 0 {
102             return Err(Error::BadDER);
103         }
104         Ok(value.read_bytes_to_end())
105     })
106 }
107 
108 // Like mozilla::pkix, we accept the nonconformant explicit encoding of
109 // the default value (false) for compatibility with real-world certificates.
optional_boolean(input: &mut untrusted::Reader) -> Result<bool, Error>110 pub fn optional_boolean(input: &mut untrusted::Reader) -> Result<bool, Error> {
111     if !input.peek(Tag::Boolean as u8) {
112         return Ok(false);
113     }
114     nested(input, Tag::Boolean, Error::BadDER, |input| {
115         match input.read_byte() {
116             Ok(0xff) => Ok(true),
117             Ok(0x00) => Ok(false),
118             _ => Err(Error::BadDER),
119         }
120     })
121 }
122 
positive_integer<'a>(input: &'a mut untrusted::Reader) -> Result<Positive<'a>, Error>123 pub fn positive_integer<'a>(input: &'a mut untrusted::Reader) -> Result<Positive<'a>, Error> {
124     ring::io::der::positive_integer(input).map_err(|_| Error::BadDER)
125 }
126 
small_nonnegative_integer<'a>(input: &'a mut untrusted::Reader) -> Result<u8, Error>127 pub fn small_nonnegative_integer<'a>(input: &'a mut untrusted::Reader) -> Result<u8, Error> {
128     ring::io::der::small_nonnegative_integer(input).map_err(|_| Error::BadDER)
129 }
130 
time_choice<'a>(input: &mut untrusted::Reader<'a>) -> Result<time::Time, Error>131 pub fn time_choice<'a>(input: &mut untrusted::Reader<'a>) -> Result<time::Time, Error> {
132     let is_utc_time = input.peek(Tag::UTCTime as u8);
133     let expected_tag = if is_utc_time {
134         Tag::UTCTime
135     } else {
136         Tag::GeneralizedTime
137     };
138 
139     fn read_digit(inner: &mut untrusted::Reader) -> Result<u64, Error> {
140         let b = inner.read_byte().map_err(|_| Error::BadDERTime)?;
141         if b < b'0' || b > b'9' {
142             return Err(Error::BadDERTime);
143         }
144         Ok((b - b'0') as u64)
145     }
146 
147     fn read_two_digits(inner: &mut untrusted::Reader, min: u64, max: u64) -> Result<u64, Error> {
148         let hi = read_digit(inner)?;
149         let lo = read_digit(inner)?;
150         let value = (hi * 10) + lo;
151         if value < min || value > max {
152             return Err(Error::BadDERTime);
153         }
154         Ok(value)
155     }
156 
157     nested(input, expected_tag, Error::BadDER, |value| {
158         let (year_hi, year_lo) = if is_utc_time {
159             let lo = read_two_digits(value, 0, 99)?;
160             let hi = if lo >= 50 { 19 } else { 20 };
161             (hi, lo)
162         } else {
163             let hi = read_two_digits(value, 0, 99)?;
164             let lo = read_two_digits(value, 0, 99)?;
165             (hi, lo)
166         };
167 
168         let year = (year_hi * 100) + year_lo;
169         let month = read_two_digits(value, 1, 12)?;
170         let days_in_month = calendar::days_in_month(year, month);
171         let day_of_month = read_two_digits(value, 1, days_in_month)?;
172         let hours = read_two_digits(value, 0, 23)?;
173         let minutes = read_two_digits(value, 0, 59)?;
174         let seconds = read_two_digits(value, 0, 59)?;
175 
176         let time_zone = value.read_byte().map_err(|_| Error::BadDERTime)?;
177         if time_zone != b'Z' {
178             return Err(Error::BadDERTime);
179         }
180 
181         calendar::time_from_ymdhms_utc(year, month, day_of_month, hours, minutes, seconds)
182     })
183 }
184 
185 macro_rules! oid {
186     ( $first:expr, $second:expr, $( $tail:expr ),* ) =>
187     (
188         [(40 * $first) + $second, $( $tail ),*]
189     )
190 }
191