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 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 45 impl From<Tag> for usize { from(tag: Tag) -> Self46 fn from(tag: Tag) -> Self { 47 tag as Self 48 } 49 } 50 51 impl From<Tag> for u8 { from(tag: Tag) -> Self52 fn from(tag: Tag) -> Self { 53 tag as Self 54 } // XXX: narrowing conversion. 55 } 56 expect_tag_and_get_value<'a>( input: &mut untrusted::Reader<'a>, tag: Tag, ) -> Result<untrusted::Input<'a>, error::Unspecified>57 pub 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 read_tag_and_get_value<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<(u8, untrusted::Input<'a>), error::Unspecified>68 pub 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] bit_string_with_no_unused_bits<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<untrusted::Input<'a>, error::Unspecified>107 pub 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 bit_string_tagged_with_no_unused_bits<'a>( tag: Tag, input: &mut untrusted::Reader<'a>, ) -> Result<untrusted::Input<'a>, error::Unspecified>113 pub(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. 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>,128 pub 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> 134 where 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 nonnegative_integer<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<untrusted::Input<'a>, error::Unspecified>141 pub(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] small_nonnegative_integer(input: &mut untrusted::Reader) -> Result<u8, error::Unspecified>171 pub 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. positive_integer<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<Positive<'a>, error::Unspecified>181 pub 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)] 189 mod tests { 190 use super::*; 191 use crate::error; 192 with_i<'a, F, R>(value: &'a [u8], f: F) -> Result<R, error::Unspecified> where F: FnOnce(&mut untrusted::Reader<'a>) -> Result<R, error::Unspecified>,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] test_small_nonnegative_integer()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] test_positive_integer()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 } 295