This is a continuation of my earlier post on Client Certificate Authentication (Part 1) aka TLS Mutual Authentication. Earlier, I had discussed on what Client Certificates are and how they work in SSL/TLS Handshake.
In this post, I will explain the SSL/TLS handshake with help of tools like WireShark & Curl. I will also explain what happens when we have Secure Negotiation enabled on the server.
Before proceeding further, lets look at the SERVER HELLO definition in RFC 5246. As per the RFC, the server will request the certificate from the client in the Server hello by including certificate_request message, which has the decimal code of 13 (0d in Hex).
enum {
hello_request(0), client_hello(1), server_hello(2),
certificate(11), server_key_exchange (12),
certificate_request(13), server_hello_done(14),
certificate_verify(15), client_key_exchange(16),
finished(20), (255)
} HandshakeType;
struct {
HandshakeType msg_type; /* handshake type */
uint24 length; /* bytes in message */
select (HandshakeType) {
case hello_request: HelloRequest;
case client_hello: ClientHello;
case server_hello: ServerHello;
case certificate: Certificate;
case server_key_exchange: ServerKeyExchange;
case certificate_request: CertificateRequest;
case server_hello_done: ServerHelloDone;
case certificate_verify: CertificateVerify;
case client_key_exchange: ClientKeyExchange;
case finished: Finished;
} body;
} Handshake;
Once the client sees the certificate_request message it will provide the certificate to the server.
Real world example:
Setup: Hosted a site on IIS inside an Azure VM. This requires a client certificate for authentication. Here is the endpoint https://azurevm.kaushal.co.in
I have added the SSL binding via netsh using the following command
netsh http add sslcert ipport=0.0.0.0:443 certhash=<certificate thumbprint goes here> appid={4dc3e181-e14b-4a21-b022-59fc669b0914} certstorename=My clientcertnegotiation=enable |
Analyzing the TLS/SSL handshake in WireShark
As shown below, the server has sent a certificate request message to the client and the client has then responded with the certificate in the next communication.
In WireShark you can set the filter to “ssl.handshake.type == 13” to specifically look for certificate_request message in Server Hello.
NOTE: Some SSL/TLS servers support only Secure negotiation. Therefore you may not see the Certificate Request message explicitly in the Server Hello. In this case, the server will send the Certificate Request message as a part of the Encrypted Handshake Message.
Analyzing the TLS/SSL handshake in cURL
By far, cURL has made it easier to determine if the server is sending the Certificate Request in Server Hello. You will have to download the version of curl that includes support SSL Protocol. This works in scenarios where the server supports only Secure Negotiation. I
You can find various builds of cURL available for download here: https://curl.haxx.se/dlwiz/?type=bin&os=Win64&flav=-&ver=*&cpu=x86_64
I am using the following
curl version: 7.54.0 – SSL enabled SSH enabled
URL: https://bintray.com/artifact/download/vszakats/generic/curl-7.54.0-win64-mingw.7z
Execute the following from command prompt
curl –v https://<hostname> –k
Where,
-v, –verbose Make the operation more talkative
-k, –insecure Allow connections to SSL sites without certs (H)
Once the request has been issued via cURL. In the verbose output, search for TLS handshake message “Request CERT (13)” as highlighted in the below example.
C:>curl -v https://azurevm.kaushal.co.in -k
* Rebuilt URL to: https://azurevm.kaushal.co.in/
* Trying ::1…
* TCP_NODELAY set
* Connected to localhost (::1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: OU=Domain Control Validated; CN=*.kaushal.co.in
* start date: May 10 09:05:00 2017 GMT
* expire date: May 10 09:05:00 2018 GMT
* issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority – G2
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
> GET / HTTP/1.1
> Host: Azure Vm.kaushal.co.in
> User-Agent: curl/7.46.
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Content-Type: text/html
< Server: Microsoft-IIS/8.5
< X-Powered-By: ASP.NET
< Date: Fri, 09 Jun 2017 16:14:39 GMT
< Content-Length: 1233. . .
<continued/>
HTH,
Kaushal