We have an interesting discussion between the server operator team and the developers of a client application.
Our setup in general is like this: There is a root-ca, let's call it "root-1". This has a sub-ca, let's call it "sub-1". Both are contained in the server's truststore. The client has got a combined key- / truststore (i.e. the same keystorefile), containing the ca chain mentioned above and a client-certificate issued by sub-1. Let's call this "client-1".
During the TLS handshake, the server sends a CertificateRequest message, containing a list of DN which are trusted (because they are in the truststore), i.e. ["root-1", "sub-1"].
The client checks the list, recognizes that it has a certificate issued by "sub-1" and sends that certificate as a certificate_list with one single entry: the client certificate.
The server operators are stating that the client should send the whole certificate chain, but may omit the root-ca. Basically, they like to delete "sub-1" from their truststore so that only "root-1" will be requested by the server. The client should find "client-1" which is issued by "sub-1" which is issued by "root-1" and then send the whole certificate chain.
The client developers are stating that this is a security breach or is at least less secure than the current solution. They say it seems like the server will then validate the client certificate agains the trustchain the client has sent by itself.
So from my point of view there are two questions resulting out of this discussion: 1. If the server requests only "root-1", should the client find "client-1" as an appropriate certificate an use it for communication? 2. If the answer to the first question would be yes, should the client send the certificate chain, i.e. [client-1, sub-1] (omitting root ca according to rfc)?
The RFC 5246 might be a little fuzzy in that section:
7.4.6. Client Certificate
[...]
Client certificates are sent using the Certificate structure
defined in Section 7.4.2.
And Section 7.4.2 says:
7.4.2. Server Certificate
[...]
Structure of this message:
opaque ASN.1Cert<1..2^24-1>;
struct {
ASN.1Cert certificate_list<0..2^24-1>;
} Certificate;
certificate_list
This is a sequence (chain) of certificates. The sender's
certificate MUST come first in the list. Each following
certificate MUST directly certify the one preceding it. Because
certificate validation requires that root keys be distributed
independently, the self-signed certificate that specifies the root
certificate authority MAY be omitted from the chain, under the
assumption that the remote end must already possess it in order to
validate it in any case.
The client developer now is interpreting this section like this:
Each following certificate MUST directly certify the one preceding it.
This means, that there MUST not be a certificate following the "senders certificate" i.e. the client certificate. Because the same structure is used for server and client certificate, the certificate_list has a length of 0..2^24-1. This means the list is valid with 0, 1, or multiple entries.
My thinking on that one is this:
- if the server has "sub-1" NOT in its truststore, it will use the ca the client is sending for validation, which sounds less secure to me. An attacker could produce a somehow valid "sub-2", then create a client certificate using "sub-2", send the chain and will be authenticated.
- A revocation list for CAs will not work then, because the rogue ca "sub-2" is unknown
- what is the advantage having only the root-ca in the server's truststore and having a client sending the whole certificate chain?
Additional information: the client is a middleware, too, so there is no possibility of any user interaction.
The client developers fear that the processing intended by the server operators brings serious security issues, which would be otherwise easily avoided. For them it makes no sense to send the sub-ca along with the client certificate, because the server should actually TRUST the sub-ca. That's why the sub-ca should reside in the server's truststore.
The server operators are saying, it would be of great effort to maintain always a set of valid sub-cas in their server's truststore, because there may be new sub-cas coming up, without their knowledge or attention. Furthermore they say, the behaviour of the client is not compliant with TLS 1.2 and that they are urged to use TLS 1.2.
But I cannot find any differences in the CCA (Client Certificate Authentication) area between TLS 1.0 and TLS 1.2. It is the same text there.
I will appreciate any clarification of this issue by any of the security experts here.
- How do you maintain similar scenarios in your projects? When implementing TLS 1.2 compliant clients, are you sending the certificate chain or a single certificate?
- Do you put the sub-cas into your servers truststore or not? And why?
Sorry for the lengthy text, but this is a tricky situation I think, and needs to be explained in detail I think. Additionaly, I think rfc 5246 is fuzzy in the aspect how mutual SSL handshake shall be done, exactly.