Skip to main content

der/asn1/
integer.rs

1//! ASN.1 `INTEGER` support.
2
3pub(super) mod int;
4pub(super) mod uint;
5
6use core::{cmp::Ordering, mem::size_of};
7
8use crate::{EncodeValue, Result, encode::encode_value_to_slice};
9
10/// Is the highest bit of the first byte in the slice set to `1`? (if present)
11#[inline]
12fn is_highest_bit_set(bytes: &[u8]) -> bool {
13    bytes.first().is_some_and(|byte| byte & 0b10000000 != 0)
14}
15
16/// Compare two integer values
17fn value_cmp<T>(a: T, b: T) -> Result<Ordering>
18where
19    T: Copy + EncodeValue + Sized,
20{
21    const MAX_INT_SIZE: usize = 16;
22    debug_assert!(size_of::<T>() <= MAX_INT_SIZE);
23
24    let mut buf1 = [0u8; MAX_INT_SIZE];
25    let mut buf2 = [0u8; MAX_INT_SIZE];
26
27    let buf1 = encode_value_to_slice(&mut buf1, &a)?;
28    let buf2 = encode_value_to_slice(&mut buf2, &b)?;
29
30    Ok(buf1.cmp(buf2))
31}
32
33#[cfg(test)]
34#[allow(clippy::unwrap_used)]
35pub(crate) mod tests {
36    use crate::{Decode, Encode, ErrorKind, Tag};
37
38    // Vectors from Section 5.7 of:
39    // https://luca.ntop.org/Teaching/Appunti/asn1.html
40    pub(crate) const I0_BYTES: &[u8] = &[0x02, 0x01, 0x00];
41    pub(crate) const I127_BYTES: &[u8] = &[0x02, 0x01, 0x7F];
42    pub(crate) const I128_BYTES: &[u8] = &[0x02, 0x02, 0x00, 0x80];
43    pub(crate) const I256_BYTES: &[u8] = &[0x02, 0x02, 0x01, 0x00];
44    pub(crate) const INEG128_BYTES: &[u8] = &[0x02, 0x01, 0x80];
45    pub(crate) const INEG129_BYTES: &[u8] = &[0x02, 0x02, 0xFF, 0x7F];
46
47    // Additional vectors
48    pub(crate) const I255_BYTES: &[u8] = &[0x02, 0x02, 0x00, 0xFF];
49    pub(crate) const I32767_BYTES: &[u8] = &[0x02, 0x02, 0x7F, 0xFF];
50    pub(crate) const I65535_BYTES: &[u8] = &[0x02, 0x03, 0x00, 0xFF, 0xFF];
51    pub(crate) const INEG32768_BYTES: &[u8] = &[0x02, 0x02, 0x80, 0x00];
52
53    #[test]
54    fn decode_i8() {
55        assert_eq!(0, i8::from_der(I0_BYTES).unwrap());
56        assert_eq!(127, i8::from_der(I127_BYTES).unwrap());
57        assert_eq!(-128, i8::from_der(INEG128_BYTES).unwrap());
58    }
59
60    #[test]
61    fn decode_i16() {
62        assert_eq!(0, i16::from_der(I0_BYTES).unwrap());
63        assert_eq!(127, i16::from_der(I127_BYTES).unwrap());
64        assert_eq!(128, i16::from_der(I128_BYTES).unwrap());
65        assert_eq!(255, i16::from_der(I255_BYTES).unwrap());
66        assert_eq!(256, i16::from_der(I256_BYTES).unwrap());
67        assert_eq!(32767, i16::from_der(I32767_BYTES).unwrap());
68        assert_eq!(-128, i16::from_der(INEG128_BYTES).unwrap());
69        assert_eq!(-129, i16::from_der(INEG129_BYTES).unwrap());
70        assert_eq!(-32768, i16::from_der(INEG32768_BYTES).unwrap());
71    }
72
73    #[test]
74    fn decode_u8() {
75        assert_eq!(0, u8::from_der(I0_BYTES).unwrap());
76        assert_eq!(127, u8::from_der(I127_BYTES).unwrap());
77        assert_eq!(255, u8::from_der(I255_BYTES).unwrap());
78    }
79
80    #[test]
81    fn decode_u16() {
82        assert_eq!(0, u16::from_der(I0_BYTES).unwrap());
83        assert_eq!(127, u16::from_der(I127_BYTES).unwrap());
84        assert_eq!(255, u16::from_der(I255_BYTES).unwrap());
85        assert_eq!(256, u16::from_der(I256_BYTES).unwrap());
86        assert_eq!(32767, u16::from_der(I32767_BYTES).unwrap());
87        assert_eq!(65535, u16::from_der(I65535_BYTES).unwrap());
88    }
89
90    #[test]
91    fn encode_i8() {
92        let mut buffer = [0u8; 3];
93
94        assert_eq!(I0_BYTES, 0i8.encode_to_slice(&mut buffer).unwrap());
95        assert_eq!(I127_BYTES, 127i8.encode_to_slice(&mut buffer).unwrap());
96
97        assert_eq!(
98            INEG128_BYTES,
99            (-128i8).encode_to_slice(&mut buffer).unwrap()
100        );
101    }
102
103    #[test]
104    fn encode_i16() {
105        let mut buffer = [0u8; 4];
106        assert_eq!(I0_BYTES, 0i16.encode_to_slice(&mut buffer).unwrap());
107        assert_eq!(I127_BYTES, 127i16.encode_to_slice(&mut buffer).unwrap());
108        assert_eq!(I128_BYTES, 128i16.encode_to_slice(&mut buffer).unwrap());
109        assert_eq!(I255_BYTES, 255i16.encode_to_slice(&mut buffer).unwrap());
110        assert_eq!(I256_BYTES, 256i16.encode_to_slice(&mut buffer).unwrap());
111        assert_eq!(I32767_BYTES, 32767i16.encode_to_slice(&mut buffer).unwrap());
112
113        assert_eq!(
114            INEG128_BYTES,
115            (-128i16).encode_to_slice(&mut buffer).unwrap()
116        );
117
118        assert_eq!(
119            INEG129_BYTES,
120            (-129i16).encode_to_slice(&mut buffer).unwrap()
121        );
122
123        assert_eq!(
124            INEG32768_BYTES,
125            (-32768i16).encode_to_slice(&mut buffer).unwrap()
126        );
127    }
128
129    #[test]
130    fn encode_u8() {
131        let mut buffer = [0u8; 4];
132        assert_eq!(I0_BYTES, 0u8.encode_to_slice(&mut buffer).unwrap());
133        assert_eq!(I127_BYTES, 127u8.encode_to_slice(&mut buffer).unwrap());
134        assert_eq!(I255_BYTES, 255u8.encode_to_slice(&mut buffer).unwrap());
135    }
136
137    #[test]
138    fn encode_u16() {
139        let mut buffer = [0u8; 5];
140        assert_eq!(I0_BYTES, 0u16.encode_to_slice(&mut buffer).unwrap());
141        assert_eq!(I127_BYTES, 127u16.encode_to_slice(&mut buffer).unwrap());
142        assert_eq!(I128_BYTES, 128u16.encode_to_slice(&mut buffer).unwrap());
143        assert_eq!(I255_BYTES, 255u16.encode_to_slice(&mut buffer).unwrap());
144        assert_eq!(I256_BYTES, 256u16.encode_to_slice(&mut buffer).unwrap());
145        assert_eq!(I32767_BYTES, 32767u16.encode_to_slice(&mut buffer).unwrap());
146        assert_eq!(I65535_BYTES, 65535u16.encode_to_slice(&mut buffer).unwrap());
147    }
148
149    /// Integers cannot be empty.
150    ///
151    /// From X.690 ยง 8.3.1: "The contents octets shall consist of one or more octets"
152    #[test]
153    fn reject_empty() {
154        const EMPTY_INT: &[u8] = &[0x02, 0x00];
155
156        let err = u8::from_der(EMPTY_INT).expect_err("empty INTEGER should return error");
157        assert_eq!(err.kind(), ErrorKind::Length { tag: Tag::Integer });
158
159        let err = i8::from_der(EMPTY_INT).expect_err("empty INTEGER should return error");
160        assert_eq!(err.kind(), ErrorKind::Length { tag: Tag::Integer });
161    }
162
163    /// Integers must be encoded with a minimum number of octets
164    #[test]
165    fn reject_non_canonical() {
166        assert!(i8::from_der(&[0x02, 0x02, 0x00, 0x00]).is_err());
167        assert!(i16::from_der(&[0x02, 0x02, 0x00, 0x00]).is_err());
168        assert!(u8::from_der(&[0x02, 0x02, 0x00, 0x00]).is_err());
169        assert!(u16::from_der(&[0x02, 0x02, 0x00, 0x00]).is_err());
170    }
171}