1use crate::*;
2use alloc::borrow::Cow;
3use alloc::vec;
4use core::convert::{TryFrom, TryInto};
5
6#[cfg(feature = "bigint")]
7#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
8pub use num_bigint::{BigInt, BigUint, Sign};
9
10fn trim_slice<'a>(any: &'a Any<'_>) -> Result<&'a [u8]> {
13 let bytes = any.data;
14
15 if bytes.is_empty() || (bytes[0] != 0x00 && bytes[0] != 0xff) {
16 return Ok(bytes);
17 }
18
19 match bytes.iter().position(|&b| b != 0) {
20 Some(0) => (),
22 None => return Ok(&bytes[bytes.len() - 1..]),
24 Some(first) => return Ok(&bytes[first..]),
25 }
26
27 match bytes.windows(2).position(|s| match s {
29 &[a, b] => !(a == 0xff && b >= 0x80),
30 _ => true,
31 }) {
32 Some(0) => (),
34 None => return Ok(&bytes[bytes.len() - 1..]),
36 Some(first) => return Ok(&bytes[first..]),
37 }
38
39 Ok(bytes)
40}
41
42fn decode_array_uint<const N: usize>(any: &Any<'_>) -> Result<[u8; N]> {
45 if is_highest_bit_set(any.data) {
46 return Err(Error::IntegerNegative);
47 }
48 let input = trim_slice(any)?;
49
50 if input.len() > N {
51 return Err(Error::IntegerTooLarge);
52 }
53
54 let mut output = [0u8; N];
56 assert!(input.len() <= N);
57 output[N.saturating_sub(input.len())..].copy_from_slice(input);
58 Ok(output)
59}
60
61fn decode_array_int<const N: usize>(any: &Any<'_>) -> Result<[u8; N]> {
65 if any.data.len() > N {
66 return Err(Error::IntegerTooLarge);
67 }
68
69 let mut output = [0xFFu8; N];
71 let offset = N.saturating_sub(any.as_bytes().len());
72 output[offset..].copy_from_slice(any.as_bytes());
73 Ok(output)
74}
75
76#[inline]
78fn is_highest_bit_set(bytes: &[u8]) -> bool {
79 bytes
80 .first()
81 .map(|byte| byte & 0b10000000 != 0)
82 .unwrap_or(false)
83}
84
85macro_rules! impl_int {
86 ($uint:ty => $int:ty) => {
87 impl<'a> TryFrom<Any<'a>> for $int {
88 type Error = Error;
89
90 fn try_from(any: Any<'a>) -> Result<Self> {
91 TryFrom::try_from(&any)
92 }
93 }
94
95 impl<'a, 'b> TryFrom<&'b Any<'a>> for $int {
96 type Error = Error;
97
98 fn try_from(any: &'b Any<'a>) -> Result<Self> {
99 $crate::debug::trace_generic(
100 core::any::type_name::<$int>(),
101 "Conversion to int",
102 |any| {
103 any.tag().assert_eq(Self::TAG)?;
104 any.header.assert_primitive()?;
105 let uint = if is_highest_bit_set(any.as_bytes()) {
106 <$uint>::from_be_bytes(decode_array_int(&any)?)
107 } else {
108 let u = <$uint>::from_be_bytes(decode_array_uint(&any)?);
110 if u > <$int>::MAX as $uint {
111 return Err(Error::IntegerTooLarge);
112 }
113 u
114 };
115 Ok(uint as $int)
116 },
117 any,
118 )
119 }
120 }
121
122 impl CheckDerConstraints for $int {
123 fn check_constraints(any: &Any) -> Result<()> {
124 check_der_int_constraints(any)
125 }
126 }
127
128 impl DerAutoDerive for $int {}
129
130 impl Tagged for $int {
131 const TAG: Tag = Tag::Integer;
132 }
133
134 #[cfg(feature = "std")]
135 impl ToDer for $int {
136 fn to_der_len(&self) -> Result<usize> {
137 let int = Integer::from(*self);
138 int.to_der_len()
139 }
140
141 fn write_der(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
142 let int = Integer::from(*self);
143 int.write_der(writer)
144 }
145
146 fn write_der_header(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
147 let int = Integer::from(*self);
148 int.write_der_header(writer)
149 }
150
151 fn write_der_content(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
152 let int = Integer::from(*self);
153 int.write_der_content(writer)
154 }
155 }
156 };
157}
158
159macro_rules! impl_uint {
160 ($ty:ty) => {
161 impl<'a> TryFrom<Any<'a>> for $ty {
162 type Error = Error;
163
164 fn try_from(any: Any<'a>) -> Result<Self> {
165 TryFrom::try_from(&any)
166 }
167 }
168 impl<'a, 'b> TryFrom<&'b Any<'a>> for $ty {
169 type Error = Error;
170
171 fn try_from(any: &'b Any<'a>) -> Result<Self> {
172 $crate::debug::trace_generic(
173 core::any::type_name::<$ty>(),
174 "Conversion to uint",
175 |any| {
176 any.tag().assert_eq(Self::TAG)?;
177 any.header.assert_primitive()?;
178 let result = Self::from_be_bytes(decode_array_uint(any)?);
179 Ok(result)
180 },
181 any,
182 )
183 }
184 }
185 impl CheckDerConstraints for $ty {
186 fn check_constraints(any: &Any) -> Result<()> {
187 check_der_int_constraints(any)
188 }
189 }
190
191 impl DerAutoDerive for $ty {}
192
193 impl Tagged for $ty {
194 const TAG: Tag = Tag::Integer;
195 }
196
197 #[cfg(feature = "std")]
198 impl ToDer for $ty {
199 fn to_der_len(&self) -> Result<usize> {
200 let int = Integer::from(*self);
201 int.to_der_len()
202 }
203
204 fn write_der(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
205 let int = Integer::from(*self);
206 int.write_der(writer)
207 }
208
209 fn write_der_header(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
210 let int = Integer::from(*self);
211 int.write_der_header(writer)
212 }
213
214 fn write_der_content(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
215 let int = Integer::from(*self);
216 int.write_der_content(writer)
217 }
218 }
219 };
220}
221
222impl_uint!(u8);
223impl_uint!(u16);
224impl_uint!(u32);
225impl_uint!(u64);
226impl_uint!(u128);
227impl_int!(u8 => i8);
228impl_int!(u16 => i16);
229impl_int!(u32 => i32);
230impl_int!(u64 => i64);
231impl_int!(u128 => i128);
232
233#[derive(Debug, Eq, PartialEq)]
291pub struct Integer<'a> {
292 pub(crate) data: Cow<'a, [u8]>,
293}
294
295impl<'a> Integer<'a> {
296 #[inline]
298 pub const fn new(s: &'a [u8]) -> Self {
299 Integer {
300 data: Cow::Borrowed(s),
301 }
302 }
303
304 #[inline]
306 pub fn any(&'a self) -> Any<'a> {
307 Any::from_tag_and_data(Self::TAG, &self.data)
308 }
309
310 #[cfg(feature = "bigint")]
312 #[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
313 pub fn as_bigint(&self) -> BigInt {
314 BigInt::from_signed_bytes_be(&self.data)
315 }
316
317 #[cfg(feature = "bigint")]
319 #[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
320 pub fn as_biguint(&self) -> Result<BigUint> {
321 if is_highest_bit_set(&self.data) {
322 Err(Error::IntegerNegative)
323 } else {
324 Ok(BigUint::from_bytes_be(&self.data))
325 }
326 }
327
328 pub fn from_const_array<const N: usize>(b: [u8; N]) -> Self {
330 if is_highest_bit_set(&b) {
332 let mut bytes = vec![0];
333 bytes.extend_from_slice(&b);
334
335 Integer {
336 data: Cow::Owned(bytes),
337 }
338 }
339 else {
341 let mut idx = 0;
342
343 while idx < b.len() - 1 {
344 if b[idx] == 0 && b[idx + 1] < 0x80 {
345 idx += 1;
346 continue;
347 }
348 break;
349 }
350
351 Integer {
352 data: Cow::Owned(b[idx..].to_vec()),
353 }
354 }
355 }
356
357 fn from_const_array_negative<const N: usize>(b: [u8; N]) -> Self {
358 let mut idx = 0;
359
360 while idx < b.len() - 1 {
362 if b[idx] == 0xFF && b[idx + 1] >= 0x80 {
363 idx += 1;
364 continue;
365 }
366 break;
367 }
368
369 if idx == b.len() {
370 Integer {
371 data: Cow::Borrowed(&[0]),
372 }
373 } else {
374 Integer {
375 data: Cow::Owned(b[idx..].to_vec()),
376 }
377 }
378 }
379}
380
381macro_rules! impl_from_to {
382 ($ty:ty, $sty:expr, $from:ident, $to:ident) => {
383 impl From<$ty> for Integer<'_> {
384 fn from(i: $ty) -> Self {
385 Self::$from(i)
386 }
387 }
388
389 impl TryFrom<Integer<'_>> for $ty {
390 type Error = Error;
391
392 fn try_from(value: Integer<'_>) -> Result<Self> {
393 value.$to()
394 }
395 }
396
397 impl Integer<'_> {
398 #[doc = "Attempts to convert an `Integer` to a `"]
399 #[doc = $sty]
400 #[doc = "`."]
401 #[doc = ""]
402 #[doc = "This function returns an `IntegerTooLarge` error if the integer will not fit into the output type."]
403 pub fn $to(&self) -> Result<$ty> {
404 self.any().try_into()
405 }
406 }
407 };
408 (IMPL SIGNED $ty:ty, $sty:expr, $from:ident, $to:ident) => {
409 impl_from_to!($ty, $sty, $from, $to);
410
411 impl Integer<'_> {
412 #[doc = "Converts a `"]
413 #[doc = $sty]
414 #[doc = "` to an `Integer`"]
415 #[doc = ""]
416 #[doc = "Note: this function allocates data."]
417 pub fn $from(i: $ty) -> Self {
418 let b = i.to_be_bytes();
419 if i >= 0 {
420 Self::from_const_array(b)
421 } else {
422 Self::from_const_array_negative(b)
423 }
424 }
425 }
426 };
427 (IMPL UNSIGNED $ty:ty, $sty:expr, $from:ident, $to:ident) => {
428 impl_from_to!($ty, $sty, $from, $to);
429
430 impl Integer<'_> {
431 #[doc = "Converts a `"]
432 #[doc = $sty]
433 #[doc = "` to an `Integer`"]
434 #[doc = ""]
435 #[doc = "Note: this function allocates data."]
436 pub fn $from(i: $ty) -> Self {
437 Self::from_const_array(i.to_be_bytes())
438 }
439 }
440 };
441 (SIGNED $ty:ty, $from:ident, $to:ident) => {
442 impl_from_to!(IMPL SIGNED $ty, stringify!($ty), $from, $to);
443 };
444 (UNSIGNED $ty:ty, $from:ident, $to:ident) => {
445 impl_from_to!(IMPL UNSIGNED $ty, stringify!($ty), $from, $to);
446 };
447}
448
449impl_from_to!(SIGNED i8, from_i8, as_i8);
450impl_from_to!(SIGNED i16, from_i16, as_i16);
451impl_from_to!(SIGNED i32, from_i32, as_i32);
452impl_from_to!(SIGNED i64, from_i64, as_i64);
453impl_from_to!(SIGNED i128, from_i128, as_i128);
454
455impl_from_to!(UNSIGNED u8, from_u8, as_u8);
456impl_from_to!(UNSIGNED u16, from_u16, as_u16);
457impl_from_to!(UNSIGNED u32, from_u32, as_u32);
458impl_from_to!(UNSIGNED u64, from_u64, as_u64);
459impl_from_to!(UNSIGNED u128, from_u128, as_u128);
460
461impl<'a> AsRef<[u8]> for Integer<'a> {
462 fn as_ref(&self) -> &[u8] {
463 &self.data
464 }
465}
466
467impl<'a> TryFrom<Any<'a>> for Integer<'a> {
468 type Error = Error;
469
470 fn try_from(any: Any<'a>) -> Result<Integer<'a>> {
471 TryFrom::try_from(&any)
472 }
473}
474
475impl<'a, 'b> TryFrom<&'b Any<'a>> for Integer<'a> {
476 type Error = Error;
477
478 fn try_from(any: &'b Any<'a>) -> Result<Integer<'a>> {
479 any.tag().assert_eq(Self::TAG)?;
480 Ok(Integer {
481 data: Cow::Borrowed(any.data),
482 })
483 }
484}
485
486impl<'a> CheckDerConstraints for Integer<'a> {
487 fn check_constraints(any: &Any) -> Result<()> {
488 check_der_int_constraints(any)
489 }
490}
491
492fn check_der_int_constraints(any: &Any) -> Result<()> {
493 any.header.assert_primitive()?;
494 any.header.length.assert_definite()?;
495 match any.as_bytes() {
496 [] => Err(Error::DerConstraintFailed(DerConstraint::IntegerEmpty)),
497 [0] => Ok(()),
498 [0, byte, ..] if *byte < 0x80 => Err(Error::DerConstraintFailed(
500 DerConstraint::IntegerLeadingZeroes,
501 )),
502 [0xff, byte, ..] if *byte >= 0x80 => {
504 Err(Error::DerConstraintFailed(DerConstraint::IntegerLeadingFF))
505 }
506 _ => Ok(()),
507 }
508}
509
510impl DerAutoDerive for Integer<'_> {}
511
512impl<'a> Tagged for Integer<'a> {
513 const TAG: Tag = Tag::Integer;
514}
515
516#[cfg(feature = "std")]
517impl ToDer for Integer<'_> {
518 fn to_der_len(&self) -> Result<usize> {
519 let sz = self.data.len();
520 if sz < 127 {
521 Ok(2 + sz)
523 } else {
524 let n = Length::Definite(sz).to_der_len()?;
527 Ok(1 + n + sz)
528 }
529 }
530
531 fn write_der_header(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
532 let header = Header::new(
533 Class::Universal,
534 false,
535 Self::TAG,
536 Length::Definite(self.data.len()),
537 );
538 header.write_der_header(writer).map_err(Into::into)
539 }
540
541 fn write_der_content(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
542 writer.write(&self.data).map_err(Into::into)
543 }
544}
545
546#[macro_export]
565macro_rules! int {
566 (raw $item:expr) => {
567 $crate::exports::asn1_rs_impl::encode_int!($item)
568 };
569 (rel $item:expr) => {
570 $crate::exports::asn1_rs_impl::encode_int!(rel $item)
571 };
572 ($item:expr) => {
573 $crate::Integer::new(
574 &$crate::int!(raw $item),
575 )
576 };
577}
578
579#[cfg(test)]
580mod tests {
581 use crate::{Any, FromDer, Header, Tag, ToDer};
582 use std::convert::TryInto;
583
584 pub(crate) const I0_BYTES: &[u8] = &[0x02, 0x01, 0x00];
587 pub(crate) const I127_BYTES: &[u8] = &[0x02, 0x01, 0x7F];
588 pub(crate) const I128_BYTES: &[u8] = &[0x02, 0x02, 0x00, 0x80];
589 pub(crate) const I256_BYTES: &[u8] = &[0x02, 0x02, 0x01, 0x00];
590 pub(crate) const INEG128_BYTES: &[u8] = &[0x02, 0x01, 0x80];
591 pub(crate) const INEG129_BYTES: &[u8] = &[0x02, 0x02, 0xFF, 0x7F];
592
593 pub(crate) const I255_BYTES: &[u8] = &[0x02, 0x02, 0x00, 0xFF];
595 pub(crate) const I32767_BYTES: &[u8] = &[0x02, 0x02, 0x7F, 0xFF];
596 pub(crate) const I65535_BYTES: &[u8] = &[0x02, 0x03, 0x00, 0xFF, 0xFF];
597 pub(crate) const INEG32768_BYTES: &[u8] = &[0x02, 0x02, 0x80, 0x00];
598
599 #[test]
600 fn decode_i8() {
601 assert_eq!(0, i8::from_der(I0_BYTES).unwrap().1);
602 assert_eq!(127, i8::from_der(I127_BYTES).unwrap().1);
603 assert_eq!(-128, i8::from_der(INEG128_BYTES).unwrap().1);
604 }
605
606 #[test]
607 fn encode_i8() {
608 assert_eq!(0i8.to_der_vec().unwrap(), I0_BYTES);
609 assert_eq!(127i8.to_der_vec().unwrap(), I127_BYTES);
610 assert_eq!((-128i8).to_der_vec().unwrap(), INEG128_BYTES);
611 }
612
613 #[test]
614 fn decode_i16() {
615 assert_eq!(0, i16::from_der(I0_BYTES).unwrap().1);
616 assert_eq!(127, i16::from_der(I127_BYTES).unwrap().1);
617 assert_eq!(128, i16::from_der(I128_BYTES).unwrap().1);
618 assert_eq!(255, i16::from_der(I255_BYTES).unwrap().1);
619 assert_eq!(256, i16::from_der(I256_BYTES).unwrap().1);
620 assert_eq!(32767, i16::from_der(I32767_BYTES).unwrap().1);
621 assert_eq!(-128, i16::from_der(INEG128_BYTES).unwrap().1);
622 assert_eq!(-129, i16::from_der(INEG129_BYTES).unwrap().1);
623 assert_eq!(-32768, i16::from_der(INEG32768_BYTES).unwrap().1);
624 }
625
626 #[test]
627 fn encode_i16() {
628 assert_eq!(0i16.to_der_vec().unwrap(), I0_BYTES);
629 assert_eq!(127i16.to_der_vec().unwrap(), I127_BYTES);
630 assert_eq!(128i16.to_der_vec().unwrap(), I128_BYTES);
631 assert_eq!(255i16.to_der_vec().unwrap(), I255_BYTES);
632 assert_eq!(256i16.to_der_vec().unwrap(), I256_BYTES);
633 assert_eq!(32767i16.to_der_vec().unwrap(), I32767_BYTES);
634 assert_eq!((-128i16).to_der_vec().unwrap(), INEG128_BYTES);
635 assert_eq!((-129i16).to_der_vec().unwrap(), INEG129_BYTES);
636 assert_eq!((-32768i16).to_der_vec().unwrap(), INEG32768_BYTES);
637 }
638
639 #[test]
640 fn decode_u8() {
641 assert_eq!(0, u8::from_der(I0_BYTES).unwrap().1);
642 assert_eq!(127, u8::from_der(I127_BYTES).unwrap().1);
643 assert_eq!(255, u8::from_der(I255_BYTES).unwrap().1);
644 }
645
646 #[test]
647 fn encode_u8() {
648 assert_eq!(0u8.to_der_vec().unwrap(), I0_BYTES);
649 assert_eq!(127u8.to_der_vec().unwrap(), I127_BYTES);
650 assert_eq!(255u8.to_der_vec().unwrap(), I255_BYTES);
651 }
652
653 #[test]
654 fn decode_u16() {
655 assert_eq!(0, u16::from_der(I0_BYTES).unwrap().1);
656 assert_eq!(127, u16::from_der(I127_BYTES).unwrap().1);
657 assert_eq!(255, u16::from_der(I255_BYTES).unwrap().1);
658 assert_eq!(256, u16::from_der(I256_BYTES).unwrap().1);
659 assert_eq!(32767, u16::from_der(I32767_BYTES).unwrap().1);
660 assert_eq!(65535, u16::from_der(I65535_BYTES).unwrap().1);
661 }
662
663 #[test]
664 fn encode_u16() {
665 assert_eq!(0u16.to_der_vec().unwrap(), I0_BYTES);
666 assert_eq!(127u16.to_der_vec().unwrap(), I127_BYTES);
667 assert_eq!(255u16.to_der_vec().unwrap(), I255_BYTES);
668 assert_eq!(256u16.to_der_vec().unwrap(), I256_BYTES);
669 assert_eq!(32767u16.to_der_vec().unwrap(), I32767_BYTES);
670 assert_eq!(65535u16.to_der_vec().unwrap(), I65535_BYTES);
671 }
672
673 #[test]
675 fn reject_non_canonical() {
676 assert!(i8::from_der(&[0x02, 0x02, 0x00, 0x00]).is_err());
677 assert!(i16::from_der(&[0x02, 0x02, 0x00, 0x00]).is_err());
678 assert!(u8::from_der(&[0x02, 0x02, 0x00, 0x00]).is_err());
679 assert!(u16::from_der(&[0x02, 0x02, 0x00, 0x00]).is_err());
680 }
681
682 #[test]
683 fn declare_int() {
684 let int = super::int!(1234);
685 assert_eq!(int.try_into(), Ok(1234));
686 }
687
688 #[test]
689 fn trim_slice() {
690 use super::trim_slice;
691 let h = Header::new_simple(Tag(0));
692 let input: &[u8] = &[0x7f, 0xff, 0x00, 0x02];
694 assert_eq!(Ok(input), trim_slice(&Any::new(h.clone(), input)));
695 let input: &[u8] = &[];
700 assert_eq!(Ok(input), trim_slice(&Any::new(h.clone(), input)));
701 let input: &[u8] = &[0];
703 assert_eq!(Ok(input), trim_slice(&Any::new(h.clone(), input)));
704 let input: &[u8] = &[0, 0, 0];
706 assert_eq!(Ok(&input[2..]), trim_slice(&Any::new(h.clone(), input)));
707 let input: &[u8] = &[0, 0, 1];
709 assert_eq!(Ok(&input[2..]), trim_slice(&Any::new(h.clone(), input)));
710 let input: &[u8] = &[0xff];
715 assert_eq!(Ok(input), trim_slice(&Any::new(h.clone(), input)));
716 let input: &[u8] = &[0xff, 0xff, 0xff];
718 assert_eq!(Ok(&input[2..]), trim_slice(&Any::new(h.clone(), input)));
719 let input: &[u8] = &[0xff, 0xff, 1];
721 assert_eq!(Ok(&input[1..]), trim_slice(&Any::new(h.clone(), input)));
722 let input: &[u8] = &[0xff, 0xff, 0x80, 1];
724 assert_eq!(Ok(&input[2..]), trim_slice(&Any::new(h.clone(), input)));
725 }
726}