3

I am wondering if there is any harm in having a TLS client send its certificate to a server before having established trust with that server. I have found a similar question, however that mostly concerns the "static" data of client cert (public, not sensitive) and key (private, needs to be guarded well).

What I am interested in is however the data sent by the client during the handshake to prove its knowledge of the private key. My understanding is that TLS should guarantee that everything is specific to a single session, and that whatever data is sent can not be used for MitMing or replay attacks. However, is it really that simple and can I carelessly do client-certificate authentication with a server even if I don't trust it, or is there some elevated risk that I should assume in that, possibly due to vulnerabilities not yet disclosed?

In case somebody wonders why I would even consider doing this: ideally, I would like to conditionally present a client certificate only to a server that I trust, but still have the option of establishing a connection to the server presenting a certificate that I do not trust (in that case however w/o a client certificate). Unfortunately, the way the Golang TLS library is written, this doesn't seem to be possible (there is a GetClientCertificate callback, but that is only parametrized with the client certificate request, but no connection state/peer certificates).

3 Answers 3

1

The server can see the information in the certificate and thus get detailed and verified information about the clients identity. This might or might not be a problem, depending on the actual use case and certificate content. The server can not use this information to identify itself against another server with the clients identity though.

0
1

Summary

Client TLS authentication is designed to be safely usable to many different parties. By design you are supposed to be able to use the same certificate and private key to authenticate to several parties. Even if one of them is malicious, it will be not able to impersonate you by “reusing” the authentication information you have sent to another server.

(In contrast, if you are authenticating by sending a password, you cannot securely use the same password to authenticate to several parties.)

However, the certificate might include PII (name, login, email address) or technical information (server name?) and you might want to avoid sending it to malicious servers.

Details

When your using client authentication, you are actually sending two messages:

  1. your client certificate (and the associated certificate chain) in the Certificate message;
  2. a CertificateVerify including a signature which proves that you have the private key.

The client certificate is supposed to be “public” information: it is safe to publish information to anyone (wrt cryptography). However, the client certificate often includes PII: user name, login, email address, etc. You might not want to send this information to a random server.

In TLS v1.2, the CertificateVerify contains a signature (with the client private) of all the previous handshake messages. As a consequence, it should not be possible for a malicious website to reuse this signature to connect to another website because the signed data includes:

  • the server certificate;
  • usually, the server name (in the SNI extension).

Note: The second point (CertificateVerify) assumes that the client certificate contains a signing key. It might instead include a static Diffie-Hellman public key but this usage is mostly discouraged (AFAIU), is even not officially part of TLS v1.2 and is probably not used in practice. I'm assuming here that your client certificate is a signing certificate.

Additional consideration

Moreover in TLS v1.2, unless your are using client authentication as part of a TLS renegotiation:

  • the server is not fully authenticated yet when you are sending the client certificate Certificate and the CertificateVerify message (the server can be considered to be fully authenticated when you receive its Finished message);
  • these messages are send sent in cleartext anyway.

Therefore, a man in the middle could definitely steal these messages.

Both of these issues are fixed in TLS v1.3:

  • the client authentication messages are sent after the server authentication is complete;
  • moreover they are sent encrypted.

Note: a consequence is that the PII included in your certificate (if any) is often sent in cleartext in TLS v1.2.

0

I am wondering if there is any harm in having a TLS client send its certificate to a server before having established trust with that server.

Yes, this is non-compliance with the TLS standard. See RFC 5246 (TLS 1.2):

The handshake protocol messages are presented below in the order they MUST be sent; sending handshake messages in an unexpected order results in a fatal error. [...]

TLS supports three authentication modes: authentication of both parties, server authentication with an unauthenticated client, and total anonymity. Whenever the server is authenticated, the channel is secure against man-in-the-middle attacks, but completely anonymous sessions are inherently vulnerable to such attacks. Anonymous servers cannot authenticate clients.

A non-anonymous server can optionally request a certificate from the client, if appropriate for the selected cipher suite. This message, if sent, will immediately follow the ServerKeyExchange message (if it is sent; otherwise, this message follows the server's Certificate message).

It is a fatal handshake_failure alert for an anonymous server to request client authentication.

On the other part of the question:

[...] I would like to conditionally present a client certificate only to a server that I trust, but still have the option of establishing a connection to the server presenting a certificate that I do not trust (in that case however w/o a client certificate). Unfortunately, the way the Golang TLS library is written, this doesn't seem to be possible [...]

I am not familiar with the Golang TLS library, however these are my experiences with other TLS client libraries. E.g. in Java, you can create an all-trusting trust manager as follows:

                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                    }
                }

This will make you trust whatever certificate presented by the server and allow you to proceed with the handshake even if the certificate presented by the server should not be trusted otherwise. This solves part of your problem: but still have the option of establishing a connection to the server presenting a certificate that I do not trust.

The next step is responding to the CertificateRequest message produced by the server. If the TLS client trusted the server in the previous step, and it was sent CertificateRequest message, it will respond with a matching client certificate, if it has one. I am not aware of a TLS client implementation which would allow you to reach this step but introduce custom logic to either send the client certificate or not, depending on either using "real" server certificate validation logic or a "fake" one - as above.

However, this is not what should worry you most. Even if you'd implement your own TLS client which doesn't send client certificate in response to CertificateRequest, this gives you no control over how TLS server responds. In a typical scenario, this would terminate the handshake as per the RFC:

If the client does not send any certificates, the server MAY at its discretion either continue the handshake without client authentication, or respond with a fatal handshake_failure alert. Also, if some aspect of the certificate chain was unacceptable (e.g., it was not signed by a known, trusted CA), the server MAY at its discretion either continue the handshake (considering the client unauthenticated) or send a fatal alert.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .