der/asn1/integer/
bigint.rs

1//! "Big" ASN.1 `INTEGER` types.
2
3use super::uint;
4use crate::{
5    asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, ErrorKind,
6    FixedTag, Header, Length, Reader, Result, Tag, Writer,
7};
8
9/// "Big" unsigned ASN.1 `INTEGER` type.
10///
11/// Provides direct access to the underlying big endian bytes which comprise an
12/// unsigned integer value.
13///
14/// Intended for use cases like very large integers that are used in
15/// cryptographic applications (e.g. keys, signatures).
16#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
17pub struct UIntRef<'a> {
18    /// Inner value
19    inner: ByteSlice<'a>,
20}
21
22impl<'a> UIntRef<'a> {
23    /// Create a new [`UIntRef`] from a byte slice.
24    pub fn new(bytes: &'a [u8]) -> Result<Self> {
25        let inner = ByteSlice::new(uint::strip_leading_zeroes(bytes))
26            .map_err(|_| ErrorKind::Length { tag: Self::TAG })?;
27
28        Ok(Self { inner })
29    }
30
31    /// Borrow the inner byte slice which contains the least significant bytes
32    /// of a big endian integer value with all leading zeros stripped.
33    pub fn as_bytes(&self) -> &'a [u8] {
34        self.inner.as_slice()
35    }
36
37    /// Get the length of this [`UIntRef`] in bytes.
38    pub fn len(&self) -> Length {
39        self.inner.len()
40    }
41
42    /// Is the inner byte slice empty?
43    pub fn is_empty(&self) -> bool {
44        self.inner.is_empty()
45    }
46}
47
48impl<'a> DecodeValue<'a> for UIntRef<'a> {
49    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
50        let bytes = ByteSlice::decode_value(reader, header)?.as_slice();
51        let result = Self::new(uint::decode_to_slice(bytes)?)?;
52
53        // Ensure we compute the same encoded length as the original any value.
54        if result.value_len()? != header.length {
55            return Err(Self::TAG.non_canonical_error());
56        }
57
58        Ok(result)
59    }
60}
61
62impl<'a> EncodeValue for UIntRef<'a> {
63    fn value_len(&self) -> Result<Length> {
64        uint::encoded_len(self.inner.as_slice())
65    }
66
67    fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
68        // Add leading `0x00` byte if required
69        if self.value_len()? > self.len() {
70            writer.write_byte(0)?;
71        }
72
73        writer.write(self.as_bytes())
74    }
75}
76
77impl<'a> From<&UIntRef<'a>> for UIntRef<'a> {
78    fn from(value: &UIntRef<'a>) -> UIntRef<'a> {
79        *value
80    }
81}
82
83impl<'a> TryFrom<AnyRef<'a>> for UIntRef<'a> {
84    type Error = Error;
85
86    fn try_from(any: AnyRef<'a>) -> Result<UIntRef<'a>> {
87        any.decode_into()
88    }
89}
90
91impl<'a> FixedTag for UIntRef<'a> {
92    const TAG: Tag = Tag::Integer;
93}
94
95impl<'a> OrdIsValueOrd for UIntRef<'a> {}
96
97#[cfg(test)]
98mod tests {
99    use super::UIntRef;
100    use crate::{
101        asn1::{integer::tests::*, AnyRef},
102        Decode, Encode, ErrorKind, SliceWriter, Tag,
103    };
104
105    #[test]
106    fn decode_uint_bytes() {
107        assert_eq!(&[0], UIntRef::from_der(I0_BYTES).unwrap().as_bytes());
108        assert_eq!(&[127], UIntRef::from_der(I127_BYTES).unwrap().as_bytes());
109        assert_eq!(&[128], UIntRef::from_der(I128_BYTES).unwrap().as_bytes());
110        assert_eq!(&[255], UIntRef::from_der(I255_BYTES).unwrap().as_bytes());
111
112        assert_eq!(
113            &[0x01, 0x00],
114            UIntRef::from_der(I256_BYTES).unwrap().as_bytes()
115        );
116
117        assert_eq!(
118            &[0x7F, 0xFF],
119            UIntRef::from_der(I32767_BYTES).unwrap().as_bytes()
120        );
121    }
122
123    #[test]
124    fn encode_uint_bytes() {
125        for &example in &[
126            I0_BYTES,
127            I127_BYTES,
128            I128_BYTES,
129            I255_BYTES,
130            I256_BYTES,
131            I32767_BYTES,
132        ] {
133            let uint = UIntRef::from_der(example).unwrap();
134
135            let mut buf = [0u8; 128];
136            let mut encoder = SliceWriter::new(&mut buf);
137            uint.encode(&mut encoder).unwrap();
138
139            let result = encoder.finish().unwrap();
140            assert_eq!(example, result);
141        }
142    }
143
144    #[test]
145    fn reject_oversize_without_extra_zero() {
146        let err = UIntRef::try_from(AnyRef::new(Tag::Integer, &[0x81]).unwrap())
147            .err()
148            .unwrap();
149
150        assert_eq!(err.kind(), ErrorKind::Value { tag: Tag::Integer });
151    }
152}