// Copyright 2015 Brian Smith. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #[cfg(feature = "alloc")] use alloc::vec::Vec; use core::marker::PhantomData; use crate::{Error, error::DerTypeId}; #[derive(Debug)] pub struct DerIterator<'a, T> { reader: untrusted::Reader<'a>, marker: PhantomData, } impl<'a, T> DerIterator<'a, T> { /// [`DerIterator`] will consume all of the bytes in `input` reading values of type `T`. pub(crate) fn new(input: untrusted::Input<'a>) -> Self { Self { reader: untrusted::Reader::new(input), marker: PhantomData, } } } impl<'a, T: FromDer<'a>> Iterator for DerIterator<'a, T> { type Item = Result; fn next(&mut self) -> Option { (!self.reader.at_end()).then(|| T::from_der(&mut self.reader)) } } pub(crate) trait FromDer<'a>: Sized + 'a { /// Parse a value of type `Self` from the given DER-encoded input. fn from_der(reader: &mut untrusted::Reader<'a>) -> Result; const TYPE_ID: DerTypeId; } pub(crate) fn read_all<'a, T: FromDer<'a>>(input: untrusted::Input<'a>) -> Result { input.read_all(Error::TrailingData(T::TYPE_ID), T::from_der) } // Copied (and extended) from ring's src/der.rs #[allow(clippy::upper_case_acronyms)] #[derive(Clone, Copy, Eq, PartialEq)] #[repr(u8)] pub(crate) enum Tag { Boolean = 0x01, Integer = 0x02, BitString = 0x03, OctetString = 0x04, OID = 0x06, Enum = 0x0A, Sequence = CONSTRUCTED | 0x10, // 0x30 UTCTime = 0x17, GeneralizedTime = 0x18, #[allow(clippy::identity_op)] ContextSpecificConstructed0 = CONTEXT_SPECIFIC | CONSTRUCTED | 0, ContextSpecificConstructed1 = CONTEXT_SPECIFIC | CONSTRUCTED | 1, ContextSpecificConstructed3 = CONTEXT_SPECIFIC | CONSTRUCTED | 3, } pub(crate) const CONSTRUCTED: u8 = 0x20; pub(crate) const CONTEXT_SPECIFIC: u8 = 0x80; impl From for usize { #[allow(clippy::as_conversions)] fn from(tag: Tag) -> Self { tag as Self } } impl From for u8 { #[allow(clippy::as_conversions)] fn from(tag: Tag) -> Self { tag as Self } // XXX: narrowing conversion. } #[inline(always)] pub(crate) fn expect_tag_and_get_value_limited<'a>( input: &mut untrusted::Reader<'a>, tag: Tag, size_limit: usize, ) -> Result, Error> { let (actual_tag, inner) = read_tag_and_get_value_limited(input, size_limit)?; if usize::from(tag) != usize::from(actual_tag) { return Err(Error::BadDer); } Ok(inner) } pub(crate) fn nested_limited<'a, R>( input: &mut untrusted::Reader<'a>, tag: Tag, error: Error, decoder: impl FnOnce(&mut untrusted::Reader<'a>) -> Result, size_limit: usize, ) -> Result { match expect_tag_and_get_value_limited(input, tag, size_limit) { Ok(value) => value.read_all(error, decoder), Err(_) => Err(error), } } // TODO: investigate taking decoder as a reference to reduce generated code // size. pub(crate) fn nested<'a, R>( input: &mut untrusted::Reader<'a>, tag: Tag, error: Error, decoder: impl FnOnce(&mut untrusted::Reader<'a>) -> Result, ) -> Result { nested_limited(input, tag, error, decoder, TWO_BYTE_DER_SIZE) } pub(crate) fn expect_tag<'a>( input: &mut untrusted::Reader<'a>, tag: Tag, ) -> Result, Error> { let (actual_tag, value) = read_tag_and_get_value_limited(input, TWO_BYTE_DER_SIZE)?; if usize::from(tag) != usize::from(actual_tag) { return Err(Error::BadDer); } Ok(value) } #[inline(always)] pub(crate) fn read_tag_and_get_value<'a>( input: &mut untrusted::Reader<'a>, ) -> Result<(u8, untrusted::Input<'a>), Error> { read_tag_and_get_value_limited(input, TWO_BYTE_DER_SIZE) } #[inline(always)] pub(crate) fn read_tag_and_get_value_limited<'a>( input: &mut untrusted::Reader<'a>, size_limit: usize, ) -> Result<(u8, untrusted::Input<'a>), Error> { let tag = input.read_byte().map_err(end_of_input_err)?; if (tag & HIGH_TAG_RANGE_START) == HIGH_TAG_RANGE_START { return Err(Error::BadDer); // High tag number form is not allowed. } // If the high order bit of the first byte is set to zero then the length // is encoded in the seven remaining bits of that byte. Otherwise, those // seven bits represent the number of bytes used to encode the length. let length = match input.read_byte().map_err(end_of_input_err)? { n if (n & SHORT_FORM_LEN_MAX) == 0 => usize::from(n), LONG_FORM_LEN_ONE_BYTE => { let length_byte = input.read_byte().map_err(end_of_input_err)?; if length_byte < SHORT_FORM_LEN_MAX { return Err(Error::BadDer); // Not the canonical encoding. } usize::from(length_byte) } LONG_FORM_LEN_TWO_BYTES => { let length_byte_one = usize::from(input.read_byte().map_err(end_of_input_err)?); let length_byte_two = usize::from(input.read_byte().map_err(end_of_input_err)?); let combined = (length_byte_one << 8) | length_byte_two; if combined <= LONG_FORM_LEN_ONE_BYTE_MAX { return Err(Error::BadDer); // Not the canonical encoding. } combined } LONG_FORM_LEN_THREE_BYTES => { let length_byte_one = usize::from(input.read_byte().map_err(end_of_input_err)?); let length_byte_two = usize::from(input.read_byte().map_err(end_of_input_err)?); let length_byte_three = usize::from(input.read_byte().map_err(end_of_input_err)?); let combined = (length_byte_one << 16) | (length_byte_two << 8) | length_byte_three; if combined <= LONG_FORM_LEN_TWO_BYTES_MAX { return Err(Error::BadDer); // Not the canonical encoding. } combined } LONG_FORM_LEN_FOUR_BYTES => { let length_byte_one = usize::from(input.read_byte().map_err(end_of_input_err)?); let length_byte_two = usize::from(input.read_byte().map_err(end_of_input_err)?); let length_byte_three = usize::from(input.read_byte().map_err(end_of_input_err)?); let length_byte_four = usize::from(input.read_byte().map_err(end_of_input_err)?); let combined = (length_byte_one << 24) | (length_byte_two << 16) | (length_byte_three << 8) | length_byte_four; if combined <= LONG_FORM_LEN_THREE_BYTES_MAX { return Err(Error::BadDer); // Not the canonical encoding. } combined } _ => { return Err(Error::BadDer); // We don't support longer lengths. } }; if length >= size_limit { return Err(Error::BadDer); // The length is larger than the caller accepts. } let inner = input.read_bytes(length).map_err(end_of_input_err)?; Ok((tag, inner)) } /// Prepend `bytes` with the given ASN.1 [`Tag`] and appropriately encoded length byte(s). /// Useful for "adding back" ASN.1 bytes to parsed content. #[cfg(feature = "alloc")] #[allow(clippy::as_conversions)] pub(crate) fn asn1_wrap(tag: Tag, bytes: &[u8]) -> Vec { let len = bytes.len(); // The length is encoded differently depending on how many bytes there are if len < usize::from(SHORT_FORM_LEN_MAX) { // Short form: the length is encoded using a single byte // Contents: Tag byte, single length byte, and passed bytes let mut ret = Vec::with_capacity(2 + len); ret.push(tag.into()); // Tag byte ret.push(len as u8); // Single length byte ret.extend_from_slice(bytes); // Passed bytes ret } else { // Long form: The length is encoded using multiple bytes // Contents: Tag byte, number-of-length-bytes byte, length bytes, and passed bytes // The first byte indicates how many more bytes will be used to encode the length // First, get a big-endian representation of the byte slice's length let size = len.to_be_bytes(); // Find the number of leading empty bytes in that representation // This will determine the smallest number of bytes we need to encode the length let leading_zero_bytes = size .iter() .position(|&byte| byte != 0) .unwrap_or(size.len()); assert!(leading_zero_bytes < size.len()); // Number of bytes used - number of not needed bytes = smallest number needed let encoded_bytes = size.len() - leading_zero_bytes; let mut ret = Vec::with_capacity(2 + encoded_bytes + len); // Indicate this is a number-of-length-bytes byte by setting the high order bit let number_of_length_bytes_byte = SHORT_FORM_LEN_MAX + encoded_bytes as u8; ret.push(tag.into()); // Tag byte ret.push(number_of_length_bytes_byte); // Number-of-length-bytes byte ret.extend_from_slice(&size[leading_zero_bytes..]); // Length bytes ret.extend_from_slice(bytes); // Passed bytes ret } } // Long-form DER encoded lengths of two bytes can express lengths up to the following limit. // // The upstream ring::io::der::read_tag_and_get_value() function limits itself to up to two byte // long-form DER lengths, and so this limit represents the maximum length that was possible to // read before the introduction of the read_tag_and_get_value_limited function. pub(crate) const TWO_BYTE_DER_SIZE: usize = LONG_FORM_LEN_TWO_BYTES_MAX; // The maximum size of a DER value that Webpki can support reading. // // Webpki limits itself to four byte long-form DER lengths, and so this limit represents // the maximum size tagged DER value that can be read for any purpose. pub(crate) const MAX_DER_SIZE: usize = LONG_FORM_LEN_FOUR_BYTES_MAX; // DER Tag identifiers have two forms: // * Low tag number form (for tags values in the range [0..30] // * High tag number form (for tag values in the range [31..] // We only support low tag number form. const HIGH_TAG_RANGE_START: u8 = 31; // DER length octets have two forms: // * Short form: 1 octet supporting lengths between 0 and 127. // * Long definite form: 2 to 127 octets, number of octets encoded into first octet. const SHORT_FORM_LEN_MAX: u8 = 128; // Leading octet for long definite form DER length expressed in second byte. const LONG_FORM_LEN_ONE_BYTE: u8 = 0x81; // Maximum size that can be expressed in a one byte long form len. const LONG_FORM_LEN_ONE_BYTE_MAX: usize = 0xff; // Leading octet for long definite form DER length expressed in subsequent two bytes. const LONG_FORM_LEN_TWO_BYTES: u8 = 0x82; // Maximum size that can be expressed in a two byte long form len. const LONG_FORM_LEN_TWO_BYTES_MAX: usize = 0xff_ff; // Leading octet for long definite form DER length expressed in subsequent three bytes. const LONG_FORM_LEN_THREE_BYTES: u8 = 0x83; // Maximum size that can be expressed in a three byte long form len. const LONG_FORM_LEN_THREE_BYTES_MAX: usize = 0xff_ff_ff; // Leading octet for long definite form DER length expressed in subsequent four bytes. const LONG_FORM_LEN_FOUR_BYTES: u8 = 0x84; // Maximum size that can be expressed in a four byte long form der len. const LONG_FORM_LEN_FOUR_BYTES_MAX: usize = 0xff_ff_ff_ff; // TODO: investigate taking decoder as a reference to reduce generated code // size. pub(crate) fn nested_of_mut<'a>( input: &mut untrusted::Reader<'a>, outer_tag: Tag, inner_tag: Tag, error: Error, allow_empty: bool, mut decoder: impl FnMut(&mut untrusted::Reader<'a>) -> Result<(), Error>, ) -> Result<(), Error> { nested(input, outer_tag, error.clone(), |outer| { if allow_empty && outer.at_end() { return Ok(()); } loop { nested(outer, inner_tag, error.clone(), |inner| decoder(inner))?; if outer.at_end() { break; } } Ok(()) }) } pub(crate) fn bit_string_with_no_unused_bits<'a>( input: &mut untrusted::Reader<'a>, ) -> Result, Error> { nested( input, Tag::BitString, Error::TrailingData(DerTypeId::BitString), |value| { let unused_bits_at_end = value.read_byte().map_err(|_| Error::BadDer)?; if unused_bits_at_end != 0 { return Err(Error::BadDer); } Ok(value.read_bytes_to_end()) }, ) } pub(crate) struct BitStringFlags<'a> { raw_bits: &'a [u8], } impl BitStringFlags<'_> { pub(crate) fn bit_set(&self, bit: usize) -> bool { let byte_index = bit / 8; let bit_shift = 7 - (bit % 8); if self.raw_bits.len() < (byte_index + 1) { false } else { ((self.raw_bits[byte_index] >> bit_shift) & 1) != 0 } } } // ASN.1 BIT STRING fields for sets of flags are encoded in DER with some peculiar details related // to padding. Notably this means we expect an indicator of the number of bits of padding, and then // the actual bit values. See this Stack Overflow discussion[0], and ITU X690-0207[1] Section 8.6 // and Section 11.2 for more information. // // [0]: https://security.stackexchange.com/a/10396 // [1]: https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf pub(crate) fn bit_string_flags(input: untrusted::Input<'_>) -> Result, Error> { input.read_all(Error::BadDer, |bit_string| { // ITU X690-0207 11.2: // "The initial octet shall encode, as an unsigned binary integer with bit 1 as the least // significant bit, the number of unused bits in the final subsequent octet. // The number shall be in the range zero to seven" let padding_bits = bit_string.read_byte().map_err(|_| Error::BadDer)?; let raw_bits = bit_string.read_bytes_to_end().as_slice_less_safe(); // It's illegal to have more than 7 bits of padding. Similarly, if the raw bitflags // are empty there should be no padding. if padding_bits > 7 || (raw_bits.is_empty() && padding_bits != 0) { return Err(Error::BadDer); } // If there are padding bits then the last bit of the last raw byte must be 0 or the // distinguished encoding rules are not being followed. let last_byte = raw_bits[raw_bits.len() - 1]; let padding_mask = (1 << padding_bits) - 1; match padding_bits > 0 && (last_byte & padding_mask) != 0 { true => Err(Error::BadDer), false => Ok(BitStringFlags { raw_bits }), } }) } impl<'a> FromDer<'a> for u8 { fn from_der(reader: &mut untrusted::Reader<'a>) -> Result { match *nonnegative_integer(reader)?.as_slice_less_safe() { [b] => Ok(b), _ => Err(Error::BadDer), } } const TYPE_ID: DerTypeId = DerTypeId::U8; } pub(crate) fn nonnegative_integer<'a>( input: &mut untrusted::Reader<'a>, ) -> Result, Error> { let value = expect_tag(input, Tag::Integer)?; match value .as_slice_less_safe() .split_first() .ok_or(Error::BadDer)? { // Zero or leading zero. (0, rest) => { match rest.first() { // Zero None => Ok(value), // Necessary leading zero. Some(&second) if second & 0x80 == 0x80 => Ok(untrusted::Input::from(rest)), // Unnecessary leading zero. _ => Err(Error::BadDer), } } // Positive value with no leading zero. (first, _) if first & 0x80 == 0x00 => Ok(value), // Negative value. (_, _) => Err(Error::BadDer), } } pub(crate) fn end_of_input_err(_: untrusted::EndOfInput) -> Error { Error::BadDer } // Like mozilla::pkix, we accept the nonconformant explicit encoding of // the default value (false) for compatibility with real-world certificates. impl<'a> FromDer<'a> for bool { fn from_der(reader: &mut untrusted::Reader<'a>) -> Result { if !reader.peek(Tag::Boolean.into()) { return Ok(false); } nested( reader, Tag::Boolean, Error::TrailingData(Self::TYPE_ID), |input| match input.read_byte() { Ok(0xff) => Ok(true), Ok(0x00) => Ok(false), _ => Err(Error::BadDer), }, ) } const TYPE_ID: DerTypeId = DerTypeId::Bool; } macro_rules! oid { ( $first:expr, $second:expr, $( $tail:expr ),* ) => ( [(40 * $first) + $second, $( $tail ),*] ) } #[cfg(test)] mod tests { use super::DerTypeId; use std::prelude::v1::*; #[cfg(feature = "alloc")] #[test] fn test_asn1_wrap() { // Prepend stuff to `bytes` to put it in a DER SEQUENCE. let wrap_in_sequence = |bytes: &[u8]| super::asn1_wrap(super::Tag::Sequence, bytes); // Empty slice assert_eq!(vec![0x30, 0x00], wrap_in_sequence(&[])); // Small size assert_eq!( vec![0x30, 0x04, 0x00, 0x11, 0x22, 0x33], wrap_in_sequence(&[0x00, 0x11, 0x22, 0x33]) ); // Medium size let mut val = Vec::new(); val.resize(255, 0x12); assert_eq!( vec![0x30, 0x81, 0xff, 0x12, 0x12, 0x12], wrap_in_sequence(&val)[..6] ); // Large size let mut val = Vec::new(); val.resize(4660, 0x12); wrap_in_sequence(&val); assert_eq!( vec![0x30, 0x82, 0x12, 0x34, 0x12, 0x12], wrap_in_sequence(&val)[..6] ); // Huge size let mut val = Vec::new(); val.resize(0xffff, 0x12); let result = wrap_in_sequence(&val); assert_eq!(vec![0x30, 0x82, 0xff, 0xff, 0x12, 0x12], result[..6]); assert_eq!(result.len(), 0xffff + 4); // Gigantic size let mut val = Vec::new(); val.resize(0x100000, 0x12); let result = wrap_in_sequence(&val); assert_eq!(vec![0x30, 0x83, 0x10, 0x00, 0x00, 0x12, 0x12], result[..7]); assert_eq!(result.len(), 0x100000 + 5); // Ludicrous size let mut val = Vec::new(); val.resize(0x1000000, 0x12); let result = wrap_in_sequence(&val); assert_eq!( vec![0x30, 0x84, 0x01, 0x00, 0x00, 0x00, 0x12, 0x12], result[..8] ); assert_eq!(result.len(), 0x1000000 + 6); } #[test] fn test_optional_boolean() { use super::{Error, FromDer}; // Empty input results in false assert!(!bool::from_der(&mut bytes_reader(&[])).unwrap()); // Optional, so another data type results in false assert!(!bool::from_der(&mut bytes_reader(&[0x05, 0x00])).unwrap()); // Only 0x00 and 0xff are accepted values assert_eq!( Err(Error::BadDer), bool::from_der(&mut bytes_reader(&[0x01, 0x01, 0x42])) ); // True assert!(bool::from_der(&mut bytes_reader(&[0x01, 0x01, 0xff])).unwrap()); // False assert!(!bool::from_der(&mut bytes_reader(&[0x01, 0x01, 0x00])).unwrap()); } #[test] fn test_bit_string_with_no_unused_bits() { use super::{Error, bit_string_with_no_unused_bits}; // Unexpected type assert_eq!( bit_string_with_no_unused_bits(&mut bytes_reader(&[0x01, 0x01, 0xff])).unwrap_err(), Error::TrailingData(DerTypeId::BitString), ); // Unexpected nonexistent type assert_eq!( bit_string_with_no_unused_bits(&mut bytes_reader(&[0x42, 0xff, 0xff])).unwrap_err(), Error::TrailingData(DerTypeId::BitString), ); // Unexpected empty input assert_eq!( bit_string_with_no_unused_bits(&mut bytes_reader(&[])).unwrap_err(), Error::TrailingData(DerTypeId::BitString), ); // Valid input with non-zero unused bits assert_eq!( bit_string_with_no_unused_bits(&mut bytes_reader(&[0x03, 0x03, 0x04, 0x12, 0x34])) .unwrap_err(), Error::BadDer, ); // Valid input assert_eq!( bit_string_with_no_unused_bits(&mut bytes_reader(&[0x03, 0x03, 0x00, 0x12, 0x34])) .unwrap() .as_slice_less_safe(), &[0x12, 0x34], ); } fn bytes_reader(bytes: &[u8]) -> untrusted::Reader<'_> { untrusted::Reader::new(untrusted::Input::from(bytes)) } #[test] fn read_tag_and_get_value_default_limit() { use super::{Error, read_tag_and_get_value}; let inputs = &[ // DER with short-form length encoded as three bytes. &[EXAMPLE_TAG, 0x83, 0xFF, 0xFF, 0xFF].as_slice(), // DER with short-form length encoded as four bytes. &[EXAMPLE_TAG, 0x84, 0xFF, 0xFF, 0xFF, 0xFF].as_slice(), ]; for input in inputs { let mut bytes = untrusted::Reader::new(untrusted::Input::from(input)); // read_tag_and_get_value should reject DER with encoded lengths larger than two // bytes as BadDer. assert!(matches!( read_tag_and_get_value(&mut bytes), Err(Error::BadDer) )); } } #[test] fn read_tag_and_get_value_limited_high_form() { use super::{Error, LONG_FORM_LEN_TWO_BYTES_MAX, read_tag_and_get_value_limited}; let mut bytes = untrusted::Reader::new(untrusted::Input::from(&[0xFF])); // read_tag_and_get_value_limited_high_form should reject DER with "high tag number form" tags. assert!(matches!( read_tag_and_get_value_limited(&mut bytes, LONG_FORM_LEN_TWO_BYTES_MAX), Err(Error::BadDer) )); } #[test] fn read_tag_and_get_value_limited_non_canonical() { use super::{Error, LONG_FORM_LEN_TWO_BYTES_MAX, read_tag_and_get_value_limited}; let inputs = &[ // Two byte length, with expressed length < 128. &[EXAMPLE_TAG, 0x81, 0x01].as_slice(), // Three byte length, with expressed length < 256. &[EXAMPLE_TAG, 0x82, 0x00, 0x01].as_slice(), // Four byte length, with expressed length, < 65536. &[EXAMPLE_TAG, 0x83, 0x00, 0x00, 0x01].as_slice(), // Five byte length, with expressed length < 16777216. &[EXAMPLE_TAG, 0x84, 0x00, 0x00, 0x00, 0x01].as_slice(), ]; for input in inputs { let mut bytes = untrusted::Reader::new(untrusted::Input::from(input)); // read_tag_and_get_value_limited should reject DER with non-canonical lengths. assert!(matches!( read_tag_and_get_value_limited(&mut bytes, LONG_FORM_LEN_TWO_BYTES_MAX), Err(Error::BadDer) )); } } #[test] #[cfg(feature = "alloc")] fn read_tag_and_get_value_limited_limits() { use super::{Error, read_tag_and_get_value_limited}; let short_input = &[0xFF]; let short_input_encoded = &[ &[EXAMPLE_TAG], der_encode_length(short_input.len()).as_slice(), short_input, ] .concat(); let long_input = &[1_u8; 65537]; let long_input_encoded = &[ &[EXAMPLE_TAG], der_encode_length(long_input.len()).as_slice(), long_input, ] .concat(); struct Testcase<'a> { input: &'a [u8], limit: usize, err: Option, } let testcases = &[ Testcase { input: short_input_encoded, limit: 1, err: Some(Error::BadDer), }, Testcase { input: short_input_encoded, limit: short_input_encoded.len() + 1, err: None, }, Testcase { input: long_input_encoded, limit: long_input.len(), err: Some(Error::BadDer), }, Testcase { input: long_input_encoded, limit: long_input.len() + 1, err: None, }, ]; for tc in testcases { let mut bytes = untrusted::Reader::new(untrusted::Input::from(tc.input)); let res = read_tag_and_get_value_limited(&mut bytes, tc.limit); match &tc.err { None => assert!(res.is_ok()), Some(e) => { let actual = res.unwrap_err(); assert_eq!(&actual, e) } } } } #[allow(clippy::as_conversions)] // infallible. const EXAMPLE_TAG: u8 = super::Tag::Sequence as u8; #[cfg(feature = "alloc")] #[allow(clippy::as_conversions)] // test code. fn der_encode_length(length: usize) -> Vec { if length < 128 { vec![length as u8] } else { let mut encoded: Vec = Vec::new(); let mut remaining_length = length; while remaining_length > 0 { let byte = (remaining_length & 0xFF) as u8; encoded.insert(0, byte); remaining_length >>= 8; } let length_octet = encoded.len() as u8 | 0x80; encoded.insert(0, length_octet); encoded } } #[test] fn misencoded_bit_string_flags() { use super::{Error, bit_string_flags}; let bad_padding_example = untrusted::Input::from(&[ 0x08, // 8 bit of padding (illegal!). 0x06, // 1 byte of bit flags asserting bits 5 and 6. ]); assert!(matches!( bit_string_flags(bad_padding_example), Err(Error::BadDer) )); let bad_padding_example = untrusted::Input::from(&[ 0x01, // 1 bit of padding. // No flags value (illegal with padding!). ]); assert!(matches!( bit_string_flags(bad_padding_example), Err(Error::BadDer) )); } #[test] fn valid_bit_string_flags() { use super::bit_string_flags; let example_key_usage = untrusted::Input::from(&[ 0x01, // 1 bit of padding. 0x06, // 1 byte of bit flags asserting bits 5 and 6. ]); let res = bit_string_flags(example_key_usage).unwrap(); assert!(!res.bit_set(0)); assert!(!res.bit_set(1)); assert!(!res.bit_set(2)); assert!(!res.bit_set(3)); assert!(!res.bit_set(4)); // NB: Bits 5 and 6 should be set. assert!(res.bit_set(5)); assert!(res.bit_set(6)); assert!(!res.bit_set(7)); assert!(!res.bit_set(8)); // Bits outside the range of values shouldn't be considered set. assert!(!res.bit_set(256)); } #[test] fn test_small_nonnegative_integer() { use super::{Error, FromDer, Tag}; for value in 0..=127 { let data = [Tag::Integer.into(), 1, value]; let mut rd = untrusted::Reader::new(untrusted::Input::from(&data)); assert_eq!(u8::from_der(&mut rd), Ok(value),); } for value in 128..=255 { let data = [Tag::Integer.into(), 2, 0x00, value]; let mut rd = untrusted::Reader::new(untrusted::Input::from(&data)); assert_eq!(u8::from_der(&mut rd), Ok(value),); } // not an integer assert_eq!( u8::from_der(&mut untrusted::Reader::new(untrusted::Input::from(&[ Tag::Sequence.into(), 1, 1 ]))), Err(Error::BadDer) ); // negative assert_eq!( u8::from_der(&mut untrusted::Reader::new(untrusted::Input::from(&[ Tag::Integer.into(), 1, 0xff ]))), Err(Error::BadDer) ); // positive but too large assert_eq!( u8::from_der(&mut untrusted::Reader::new(untrusted::Input::from(&[ Tag::Integer.into(), 2, 0x01, 0x00 ]))), Err(Error::BadDer) ); // unnecessary leading zero assert_eq!( u8::from_der(&mut untrusted::Reader::new(untrusted::Input::from(&[ Tag::Integer.into(), 2, 0x00, 0x05 ]))), Err(Error::BadDer) ); // truncations assert_eq!( u8::from_der(&mut untrusted::Reader::new(untrusted::Input::from(&[]))), Err(Error::BadDer) ); assert_eq!( u8::from_der(&mut untrusted::Reader::new(untrusted::Input::from(&[ Tag::Integer.into(), ]))), Err(Error::BadDer) ); assert_eq!( u8::from_der(&mut untrusted::Reader::new(untrusted::Input::from(&[ Tag::Integer.into(), 1, ]))), Err(Error::BadDer) ); assert_eq!( u8::from_der(&mut untrusted::Reader::new(untrusted::Input::from(&[ Tag::Integer.into(), 2, 0 ]))), Err(Error::BadDer) ); } }