I am trying to understand the practical mechanisms of cross-signing (intermediate) certificates. As an example, I am looking at the Let's Encrypt Chain of Trust. That page mentions:
IdenTrust has cross-signed our intermediates. This allows our end certificates to be accepted by all major browsers while we propagate our own root.
Additionally, the page contains links to both the intermediate certificate signed with the private key belonging to their own ISRG Root CA as well as the intermediate certificate cross-signed with the private key belong to IdenTrust's CA.
My expectation was to see both of those intermediate certificates coming by on the wire when setting up a TLS connection with www.letsencrypt.org, leaving it up to the client to decide which of the two intermediates to use to build a chain of trust. However, I only see the intermediate signed by IdenTrust.
I have observed this with wireshark, analyzing the TLS traffic as I browsed www.letsencrypt.org with my web browser. To force "the other" chain of trust, I un-trusted the DST Root CA X3 certificate in the Keychain Access app (I am on a Mac) and indeed I was no longer able to browse the site. Then I added the ISRG Root X1 certificate, indicating to always trust it but I could still not browse the site. This supports my observation that the intermediate certificate signed by ISRG is never provided by the server.
I also tried the
openssl s_client app, but to no avail.
Suppose that I happen to trust the ISRG Root and not IdenTrust, how do I make the server share with me the intermediate certificate signed by the ISRG Root? Or more generally asked, if multiple chains of trust are available, for example because of cross-signing, how are the certificates of both chains shared with clients? Why do I not receive a bundle that contains both certificates for the intermediate?
Update: the first answer states that the TLS spec does not allow for multiple certificate chains to be exchanged. That explains a lot.
However, my expectations are set by the answers to the question What is the use of cross signing certificates in X.509?. The accepted answer there mentions: "It's about expanding trust" and "increasing the ease of verification of trust, such as situations where you've got clients that trust CA1 or CA2 (but not both). In such a case, you can cross-sign a cert to be trusted by both.".
If only one chain is allowed to be exchanged, then that does not seem like "expanding trust" but more like "modifying trust". Also, for a particular server, if it has to select one particular chain then the "ease of verification" argument no longer holds either -- at least not if your only mechanism available is the TLS handshake. Is that correct?
This question is somewhat related, and you can see from StackzOfZtuff's answer that only one chain can be sent. When connecting with
openssl s_client -connect letsencrypt.org:443 it's returning the chain the the IdenTrust root (Digital Signature Trust Co. which IdenTrust bought a long time ago):
Certificate chain 0 s:/CN=www.letsencrypt.org i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 i:/O=Digital Signature Trust Co./CN=DST Root CA X3
Since the certificate chain sent has the signature from IdenTrust, it can't be verified with the ISRG root.
As noted here the client is under no obligation to use the chain the server sends, it may attempt to build its own chain to a trusted root. However, this requires that the client already have all of the necessary intermediates that weren't sent by the server.
If I add the intermediate signed by ISRG Root X1 to my trust store,
s_client will discover that chain despite being sent the IdenTrust chain (unless told not to by using
$ openssl s_client -connect letsencrypt.org:443 CONNECTED(00000003) depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1 verify return:1 depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 verify return:1 depth=0 CN = www.letsencrypt.org verify return:1 --- Certificate chain 0 s:/CN=www.letsencrypt.org i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 i:/O=Digital Signature Trust Co./CN=DST Root CA X3
External links referenced by this document:
Local articles referenced by this article: