Skip to content

Commit 0c5789e

Browse files
committed
Negative test case for constructed, definite-length octet string
Ensure octet strings with constructed, definite-length method return an error, rather than an incorrect decoding.
1 parent 9ca99ba commit 0c5789e

File tree

24 files changed

+158
-75
lines changed

24 files changed

+158
-75
lines changed

der/src/asn1/any.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,7 @@ impl<'a> AnyRef<'a> {
5959

6060
/// Returns [`Tag`] and [`Length`] of self.
6161
pub fn header(&self) -> Header {
62-
Header {
63-
tag: self.tag,
64-
length: self.value.len(),
65-
}
62+
Header::new(self.tag, self.value.len())
6663
}
6764

6865
/// Attempt to decode this [`AnyRef`] type into the inner value.
@@ -131,7 +128,7 @@ impl<'a> DecodeValue<'a> for AnyRef<'a> {
131128

132129
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self, Error> {
133130
Ok(Self {
134-
tag: header.tag,
131+
tag: header.tag(),
135132
value: <&'a BytesRef>::decode_value(reader, header)?,
136133
})
137134
}
@@ -210,10 +207,7 @@ mod allocating {
210207

211208
/// Returns [`Tag`] and [`Length`] of self.
212209
pub fn header(&self) -> Header {
213-
Header {
214-
tag: self.tag,
215-
length: self.value.len(),
216-
}
210+
Header::new(self.tag, self.value.len())
217211
}
218212

219213
/// Attempt to decode this [`Any`] type into the inner value.
@@ -295,7 +289,7 @@ mod allocating {
295289

296290
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self, Error> {
297291
Ok(Self {
298-
tag: header.tag,
292+
tag: header.tag(),
299293
value: BytesOwned::decode_value(reader, header)?,
300294
})
301295
}

der/src/asn1/bit_string.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,7 @@ impl<'a> DecodeValue<'a> for BitStringRef<'a> {
139139
type Error = Error;
140140

141141
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
142-
let header = Header {
143-
tag: header.tag,
144-
length: (header.length - Length::ONE)?,
145-
};
142+
let header = header.copy_with_length((header.length() - Length::ONE)?);
146143

147144
let unused_bits = reader.read_byte()?;
148145
let inner = <&'a BytesRef>::decode_value(reader, header)?;
@@ -354,7 +351,7 @@ mod allocating {
354351
type Error = Error;
355352

356353
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
357-
let inner_len = (header.length - Length::ONE)?;
354+
let inner_len = (header.length() - Length::ONE)?;
358355
let unused_bits = reader.read_byte()?;
359356
let inner = reader.read_vec(inner_len)?;
360357
Self::new(unused_bits, inner)

der/src/asn1/bmp_string.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ impl<'a> DecodeValue<'a> for BmpString {
9393
type Error = Error;
9494

9595
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
96-
Self::from_ucs2(reader.read_vec(header.length)?)
96+
Self::from_ucs2(reader.read_vec(header.length())?)
9797
}
9898
}
9999

der/src/asn1/boolean.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ impl<'a> DecodeValue<'a> for bool {
1818
type Error = Error;
1919

2020
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
21-
if header.length != Length::ONE {
21+
if header.length() != Length::ONE {
2222
return Err(reader.error(ErrorKind::Length { tag: Self::TAG }));
2323
}
2424

der/src/asn1/generalized_time.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ impl<'a> DecodeValue<'a> for GeneralizedTime {
7878
type Error = Error;
7979

8080
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
81-
if Self::LENGTH != usize::try_from(header.length)? {
81+
if Self::LENGTH != usize::try_from(header.length())? {
8282
return Err(reader.error(Self::TAG.value_error()));
8383
}
8484

der/src/asn1/integer/int.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ macro_rules! impl_encoding_traits {
1818

1919
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> $crate::Result<Self> {
2020
let mut buf = [0u8; Self::BITS as usize / 8];
21-
let max_length = u32::from(header.length) as usize;
21+
let max_length = u32::from(header.length()) as usize;
2222

2323
if max_length == 0 {
2424
return Err(reader.error(Tag::Integer.length_error()));
@@ -39,7 +39,7 @@ macro_rules! impl_encoding_traits {
3939
};
4040

4141
// Ensure we compute the same encoded length as the original any value
42-
if header.length != result.value_len()? {
42+
if header.length() != result.value_len()? {
4343
return Err(reader.error(Self::TAG.non_canonical_error()));
4444
}
4545

@@ -143,7 +143,7 @@ impl<'a> DecodeValue<'a> for IntRef<'a> {
143143
let result = Self::new(bytes.as_slice())?;
144144

145145
// Ensure we compute the same encoded length as the original any value.
146-
if result.value_len()? != header.length {
146+
if result.value_len()? != header.length() {
147147
return Err(reader.error(Self::TAG.non_canonical_error()));
148148
}
149149

@@ -237,7 +237,7 @@ mod allocating {
237237
let result = Self::new(bytes.as_slice())?;
238238

239239
// Ensure we compute the same encoded length as the original any value.
240-
if result.value_len()? != header.length {
240+
if result.value_len()? != header.length() {
241241
return Err(reader.error(Self::TAG.non_canonical_error()));
242242
}
243243

der/src/asn1/integer/uint.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ macro_rules! impl_encoding_traits {
2222
const UNSIGNED_HEADROOM: usize = 1;
2323

2424
let mut buf = [0u8; (Self::BITS as usize / 8) + UNSIGNED_HEADROOM];
25-
let max_length = u32::from(header.length) as usize;
25+
let max_length = u32::from(header.length()) as usize;
2626

2727
if max_length == 0 {
2828
return Err(reader.error(Tag::Integer.length_error()));
@@ -36,7 +36,7 @@ macro_rules! impl_encoding_traits {
3636
let result = Self::from_be_bytes(decode_to_array(bytes)?);
3737

3838
// Ensure we compute the same encoded length as the original any value
39-
if header.length != result.value_len()? {
39+
if header.length() != result.value_len()? {
4040
return Err(reader.error(Self::TAG.non_canonical_error()));
4141
}
4242

@@ -126,7 +126,7 @@ impl<'a> DecodeValue<'a> for UintRef<'a> {
126126
let result = Self::new(decode_to_slice(bytes)?)?;
127127

128128
// Ensure we compute the same encoded length as the original any value.
129-
if result.value_len()? != header.length {
129+
if result.value_len()? != header.length() {
130130
return Err(reader.error(Self::TAG.non_canonical_error()));
131131
}
132132

@@ -221,7 +221,7 @@ mod allocating {
221221
let result = Self::new(decode_to_slice(bytes.as_slice())?)?;
222222

223223
// Ensure we compute the same encoded length as the original any value.
224-
if result.value_len()? != header.length {
224+
if result.value_len()? != header.length() {
225225
return Err(reader.error(Self::TAG.non_canonical_error()));
226226
}
227227

der/src/asn1/internal_macros.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,9 @@ macro_rules! impl_custom_class {
147147
let header = Header::decode(reader)?;
148148

149149
// the encoding shall be constructed if the base encoding is constructed
150-
if header.tag.is_constructed() != T::CONSTRUCTED
150+
if header.tag().is_constructed() != T::CONSTRUCTED
151151
&& reader.encoding_rules() == EncodingRules::Der {
152-
return Err(reader.error(header.tag.non_canonical_error()).into());
152+
return Err(reader.error(header.tag().non_canonical_error()).into());
153153
}
154154

155155
// read_value checks if header matches decoded length
@@ -183,10 +183,10 @@ macro_rules! impl_custom_class {
183183
let header = Header::decode(reader)?;
184184

185185
// encoding shall be constructed
186-
if !header.tag.is_constructed() {
187-
return Err(reader.error(header.tag.non_canonical_error()).into());
186+
if !header.tag().is_constructed() {
187+
return Err(reader.error(header.tag().non_canonical_error()).into());
188188
}
189-
match header.tag {
189+
match header.tag() {
190190
Tag::$class_enum_name { number, .. } => Ok(Self {
191191
tag_number: number,
192192
tag_mode: TagMode::default(),

der/src/asn1/null.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ impl<'a> DecodeValue<'a> for Null {
1515
type Error = Error;
1616

1717
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
18-
if header.length.is_zero() {
18+
if header.length().is_zero() {
1919
Ok(Null)
2020
} else {
2121
Err(reader.error(ErrorKind::Length { tag: Self::TAG }))

der/src/asn1/octet_string.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,25 @@ mod tests {
375375

376376
#[test]
377377
#[cfg(feature = "alloc")]
378-
fn decode_ber() {
378+
fn decode_ber_primitive_definite() {
379+
use crate::{Decode, asn1::OctetString};
380+
use hex_literal::hex;
381+
382+
const EXAMPLE: &[u8] = &hex!(
383+
"040c" // primitive definite length OCTET STRING
384+
"48656c6c6f2c20776f726c64" // "Hello, world"
385+
);
386+
387+
let decoded = OctetString::from_ber(EXAMPLE).unwrap();
388+
assert_eq!(decoded.as_bytes(), b"Hello, world");
389+
390+
let decoded = OctetString::from_der(EXAMPLE).unwrap();
391+
assert_eq!(decoded.as_bytes(), b"Hello, world");
392+
}
393+
394+
#[test]
395+
#[cfg(feature = "alloc")]
396+
fn decode_ber_constructed_indefinite() {
379397
use crate::{Decode, asn1::OctetString};
380398
use hex_literal::hex;
381399

@@ -390,6 +408,28 @@ mod tests {
390408
assert_eq!(decoded.as_bytes(), b"Hello, world");
391409
}
392410

411+
#[test]
412+
#[cfg(feature = "alloc")]
413+
fn decode_ber_constructed_definite() {
414+
use crate::{Decode, Error, ErrorKind, Length, Tag, asn1::OctetString};
415+
use hex_literal::hex;
416+
417+
const EXAMPLE_BER: &[u8] = &hex!(
418+
"2410" // Constructed definite length OCTET STRING
419+
"040648656c6c6f2c" // Segment containing "Hello,"
420+
"040620776f726c64" // Segment containing " world"
421+
);
422+
423+
let err = OctetString::from_ber(EXAMPLE_BER).err().unwrap();
424+
let expected = Error::new(
425+
ErrorKind::Noncanonical {
426+
tag: Tag::OctetString,
427+
},
428+
Length::new(1),
429+
);
430+
assert_eq!(expected, err);
431+
}
432+
393433
#[test]
394434
#[cfg(feature = "alloc")]
395435
fn decode_context_specific_ber_explicit() {

0 commit comments

Comments
 (0)