• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Length calculations for encoded ASN.1 DER values
2 
3 use crate::{Decode, DerOrd, Encode, Error, ErrorKind, Reader, Result, SliceWriter, Writer};
4 use core::{
5     cmp::Ordering,
6     fmt,
7     ops::{Add, Sub},
8 };
9 
10 /// Maximum number of octets in a DER encoding of a [`Length`] using the
11 /// rules implemented by this crate.
12 const MAX_DER_OCTETS: usize = 5;
13 
14 /// Maximum length as a `u32` (256 MiB).
15 const MAX_U32: u32 = 0xfff_ffff;
16 
17 /// ASN.1-encoded length.
18 ///
19 /// Maximum length is defined by the [`Length::MAX`] constant (256 MiB).
20 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
21 pub struct Length(u32);
22 
23 impl Length {
24     /// Length of `0`
25     pub const ZERO: Self = Self(0);
26 
27     /// Length of `1`
28     pub const ONE: Self = Self(1);
29 
30     /// Maximum length currently supported: 256 MiB
31     pub const MAX: Self = Self(MAX_U32);
32 
33     /// Create a new [`Length`] for any value which fits inside of a [`u16`].
34     ///
35     /// This function is const-safe and therefore useful for [`Length`] constants.
new(value: u16) -> Self36     pub const fn new(value: u16) -> Self {
37         Self(value as u32)
38     }
39 
40     /// Is this length equal to zero?
is_zero(self) -> bool41     pub fn is_zero(self) -> bool {
42         self == Self::ZERO
43     }
44 
45     /// Get the length of DER Tag-Length-Value (TLV) encoded data if `self`
46     /// is the length of the inner "value" portion of the message.
for_tlv(self) -> Result<Self>47     pub fn for_tlv(self) -> Result<Self> {
48         Self::ONE + self.encoded_len()? + self
49     }
50 
51     /// Perform saturating addition of two lengths.
saturating_add(self, rhs: Self) -> Self52     pub fn saturating_add(self, rhs: Self) -> Self {
53         Self(self.0.saturating_add(rhs.0))
54     }
55 
56     /// Perform saturating subtraction of two lengths.
saturating_sub(self, rhs: Self) -> Self57     pub fn saturating_sub(self, rhs: Self) -> Self {
58         Self(self.0.saturating_sub(rhs.0))
59     }
60 
61     /// Get initial octet of the encoded length (if one is required).
62     ///
63     /// From X.690 Section 8.1.3.5:
64     /// > In the long form, the length octets shall consist of an initial octet
65     /// > and one or more subsequent octets. The initial octet shall be encoded
66     /// > as follows:
67     /// >
68     /// > a) bit 8 shall be one;
69     /// > b) bits 7 to 1 shall encode the number of subsequent octets in the
70     /// >    length octets, as an unsigned binary integer with bit 7 as the
71     /// >    most significant bit;
72     /// > c) the value 11111111₂ shall not be used.
initial_octet(self) -> Option<u8>73     fn initial_octet(self) -> Option<u8> {
74         match self.0 {
75             0x80..=0xFF => Some(0x81),
76             0x100..=0xFFFF => Some(0x82),
77             0x10000..=0xFFFFFF => Some(0x83),
78             0x1000000..=MAX_U32 => Some(0x84),
79             _ => None,
80         }
81     }
82 }
83 
84 impl Add for Length {
85     type Output = Result<Self>;
86 
add(self, other: Self) -> Result<Self>87     fn add(self, other: Self) -> Result<Self> {
88         self.0
89             .checked_add(other.0)
90             .ok_or_else(|| ErrorKind::Overflow.into())
91             .and_then(TryInto::try_into)
92     }
93 }
94 
95 impl Add<u8> for Length {
96     type Output = Result<Self>;
97 
add(self, other: u8) -> Result<Self>98     fn add(self, other: u8) -> Result<Self> {
99         self + Length::from(other)
100     }
101 }
102 
103 impl Add<u16> for Length {
104     type Output = Result<Self>;
105 
add(self, other: u16) -> Result<Self>106     fn add(self, other: u16) -> Result<Self> {
107         self + Length::from(other)
108     }
109 }
110 
111 impl Add<u32> for Length {
112     type Output = Result<Self>;
113 
add(self, other: u32) -> Result<Self>114     fn add(self, other: u32) -> Result<Self> {
115         self + Length::try_from(other)?
116     }
117 }
118 
119 impl Add<usize> for Length {
120     type Output = Result<Self>;
121 
add(self, other: usize) -> Result<Self>122     fn add(self, other: usize) -> Result<Self> {
123         self + Length::try_from(other)?
124     }
125 }
126 
127 impl Add<Length> for Result<Length> {
128     type Output = Self;
129 
add(self, other: Length) -> Self130     fn add(self, other: Length) -> Self {
131         self? + other
132     }
133 }
134 
135 impl Sub for Length {
136     type Output = Result<Self>;
137 
sub(self, other: Length) -> Result<Self>138     fn sub(self, other: Length) -> Result<Self> {
139         self.0
140             .checked_sub(other.0)
141             .ok_or_else(|| ErrorKind::Overflow.into())
142             .and_then(TryInto::try_into)
143     }
144 }
145 
146 impl Sub<Length> for Result<Length> {
147     type Output = Self;
148 
sub(self, other: Length) -> Self149     fn sub(self, other: Length) -> Self {
150         self? - other
151     }
152 }
153 
154 impl From<u8> for Length {
from(len: u8) -> Length155     fn from(len: u8) -> Length {
156         Length(len.into())
157     }
158 }
159 
160 impl From<u16> for Length {
from(len: u16) -> Length161     fn from(len: u16) -> Length {
162         Length(len.into())
163     }
164 }
165 
166 impl From<Length> for u32 {
from(length: Length) -> u32167     fn from(length: Length) -> u32 {
168         length.0
169     }
170 }
171 
172 impl TryFrom<u32> for Length {
173     type Error = Error;
174 
try_from(len: u32) -> Result<Length>175     fn try_from(len: u32) -> Result<Length> {
176         if len <= Self::MAX.0 {
177             Ok(Length(len))
178         } else {
179             Err(ErrorKind::Overflow.into())
180         }
181     }
182 }
183 
184 impl TryFrom<usize> for Length {
185     type Error = Error;
186 
try_from(len: usize) -> Result<Length>187     fn try_from(len: usize) -> Result<Length> {
188         u32::try_from(len)
189             .map_err(|_| ErrorKind::Overflow)?
190             .try_into()
191     }
192 }
193 
194 impl TryFrom<Length> for usize {
195     type Error = Error;
196 
try_from(len: Length) -> Result<usize>197     fn try_from(len: Length) -> Result<usize> {
198         len.0.try_into().map_err(|_| ErrorKind::Overflow.into())
199     }
200 }
201 
202 impl<'a> Decode<'a> for Length {
decode<R: Reader<'a>>(reader: &mut R) -> Result<Length>203     fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Length> {
204         match reader.read_byte()? {
205             // Note: per X.690 Section 8.1.3.6.1 the byte 0x80 encodes indefinite
206             // lengths, which are not allowed in DER, so disallow that byte.
207             len if len < 0x80 => Ok(len.into()),
208             // 1-4 byte variable-sized length prefix
209             tag @ 0x81..=0x84 => {
210                 let nbytes = tag.checked_sub(0x80).ok_or(ErrorKind::Overlength)? as usize;
211                 debug_assert!(nbytes <= 4);
212 
213                 let mut decoded_len = 0u32;
214                 for _ in 0..nbytes {
215                     decoded_len = decoded_len.checked_shl(8).ok_or(ErrorKind::Overflow)?
216                         | u32::from(reader.read_byte()?);
217                 }
218 
219                 let length = Length::try_from(decoded_len)?;
220 
221                 // X.690 Section 10.1: DER lengths must be encoded with a minimum
222                 // number of octets
223                 if length.initial_octet() == Some(tag) {
224                     Ok(length)
225                 } else {
226                     Err(ErrorKind::Overlength.into())
227                 }
228             }
229             _ => {
230                 // We specialize to a maximum 4-byte length (including initial octet)
231                 Err(ErrorKind::Overlength.into())
232             }
233         }
234     }
235 }
236 
237 impl Encode for Length {
encoded_len(&self) -> Result<Length>238     fn encoded_len(&self) -> Result<Length> {
239         match self.0 {
240             0..=0x7F => Ok(Length(1)),
241             0x80..=0xFF => Ok(Length(2)),
242             0x100..=0xFFFF => Ok(Length(3)),
243             0x10000..=0xFFFFFF => Ok(Length(4)),
244             0x1000000..=MAX_U32 => Ok(Length(5)),
245             _ => Err(ErrorKind::Overflow.into()),
246         }
247     }
248 
encode(&self, writer: &mut dyn Writer) -> Result<()>249     fn encode(&self, writer: &mut dyn Writer) -> Result<()> {
250         match self.initial_octet() {
251             Some(tag_byte) => {
252                 writer.write_byte(tag_byte)?;
253 
254                 // Strip leading zeroes
255                 match self.0.to_be_bytes() {
256                     [0, 0, 0, byte] => writer.write_byte(byte),
257                     [0, 0, bytes @ ..] => writer.write(&bytes),
258                     [0, bytes @ ..] => writer.write(&bytes),
259                     bytes => writer.write(&bytes),
260                 }
261             }
262             #[allow(clippy::cast_possible_truncation)]
263             None => writer.write_byte(self.0 as u8),
264         }
265     }
266 }
267 
268 impl DerOrd for Length {
der_cmp(&self, other: &Self) -> Result<Ordering>269     fn der_cmp(&self, other: &Self) -> Result<Ordering> {
270         let mut buf1 = [0u8; MAX_DER_OCTETS];
271         let mut buf2 = [0u8; MAX_DER_OCTETS];
272 
273         let mut encoder1 = SliceWriter::new(&mut buf1);
274         encoder1.encode(self)?;
275 
276         let mut encoder2 = SliceWriter::new(&mut buf2);
277         encoder2.encode(other)?;
278 
279         Ok(encoder1.finish()?.cmp(encoder2.finish()?))
280     }
281 }
282 
283 impl fmt::Display for Length {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result284     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285         self.0.fmt(f)
286     }
287 }
288 
289 #[cfg(test)]
290 mod tests {
291     use super::Length;
292     use crate::{Decode, DerOrd, Encode, ErrorKind};
293     use core::cmp::Ordering;
294 
295     #[test]
decode()296     fn decode() {
297         assert_eq!(Length::ZERO, Length::from_der(&[0x00]).unwrap());
298 
299         assert_eq!(Length::from(0x7Fu8), Length::from_der(&[0x7F]).unwrap());
300 
301         assert_eq!(
302             Length::from(0x80u8),
303             Length::from_der(&[0x81, 0x80]).unwrap()
304         );
305 
306         assert_eq!(
307             Length::from(0xFFu8),
308             Length::from_der(&[0x81, 0xFF]).unwrap()
309         );
310 
311         assert_eq!(
312             Length::from(0x100u16),
313             Length::from_der(&[0x82, 0x01, 0x00]).unwrap()
314         );
315 
316         assert_eq!(
317             Length::try_from(0x10000u32).unwrap(),
318             Length::from_der(&[0x83, 0x01, 0x00, 0x00]).unwrap()
319         );
320     }
321 
322     #[test]
encode()323     fn encode() {
324         let mut buffer = [0u8; 4];
325 
326         assert_eq!(&[0x00], Length::ZERO.encode_to_slice(&mut buffer).unwrap());
327 
328         assert_eq!(
329             &[0x7F],
330             Length::from(0x7Fu8).encode_to_slice(&mut buffer).unwrap()
331         );
332 
333         assert_eq!(
334             &[0x81, 0x80],
335             Length::from(0x80u8).encode_to_slice(&mut buffer).unwrap()
336         );
337 
338         assert_eq!(
339             &[0x81, 0xFF],
340             Length::from(0xFFu8).encode_to_slice(&mut buffer).unwrap()
341         );
342 
343         assert_eq!(
344             &[0x82, 0x01, 0x00],
345             Length::from(0x100u16).encode_to_slice(&mut buffer).unwrap()
346         );
347 
348         assert_eq!(
349             &[0x83, 0x01, 0x00, 0x00],
350             Length::try_from(0x10000u32)
351                 .unwrap()
352                 .encode_to_slice(&mut buffer)
353                 .unwrap()
354         );
355     }
356 
357     #[test]
reject_indefinite_lengths()358     fn reject_indefinite_lengths() {
359         assert!(Length::from_der(&[0x80]).is_err());
360     }
361 
362     #[test]
add_overflows_when_max_length_exceeded()363     fn add_overflows_when_max_length_exceeded() {
364         let result = Length::MAX + Length::ONE;
365         assert_eq!(
366             result.err().map(|err| err.kind()),
367             Some(ErrorKind::Overflow)
368         );
369     }
370 
371     #[test]
der_ord()372     fn der_ord() {
373         assert_eq!(Length::ONE.der_cmp(&Length::MAX).unwrap(), Ordering::Less);
374     }
375 }
376