Skip to content

der: remove 256 MiB limit on Length #1726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 17, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 18 additions & 34 deletions der/src/length.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ use core::{
ops::{Add, Sub},
};

/// Maximum length as a `u32` (256 MiB).
const MAX_U32: u32 = 0xfff_ffff;

/// Octet identifying an indefinite length as described in X.690 Section
/// 8.1.3.6.1:
///
Expand All @@ -18,8 +15,6 @@ const MAX_U32: u32 = 0xfff_ffff;
const INDEFINITE_LENGTH_OCTET: u8 = 0b10000000; // 0x80

/// ASN.1-encoded length.
///
/// Maximum length is defined by the [`Length::MAX`] constant (256 MiB).
#[derive(Copy, Clone, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct Length(u32);

Expand All @@ -30,8 +25,8 @@ impl Length {
/// Length of `1`
pub const ONE: Self = Self(1);

/// Maximum length currently supported: 256 MiB
pub const MAX: Self = Self(MAX_U32);
/// Maximum length (`u32::MAX`).
pub const MAX: Self = Self(u32::MAX);

/// Maximum number of octets in a DER encoding of a [`Length`] using the
/// rules implemented by this crate.
Expand Down Expand Up @@ -94,7 +89,7 @@ impl Length {
0x80..=0xFF => Some(0x81),
0x100..=0xFFFF => Some(0x82),
0x10000..=0xFFFFFF => Some(0x83),
0x1000000..=MAX_U32 => Some(0x84),
0x1000000..=0xFFFFFFFF => Some(0x84),
_ => None,
}
}
Expand All @@ -107,7 +102,7 @@ impl Add for Length {
self.0
.checked_add(other.0)
.ok_or_else(|| ErrorKind::Overflow.into())
.and_then(TryInto::try_into)
.map(Self)
}
}

Expand All @@ -131,7 +126,7 @@ impl Add<u32> for Length {
type Output = Result<Self>;

fn add(self, other: u32) -> Result<Self> {
self + Length::try_from(other)?
self + Length::from(other)
}
}

Expand All @@ -158,7 +153,7 @@ impl Sub for Length {
self.0
.checked_sub(other.0)
.ok_or_else(|| ErrorKind::Overflow.into())
.and_then(TryInto::try_into)
.map(Self)
}
}

Expand All @@ -182,21 +177,15 @@ impl From<u16> for Length {
}
}

impl From<Length> for u32 {
fn from(length: Length) -> u32 {
length.0
impl From<u32> for Length {
fn from(len: u32) -> Length {
Length(len)
}
}

impl TryFrom<u32> for Length {
type Error = Error;

fn try_from(len: u32) -> Result<Length> {
if len <= Self::MAX.0 {
Ok(Length(len))
} else {
Err(ErrorKind::Overflow.into())
}
impl From<Length> for u32 {
fn from(length: Length) -> u32 {
length.0
}
}

Expand Down Expand Up @@ -236,7 +225,7 @@ impl<'a> Decode<'a> for Length {
| u32::from(reader.read_byte()?);
}

let length = Length::try_from(decoded_len)?;
let length = Length::from(decoded_len);

// X.690 Section 10.1: DER lengths must be encoded with a minimum
// number of octets
Expand All @@ -261,8 +250,7 @@ impl Encode for Length {
0x80..=0xFF => Ok(Length(2)),
0x100..=0xFFFF => Ok(Length(3)),
0x10000..=0xFFFFFF => Ok(Length(4)),
0x1000000..=MAX_U32 => Ok(Length(5)),
_ => Err(ErrorKind::Overflow.into()),
0x1000000..=0xFFFFFFFF => Ok(Length(5)),
}
}

Expand Down Expand Up @@ -311,7 +299,7 @@ impl fmt::Display for Length {
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for Length {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Self(u.int_in_range(0..=MAX_U32)?))
Ok(Self(u.arbitrary()?))
}

fn size_hint(depth: usize) -> (usize, Option<usize>) {
Expand Down Expand Up @@ -454,7 +442,7 @@ mod tests {
);

assert_eq!(
Length::try_from(0x10000u32).unwrap(),
Length::from(0x10000u32),
Length::from_der(&[0x83, 0x01, 0x00, 0x00]).unwrap()
);
}
Expand Down Expand Up @@ -487,8 +475,7 @@ mod tests {

assert_eq!(
&[0x83, 0x01, 0x00, 0x00],
Length::try_from(0x10000u32)
.unwrap()
Length::from(0x10000u32)
.encode_to_slice(&mut buffer)
.unwrap()
);
Expand All @@ -507,10 +494,7 @@ mod tests {
// It also supports definite lengths.
let length = IndefiniteLength::from_der(&[0x83, 0x01, 0x00, 0x00]).unwrap();
assert!(length.is_definite());
assert_eq!(
Length::try_from(0x10000u32).unwrap(),
length.try_into().unwrap()
);
assert_eq!(Length::from(0x10000u32), length.try_into().unwrap());
}

#[test]
Expand Down