structured_asn1/
length.rs1use crate::error::ErrorCode;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum Length {
8 Definite(u64),
10 Indefinite,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum Encoding {
17 Der,
19 Ber,
22}
23
24impl Encoding {
25 #[must_use]
27 pub fn is_der(self) -> bool {
28 self == Self::Der
29 }
30}
31
32#[derive(Debug, Clone, Copy)]
40pub struct DerLength {
41 bytes: [u8; 9],
42 length: u8,
43}
44
45impl DerLength {
46 #[must_use]
49 pub fn new(length: u64) -> Self {
50 let mut bytes = [0; 9];
51 if length < 128 {
52 bytes[0] = length.to_be_bytes()[7];
53 return Self { bytes, length: 1 };
54 }
55 let count = (64 - length.leading_zeros()).div_ceil(8).to_le_bytes()[0];
56 bytes[0] = 0x80 | count;
57 let count_usize = usize::from(count);
58 bytes[1..=count_usize].copy_from_slice(&length.to_be_bytes()[8 - count_usize..]);
59 Self {
60 bytes,
61 length: 1 + count,
62 }
63 }
64
65 #[must_use]
67 pub fn as_bytes(&self) -> &[u8] {
68 &self.bytes[..usize::from(self.length)]
69 }
70}
71
72impl AsRef<[u8]> for DerLength {
73 fn as_ref(&self) -> &[u8] {
74 self.as_bytes()
75 }
76}
77
78pub(crate) fn read_accounted(
89 input: &[u8],
90 encoding: Encoding,
91 offset: u64,
92 mut charge: impl FnMut(u64) -> Result<(), ErrorCode>,
93) -> Result<(Length, usize), (ErrorCode, u64)> {
94 let fail = |code| (code, offset);
95
96 charge(1).map_err(fail)?;
97
98 let first = *input
99 .first()
100 .ok_or_else(|| fail(ErrorCode::UnexpectedEnd))?;
101
102 if first & 0x80 == 0 {
103 return Ok((Length::Definite(u64::from(first)), 1));
104 }
105
106 let count = usize::from(first & 0x7f);
107
108 if count == 0 {
109 return match encoding {
110 Encoding::Ber => Ok((Length::Indefinite, 1)),
111 Encoding::Der => Err(fail(ErrorCode::IndefiniteLengthNotAllowed)),
112 };
113 }
114
115 if count == 0x7f {
117 return Err(fail(ErrorCode::LengthTooLarge));
118 }
119
120 charge(count as u64).map_err(fail)?;
122
123 let bytes = input
124 .get(1..=count)
125 .ok_or_else(|| fail(ErrorCode::UnexpectedEnd))?;
126
127 if encoding.is_der() {
128 if bytes[0] == 0 {
130 return Err(fail(ErrorCode::LengthNotMinimal));
131 }
132 if count == 1 && bytes[0] < 0x80 {
134 return Err(fail(ErrorCode::LengthNotMinimal));
135 }
136 }
137
138 let significant = bytes.iter().skip_while(|byte| **byte == 0).count();
141 if significant > 8 {
142 return Err(fail(ErrorCode::LengthTooLarge));
143 }
144
145 let mut value: u64 = 0;
146 for byte in bytes {
147 value = value
148 .checked_mul(256)
149 .and_then(|shifted| shifted.checked_add(u64::from(*byte)))
150 .ok_or_else(|| fail(ErrorCode::LengthTooLarge))?;
151 }
152
153 Ok((Length::Definite(value), 1 + count))
154}
155
156#[cfg(test)]
157fn read(
158 input: &[u8],
159 encoding: Encoding,
160 offset: u64,
161) -> Result<(Length, usize), (ErrorCode, u64)> {
162 read_accounted(input, encoding, offset, |_| Ok(()))
163}
164
165#[cfg(test)]
166mod tests;