Project

General

Profile

Actions

Bug #9889

closed

Cannot validate Certificates against Certificate Revocation Lists for Intermediate Certificate Authorities

Added by Jim Pingle about 5 years ago. Updated about 1 year ago.

Status:
Resolved
Priority:
Very Low
Assignee:
Category:
Certificates
Target version:
Start date:
11/08/2019
Due date:
% Done:

100%

Estimated time:
Plus Target Version:
23.09
Release Notes:
Affected Version:
All
Affected Architecture:
All

Description

Adding this for tracking, but I don't think it's a bug in pfSense or FreeBSD, but OpenSSL itself. It could potentially be a flaw in the testing methods/setup, if someone sees a problem, definitely give suggestions for other things to try.

There have been a couple reports that CRLs fail to validate against intermediate certificates, primarily in OpenVPN. This appears to be a legitimate problem, but none of the workarounds I have tried seems to help. There are reports that using the ca and crlfile directives in OpenVPN will fail for this, but using capath with a proper setup helps. However, that also fails for me. Both in OpenVPN and directly with OpenSSL commands.

Walking through the process:

I setup a root CA, an intermediate CA signed by the root, and a user certificate issued by both. I made a CRL for the root and the intermediate, and revoked entries on both. I exported this structure to my workstation (Mint using OpenSSL 1.1.1) and I tried the same test with identical results on FreeBSD 12 and pfSense 2.5.0 snapshots.

First, check the issuers and subjects. It's all as expected:

$ openssl x509 -issuer -subject -noout -in CR.crt
issuer=CN = chain-root-ca
subject=CN = chain-root-ca
$ openssl x509 -issuer -subject -noout -in CI.crt
issuer=CN = chain-root-ca
subject=CN = chain-intermediate-ca
$ openssl x509 -issuer -subject -noout -in rootverifytest.crt
issuer=CN = chain-root-ca
subject=CN = rootverifytest
$ openssl x509 -issuer -subject -noout -in jimp.crt
issuer=CN = chain-intermediate-ca
subject=CN = jimp

Next check the CRLs. Note they have the correct issuer and validate OK on their own.

$ openssl crl -issuer -noout -in CR.crl
issuer=CN = chain-root-ca
$ openssl crl -issuer -noout -in CI.crl
issuer=CN = chain-intermediate-ca
$ openssl crl -CAfile CR.crt -noout -in CR.crl
verify OK
$ openssl crl -CAfile CI.crt -noout -in CI.crl
verify OK

Next, CApath requires files named after the hash of the CA. <cahash>.<n> for the CA and <cahash>.r<n> for CRLs. So let's check the hash and then setup some symlinks. I've also tried this using c_rehash on Linux and received the same results. Same as well with copied or renamed files.

$ openssl x509 -hash -noout -in CR.crt
485491b5
$ openssl crl -hash -noout -in CR.crl
485491b5
$ openssl x509 -hash -noout -in CI.crt
39ba1131
$ openssl crl -hash -noout -in CI.crl
39ba1131
$ ln -s CR.crt 485491b5.0
$ ln -s CR.crl 485491b5.r0
$ ln -s CI.crt 39ba1131.0
$ ln -s CI.crl 39ba1131.r0

Now let's test the CApath setup to validate the CRLs. They both validate OK.

$ openssl crl -CApath . -noout -in CR.crl
verify OK
$ openssl crl -CApath . -noout -in CI.crl
verify OK

Manually double check the certificate serials and confirm they are revoked in the CRL text:

$ openssl x509 -serial -noout -in rootverifytest.crt
serial=02
$ openssl x509 -serial -noout -in jimp.crt
serial=02
$ openssl crl -text -noout -in CR.crl | grep -A1 'Revoked'
Revoked Certificates:
    Serial Number: 02
$ openssl crl -text -noout -in CI.crl | grep -A1 'Revoked'
Revoked Certificates:
    Serial Number: 02

Now let's validate the user certificate signed by the root, and then check it with the root CA CRL. This works as expected (good!), first showing that the certificate is valid and then that it is revoked.

$ openssl verify -CApath . rootverifytest.crt
rootverifytest.crt: OK
$ openssl verify -CApath . -crl_check rootverifytest.crt
CN = rootverifytest
error 23 at 0 depth lookup: certificate revoked
error rootverifytest.crt: verification failed

Now let's try the same with the user certificate signed by the intermediate. It validates OK without the CRL, but checking the CRL, it produces an error:

$ openssl verify -CApath . jimp.crt
jimp.crt: OK
$ openssl verify -CApath . -crl_check jimp.crt
CN = jimp
error 3 at 0 depth lookup: unable to get certificate CRL
error jimp.crt: verification failed

I've tried with -crl_check_all, -extended_crl, and various related combinations, all failed the same way. I've also tried using -CAfile with the chain+CRLs included together and it also failed. Any reference I can find to "unable to get certificate CRL" is not relevant to this setup or involves an error in the setup not present here. Checking with truss/strace there is no obvious source of error either. I see it read the CRL, and also check to see if there is a newer copy, then it stops.

The CA/Cert structure contains nothing private, since it was created only for these tests. I have attached the relevant certificates and CRLs for others to test/confirm if needed.


Files

crl-intermediate-problem.tgz (4.41 KB) crl-intermediate-problem.tgz CA, CRL, and Certificates used in testing Jim Pingle, 11/08/2019 11:00 AM
Actions #1

Updated by Jim Pingle about 5 years ago

  • Description updated (diff)
Actions #2

Updated by Jim Pingle about 1 year ago

  • Status changed from New to Feedback
  • Target version set to 2.8.0
  • % Done changed from 0 to 100
  • Plus Target Version set to 23.09

We received a submission privately from MalteHillmann with a fix for this. It's a problem in the security/php-openssl_x509_crl we use to generate CRLs:

--- a/a/usr/local/share/openssl_x509_crl/X509_CERT.php
+++ b/b/usr/local/share/openssl_x509_crl/X509_CERT.php
@@ -90,7 +90,7 @@ class X509_CERT
         $ret->content['keyIdentifier']->setType(0, false, ASN1_CLASSTYPE_CONTEXT);

         //Copy subject
-        $subject = $cert_root->content[0]->content[$is_v1 ? 4 : 5];
+        $subject = $cert_root->content[0]->content[$is_v1 ? 2 : 3];

         //Write into authorityCertIssuer ([4] EXPLICIT Name)
         $ret->content['authorityCertIssuer'] = new ASN1_SEQUENCE; //it's GeneralNames

I have added a patch file for this in the security/php-openssl_x509_crl port so we will have the fix on future versions:

https://github.com/pfsense/FreeBSD-ports/commit/e573756c98d1181583fee0f7d818c6be0ea3da0e

I will also be adding an entry for this to the system patches package recommended patches for Plus 23.05.1 / CE 2.7.0 shortly.

Actions #4

Updated by Jim Pingle about 1 year ago

  • Subject changed from CRL check for Intermediate CA CRLs fails to Cannot validate Certificates against Certificate Revocation Lists for Intermediate Certificate Authorities

Updating subject for release notes.

Actions #5

Updated by Jim Pingle about 1 year ago

  • Status changed from Feedback to Resolved

Working as expected in current dev snapshots.

Actions #6

Updated by Chris Merchant about 1 year ago

This patch appears to break two items in 2.7.0-RELEASE (at least from what I have discovered so far)

1. Version information section no longer confirms installed version status
2. In Package Manager, 'Please wait while the list of packages is retrieved and formatted' is as far as that function will proceed. It will not show installed packages status.

Once the 9889 patch is reverted, the two items above function properly again.

Actions #7

Updated by Jim Pingle about 1 year ago

Chris Merchant wrote in #note-6:

This patch appears to break two items in 2.7.0-RELEASE (at least from what I have discovered so far)

1. Version information section no longer confirms installed version status
2. In Package Manager, 'Please wait while the list of packages is retrieved and formatted' is as far as that function will proceed. It will not show installed packages status.

Once the 9889 patch is reverted, the two items above function properly again.

1. Version information where? Dashboard? Upgrade check? Somewhere else?
2. Do you get errors with pkg-static update -f from the CLI?

I can't replicate either of those problems here. The patch would not affect any certificate operations done by pkg which is what would be involved in upgrade and package operations.

The patch here only affects CRL operations for GUI certificates/chains and those have no involvement in any outbound connections from the firewall itself.

Actions #8

Updated by Chris Merchant about 1 year ago

1. Version information on dashboard. I've just applied the patch again, and the readout is now 'Unable to check for updates'.
2. The shell command eventually times out with the browser (Brave) throwing a 504 Gateway Time-out.
No biggie from your description, just thought you'd like to be aware. cheers

Actions #9

Updated by Jim Pingle about 1 year ago

  • Target version changed from 2.8.0 to 2.7.1
Actions

Also available in: Atom PDF