-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Fix ASN.1 issues in PKCS#7 and S/MIME signing #10373
Conversation
Haven't re-reviewed the RFC, but we should add a test for this. |
2e5b1e2
to
67c1a60
Compare
2755b62
to
1f797f8
Compare
src/rust/src/pkcs7.rs
Outdated
if key_type == x509::sign::KeyType::Rsa && !has_pss_padding { | ||
Ok(common::AlgorithmIdentifier { | ||
oid: asn1::DefinedByMarker::marker(), | ||
params: common::AlgorithmParameters::Rsa(None), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
params: common::AlgorithmParameters::Rsa(None), | |
params: common::AlgorithmParameters::Rsa(Some(())), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/rust/src/pkcs7.rs
Outdated
rsa_padding: &'p pyo3::PyAny, | ||
) -> pyo3::PyResult<common::AlgorithmIdentifier<'static>> { | ||
let key_type = x509::sign::identify_key_type(py, private_key)?; | ||
let has_pss_padding = !rsa_padding.is_none() && rsa_padding.is_instance(types::PSS.get(py)?)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let has_pss_padding = !rsa_padding.is_none() && rsa_padding.is_instance(types::PSS.get(py)?)?; | |
let has_pss_padding = rsa_padding.is_instance(types::PSS.get(py)?)?; |
I don't think the is_none()
check is required? None isn't an instance of PSS :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I got that code from
cryptography/src/rust/src/x509/sign.rs
Lines 135 to 137 in 50ea0fa
// If this is RSA-PSS we need to compute the signature algorithm from the | |
// parameters provided in rsa_padding. | |
if !rsa_padding.is_none() && rsa_padding.is_instance(types::PSS.get(py)?)? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably that should be fixed, but no need to do it in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
The current implementation defines the SMIMECapabilities attribute so that its value is a SEQUENCE of all the algorithm OIDs that are supported. However, the S/MIME v3 spec (RFC 2633) specifies that each algorithm should be specified in its own SEQUENCE: SMIMECapabilities ::= SEQUENCE OF SMIMECapability SMIMECapability ::= SEQUENCE { capabilityID OBJECT IDENTIFIER, parameters ANY DEFINED BY capabilityID OPTIONAL } (RFC 2633, Appendix A) This commit changes the implementation so that each algorithm is inside its own SEQUENCE. This also matches the OpenSSL implementation.
The current implementation computes the algorithm identifier used in the `digest_encryption_algorithm` PKCS#7 field (or `SignatureAlgorithmIdentifier` in S/MIME) based on both the algorithm used to sign (e.g. RSA) and the digest algorithm (e.g. SHA512). This is correct for ECDSA signatures, where the OIDs used include the digest algorithm (e.g: ecdsa-with-SHA512). However, due to historical reasons, when signing with RSA the OID specified should be the one corresponding to just RSA ("1.2.840.113549.1.1.1" rsaEncryption), rather than OIDs which also include the digest algorithm (such as "1.2.840.113549.1.1.13", sha512WithRSAEncryption). This means that the logic to compute the algorithm identifier is the same except when signing with RSA, in which case the OID will always be `rsaEncryption`. This is consistent with the OpenSSL implementation, and the RFCs that define PKCS#7 and S/MIME. See RFC 3851 (section 2.2), and RFC 3370 (section 3.2) for more details.
1f797f8
to
99f6aba
Compare
@alex I also added an item to the CHANGELOG |
* Fix ASN.1 for S/MIME capabilities. The current implementation defines the SMIMECapabilities attribute so that its value is a SEQUENCE of all the algorithm OIDs that are supported. However, the S/MIME v3 spec (RFC 2633) specifies that each algorithm should be specified in its own SEQUENCE: SMIMECapabilities ::= SEQUENCE OF SMIMECapability SMIMECapability ::= SEQUENCE { capabilityID OBJECT IDENTIFIER, parameters ANY DEFINED BY capabilityID OPTIONAL } (RFC 2633, Appendix A) This commit changes the implementation so that each algorithm is inside its own SEQUENCE. This also matches the OpenSSL implementation. * Fix the RSA OID used for signing PKCS#7/SMIME The current implementation computes the algorithm identifier used in the `digest_encryption_algorithm` PKCS#7 field (or `SignatureAlgorithmIdentifier` in S/MIME) based on both the algorithm used to sign (e.g. RSA) and the digest algorithm (e.g. SHA512). This is correct for ECDSA signatures, where the OIDs used include the digest algorithm (e.g: ecdsa-with-SHA512). However, due to historical reasons, when signing with RSA the OID specified should be the one corresponding to just RSA ("1.2.840.113549.1.1.1" rsaEncryption), rather than OIDs which also include the digest algorithm (such as "1.2.840.113549.1.1.13", sha512WithRSAEncryption). This means that the logic to compute the algorithm identifier is the same except when signing with RSA, in which case the OID will always be `rsaEncryption`. This is consistent with the OpenSSL implementation, and the RFCs that define PKCS#7 and S/MIME. See RFC 3851 (section 2.2), and RFC 3370 (section 3.2) for more details. * Add tests for the changes in PKCS7 signing * PKCS7 fixes from code review * Update CHANGELOG
* Fix ASN.1 for S/MIME capabilities. The current implementation defines the SMIMECapabilities attribute so that its value is a SEQUENCE of all the algorithm OIDs that are supported. However, the S/MIME v3 spec (RFC 2633) specifies that each algorithm should be specified in its own SEQUENCE: SMIMECapabilities ::= SEQUENCE OF SMIMECapability SMIMECapability ::= SEQUENCE { capabilityID OBJECT IDENTIFIER, parameters ANY DEFINED BY capabilityID OPTIONAL } (RFC 2633, Appendix A) This commit changes the implementation so that each algorithm is inside its own SEQUENCE. This also matches the OpenSSL implementation. * Fix the RSA OID used for signing PKCS#7/SMIME The current implementation computes the algorithm identifier used in the `digest_encryption_algorithm` PKCS#7 field (or `SignatureAlgorithmIdentifier` in S/MIME) based on both the algorithm used to sign (e.g. RSA) and the digest algorithm (e.g. SHA512). This is correct for ECDSA signatures, where the OIDs used include the digest algorithm (e.g: ecdsa-with-SHA512). However, due to historical reasons, when signing with RSA the OID specified should be the one corresponding to just RSA ("1.2.840.113549.1.1.1" rsaEncryption), rather than OIDs which also include the digest algorithm (such as "1.2.840.113549.1.1.13", sha512WithRSAEncryption). This means that the logic to compute the algorithm identifier is the same except when signing with RSA, in which case the OID will always be `rsaEncryption`. This is consistent with the OpenSSL implementation, and the RFCs that define PKCS#7 and S/MIME. See RFC 3851 (section 2.2), and RFC 3370 (section 3.2) for more details. * Add tests for the changes in PKCS7 signing * PKCS7 fixes from code review * Update CHANGELOG Co-authored-by: Facundo Tuesca <[email protected]>
This PR fixes two issues with the ASN.1 generated when signing using PKCS#7:
First issue
The current implementation defines the SMIMECapabilities attribute so that its value is a SEQUENCE of all the algorithm OIDs that are supported. This is what the ASN.1 currently looks like for a signed message using
cryptography
:However, the S/MIME v3 spec (RFC 2633) specifies that each algorithm should be specified in its own SEQUENCE:
(RFC 2633, Appendix A)
The spec matches what OpenSSL outputs (using
openssl smime -sign
):This PR changes the implementation so that each algorithm is inside its own SEQUENCE. After the changes in this PR, the ASN.1 output looks like:
Second issue
There is an issue with the RSA OID used for signing PKCS#7/SMIME, in the
SignatureAlgorithmIdentifier
field.The current implementation computes the algorithm identifier used in the
digest_encryption_algorithm
PKCS#7 field(or
SignatureAlgorithmIdentifier
in S/MIME) based on both the algorithm used to sign (e.g. RSA) and the digest algorithm (e.g. SHA512).This is correct for ECDSA signatures, where the OIDs used include the digest algorithm (e.g:
ecdsa-with-SHA512
). However, due to historical reasons, when signing with RSA the OID specified should be the onecorresponding to just RSA (
"1.2.840.113549.1.1.1" rsaEncryption
), rather than OIDs which also include the digest algorithm (such as"1.2.840.113549.1.1.13" sha512WithRSAEncryption
).This means that the logic to compute the algorithm identifier is the same except when signing with RSA, in which case the OID will always be
rsaEncryption
. This is consistent with the OpenSSL implementation, and the RFCs that define PKCS#7 and S/MIME.See RFC 3851 (section 2.2), and RFC 3370 (section 3.2) for more details.