der/asn1/integer/
uint.rs

1//! Unsigned integer decoders/encoders.
2
3use super::value_cmp;
4use crate::{
5    ord::OrdIsValueOrd, AnyRef, BytesRef, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag,
6    Header, Length, Reader, Result, Tag, ValueOrd, Writer,
7};
8use core::cmp::Ordering;
9
10#[cfg(feature = "alloc")]
11pub use allocating::Uint;
12
13macro_rules! impl_encoding_traits {
14    ($($uint:ty),+) => {
15        $(
16            impl<'a> DecodeValue<'a> for $uint {
17                fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
18                    // Integers always encodes as a signed value, unsigned gets a leading 0x00 that
19                    // needs to be stripped off. We need to provide room for it.
20                    const UNSIGNED_HEADROOM: usize = 1;
21
22                    let mut buf = [0u8; (Self::BITS as usize / 8) + UNSIGNED_HEADROOM];
23                    let max_length = u32::from(header.length) as usize;
24
25                    if max_length > buf.len() {
26                        return Err(Self::TAG.non_canonical_error());
27                    }
28
29                    let bytes = reader.read_into(&mut buf[..max_length])?;
30
31                    let result = Self::from_be_bytes(decode_to_array(bytes)?);
32
33                    // Ensure we compute the same encoded length as the original any value
34                    if header.length != result.value_len()? {
35                        return Err(Self::TAG.non_canonical_error());
36                    }
37
38                    Ok(result)
39                }
40            }
41
42            impl EncodeValue for $uint {
43                fn value_len(&self) -> Result<Length> {
44                    encoded_len(&self.to_be_bytes())
45                }
46
47                fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
48                    encode_bytes(writer, &self.to_be_bytes())
49                }
50            }
51
52            impl FixedTag for $uint {
53                const TAG: Tag = Tag::Integer;
54            }
55
56            impl ValueOrd for $uint {
57                fn value_cmp(&self, other: &Self) -> Result<Ordering> {
58                    value_cmp(*self, *other)
59                }
60            }
61
62            impl TryFrom<AnyRef<'_>> for $uint {
63                type Error = Error;
64
65                fn try_from(any: AnyRef<'_>) -> Result<Self> {
66                    any.decode_as()
67                }
68            }
69        )+
70    };
71}
72
73impl_encoding_traits!(u8, u16, u32, u64, u128);
74
75/// Unsigned arbitrary precision ASN.1 `INTEGER` reference type.
76///
77/// Provides direct access to the underlying big endian bytes which comprise an
78/// unsigned integer value.
79///
80/// Intended for use cases like very large integers that are used in
81/// cryptographic applications (e.g. keys, signatures).
82#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
83pub struct UintRef<'a> {
84    /// Inner value
85    inner: BytesRef<'a>,
86}
87
88impl<'a> UintRef<'a> {
89    /// Create a new [`UintRef`] from a byte slice.
90    pub fn new(bytes: &'a [u8]) -> Result<Self> {
91        let inner = BytesRef::new(strip_leading_zeroes(bytes))
92            .map_err(|_| ErrorKind::Length { tag: Self::TAG })?;
93
94        Ok(Self { inner })
95    }
96
97    /// Borrow the inner byte slice which contains the least significant bytes
98    /// of a big endian integer value with all leading zeros stripped.
99    pub fn as_bytes(&self) -> &'a [u8] {
100        self.inner.as_slice()
101    }
102
103    /// Get the length of this [`UintRef`] in bytes.
104    pub fn len(&self) -> Length {
105        self.inner.len()
106    }
107
108    /// Is the inner byte slice empty?
109    pub fn is_empty(&self) -> bool {
110        self.inner.is_empty()
111    }
112}
113
114impl_any_conversions!(UintRef<'a>, 'a);
115
116impl<'a> DecodeValue<'a> for UintRef<'a> {
117    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
118        let bytes = BytesRef::decode_value(reader, header)?.as_slice();
119        let result = Self::new(decode_to_slice(bytes)?)?;
120
121        // Ensure we compute the same encoded length as the original any value.
122        if result.value_len()? != header.length {
123            return Err(Self::TAG.non_canonical_error());
124        }
125
126        Ok(result)
127    }
128}
129
130impl<'a> EncodeValue for UintRef<'a> {
131    fn value_len(&self) -> Result<Length> {
132        encoded_len(self.inner.as_slice())
133    }
134
135    fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
136        // Add leading `0x00` byte if required
137        if self.value_len()? > self.len() {
138            writer.write_byte(0)?;
139        }
140
141        writer.write(self.as_bytes())
142    }
143}
144
145impl<'a> From<&UintRef<'a>> for UintRef<'a> {
146    fn from(value: &UintRef<'a>) -> UintRef<'a> {
147        *value
148    }
149}
150
151impl<'a> FixedTag for UintRef<'a> {
152    const TAG: Tag = Tag::Integer;
153}
154
155impl<'a> OrdIsValueOrd for UintRef<'a> {}
156
157#[cfg(feature = "alloc")]
158mod allocating {
159    use super::{decode_to_slice, encoded_len, strip_leading_zeroes, UintRef};
160    use crate::{
161        ord::OrdIsValueOrd,
162        referenced::{OwnedToRef, RefToOwned},
163        BytesOwned, DecodeValue, EncodeValue, ErrorKind, FixedTag, Header, Length, Reader, Result,
164        Tag, Writer,
165    };
166
167    /// Unsigned arbitrary precision ASN.1 `INTEGER` type.
168    ///
169    /// Provides heap-allocated storage for big endian bytes which comprise an
170    /// unsigned integer value.
171    ///
172    /// Intended for use cases like very large integers that are used in
173    /// cryptographic applications (e.g. keys, signatures).
174    #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
175    pub struct Uint {
176        /// Inner value
177        inner: BytesOwned,
178    }
179
180    impl Uint {
181        /// Create a new [`Uint`] from a byte slice.
182        pub fn new(bytes: &[u8]) -> Result<Self> {
183            let inner = BytesOwned::new(strip_leading_zeroes(bytes))
184                .map_err(|_| ErrorKind::Length { tag: Self::TAG })?;
185
186            Ok(Self { inner })
187        }
188
189        /// Borrow the inner byte slice which contains the least significant bytes
190        /// of a big endian integer value with all leading zeros stripped.
191        pub fn as_bytes(&self) -> &[u8] {
192            self.inner.as_slice()
193        }
194
195        /// Get the length of this [`Uint`] in bytes.
196        pub fn len(&self) -> Length {
197            self.inner.len()
198        }
199
200        /// Is the inner byte slice empty?
201        pub fn is_empty(&self) -> bool {
202            self.inner.is_empty()
203        }
204    }
205
206    impl_any_conversions!(Uint);
207
208    impl<'a> DecodeValue<'a> for Uint {
209        fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
210            let bytes = BytesOwned::decode_value(reader, header)?;
211            let result = Self::new(decode_to_slice(bytes.as_slice())?)?;
212
213            // Ensure we compute the same encoded length as the original any value.
214            if result.value_len()? != header.length {
215                return Err(Self::TAG.non_canonical_error());
216            }
217
218            Ok(result)
219        }
220    }
221
222    impl EncodeValue for Uint {
223        fn value_len(&self) -> Result<Length> {
224            encoded_len(self.inner.as_slice())
225        }
226
227        fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
228            // Add leading `0x00` byte if required
229            if self.value_len()? > self.len() {
230                writer.write_byte(0)?;
231            }
232
233            writer.write(self.as_bytes())
234        }
235    }
236
237    impl<'a> From<&UintRef<'a>> for Uint {
238        fn from(value: &UintRef<'a>) -> Uint {
239            let inner = BytesOwned::new(value.as_bytes()).expect("Invalid Uint");
240            Uint { inner }
241        }
242    }
243
244    impl FixedTag for Uint {
245        const TAG: Tag = Tag::Integer;
246    }
247
248    impl OrdIsValueOrd for Uint {}
249
250    impl<'a> RefToOwned<'a> for UintRef<'a> {
251        type Owned = Uint;
252        fn ref_to_owned(&self) -> Self::Owned {
253            let inner = self.inner.ref_to_owned();
254
255            Uint { inner }
256        }
257    }
258
259    impl OwnedToRef for Uint {
260        type Borrowed<'a> = UintRef<'a>;
261        fn owned_to_ref(&self) -> Self::Borrowed<'_> {
262            let inner = self.inner.owned_to_ref();
263
264            UintRef { inner }
265        }
266    }
267}
268
269/// Decode an unsigned integer into a big endian byte slice with all leading
270/// zeroes removed.
271///
272/// Returns a byte array of the requested size containing a big endian integer.
273pub(crate) fn decode_to_slice(bytes: &[u8]) -> Result<&[u8]> {
274    // The `INTEGER` type always encodes a signed value, so for unsigned
275    // values the leading `0x00` byte may need to be removed.
276    //
277    // We also disallow a leading byte which would overflow a signed ASN.1
278    // integer (since we're decoding an unsigned integer).
279    // We expect all such cases to have a leading `0x00` byte.
280    match bytes {
281        [] => Err(Tag::Integer.non_canonical_error()),
282        [0] => Ok(bytes),
283        [0, byte, ..] if *byte < 0x80 => Err(Tag::Integer.non_canonical_error()),
284        [0, rest @ ..] => Ok(rest),
285        [byte, ..] if *byte >= 0x80 => Err(Tag::Integer.value_error()),
286        _ => Ok(bytes),
287    }
288}
289
290/// Decode an unsigned integer into a byte array of the requested size
291/// containing a big endian integer.
292pub(super) fn decode_to_array<const N: usize>(bytes: &[u8]) -> Result<[u8; N]> {
293    let input = decode_to_slice(bytes)?;
294
295    // Compute number of leading zeroes to add
296    let num_zeroes = N
297        .checked_sub(input.len())
298        .ok_or_else(|| Tag::Integer.length_error())?;
299
300    // Copy input into `N`-sized output buffer with leading zeroes
301    let mut output = [0u8; N];
302    output[num_zeroes..].copy_from_slice(input);
303    Ok(output)
304}
305
306/// Encode the given big endian bytes representing an integer as ASN.1 DER.
307pub(crate) fn encode_bytes<W>(encoder: &mut W, bytes: &[u8]) -> Result<()>
308where
309    W: Writer + ?Sized,
310{
311    let bytes = strip_leading_zeroes(bytes);
312
313    if needs_leading_zero(bytes) {
314        encoder.write_byte(0)?;
315    }
316
317    encoder.write(bytes)
318}
319
320/// Get the encoded length for the given unsigned integer serialized as bytes.
321#[inline]
322pub(crate) fn encoded_len(bytes: &[u8]) -> Result<Length> {
323    let bytes = strip_leading_zeroes(bytes);
324    Length::try_from(bytes.len())? + u8::from(needs_leading_zero(bytes))
325}
326
327/// Strip the leading zeroes from the given byte slice
328pub(crate) fn strip_leading_zeroes(mut bytes: &[u8]) -> &[u8] {
329    while let Some((byte, rest)) = bytes.split_first() {
330        if *byte == 0 && !rest.is_empty() {
331            bytes = rest;
332        } else {
333            break;
334        }
335    }
336
337    bytes
338}
339
340/// Does the given integer need a leading zero?
341fn needs_leading_zero(bytes: &[u8]) -> bool {
342    matches!(bytes.first(), Some(byte) if *byte >= 0x80)
343}
344
345#[cfg(test)]
346mod tests {
347    use super::{decode_to_array, UintRef};
348    use crate::{asn1::integer::tests::*, AnyRef, Decode, Encode, ErrorKind, SliceWriter, Tag};
349
350    #[test]
351    fn decode_to_array_no_leading_zero() {
352        let arr = decode_to_array::<4>(&[1, 2]).unwrap();
353        assert_eq!(arr, [0, 0, 1, 2]);
354    }
355
356    #[test]
357    fn decode_to_array_leading_zero() {
358        let arr = decode_to_array::<4>(&[0x00, 0xFF, 0xFE]).unwrap();
359        assert_eq!(arr, [0x00, 0x00, 0xFF, 0xFE]);
360    }
361
362    #[test]
363    fn decode_to_array_extra_zero() {
364        let err = decode_to_array::<4>(&[0, 1, 2]).err().unwrap();
365        assert_eq!(err.kind(), ErrorKind::Noncanonical { tag: Tag::Integer });
366    }
367
368    #[test]
369    fn decode_to_array_missing_zero() {
370        // We're decoding an unsigned integer, but this value would be signed
371        let err = decode_to_array::<4>(&[0xFF, 0xFE]).err().unwrap();
372        assert_eq!(err.kind(), ErrorKind::Value { tag: Tag::Integer });
373    }
374
375    #[test]
376    fn decode_to_array_oversized_input() {
377        let err = decode_to_array::<1>(&[1, 2, 3]).err().unwrap();
378        assert_eq!(err.kind(), ErrorKind::Length { tag: Tag::Integer });
379    }
380
381    #[test]
382    fn decode_uintref() {
383        assert_eq!(&[0], UintRef::from_der(I0_BYTES).unwrap().as_bytes());
384        assert_eq!(&[127], UintRef::from_der(I127_BYTES).unwrap().as_bytes());
385        assert_eq!(&[128], UintRef::from_der(I128_BYTES).unwrap().as_bytes());
386        assert_eq!(&[255], UintRef::from_der(I255_BYTES).unwrap().as_bytes());
387
388        assert_eq!(
389            &[0x01, 0x00],
390            UintRef::from_der(I256_BYTES).unwrap().as_bytes()
391        );
392
393        assert_eq!(
394            &[0x7F, 0xFF],
395            UintRef::from_der(I32767_BYTES).unwrap().as_bytes()
396        );
397    }
398
399    #[test]
400    fn encode_uintref() {
401        for &example in &[
402            I0_BYTES,
403            I127_BYTES,
404            I128_BYTES,
405            I255_BYTES,
406            I256_BYTES,
407            I32767_BYTES,
408        ] {
409            let uint = UintRef::from_der(example).unwrap();
410
411            let mut buf = [0u8; 128];
412            let mut encoder = SliceWriter::new(&mut buf);
413            uint.encode(&mut encoder).unwrap();
414
415            let result = encoder.finish().unwrap();
416            assert_eq!(example, result);
417        }
418    }
419
420    #[test]
421    fn reject_oversize_without_extra_zero() {
422        let err = UintRef::try_from(AnyRef::new(Tag::Integer, &[0x81]).unwrap())
423            .err()
424            .unwrap();
425
426        assert_eq!(err.kind(), ErrorKind::Value { tag: Tag::Integer });
427    }
428}