1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
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
.first()
.map(|byte| byte & 0b10000000 != 0)
.unwrap_or(false)
}