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: <pre> $ 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 </pre> Next check the CRLs. Note they have the correct issuer and validate OK on their own. <pre> $ 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 </pre> 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. <pre> $ 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 </pre> Now let's test the CApath setup to validate the CRLs. They both validate OK. <pre> $ openssl crl -CApath . -noout -in CR.crl verify OK $ openssl crl -CApath . -noout -in CI.crl verify OK </pre> Manually double check the certificate serials and confirm they are revoked in the CRL text: <pre> $ 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 </pre> 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. <pre> $ 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 </pre> 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: <pre> $ 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 </pre> 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.