der_parser/ber/
integer.rs

1use crate::error::*;
2
3/// Decode an unsigned integer into a big endian byte slice with all leading
4/// zeroes removed.
5///
6/// Returns a byte array of the requested size containing a big endian integer.
7fn remove_zeroes(bytes: &[u8]) -> Result<&[u8], BerError> {
8    // skip leading 0s
9    match bytes {
10        // [] => Err(BerError::DerConstraintFailed),
11        [0] => Ok(bytes),
12        // [0, byte, ..] if *byte < 0x80 => Err(BerError::DerConstraintFailed),
13        // [0, rest @ ..] => Ok(&rest),
14        [0, rest @ ..] => remove_zeroes(rest),
15        // [byte, ..] if *byte >= 0x80 => Err(BerError::IntegerTooLarge),
16        _ => Ok(bytes),
17    }
18}
19
20// XXX const generics require rustc >= 1.51
21// /// Decode an unsigned integer into a byte array of the requested size
22// /// containing a big endian integer.
23// pub(crate) fn decode_array_uint<const N: usize>(bytes: &[u8]) -> Result<[u8; N], BerError> {
24//     // Check if MSB is set *before* leading zeroes
25//     if is_highest_bit_set(bytes) {
26//         return Err(BerError::IntegerNegative);
27//     }
28//     let input = remove_zeroes(bytes)?;
29
30//     if input.len() > N {
31//         return Err(BerError::IntegerTooLarge);
32//     }
33
34//     // Input has leading zeroes removed, so we need to add them back
35//     let mut output = [0u8; N];
36//     assert!(input.len() <= N);
37//     output[N.saturating_sub(input.len())..].copy_from_slice(input);
38//     Ok(output)
39// }
40
41pub(crate) fn decode_array_uint8(bytes: &[u8]) -> Result<[u8; 8], BerError> {
42    // Check if MSB is set *before* leading zeroes
43    if is_highest_bit_set(bytes) {
44        return Err(BerError::IntegerNegative);
45    }
46    let input = remove_zeroes(bytes)?;
47
48    if input.len() > 8 {
49        return Err(BerError::IntegerTooLarge);
50    }
51
52    // Input has leading zeroes removed, so we need to add them back
53    let mut output = [0u8; 8];
54    assert!(input.len() <= 8);
55    output[8_usize.saturating_sub(input.len())..].copy_from_slice(input);
56    Ok(output)
57}
58
59pub(crate) fn decode_array_uint4(bytes: &[u8]) -> Result<[u8; 4], BerError> {
60    // Check if MSB is set *before* leading zeroes
61    if is_highest_bit_set(bytes) {
62        return Err(BerError::IntegerNegative);
63    }
64    let input = remove_zeroes(bytes)?;
65
66    if input.len() > 4 {
67        return Err(BerError::IntegerTooLarge);
68    }
69
70    // Input has leading zeroes removed, so we need to add them back
71    let mut output = [0u8; 4];
72    assert!(input.len() <= 4);
73    output[4_usize.saturating_sub(input.len())..].copy_from_slice(input);
74    Ok(output)
75}
76
77// XXX const generics require rustc >= 1.51
78// /// Decode an unsigned integer of the specified size.
79// ///
80// /// Returns a byte array of the requested size containing a big endian integer.
81// pub(crate) fn decode_array_int<const N: usize>(input: &[u8]) -> Result<[u8; N], BerError> {
82//     let input = remove_zeroes(input)?;
83
84//     if input.len() > N {
85//         return Err(BerError::IntegerTooLarge);
86//     }
87
88//     // any.tag().assert_eq(Tag::Integer)?;
89//     let mut output = [0xFFu8; N];
90//     let offset = N.saturating_sub(input.len());
91//     output[offset..].copy_from_slice(input);
92//     Ok(output)
93// }
94
95pub(crate) fn decode_array_int8(input: &[u8]) -> Result<[u8; 8], BerError> {
96    let input = remove_zeroes(input)?;
97
98    if input.len() > 8 {
99        return Err(BerError::IntegerTooLarge);
100    }
101
102    // any.tag().assert_eq(Tag::Integer)?;
103    let mut output = [0xFFu8; 8];
104    let offset = 8_usize.saturating_sub(input.len());
105    output[offset..].copy_from_slice(input);
106    Ok(output)
107}
108
109pub(crate) fn decode_array_int4(input: &[u8]) -> Result<[u8; 4], BerError> {
110    let input = remove_zeroes(input)?;
111
112    if input.len() > 4 {
113        return Err(BerError::IntegerTooLarge);
114    }
115
116    // any.tag().assert_eq(Tag::Integer)?;
117    let mut output = [0xFFu8; 4];
118    let offset = 4_usize.saturating_sub(input.len());
119    output[offset..].copy_from_slice(input);
120    Ok(output)
121}
122
123/// Is the highest bit of the first byte in the slice 1? (if present)
124#[inline]
125pub(crate) fn is_highest_bit_set(bytes: &[u8]) -> bool {
126    bytes
127        .first()
128        .map(|byte| byte & 0b10000000 != 0)
129        .unwrap_or(false)
130}