How to list certificates, trusted by OpenSSL?

I recently looked into this, and found no way to get OpenSSL to list the certificates in its trusted set. The best way I found was to, as you point out, "consult that file [/etc/ssl/certs] myself (on my particular installation of OpenSSL)".

You can be more installation-independent about finding the directory which OpenSSL consults. openssl version -d prints the path to it.

% openssl version -d
OPENSSLDIR: "/opt/local/etc/openssl"

OpenSSL looks here for a file named cert.pem and a subdirectory certs/. Certificates it finds there are treated as trusted by openssl s_client and openssl verify (source: the article, What certificate authorities does OpenSSL recognize?).

So, you can do something like:

% find -H `openssl version -d | sed -E 's/OPENSSLDIR: "([^"]*)"/\1/'`/(cert.pem|certs) \ 
-type f -exec cat {} \+  

This prints out the entire contents of the files which OpenSSL expects to contain certificates. If you want less than the entire file, then replace cat with the appropriate commands.


AFAIK OpenSSL just consults a list (such as, for example, /etc/ssl/certs) and checks if the certificate is present there.

No, OpenSSL trusts nothing by default. You have to instruct it what to trust. There's even a FAQ topic covering it: Why does <SSL program> fail with a certificate verify error?:

This problem is usually indicated by log messages saying something like "unable to get local issuer certificate" or "self signed certificate". When a certificate is verified its root CA must be "trusted" by OpenSSL this typically means that the CA certificate must be placed in a directory or file and the relevant program configured to read it. The OpenSSL program 'verify' behaves in a similar way and issues similar error messages: check the verify(1) program manual page for more information.

You can also test your connection to Google to see how OpenSSL behaves:

$ openssl s_client -connect google.com:443
CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
...
Start Time: 1407377002
Timeout   : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)

Notice the above fails because OpenSSL does not trust GeoTrust Global CA by default. Actually, there's another trust point in the chain and that's Google Internet Authority G2.

You can remedy the situation by telling OpenSSL what to trust. Below, I use -CAfile option with Google Internet Authority G2:

$ openssl s_client -connect google.com:443 -CAfile google-ca.pem 
CONNECTED(00000003)
depth=3 C = US, O = Equifax, OU = Equifax Secure Certificate Authority
verify return:1
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify return:1
depth=1 C = US, O = Google Inc, CN = Google Internet Authority G2
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google Inc, CN = google.com
verify return:1
...
Start Time: 1407377196
Timeout   : 300 (sec)
Verify return code: 0 (ok)

Next, you can act like a browser by going to cURL and download cacert.pem. cacert.pem has lots of CAs in it:

$ openssl s_client -connect google.com:443 -CAfile cacert.pem 
CONNECTED(00000003)
depth=3 C = US, O = Equifax, OU = Equifax Secure Certificate Authority
verify return:1
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify return:1
depth=1 C = US, O = Google Inc, CN = Google Internet Authority G2
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google Inc, CN = google.com
verify return:1
...
Start Time: 1407377356
Timeout   : 300 (sec)
Verify return code: 0 (ok)

You're not quite as bad as a browser with its hundreds of CAs and subordinate CAs, but you're getting close:

$ cat cacert.pem | grep -o "\-\-\-\-\-BEGIN" | wc -l
     153

OpenSSL security model is in contrast to the web app/browser security model, where the browser carries around a list of trust anchors or trust points known as Certificate Authorities (CAs). Note: in this model, the wrong CA could claim to certify a site, and the browser would be no wiser.

This has happened in the past, and it will likely happen again in the future. For a good history of PKIX funny business, see CAcert's Risk History. For example, you know Google Internet Authority G2 and GeoTrust Global CA certify Google's sites. There's no reason for a Dutch CA called Diginotar to claim to certify them, or a French Cyberdefense Agency to claim to certify them.

Related to security models: another problem with the web app/browser model is you cannot package the one trust anchor or CA needed for your app and use it (assuming you have a trusted distribution channel). Your certificates gets tossed in the pile with the CA Zoo. Others can still claim to certify your site, and you can claim to certify other sites.

The security model one of the reasons web apps are relegated to low value data. Web apps should not handle medium value or high value data because we can't place the needed security controls.


Is there a way for OpenSSL to list all certificates which it trusts?

No need since the list has 0 members :)


Also see How to find out the path for openssl trusted certificate?.