rusticata / x509-parser

X.509 parser written in pure Rust. Fast, zero-copy, safe.
Other
206 stars 67 forks source link

0.12 fails to verify ECDSA self-signed certificates where curve length is not equal to SHA length. #116

Closed thomas001 closed 2 years ago

thomas001 commented 2 years ago

I tried to verify the following certificate:

openssl x509 -in cert.der -inform der -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            45:03:e3:0c:f0:e7:f8:e6:76:11:d4:9c:8c:1e:21:62:21:42:7e:03
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: CN = syncthing-cloud
        Validity
            Not Before: Feb  6 22:26:28 2022 GMT
            Not After : Feb  1 22:26:28 2023 GMT
        Subject: CN = syncthing-cloud
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (384 bit)
                pub:
                    04:f7:fe:06:6c:38:bb:c6:fd:8a:05:76:8e:75:26:
                    46:a7:72:92:e8:0f:bb:c2:a8:85:b2:7e:db:39:81:
                    11:37:99:ae:bf:d6:ef:68:bc:97:3e:c8:42:b3:82:
                    59:12:46:4e:c5:e5:4c:c2:fd:94:e8:3d:9f:bf:d8:
                    2d:56:70:a3:b9:42:a3:ce:5d:40:eb:64:29:0b:1e:
                    f6:2d:a7:60:bc:ad:a4:b4:4d:47:71:bf:a7:f8:a3:
                    ea:54:3b:a1:46:f6:c0
                ASN1 OID: secp384r1
                NIST CURVE: P-384
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                66:56:82:FD:CE:EA:F2:84:F7:93:B4:C2:32:8C:38:CF:0A:E9:A8:66
            X509v3 Authority Key Identifier:
                keyid:66:56:82:FD:CE:EA:F2:84:F7:93:B4:C2:32:8C:38:CF:0A:E9:A8:66

            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: ecdsa-with-SHA256
         30:65:02:31:00:d2:3f:49:9e:84:2b:df:0c:dc:3a:b5:d4:0c:
         0c:2c:fb:fb:a8:cc:47:c9:35:18:f6:77:e6:27:19:3c:56:bc:
         38:56:b6:ed:06:fb:8b:32:f9:87:1d:b2:18:09:eb:a6:ed:02:
         30:55:1c:75:ba:68:0d:a1:2c:85:9e:00:1d:9a:d3:2b:41:e0:
         71:19:8f:17:4c:be:5e:df:bc:42:16:3b:cc:35:f2:00:f5:58:
         40:11:92:70:db:2e:5e:b9:4a:2b:ac:ee:2f

which is self signed (but I don't think that matters here). The interesting part is that it is using curve P-384 but hash algorithm SHA-256. This is even the OpenSSL default when creating a EC certificate. Yet, the certificate fails to signature check in a call to verify_signature. After setting the break point at https://github.com/rusticata/x509-parser/blob/x509-parser-0.12.0/src/certificate.rs#L142 I found that

142             let key = signature::UnparsedPublicKey::new(verification_alg, spki.subject_public_key.data);
(gdb) print verification_alg
$3 = &dyn ring::signature::VerificationAlgorithm {pointer: 0x7ff7db7454b0 <ring::ec::suite_b::ecdsa::verification::ECDSA_P256_SHA256_ASN1>, vtable: 0x7ff7db7031f8 <str+337048>}

which is not correct it should probably be ECDSA_P384_SHA256_ASN1. Due to the incorrect curve size the verification already fails when parsing the public key in ring.

This is the certificate: cert.zip

thomas001 commented 2 years ago

Thanks for fixing this so quickly!