OpenSSL APIメモ(handshake failure)

OpenSSL APIを使うクライアントプログラムを書いて、あるサイトにアクセスした時にエラーが出た。
ハマったのでメモしておく。

error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure

TLSを指定している(↓)のに何故SSLv3?

    ctx = SSL_CTX_new(TLSv1_client_method());

SSLv3に変えてみると、

    ctx = SSL_CTX_new(SSLv23_client_method());
    SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2);     /* SSLv2を無効にする */

エラーメッセージが変わった。

error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure

結果的に原因はプロトコル(SSLv3やTLS1.0)ではなく、「Client Hello」時に、サーバへ渡す情報の不足。

SSL接続時にHandshakeに失敗する場合はSNIが原因かもしれない - TODESKING

SSL/TLS(SSL3.0~TLS1.2)のハンドシェイクを復習する - Qiita

TLS 1.3 Encrypted SNI拡張の議論 - 株式会社レピダム


もう少し違ったメッセージを出せないものだろうか。。。
以下を追加したら正常に接続できた。

    SSL_set_tlsext_host_name(ssl, "<アクセス先サーバのHOSTNAME>");

SNIについて、wikiに以下の記載有り。

SSL_set_tlsext_host_name uses the TLS SNI extension to set the hostname.
If you are connecting to a Server Name Indication-aware server (such as Apache with name-based virtual hosts or IIS 8.0), then you will receive the proper certificate during the handshake.