Skip to main content

der/asn1/integer/
int.rs

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