Online CRL verification fails if the ca_dir contains multiple CAs with the same subject
lamawithonel opened this issue · 2 comments
Overview
After setting this up for U.S. Government PIV card authentication, I found a problem: everything fails when online CRL checks are enabled. I traced the problem to how CRLs are validated when using a CA hash_dir. Basically, if multiple CAs exist with the same subject
, the CRL signature is only checked against the first one (index 0). The others are read, but ignored.
I think this has something to do with how the EVP_PKEY
is fetched in verify_crl()
, but I'm not entirely sure. It could also be a shortcoming in the OpenSSL API, because the same bug exists in the openssl crl
utility (source link).
Steps to repeat
- Configure pam_pkcs11 to use the OpenSC
pkcs11_module
, make sure thecert_policy
includesca_online
, and thatca_dir
is a directory. - Create two CAs with the same
subject
and a CRL distribution point. The CRL distribution point can be unique to each. I will call these CA1 and CA2. For greater realism, you could also create a common root CA, but that shouldn't matter. - Create an empty CRL for CA2 and make it available via the CRL distribution point. I'm not sure if
file:///
URLs are supported as distribution points, but if not you may need an HTTP server. - Use CA2 to sign a certificate on a test card.
- Place the public certificates for both CA1 and CA2 into the
ca_dir
and executepkcs11_make_hash_dir
. The hashes generated for each of the CAs should be identical, so the links should be likehash.0
andhash.1
. - With the test card inserted, execute
pkcs11_inspect
.
Expected behavior
Knowing that the certificate is valid for a trusted CA, and that it is NOT revoked, it should verify as OK and output the fingerprint.
Actual behavior
Assuming hash.0
points to CA1 and hash.1
points to CA2, you should see something like this with debug=true
:
DEBUG:pkcs11_inspect.c:132: verifing the certificate #1
DEBUG:cert_vfy.c:338: Adding hashdir lookup to x509_store
DEBUG:cert_vfy.c:350: Adding hash dir '/etc/pam_pkcs11/cacerts' to CACERT checks
DEBUG:cert_vfy.c:450: certificate is valid
DEBUG:cert_vfy.c:207: crl policy: 3
DEBUG:cert_vfy.c:207: crl policy: 1
DEBUG:cert_vfy.c:232: extracting crl distribution points
DEBUG:cert_vfy.c:256: downloading crl from http://example.org/CRL2.crl
DEBUG:uri.c:593: parsing uri:
DEBUG:uri.c:255: protocol = [http]
DEBUG:uri.c:256: user = [(null)]
DEBUG:uri.c:257: password = [(null)]
DEBUG:uri.c:258: host = [example.org]
DEBUG:uri.c:259: port = [(null)]
DEBUG:uri.c:260: path = [/CRL2.crl]
DEBUG:uri.c:395: connecting...
DEBUG:uri.c:420: receiving...
DEBUG:uri.c:451: decoding...
DEBUG:cert_vfy.c:130: crl is der encoded
DEBUG:cert_vfy.c:281: verifying crl
DEBUG:cert_vfy.c:165: crl is invalid
DEBUG:cert_vfy.c:462: certificate has been revoked
ERROR:pkcs11_inspect.c:142: verify_certificate() failed:
If you manually rearrange the CA hash links so hash.0
points to CA2 and hash.1
points to CA1, it should succeed. Likewise, if you set ca_dir
to point directly at CA2, it should succeed.
Versions affected
I've tested this using 0.6.7-1 on Ubuntu 12.04, but I'm fairly confident it's still a problem on newer versions. The code I believe to be responsible has not changed since 2005 (0.5.2?).
Thanks for the bug report.
Can you propose a patch?