use crate::error::*; /// Decode an unsigned integer into a big endian byte slice with all leading /// zeroes removed. /// /// Returns a byte array of the requested size containing a big endian integer. fn remove_zeroes(bytes: &[u8]) -> Result<&[u8], BerError> { // skip leading 0s match bytes { // [] => Err(BerError::DerConstraintFailed), [0] => Ok(bytes), // [0, byte, ..] if *byte < 0x80 => Err(BerError::DerConstraintFailed), // [0, rest @ ..] => Ok(&rest), [0, rest @ ..] => remove_zeroes(rest), // [byte, ..] if *byte >= 0x80 => Err(BerError::IntegerTooLarge), _ => Ok(bytes), } } // XXX const generics require rustc >= 1.51 // /// Decode an unsigned integer into a byte array of the requested size // /// containing a big endian integer. // pub(crate) fn decode_array_uint(bytes: &[u8]) -> Result<[u8; N], BerError> { // // Check if MSB is set *before* leading zeroes // if is_highest_bit_set(bytes) { // return Err(BerError::IntegerNegative); // } // let input = remove_zeroes(bytes)?; // if input.len() > N { // return Err(BerError::IntegerTooLarge); // } // // Input has leading zeroes removed, so we need to add them back // let mut output = [0u8; N]; // assert!(input.len() <= N); // output[N.saturating_sub(input.len())..].copy_from_slice(input); // Ok(output) // } pub(crate) fn decode_array_uint8(bytes: &[u8]) -> Result<[u8; 8], BerError> { // Check if MSB is set *before* leading zeroes if is_highest_bit_set(bytes) { return Err(BerError::IntegerNegative); } let input = remove_zeroes(bytes)?; if input.len() > 8 { return Err(BerError::IntegerTooLarge); } // Input has leading zeroes removed, so we need to add them back let mut output = [0u8; 8]; assert!(input.len() <= 8); output[8_usize.saturating_sub(input.len())..].copy_from_slice(input); Ok(output) } pub(crate) fn decode_array_uint4(bytes: &[u8]) -> Result<[u8; 4], BerError> { // Check if MSB is set *before* leading zeroes if is_highest_bit_set(bytes) { return Err(BerError::IntegerNegative); } let input = remove_zeroes(bytes)?; if input.len() > 4 { return Err(BerError::IntegerTooLarge); } // Input has leading zeroes removed, so we need to add them back let mut output = [0u8; 4]; assert!(input.len() <= 4); output[4_usize.saturating_sub(input.len())..].copy_from_slice(input); Ok(output) } // XXX const generics require rustc >= 1.51 // /// Decode an unsigned integer of the specified size. // /// // /// Returns a byte array of the requested size containing a big endian integer. // pub(crate) fn decode_array_int(input: &[u8]) -> Result<[u8; N], BerError> { // let input = remove_zeroes(input)?; // if input.len() > N { // return Err(BerError::IntegerTooLarge); // } // // any.tag().assert_eq(Tag::Integer)?; // let mut output = [0xFFu8; N]; // let offset = N.saturating_sub(input.len()); // output[offset..].copy_from_slice(input); // Ok(output) // } pub(crate) fn decode_array_int8(input: &[u8]) -> Result<[u8; 8], BerError> { let input = remove_zeroes(input)?; if input.len() > 8 { return Err(BerError::IntegerTooLarge); } // any.tag().assert_eq(Tag::Integer)?; let mut output = [0xFFu8; 8]; let offset = 8_usize.saturating_sub(input.len()); output[offset..].copy_from_slice(input); Ok(output) } pub(crate) fn decode_array_int4(input: &[u8]) -> Result<[u8; 4], BerError> { let input = remove_zeroes(input)?; if input.len() > 4 { return Err(BerError::IntegerTooLarge); } // any.tag().assert_eq(Tag::Integer)?; let mut output = [0xFFu8; 4]; let offset = 4_usize.saturating_sub(input.len()); output[offset..].copy_from_slice(input); Ok(output) } /// Is the highest bit of the first byte in the slice 1? (if present) #[inline] pub(crate) fn is_highest_bit_set(bytes: &[u8]) -> bool { bytes .get(0) .map(|byte| byte & 0b10000000 != 0) .unwrap_or(false) }