rustls / webpki

WebPKI X.509 Certificate Validation in Rust
https://docs.rs/rustls-webpki/latest/webpki/
Other
94 stars 50 forks source link

Support non-CABF approved curve/digest combinations #267

Closed samin-cf closed 2 months ago

samin-cf commented 3 months ago

There appears to be a (potential) issue with the way a server certificate is verified against a root CA. Based on my testing, the signed_data.rs::verify_signed_data function fails if the signature algorithm of the server certificate is not the same as the signature algorithm of the CA.

I have created a minimal example to illustrate the problem: https://github.com/samin-cf/webpki-cert-test. The CA used in the example is signed with ecdsa-with-SHA512 algorithm. There are three server certificates, each signed by that same CA and have different signature algorithms (sha256 vs sha384 vs sha512). When the example is run, the following is printed:

Server certificate signed with ecdsa-with-sha256 failed to be verified: UnsupportedSignatureAlgorithmForPublicKey
Server certificate signed with ecdsa-with-sha384 failed to be verified: UnsupportedSignatureAlgorithmForPublicKey
Server certificate signed with ecdsa-with-sha512 verified successfully

For comparison, OpenSSL is able to successfully verify all three certificates against the CA.

Is this expected?

ctz commented 3 months ago

Hi, thanks for the report. The current combinations of ECDSA curve and hash algorithm supported are:

Curve Hash
P256 SHA256
P256 SHA384
P384 SHA256
P384 SHA384
P521 SHA512 aws-lc-rs only

This test case demands P521 and SHA256/SHA384.

samin-cf commented 3 months ago

Thanks for the response. It looks like this is essentially the same limitation that https://github.com/rustls/rustls/pull/1924 addresses.

samin-cf commented 3 months ago

I guess this will require both webpki and aws-lc-rs to support P521 with SHA256/SHA384. @ctz Are you aware of any active issues tracking the effort for this? I wasn't able to find any.

ctz commented 3 months ago

Not to my knowledge. I think that means this one is it!

I think the first step would be to send a PR to aws-lc-rs and see how amenable they are to it & what testing they would like to see.

cpu commented 3 months ago

Not to my knowledge. I think that means this one is it!

I've updated the title to better reflect the feature request. As noted in my comment here the combinations being requested aren't approved by the CA/BF server cert profile. That isn't a vote against implementation from me, just a note that I think should help colour prioritization.

samin-cf commented 3 months ago

Thanks for the reply!

The CA I am using is signed with ecdsa-with-SHA512, and the private key used to sign the CA uses P-521. That seems to meet the requirement outlined in 7.1.3.2.2.

If the server certificate is signed with something other than the P-521/SHA512 combination (say P-256/SHA256), is that still considered non-CABF approved? In other words, does CABF not allow a P-256/SHA256 server cert to be successfully verified by a P-521/SHA512 CA?

cpu commented 2 months ago

Sorry for the late reply, I had missed your follow-up!

The CA I am using is signed with ecdsa-with-SHA512, and the private key used to sign the CA uses P-521. That seems to meet the requirement outlined in 7.1.3.2.2.

Agreed :+1: The issue is with the end entity cert's signature algorithm.

If the server certificate is signed with something other than the P-521/SHA512 combination (say P-256/SHA256), is that still considered non-CABF approved?

It isn't a requirement that the intermediate's signing key be the same algorithm as the server certificate's public key. For example, Let's Encrypt didn't have an ECDSA intermediate or root for some time (e.g. see this announcement post from when that changed). However, they did allow ECDSA subscriber certificates to be issued prior to that date (since ~2016) that were signed by the existing RSA hierarchy.

The requirement here (as I understand it) is that if you use a P-521 issuer to sign a P-256 end entity certificate the signature MUST use ECDSA with SHA-512. It doesn't matter that the end entity cert is a P-256 cert, it's the signing key that dictates the required signature alg.

This is where your example in https://github.com/samin-cf/webpki-cert-test goes off the beaten path, the server_sha256.crt has a signature algorithm of ecdsa-with-sha256 but the private key for the ca.crt is P-521. My understanding is that if this server_sha256.crt cert were issued by a trusted CA in the web pki it would prompt a miss-issuance event & revocation.