Verify certificate chain with OpenSSL

Published by Tobias Hofmann on

6 min read

A good TLS setup includes providing a complete certificate chain to your clients. This means that your web server is sending out all certificates needed to validate its certificate, except the root certificate. This is best practice and helps you achieving a good rating from SSL Labs. In a normal situation, your server certificate is signed by an intermediate CA. With this, your complete certificate chain is composed of the Root CA, intermediate CA and server certificate.

You do get signed your certificate by an intermediate CA and not the Root CA, because the Root CA is normally an offline CA. As the name suggests, the server is offline, and is not capable of signing certificates. Its certificate is included into the build-in root CA list of clients (browsers).The intermediate CA is online, and it`s task is to sign certificates. Compared to the root CA, its own certificate is not included in the built-in list of certificates of clients. Of course, the web server certificate is also not part of this list. For a client to verify the certificate chain, all involved certificates must be verified. Server certificate by intermediate CA, which is verified by Root CA. Client already has the root CA certificate, and at least gets the server certificate. Missing certificate therefore is the one of the intermediate CA.

When a client connects to your server, it gets back at least the server certificate. To validate this certificate, the client must have the intermediate CA. For this, he will have to download it from the CA server. The root CA is pre-installed and can be used to validate the intermediate CA. Well, it should download. But not all server certificates include the necessary information, or the client cannot download the missing certificate (hello firewall!). In that case, it is not possible to validate the server`s certificate. Therefore the server should include the intermediate CA in the response.

Now the client has all the certificates at hand to validate the server. In case more than one intermediate CAs are involved, all the certificates must be included. The chain is N-1, where N = numbers of CAs.

Verify certificate chain with OpenSSL

Enough theory, let`s apply this IRL. Use OpenSSL to connect to a HTTPS server (using my very own one here in the example).

openssl.exe s_client -connect www.itsfullofstars.de:443

Output

Loading 'screen' into random state - done
CONNECTED(000001EC)
depth=1 C = IL, O = StartCom Ltd., OU = StartCom Certification Authority, CN = StartCom Class 1 DV Server CA
verify error:num=20:unable to get local issuer certificate
---
Certificate chain
0 s:/CN=www.itsfullofstars.de
i:/C=IL/O=StartCom Ltd./OU=StartCom Certification Authority/CN=StartCom Class1 DV Server CA
1 s:/C=IL/O=StartCom Ltd./OU=StartCom Certification Authority/CN=StartCom Class1 DV Server CA
i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIGJjCCBQ6gAwIBAgIQEH6ZTKIfC5k6iN7ERWeE9zANBgkqhkiG9w0BAQsFADB4sH+ryHeVQVMe4WxKH2nUKbTtE0ppeCQqXL1ExXXDCD1jANVy0pjlVNHbJJJq9voViyYWxhBveiaEJ02N/gOfgkawwIhYiE3Ur6DLlJh0ynXVuXSsRrV5zCI0
-----END CERTIFICATE-----
subject=/CN=www.itsfullofstars.de
issuer=/C=IL/O=StartCom Ltd./OU=StartCom Certification Authority/CN=StartCom Class 1 DV Server CA
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 4041 bytes and written 443 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 4096 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: 2D5[…]2F0
Session-ID-ctx: Master-Key: 9D8[…]DCF
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
0000 - 3d 21 23 92 67 cc 97 a5-17 c5 09 9e 69 da ea 6d =!#.g.......i..m[…]
00b0 - ac fb 79 22 fc c6 fa 9b-ef c8 0e cb 6c 27 72 83 ..y"........l'r.
Start Time: 1455216192
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
---

If you cannot interpret the result: it failed. Verify return code:20 means that openssl is not able to validate the certificate chain. The certificate chain can be seen here:

  • 0: the certificate of the server
  • 1: the certificate of the CA that signed the servers certificate (0)
  • s: is the name of the server, while I is the name of the signing CA. To get a clearer understanding of the chain, take a look at how this is presented in Chrome:

The certificates send by my server include its own and the StartCom Class 1 DV Server CA.

Server certificate:

StartCom Class 1 DV Server CA

Missing: Root CA: StartCom Certificate Authority. This is the Root CA and already available in a browser. It`s not available in OpenSSL, as the tool comes without a list of trusted CAs. To “install” the root CA as trusted, OpenSSL offers two paramters:

  • CAfile. Point to a single certificate that is used as trusted Root CA
  • CApath. Point to a directory with certificates going to be used as trusted Root CAs.

I will use the CAfile parameter. For this, I`ll have to download the CA certificate from StartSSL (or via Chrome).

openssl.exe s_client -connect www.itsfullofstars.de:443 -CAfile startssl_rootca.cer

Output

Loading 'screen' into random state - done
CONNECTED(000001EC)
depth=2 C = IL, O = StartCom Ltd., OU = Secure Digital Certificate Signing, CN =StartCom Certification Authority
verify return:1
depth=1 C = IL, O = StartCom Ltd., OU = StartCom Certification Authority, CN = StartCom Class 1 DV Server CA
verify return:1
depth=0 CN = www.itsfullofstars.de
verify return:1
---
Certificate chain
0 s:/CN=www.itsfullofstars.de
i:/C=IL/O=StartCom Ltd./OU=StartCom Certification Authority/CN=StartCom Class1 DV Server CA
1 s:/C=IL/O=StartCom Ltd./OU=StartCom Certification Authority/CN=StartCom Class1 DV Server CA
i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIGJjCCBQ6gAwIBAgIQEH6ZTKIfC5k6iN7ERWeE9zANBgkqhkiG9w0BAQsFADB4sH+ryHeVQVMe4WxKH2nUKbTtE0ppeCQqXL1ExXXDCD1jANVy0pjlVNHbJJJq9voViyYWxhBveiaEJ02N/gOfgkawwIhYiE3Ur6DLlJh0ynXVuXSsRrV5zCI0
-----END CERTIFICATE-----
subject=/CN=www.itsfullofstars.de
issuer=/C=IL/O=StartCom Ltd./OU=StartCom Certification Authority/CN=StartCom Class 1 DV Server CA
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 4041 bytes and written 443 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 4096 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: 9[…]43
Session-ID-ctx: Master-Key: 4C[…]2D
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
0000 - 3d 21 23 92 67 cc 97 a5-17 c5 09 9e 69 da ea 6d =!#.g.......i..m
0010 - fc 05 be 96 ce bd 98 d6-d0 80 f9 67 1c 09 8c 4a ...........g...J
00b0 - 3a c2 73 77 e3 40 ab 22-84 1b f2 6a 5a 4a 8e 68 :.sw.@."...jZJ.h
Start Time: 1455217879
Timeout : 300 (sec)
Verify return code: 0 (ok)
---

Return code is 0. Now it worked. OpenSSL was able to validate all certificates and the certificate chain is working.

More resources

https://community.qualys.com/docs/DOC-1931

https://www.openssl.org/docs/manmaster/apps/verify.html

Let the world know

Tobias Hofmann

Doing stuff with SAP since 1998. Open, web, UX, cloud. I am not a Basis guy, but very knowledgeable about Basis stuff, as it's the foundation of everything I do (DevOps). Performance is king, and unit tests is something I actually do. Developing HTML5 apps when HTML5 wasn't around. HCP/SCP user since 2012, NetWeaver since 2002, ABAP since 1998.

2 Comments

Arnaud · August 31, 2019 at 18:33

thank you for your an article

Alessandro · September 4, 2020 at 10:34

Great!!! thanks a lot

Ale

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.