-
Notifications
You must be signed in to change notification settings - Fork 132
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
der: preservation of order in sets during reencode #1386
Comments
In DER,
However, the schema uses It seems the problem is the |
I’m not sure what you are getting at with SET vs SET OF but the case here is SET OF in any case:
SignedAttributes ::= SET SIZE (1..MAX) OF Attribute
The CMS RFC is very clear on this: “SignedAttributes MUST be DER encoded, even if the rest of the structure is BER encoded.”
The problem is that the generator signed a BER encoding and the verifier is using a DER encoding for verification (with the length field is what establishes the ordering here). The comment in the OpenSSL codebase describes the hack they used to work around this (i.e., they are re-encoding the elements as a SEQUENCE then changing the tag to be SET at verification time). Something like that would likely work here too (depending on if the order returned from the decoder is as received, which I am not certain of offhand).
Where I’ve run into stuff like this, I’ve used the defer decoding capability to avoid the need to re-encode entirely. That likely would work here but would require variants of SignedData, SignerInfos and SignerInfo to reference the defer decoding. There is an example that uses defer decoding in the x509_cert crate test cases: https://github.com/RustCrypto/formats/blob/1cb066a80b361e1b5cd3bafd1e84217d7a352cf6/x509-cert/tests/certificate.rs#L62. A somewhat less contrived example is here (to defer decoding the TBSCertificate field of a Certificate): https://github.com/carl-wallace/rust-pki/blob/2dbd11e1fd6f21079e700ce60ee3ec27856a1b02/certval/src/validator/pdv_certificate.rs#L237. Then use the original structures when generating and the structures that support defer decoding when verifying.
From: Tony Arcieri ***@***.***>
Reply-To: RustCrypto/formats ***@***.***>
Date: Friday, April 19, 2024 at 8:50 AM
To: RustCrypto/formats ***@***.***>
Cc: Carl Wallace ***@***.***>, Mention ***@***.***>
Subject: Re: [RustCrypto/formats] [Question] Preservation of order in sets during reencode (Issue #1386)
In DER, SET OF requires an ordered encoding. From ITU X.690:
11.6 Set-of components
The encodings of the component values of a set-of value shall appear in ascending order, the encodings being compared as octet strings with the shorter components being padded at their trailing end with 0-octets.
However, the schema uses SET, not SET OF.
It seems the problem is the cms crate is using the der::SetOf* types to model SET (rather than SET OF) which does not stipulate a sorted encoding.
cc @carl-wallace
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
Aah, my bad, that is a really wacky hack on OpenSSL's part. |
Thank you. I'll try to look into the deferred decoding as having access to the original data would most probably solve the problem. The only thing that I see as a difference is that original data starts as And btw, the encoded data is not under my control and I have no idea how it was created. It's taken from real, in the wild, examples so it's not like it's just something I purposefully created but it seems like there are encoders with these issues out there. |
The tag difference is due to IMPLICIT tagging. I forgot about that in my reply. The Rust code I have for verifying SignedData is just reencoding SignedAttributes (but I control both sides in that case). I looked back at some C code that was more generic and it defer decodes then fixes the tag.
There’s probably not much else to be done. Either re-encode in order preserving way (as OpenSSL did) and change the tag from SEQUENCE to SET or defer decode and change the tag from the IMPLICIT[0] to SET.
From: Marek Milkovič ***@***.***>
Reply-To: RustCrypto/formats ***@***.***>
Date: Friday, April 19, 2024 at 10:54 AM
To: RustCrypto/formats ***@***.***>
Cc: Carl Wallace ***@***.***>, Mention ***@***.***>
Subject: Re: [RustCrypto/formats] [Question] Preservation of order in sets during reencode (Issue #1386)
Thank you. I'll try to look into the deferred decoding as having access to the original data would most probably solve the problem. The only thing that I see as a difference is that original data starts as a081... while OpenSSL gives me 3181... but I guess that has to do with the BER encoding. I'll just have to read through the standards to actually know the exact difference. This helped me a lot.
And btw, the encoded data is not under my control and I have no idea how it was created. It's taken real, in the wild, examples so it's not like it's just something I purposefully created but it seems like there are encoder with these issues out there.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
We now have We could potentially add BER encoding support which doesn't eagerly sort the fields. |
Hi. Recently I ran into this PKCS7/CMS structure which contains what seems like non-canonical signed/authenticated attributes. It was failing signature verification in Rust code and after closer look, it seems like reencode of the signed/authenticated attributes returns a different DER encoding than OpenSSL for example. This results in different digest being calculated and even though everything is correctly verified, the hashes won't match.
Here's the PKCS7:
Code used to extract the signed attributes from this on the Rust side:
Here's what I get from your crate:
Here's what I get from OpenSSL:
Here's the base64 encoded DER of what OpenSSL gives me (considering I use
PKCS7_ATTR_VERIFY
, see below for more info):Seems to be related to ordering of sets in the canonical form which is mentioned in your codebase and also OpenSSL with their
PKCS7_ATTR_VERIFY
which was specially created for this purpose.I am just considering what are my options here because if the sets are ordered during decode, then I won't really get back the original order. So the very first question would be whether it's even somehow possible to use this crate for my use-case? If not, would you be interested in maybe supporting also non-canonical form? I'm not sure what it entails all together other than ordering, but I wouldn't have problem contributing to this if it helped me to obtain exactly what I want. Thanks!
The text was updated successfully, but these errors were encountered: