Skip to content

der: read_nested: check header length matches contents of IMPLICIT #1739

New issue

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

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

Already on GitHub? # to your account

Merged
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
14 changes: 12 additions & 2 deletions der/src/asn1/context_specific.rs
Original file line number Diff line number Diff line change
@@ -63,8 +63,14 @@ impl<T> ContextSpecific<T> {
T: DecodeValue<'a> + Tagged,
{
Self::decode_with::<_, _, T::Error>(reader, tag_number, |reader| {
// Decode IMPLICIT header
let header = Header::decode(reader)?;
let value = T::decode_value(reader, header)?;

// read_nested checks if header matches decoded length
let value = reader.read_nested(header.length, |reader| {
// Decode inner IMPLICIT value
T::decode_value(reader, header)
})?;

if header.tag.is_constructed() != value.tag().is_constructed() {
return Err(header.tag.non_canonical_error().into());
@@ -119,6 +125,7 @@ where
type Error = T::Error;

fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Self, Self::Error> {
// Decode EXPLICIT header
let header = Header::decode(reader)?;

match header.tag {
@@ -128,7 +135,10 @@ where
} => Ok(Self {
tag_number: number,
tag_mode: TagMode::default(),
value: reader.read_nested(header.length, |reader| T::decode(reader))?,
value: reader.read_nested(header.length, |reader| {
// Decode inner tag-length-value of EXPLICIT
T::decode(reader)
})?,
}),
tag => Err(tag.unexpected_error(None).into()),
}
16 changes: 12 additions & 4 deletions x509-cert/tests/pkix_extensions.rs
Original file line number Diff line number Diff line change
@@ -843,8 +843,6 @@ fn decode_cert() {

#[test]
fn decode_idp() {
use der::TagNumber;

// IDP from 04A8739769B3C090A11DCDFABA3CF33F4BEF21F3.crl in PKITS 2048 in ficam-scvp-testing repo
let idp = IssuingDistributionPoint::from_der(&hex!("30038201FF")).unwrap();
assert_eq!(idp.only_contains_ca_certs, true);
@@ -1112,7 +1110,11 @@ fn decode_idp() {
panic!("Expected FullName")
}
}
}

#[test]
fn decode_idp_negative() {
use der::TagNumber;
//---------------------------------
// Negative tests
//---------------------------------
@@ -1143,7 +1145,7 @@ fn decode_idp() {
"3067A060A05EA45C305A310B3009060355040613025553311F301D060355040A131654657374204365727469666963617465732032303137311C301A060355040B13136F6E6C79536F6D65526561736F6E7320434133310C300A0603550403130343524C8304079F80"
));
let err = idp.err().unwrap();
assert_eq!(err.position().unwrap(), 103u8.into());
assert_eq!(err.position().unwrap(), 105u8.into());
assert_eq!(
ErrorKind::Incomplete {
expected_len: 106u8.into(),
@@ -1197,7 +1199,13 @@ fn decode_idp() {
"30820168A0820161A082015DA4753073310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353129302706035504031320696E6469726563742043524C20666F7220696E64697265637443524C20434136A4753073310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353129302706035504031320696E6469726563742043524C20666F7220696E64697265637443524C20434137A46D306B310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353121301F0603550403131843524C3120666F7220696E64697265637443524C204341358402FFFF"
));
let err = idp.err().unwrap();
assert_eq!(ErrorKind::Length { tag: Tag::Boolean }, err.kind());
assert_eq!(
ErrorKind::Incomplete {
expected_len: Length::new(365),
actual_len: Length::new(364)
},
err.kind()
);

// Boolean value is neither 0x00 nor 0xFF
let idp = IssuingDistributionPoint::from_der(&hex!(