-
Notifications
You must be signed in to change notification settings - Fork 29
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
handle context-specific tag incorrect #38
Comments
I'm not sure if this function should process if hdr.class is DerClass::ContextSpecific fn der_read_element_content_recursive<'a>(
i: &'a [u8],
hdr: DerObjectHeader<'a>,
max_depth: usize,
) -> DerResult<'a> {
match hdr.class {
DerClass::Universal | DerClass::Private => (),
_ => {
let (i, content) = ber_get_object_content(i, &hdr, max_depth)?;
let content = DerObjectContent::Unknown(hdr.tag, content);
let obj = DerObject::from_header_and_content(hdr, content);
return Ok((i, obj));
}
}
match der_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), max_depth) {
Ok((rem, content)) => Ok((rem, DerObject::from_header_and_content(hdr, content))),
Err(Err::Error(BerError::UnknownTag)) => {
let (rem, content) = ber_get_object_content(i, &hdr, max_depth)?;
let content = DerObjectContent::Unknown(hdr.tag, content);
let obj = DerObject::from_header_and_content(hdr, content);
Ok((rem, obj))
}
Err(e) => Err(e),
}
} |
Hmm, The usual method with What are you trying to do? Maybe I can help if you give more details |
@chifflier FWIW I am encountering a similar issue. In my case, I am attempting to parse a CMS (RFC 5652) data structure, specifically the signed and unsigned attributes types, where the structure of the data is not assigned within the RFC that I'm parsing. I've observed that a context-specific |
@cuserdzy don't know if you're still facing this issue (or someone else may come along who does have a similar issue), but you can reparse the data blobs. The following code snippet could probably use some cleaning up, but it will reparse into such structures recursively: fn reparse_unknown_o<'a>(o: BerObject<'a>) -> BerResult<'a> {
// Workaround for https://github.com/rusticata/der-parser/issues/38.
let new_o = match o.content {
BerObjectContent::Sequence(v) => {
let (_, new_v) = reparse_unknown_v(v)?;
BerObject::from_header_and_content(o.header, BerObjectContent::Sequence(new_v))
}
BerObjectContent::Set(v) => {
let (_, new_v) = reparse_unknown_v(v)?;
BerObject::from_header_and_content(o.header, BerObjectContent::Set(new_v))
}
BerObjectContent::Optional(Some(boxed_obj)) => {
let (_, new_o) = reparse_unknown_o(*boxed_obj)?;
BerObject::from_header_and_content(
o.header,
BerObjectContent::Optional(Some(Box::new(new_o))),
)
}
BerObjectContent::Tagged(class, tag, boxed_obj) => {
let (_, new_o) = reparse_unknown_o(*boxed_obj)?;
BerObject::from_header_and_content(
o.header,
BerObjectContent::Tagged(class, tag, Box::new(new_o)),
)
}
BerObjectContent::Unknown(_tag, data) => {
if o.header.class == BerClass::ContextSpecific && o.header.structured == 1 {
// Tagged entries may contain multiple objects. The BerObjectContent enum
// doesn't have a way to represent this directly, so we wrap this in an
// implicit sequence.
let mut objs: Vec<BerObject<'a>> = Vec::new();
let mut i = data;
while !i.is_empty() {
let (i2, obj) = parse_der(i)?;
let (_, obj) = reparse_unknown_o(obj)?;
objs.push(obj);
i = i2;
}
BerObject::from_header_and_content(o.header, BerObjectContent::Sequence(objs))
} else {
o
}
}
_ => o,
};
Ok((&[], new_o))
}
fn reparse_unknown_v<'a>(v: Vec<BerObject<'a>>) -> BerResult<Vec<BerObject<'a>>> {
let new_v: Result<Vec<BerObject<'a>>, nom::Err<BerError>> = v
.into_iter()
.map(|o| match reparse_unknown_o(o) {
Ok((_i, new_o)) => Ok(new_o),
Err(e) => Err(e),
})
.collect();
match new_v {
Ok(v) => Ok((&[], v)),
Err(e) => Err(e),
}
} |
I would add to the problem that I also share the same Unknown content for CMS data. And it get worse, as in X.509 ber sequence, with extra information (extension). PKCS#7/CMS data contains a nested list of certificate X.509, which also has a Why don't we support 0xA0 tag? It is in the specs anyway. https://stackoverflow.com/a/43056617/13173256 P.S: the binary for my data is the signature blob in Mach-O (Apple binary) for signed binary. So I would expect the binary data is correctly encoded. P.S 2: BER encoding, but DER also share the same |
Hi, Note: I have a crate (not yet published, but the code is mostly ready) to decode most PKCS formats, including PKCS#7 and CMS (the crate does not perform cryptographic operations). I intended to publish it later, but if you are interested I can push it to github. |
FWIW I am unsubscribing as I no longer have the need for CMS parsing. |
I would love to see the crate published. But I don't insist pushing something to the public when you're not feeling it. Having a good parser for most certificate standards is very useful. Thank you. Just a guessing, I think you use serialization to make the decodable/codable (cryptographic standard) structs. Because manually parsing is more error-prone than serializing. And while serialization is experimental, it would be too early to publish code using the feature. |
The initial problem is now fixed ( |
I have a signed data encoded by DER, but get strange output while parse
The input
The output
As show above, I think 0xA0 is not a unknown tag and the tag number should not be parsed as EOC, this is a context-specific tag.
The text was updated successfully, but these errors were encountered: