//! Support for encoding signed integers use super::{is_highest_bit_set, uint, value_cmp}; use crate::{ ord::OrdIsValueOrd, AnyRef, BytesRef, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, ValueOrd, Writer, }; use core::cmp::Ordering; #[cfg(feature = "alloc")] pub use allocating::Int; macro_rules! impl_encoding_traits { ($($int:ty => $uint:ty),+) => { $( impl<'a> DecodeValue<'a> for $int { fn decode_value>(reader: &mut R, header: Header) -> Result { let mut buf = [0u8; Self::BITS as usize / 8]; let max_length = u32::from(header.length) as usize; if max_length > buf.len() { return Err(Self::TAG.non_canonical_error()); } let bytes = reader.read_into(&mut buf[..max_length])?; let result = if is_highest_bit_set(bytes) { <$uint>::from_be_bytes(decode_to_array(bytes)?) as $int } else { Self::from_be_bytes(uint::decode_to_array(bytes)?) }; // Ensure we compute the same encoded length as the original any value if header.length != result.value_len()? { return Err(Self::TAG.non_canonical_error()); } Ok(result) } } impl EncodeValue for $int { fn value_len(&self) -> Result { if *self < 0 { negative_encoded_len(&(*self as $uint).to_be_bytes()) } else { uint::encoded_len(&self.to_be_bytes()) } } fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { if *self < 0 { encode_bytes(writer, &(*self as $uint).to_be_bytes()) } else { uint::encode_bytes(writer, &self.to_be_bytes()) } } } impl FixedTag for $int { const TAG: Tag = Tag::Integer; } impl ValueOrd for $int { fn value_cmp(&self, other: &Self) -> Result { value_cmp(*self, *other) } } impl TryFrom> for $int { type Error = Error; fn try_from(any: AnyRef<'_>) -> Result { any.decode_as() } } )+ }; } impl_encoding_traits!(i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128); /// Signed arbitrary precision ASN.1 `INTEGER` reference type. /// /// Provides direct access to the underlying big endian bytes which comprise /// an signed integer value. /// /// Intended for use cases like very large integers that are used in /// cryptographic applications (e.g. keys, signatures). #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct IntRef<'a> { /// Inner value inner: BytesRef<'a>, } impl<'a> IntRef<'a> { /// Create a new [`IntRef`] from a byte slice. pub fn new(bytes: &'a [u8]) -> Result { let inner = BytesRef::new(strip_leading_ones(bytes)) .map_err(|_| ErrorKind::Length { tag: Self::TAG })?; Ok(Self { inner }) } /// Borrow the inner byte slice which contains the least significant bytes /// of a big endian integer value with all leading ones stripped. pub fn as_bytes(&self) -> &'a [u8] { self.inner.as_slice() } /// Get the length of this [`IntRef`] in bytes. pub fn len(&self) -> Length { self.inner.len() } /// Is the inner byte slice empty? pub fn is_empty(&self) -> bool { self.inner.is_empty() } } impl_any_conversions!(IntRef<'a>, 'a); impl<'a> DecodeValue<'a> for IntRef<'a> { fn decode_value>(reader: &mut R, header: Header) -> Result { let bytes = BytesRef::decode_value(reader, header)?; validate_canonical(bytes.as_slice())?; let result = Self::new(bytes.as_slice())?; // Ensure we compute the same encoded length as the original any value. if result.value_len()? != header.length { return Err(Self::TAG.non_canonical_error()); } Ok(result) } } impl<'a> EncodeValue for IntRef<'a> { fn value_len(&self) -> Result { // Signed integers always hold their full encoded form. Ok(self.inner.len()) } fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { writer.write(self.as_bytes()) } } impl<'a> From<&IntRef<'a>> for IntRef<'a> { fn from(value: &IntRef<'a>) -> IntRef<'a> { *value } } impl<'a> FixedTag for IntRef<'a> { const TAG: Tag = Tag::Integer; } impl<'a> OrdIsValueOrd for IntRef<'a> {} #[cfg(feature = "alloc")] mod allocating { use super::{strip_leading_ones, validate_canonical, IntRef}; use crate::{ asn1::Uint, ord::OrdIsValueOrd, referenced::{OwnedToRef, RefToOwned}, BytesOwned, DecodeValue, EncodeValue, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, Writer, }; use alloc::vec::Vec; /// Signed arbitrary precision ASN.1 `INTEGER` type. /// /// Provides heap-allocated storage for big endian bytes which comprise an /// signed integer value. /// /// Intended for use cases like very large integers that are used in /// cryptographic applications (e.g. keys, signatures). #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Int { /// Inner value inner: BytesOwned, } impl Int { /// Create a new [`Int`] from a byte slice. pub fn new(bytes: &[u8]) -> Result { let inner = BytesOwned::new(strip_leading_ones(bytes)) .map_err(|_| ErrorKind::Length { tag: Self::TAG })?; Ok(Self { inner }) } /// Borrow the inner byte slice which contains the least significant bytes /// of a big endian integer value with all leading ones stripped. pub fn as_bytes(&self) -> &[u8] { self.inner.as_slice() } /// Get the length of this [`Int`] in bytes. pub fn len(&self) -> Length { self.inner.len() } /// Is the inner byte slice empty? pub fn is_empty(&self) -> bool { self.inner.is_empty() } } impl_any_conversions!(Int); impl<'a> DecodeValue<'a> for Int { fn decode_value>(reader: &mut R, header: Header) -> Result { let bytes = BytesOwned::decode_value(reader, header)?; validate_canonical(bytes.as_slice())?; let result = Self::new(bytes.as_slice())?; // Ensure we compute the same encoded length as the original any value. if result.value_len()? != header.length { return Err(Self::TAG.non_canonical_error()); } Ok(result) } } impl EncodeValue for Int { fn value_len(&self) -> Result { // Signed integers always hold their full encoded form. Ok(self.inner.len()) } fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { writer.write(self.as_bytes()) } } impl<'a> From<&IntRef<'a>> for Int { fn from(value: &IntRef<'a>) -> Int { let inner = BytesOwned::new(value.as_bytes()).expect("Invalid Int"); Int { inner } } } impl From for Int { fn from(value: Uint) -> Self { let mut inner: Vec = Vec::new(); // Add leading `0x00` byte if required if value.value_len().expect("invalid Uint") > value.len() { inner.push(0x00); } inner.extend_from_slice(value.as_bytes()); let inner = BytesOwned::new(inner).expect("invalid Uint"); Int { inner } } } impl FixedTag for Int { const TAG: Tag = Tag::Integer; } impl OrdIsValueOrd for Int {} impl<'a> RefToOwned<'a> for IntRef<'a> { type Owned = Int; fn ref_to_owned(&self) -> Self::Owned { let inner = self.inner.ref_to_owned(); Int { inner } } } impl OwnedToRef for Int { type Borrowed<'a> = IntRef<'a>; fn owned_to_ref(&self) -> Self::Borrowed<'_> { let inner = self.inner.owned_to_ref(); IntRef { inner } } } } /// Ensure `INTEGER` is canonically encoded. fn validate_canonical(bytes: &[u8]) -> Result<()> { // The `INTEGER` type always encodes a signed value and we're decoding // as signed here, so we allow a zero extension or sign extension byte, // but only as permitted under DER canonicalization. match bytes { [] => Err(Tag::Integer.non_canonical_error()), [0x00, byte, ..] if *byte < 0x80 => Err(Tag::Integer.non_canonical_error()), [0xFF, byte, ..] if *byte >= 0x80 => Err(Tag::Integer.non_canonical_error()), _ => Ok(()), } } /// Decode an signed integer of the specified size. /// /// Returns a byte array of the requested size containing a big endian integer. fn decode_to_array(bytes: &[u8]) -> Result<[u8; N]> { match N.checked_sub(bytes.len()) { Some(offset) => { let mut output = [0xFFu8; N]; output[offset..].copy_from_slice(bytes); Ok(output) } None => { let expected_len = Length::try_from(N)?; let actual_len = Length::try_from(bytes.len())?; Err(ErrorKind::Incomplete { expected_len, actual_len, } .into()) } } } /// Encode the given big endian bytes representing an integer as ASN.1 DER. fn encode_bytes(writer: &mut W, bytes: &[u8]) -> Result<()> where W: Writer + ?Sized, { writer.write(strip_leading_ones(bytes)) } /// Get the encoded length for the given **negative** integer serialized as bytes. #[inline] fn negative_encoded_len(bytes: &[u8]) -> Result { Length::try_from(strip_leading_ones(bytes).len()) } /// Strip the leading all-ones bytes from the given byte slice. pub(crate) fn strip_leading_ones(mut bytes: &[u8]) -> &[u8] { while let Some((byte, rest)) = bytes.split_first() { if *byte == 0xFF && is_highest_bit_set(rest) { bytes = rest; continue; } break; } bytes } #[cfg(test)] mod tests { use super::{validate_canonical, IntRef}; use crate::{asn1::integer::tests::*, Decode, Encode, SliceWriter}; #[test] fn validate_canonical_ok() { assert_eq!(validate_canonical(&[0x00]), Ok(())); assert_eq!(validate_canonical(&[0x01]), Ok(())); assert_eq!(validate_canonical(&[0x00, 0x80]), Ok(())); assert_eq!(validate_canonical(&[0xFF, 0x00]), Ok(())); } #[test] fn validate_canonical_err() { // Empty integers are always non-canonical. assert!(validate_canonical(&[]).is_err()); // Positives with excessive zero extension are non-canonical. assert!(validate_canonical(&[0x00, 0x00]).is_err()); // Negatives with excessive sign extension are non-canonical. assert!(validate_canonical(&[0xFF, 0x80]).is_err()); } #[test] fn decode_intref() { // Positive numbers decode, but have zero extensions as necessary // (to distinguish them from negative representations). assert_eq!(&[0], IntRef::from_der(I0_BYTES).unwrap().as_bytes()); assert_eq!(&[127], IntRef::from_der(I127_BYTES).unwrap().as_bytes()); assert_eq!(&[0, 128], IntRef::from_der(I128_BYTES).unwrap().as_bytes()); assert_eq!(&[0, 255], IntRef::from_der(I255_BYTES).unwrap().as_bytes()); assert_eq!( &[0x01, 0x00], IntRef::from_der(I256_BYTES).unwrap().as_bytes() ); assert_eq!( &[0x7F, 0xFF], IntRef::from_der(I32767_BYTES).unwrap().as_bytes() ); // Negative integers decode. assert_eq!(&[128], IntRef::from_der(INEG128_BYTES).unwrap().as_bytes()); assert_eq!( &[255, 127], IntRef::from_der(INEG129_BYTES).unwrap().as_bytes() ); assert_eq!( &[128, 0], IntRef::from_der(INEG32768_BYTES).unwrap().as_bytes() ); } #[test] fn encode_intref() { for &example in &[ I0_BYTES, I127_BYTES, I128_BYTES, I255_BYTES, I256_BYTES, I32767_BYTES, ] { let uint = IntRef::from_der(example).unwrap(); let mut buf = [0u8; 128]; let mut encoder = SliceWriter::new(&mut buf); uint.encode(&mut encoder).unwrap(); let result = encoder.finish().unwrap(); assert_eq!(example, result); } for &example in &[INEG128_BYTES, INEG129_BYTES, INEG32768_BYTES] { let uint = IntRef::from_der(example).unwrap(); let mut buf = [0u8; 128]; let mut encoder = SliceWriter::new(&mut buf); uint.encode(&mut encoder).unwrap(); let result = encoder.finish().unwrap(); assert_eq!(example, result); } } }