1use super::Positive;
11use crate::error;
12
13pub const CONSTRUCTED: u8 = 1 << 5;
14pub const CONTEXT_SPECIFIC: u8 = 2 << 6;
15
16#[non_exhaustive]
17#[derive(Clone, Copy, PartialEq, Eq, Debug)]
18#[repr(u8)]
19pub enum Tag {
20 Boolean = 0x01,
21 Integer = 0x02,
22 BitString = 0x03,
23 OctetString = 0x04,
24 Null = 0x05,
25 OID = 0x06,
26 Sequence = CONSTRUCTED | 0x10, UTCTime = 0x17,
28 GeneralizedTime = 0x18,
29
30 ContextSpecificConstructed0 = CONTEXT_SPECIFIC | CONSTRUCTED,
31 ContextSpecificConstructed1 = CONTEXT_SPECIFIC | CONSTRUCTED | 1,
32 ContextSpecificConstructed3 = CONTEXT_SPECIFIC | CONSTRUCTED | 3,
33}
34
35impl From<Tag> for usize {
36 fn from(tag: Tag) -> Self {
37 tag as Self
38 }
39}
40
41impl From<Tag> for u8 {
42 fn from(tag: Tag) -> Self {
43 tag as Self
44 } }
46
47pub fn expect_tag_and_get_value<'a>(
48 input: &mut untrusted::Reader<'a>,
49 tag: Tag,
50) -> Result<untrusted::Input<'a>, error::Unspecified> {
51 let (actual_tag, inner) = read_tag_and_get_value(input)?;
52 if usize::from(tag) != usize::from(actual_tag) {
53 return Err(error::Unspecified);
54 }
55 Ok(inner)
56}
57
58pub fn read_tag_and_get_value<'a>(
59 input: &mut untrusted::Reader<'a>,
60) -> Result<(u8, untrusted::Input<'a>), error::Unspecified> {
61 let tag = input.read_byte()?;
62 if (tag & 0x1F) == 0x1F {
63 return Err(error::Unspecified); }
65
66 let length = match input.read_byte()? {
70 n if (n & 0x80) == 0 => usize::from(n),
71 0x81 => {
72 let second_byte = input.read_byte()?;
73 if second_byte < 128 {
74 return Err(error::Unspecified); }
76 usize::from(second_byte)
77 }
78 0x82 => {
79 let second_byte = usize::from(input.read_byte()?);
80 let third_byte = usize::from(input.read_byte()?);
81 let combined = (second_byte << 8) | third_byte;
82 if combined < 256 {
83 return Err(error::Unspecified); }
85 combined
86 }
87 _ => {
88 return Err(error::Unspecified); }
90 };
91
92 let inner = input.read_bytes(length)?;
93 Ok((tag, inner))
94}
95
96pub fn bit_string_with_no_unused_bits<'a>(
97 input: &mut untrusted::Reader<'a>,
98) -> Result<untrusted::Input<'a>, error::Unspecified> {
99 nested(input, Tag::BitString, error::Unspecified, |value| {
100 let unused_bits_at_end = value.read_byte()?;
101 if unused_bits_at_end != 0 {
102 return Err(error::Unspecified);
103 }
104 Ok(value.read_bytes_to_end())
105 })
106}
107
108pub fn nested<'a, F, R, E: Copy>(
111 input: &mut untrusted::Reader<'a>,
112 tag: Tag,
113 error: E,
114 decoder: F,
115) -> Result<R, E>
116where
117 F: FnOnce(&mut untrusted::Reader<'a>) -> Result<R, E>,
118{
119 let inner = expect_tag_and_get_value(input, tag).map_err(|_| error)?;
120 inner.read_all(error, decoder)
121}
122
123fn nonnegative_integer<'a>(
124 input: &mut untrusted::Reader<'a>,
125 min_value: u8,
126) -> Result<untrusted::Input<'a>, error::Unspecified> {
127 fn check_minimum(input: untrusted::Input, min_value: u8) -> Result<(), error::Unspecified> {
130 input.read_all(error::Unspecified, |input| {
131 let first_byte = input.read_byte()?;
132 if input.at_end() && first_byte < min_value {
133 return Err(error::Unspecified);
134 }
135 let _: untrusted::Input = input.read_bytes_to_end();
136 Ok(())
137 })
138 }
139
140 let value = expect_tag_and_get_value(input, Tag::Integer)?;
141
142 value.read_all(error::Unspecified, |input| {
143 let first_byte = input.read_byte()?;
145
146 if first_byte == 0 {
147 if input.at_end() {
148 if min_value > 0 {
150 return Err(error::Unspecified);
151 }
152 return Ok(value);
153 }
154
155 let r = input.read_bytes_to_end();
156 r.read_all(error::Unspecified, |input| {
157 let second_byte = input.read_byte()?;
158 if (second_byte & 0x80) == 0 {
159 return Err(error::Unspecified);
162 }
163 let _: untrusted::Input = input.read_bytes_to_end();
164 Ok(())
165 })?;
166 check_minimum(r, min_value)?;
167 return Ok(r);
168 }
169
170 if (first_byte & 0x80) != 0 {
172 return Err(error::Unspecified);
173 }
174
175 let _: untrusted::Input = input.read_bytes_to_end();
176 check_minimum(value, min_value)?;
177 Ok(value)
178 })
179}
180
181#[inline]
184pub fn small_nonnegative_integer(input: &mut untrusted::Reader) -> Result<u8, error::Unspecified> {
185 let value = nonnegative_integer(input, 0)?;
186 value.read_all(error::Unspecified, |input| {
187 let r = input.read_byte()?;
188 Ok(r)
189 })
190}
191
192pub fn positive_integer<'a>(
195 input: &mut untrusted::Reader<'a>,
196) -> Result<Positive<'a>, error::Unspecified> {
197 Ok(Positive::new_non_empty_without_leading_zeros(
198 nonnegative_integer(input, 1)?,
199 ))
200}
201
202#[cfg(test)]
203mod tests {
204 use super::*;
205 use untrusted::Input;
206
207 fn with_good_i<F, R>(value: &[u8], f: F)
208 where
209 F: FnOnce(&mut untrusted::Reader) -> Result<R, error::Unspecified>,
210 {
211 let r = Input::from(value).read_all(error::Unspecified, f);
212 assert!(r.is_ok());
213 }
214
215 fn with_bad_i<F, R>(value: &[u8], f: F)
216 where
217 F: FnOnce(&mut untrusted::Reader) -> Result<R, error::Unspecified>,
218 {
219 let r = Input::from(value).read_all(error::Unspecified, f);
220 assert!(r.is_err());
221 }
222
223 static ZERO_INTEGER: &[u8] = &[0x02, 0x01, 0x00];
224
225 static GOOD_POSITIVE_INTEGERS: &[(&[u8], u8)] = &[
226 (&[0x02, 0x01, 0x01], 0x01),
227 (&[0x02, 0x01, 0x02], 0x02),
228 (&[0x02, 0x01, 0x7e], 0x7e),
229 (&[0x02, 0x01, 0x7f], 0x7f),
230 (&[0x02, 0x02, 0x00, 0x80], 0x80),
233 (&[0x02, 0x02, 0x00, 0x81], 0x81),
234 (&[0x02, 0x02, 0x00, 0xfe], 0xfe),
235 (&[0x02, 0x02, 0x00, 0xff], 0xff),
236 ];
237
238 #[allow(clippy::type_complexity)]
239 static GOOD_BIG_POSITIVE_INTEGERS: &[((&[u8], &[u8]), (&[u8], &[u8]))] = &[
240 ((&[0x02, 0x81, 129u8, 1], &[0; 128]), (&[1], &[0; 128])),
241 ((&[0x02, 0x82, 0x01, 0x00, 1], &[0; 255]), (&[1], &[0; 255])),
242 ];
243
244 static BAD_NONNEGATIVE_INTEGERS: &[&[u8]] = &[
245 &[], &[0x02], &[0x02, 0x00], &[0x02, 0x00, 0x01],
250 &[0x02, 0x01],
251 &[0x02, 0x01, 0x00, 0x01],
252 &[0x02, 0x01, 0x01, 0x00], &[0x02, 0x02, 0x01],
254 &[0x02, 0x01, 0x80],
256 &[0x02, 0x01, 0xfe],
257 &[0x02, 0x01, 0xff],
258 &[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]
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 {
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 {
279 with_bad_i(test_in, |input| {
280 let _: u8 = small_nonnegative_integer(input)?;
281 Ok(())
282 });
283 }
284 }
285
286 #[test]
287 fn test_positive_integer() {
288 with_bad_i(ZERO_INTEGER, |input| {
289 let _: Positive<'_> = positive_integer(input)?;
290 Ok(())
291 });
292 for &(test_in, test_out) in GOOD_POSITIVE_INTEGERS {
293 with_good_i(test_in, |input| {
294 let test_out = [test_out];
295 assert_eq!(
296 positive_integer(input)?
297 .big_endian_without_leading_zero_as_input()
298 .as_slice_less_safe(),
299 Input::from(&test_out[..]).as_slice_less_safe()
300 );
301 Ok(())
302 });
303 }
304 for &test_in in BAD_NONNEGATIVE_INTEGERS {
305 with_bad_i(test_in, |input| {
306 let _: Positive<'_> = positive_integer(input)?;
307 Ok(())
308 });
309 }
310 }
311
312 #[test]
313 fn test_tag() {
314 let tgt = usize::from(Tag::GeneralizedTime);
315 assert_eq!(0x18usize, tgt);
316
317 let tgt = u8::from(Tag::GeneralizedTime);
318 assert_eq!(0x18u8, tgt);
319
320 let tgt = Tag::GeneralizedTime;
321 assert_eq!(tgt, Tag::GeneralizedTime);
322 }
323
324 #[test]
325 fn test_big() {
326 for &((bytes_in_a, bytes_in_b), (bytes_out_a, bytes_out_b)) in GOOD_BIG_POSITIVE_INTEGERS {
327 let mut bytes_in = Vec::new();
328 bytes_in.extend(bytes_in_a);
329 bytes_in.extend(bytes_in_b);
330 let mut bytes_out: Vec<u8> = Vec::new();
331 bytes_out.extend(bytes_out_a);
332 bytes_out.extend(bytes_out_b);
333
334 with_good_i(&bytes_in, |input| {
335 let positive = positive_integer(input)?;
336 let expected_bytes = positive.big_endian_without_leading_zero();
337 assert_eq!(expected_bytes, &bytes_out);
338 Ok(())
339 });
340 }
341 }
342
343 #[test]
344 fn test_bit_string_with_no_unused_bits() {
345 let mut reader_bad = untrusted::Reader::new(Input::from(&[0x02, 0x01]));
347 assert!(bit_string_with_no_unused_bits(&mut reader_bad).is_err());
348 let mut reader_bad2 = untrusted::Reader::new(Input::from(&[0x03, 0x01, 0x01]));
350 assert!(bit_string_with_no_unused_bits(&mut reader_bad2).is_err());
351
352 let mut reader_good = untrusted::Reader::new(Input::from(&[0x03, 0x01, 0x00]));
353 let input = bit_string_with_no_unused_bits(&mut reader_good).unwrap();
354 let expected_result: &[u8] = &[];
355 assert_eq!(expected_result, input.as_slice_less_safe());
356 }
357}