Skip to main content

der/asn1/integer/
uint.rs

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