blob: 1c05bec1b055c67fd27990d6b3be7c3fb70ecefa [file] [log] [blame]
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<const N: usize>(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<const N: usize>(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)
}