Skip to main content

der/asn1/
integer.rs

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