Reputation: 1503
When running openssl command:
echo | openssl s_client -cipher 'ECDHE-ECDSA-AES128-GCM-SHA256' -connect www.googleapis.com:443 -tls1_2
CONNECTED(00000005)
depth=2 OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign
verify return:1
depth=1 C = US, O = Google Trust Services, CN = GTS CA 1O1
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google LLC, CN = *.googleapis.com
verify return:1
---
Certificate chain
0 s:C = US, ST = California, L = Mountain View, O = Google LLC, CN = *.googleapis.com
i:C = US, O = Google Trust Services, CN = GTS CA 1O1
1 s:C = US, O = Google Trust Services, CN = GTS CA 1O1
i:OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: ECDSA
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 4111 bytes and written 262 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-ECDSA-AES128-GCM-SHA256
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-ECDSA-AES128-GCM-SHA256
Session-ID: ...
Session-ID-ctx: ....
Master-Key: ...
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 100800 (seconds)
Start Time: 1574424718
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: yes
---
DONE
it shows a succesful ssl connection.
However, when I setup the equivalent ssl connection in c++ code:
asio::ssl::context cntx{asio::ssl::context::tlsv12_client};
cntx.set_options(boost::asio::ssl::context::default_workarounds);
cntx.set_verify_mode(asio::ssl::verify_peer, ec);
constexpr char kCiphers[] = "ECDHE-ECDSA-AES128-GCM-SHA256";
SSL_CTX_set_cipher_list(ssl_cntx, kCiphers));
SSL_CTX_set_ecdh_auto(ssl_cntx, 1);
the handshake fails with sslv3 alert handshake failure
.
When I use a cipher based on RSA like ECDHE-RSA-AES128-GCM-SHA256
, my c++ client succeeds to perform a successful handshake. What I am missing with "ECDSA" ?
Upvotes: 1
Views: 1417
Reputation: 123260
ECDSA ciphers require a ECC certificate. This certificate is only configured by the server when the client uses SNI, i.e. sends the intended hostname inside the ClientHello. openssl 1.1.1 (which you use) does SNI by default but your code does not use SNI.
For comparison s_client
with (the default) SNI (using openssl 1.1.1):
$ openssl s_client -cipher 'ECDHE-ECDSA-AES128-GCM-SHA256' -connect www.googleapis.com:443 -tls1_2
...
Cipher : ECDHE-ECDSA-AES128-GCM-SHA256
And without SNI:
$ openssl s_client -noservername -cipher 'ECDHE-ECDSA-AES128-GCM-SHA256' -connect www.googleapis.com:443 -tls1_2
CONNECTED(00000005)
140265233306048:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:../ssl/record/rec_layer_s3.c:1528:SSL alert number 40
...
Cipher : 0000
As for setting SNI in your own code see How to implement Server Name Indication (SNI) or see this code example with boost::asio which also implements SNI using SSL_set_tlsext_host_name.
Upvotes: 3