組込み向けTLS1.3を試してみる

###概要
[wolfSSL](https://www.wolfssl.jp/products/wolfssl)はIoTデバイス、組込み向けのSSL/TLSライブラリです。ここではwolfSSLのTLS1.3機能をインストールして簡単に試してみます。本来は組込向けMCUでそのAPIを呼び出すテストプログラムを作ってみるのがよいのですが、ここでは簡単のためにLinuxやパソコン上で動くサンプルのクライアント、サーバプログラムをビルドして動かしてみます。

その他使うもの：ハンドシェークの様子をみるためにWiresharkでパケットをキャプチャーしてみます。

###1. ダウンロード、ビルド、インストール

１） ソースコード一式のダウンロード
正式版はwolfSSLサイトから、最新版はGithubからダウンロードします。

正式版：
https://www.wolfssl.jp/download/ からwolfssl-x.x.0.zip を選択してダウンロード、解凍します。

最新版：
https://github.com/wolfssl/wolfssl からcloneします。cloneの後、wolfsslデイレクトリでsh autogen.shを実行しconfigureなど必要ファイルを生成します。

```
$ git clone https://github.com/wolfssl/wolfssl
Cloning into 'wolfssl'...
remote: Enumerating objects: 5, done.
...
Resolving deltas: 100% (64503/64503), done.

$ cd wolfssl
$ sh autogen.sh
autoreconf: Entering directory `.'
...
parallel-tests: installing 'build-aux/test-driver'
autoreconf: Leaving directory `.'
```

２） ビルド
次に、ライブラリとサンプルプログラム一式をビルドします。configureコマンドでMakefileを生成し、makeコマンドにてビルドします。configureコマンドではTLS1.3機能を有効化指定（"--enable-tls13"）してビルドします。make checkのように指定するとコンパイル完了後、ローカルテストを実行するのですべてのテストが正常終了することを確認します。

```
$ ./configure --enable-tls13
...
   * TLS v1.3:                   yes
...

$ make check
/Applications/Xcode.app/Contents/Developer/usr/bin/make -j17  check-am
  CC       wolfcrypt/benchmark/benchmark.o
  CC       wolfcrypt/src/src_libwolfssl_la-hmac.lo
...
PASS: scripts/tls13.test
PASS: tests/unit.test
============================================================================
Testsuite summary for wolfssl 4.4.1
============================================================================
# TOTAL: 7
# PASS:  7
# SKIP:  0
# XFAIL: 0
# FAIL:  0
# XPASS: 0
# ERROR: 0
============================================================================
```

###2. 実行
TLS通信の様子をみるために、まずWiresharkを立ち上げます。wolfSSlのサンプルサーバ、クライアントはデフォルトでポート11111が使用されます。Wiresharkのメニューバーの　Analyze -> Decode As　でポート11111にSSLを登録しておき、FIlterに"ssl"を指定します。

サーバ、クライアントは同じパソコンの別コマンドウィンドウで起動してもいいですが、できればそれぞれ別ノード（IPアドレスが異なるような環境）で起動するとWireshark上でメッセージの方向がわかりやすくなり、1.2と1.3でのハンドシェークの往復回数の違いが掴みやすくなるので、おすすめです。

まずは比較のために"-v 3"を指定してTLS1.2のサーバ、クライアント間で通信させてみます。

サーバ側：

```
$ ./examples/server/server -b -v 3
SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
SSL curve name is SECP256R1
Client message: hello wolfssl!
```

クライアント側：

```
$ ./examples/client/client -h <サーバIPアドレス> -v 3
SSL version is TLSv1.2
SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
SSL curve name is SECP256R1
Client message: hello wolfssl!
```

Wiresharkにフルハンドシェークと１往復のアプリケーションメッセージがキャプチャできるはずです。
![tls12-full.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263939/2c1db87b-ff9c-b9c2-1e4c-1edca2dfeb90.jpeg)

黄色の矢印がハンドシェーク、緑の矢印はアプリケーションデータのフレートです。実験している環境では192.168.1.27がクライアントなので、クライアントからClient Helloが送信され、２往復の後、３往復めの往路でクライアントからサーバへのアプリケーションデータが送信されていることがわかります。

次に、"-v 4"でTLS1.3を指定して同じことをやってみます。

サーバ側：

```
$ ./examples/server/server -b -v 4
SSL version is TLSv1.3
SSL cipher suite is TLS_AES_128_GCM_SHA256
SSL curve name is SECP256R1
Client message: hello wolfssl!
```

クライアント側：

```
$ ./examples/client/client -h <サーバIPアドレス>  -v 4
SSL version is TLSv1.3
SSL cipher suite is TLS_AES_128_GCM_SHA256
SSL curve name is SECP256R1
Client message: hello wolfssl!
```

WiresharkにTLS1.3のフルハンドシェークと１往復のアプリケーションメッセージがキャプチャできるはずです。
![tls13-full.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263939/8ce7fb80-3193-364b-dd6e-e4e6bebbe6e9.jpeg)

TLS1.3では、ハンドシェークは２往復めの往路で完了し、この往路に引き続いてクライアントからサーバへのアプリケーションデータの転送が行われていることがわかります。また、Server Helloの後はレコードが暗号化されているので、WiresharkではApplicationDataとして表示されています。

Client Helloレコードの詳細をみてみると、Cipher SuitesのリストにはTLS1.3向けの各スイートが含まれていることがわかります。

![CipherSuites.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263939/aea56a83-7076-7fdd-7b76-d40f6c8b7f89.jpeg)

また、Supported VersionsにはTLS1.3、Key Share拡張にはECDHとFFDHのためのKey Shareが含まれていていることがわかります。
![SupportedVersion.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263939/8269a103-4d78-ccac-dd8b-356641d56dc5.jpeg)

TLS1.2以前のバージョンしかサポートされていないサーバのためにクライアント側がバージョンをあわせてハンドシェークを進めることも可能です。
試しにサーバ側で、アクセプトできるバージョンとしてTLS1.2を指定します。

サーバ側：

```
$ ./examples/server/server -b -v 3
```
これに対して、クライアント側で古いバージョンを含めてコネクトを認める指定をしてみると、以下のようにTLS1.2で接続が成立します。

クライアント側：

```
$ ./examples/client/client -h <サーバIPアドレス> -v d
SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
SSL curve name is SECP256R1
Client message: hello wolfssl!
```
この時、Client HelloのSupported Versionsには接続を受け入れる複数のバージョンが含まれていることがわかります。
![SupportedVersionsTLS1.x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263939/e71534de-f276-7914-6522-87d5d7492532.jpeg)

###まとめ
以上、wolfSSLのTLS1.3機能を追加インストールして、簡単に試してみました。なお、wolfSSL4.5.0以降ではTLS1.3機能はデフォルトのビルドでも含まれるようになりました。また、このライブラリーではこの他にも新しいセッション再開、Early DataやPost Handshake Authenticationその他多くの機能をサポートしています。詳細にについては[こちら](https://www.wolfssl.jp/product-wolfssl-tls1-3/)を参照してください。

この記事の内容を含めてTLプログラミングについて解説をまとめる機会をいただきました。興味のあるかたはご覧ください。[徹底解剖 TLS 1.3](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E8%A7%A3%E5%89%96-TLS-1-3-%E5%8F%A4%E5%9F%8E-%E9%9A%86/dp/4798171417/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1WX07IBUINBBR&keywords=%E7%BF%94%E6%B3%B3%E7%A4%BE+TLS&qid=1643343354&sprefix=%E7%BF%94%E6%B3%B3%E7%A4%BE+tls%2Caps%2C177&sr=8-1) (翔泳社から 3/7刊行)。

####参考資料：
IETF RFC-8446(TLS1.3)：https://tools.ietf.org/html/rfc8446
IETF RFC-8446(日本語、インターネット協会)：https://tex2e.github.io/rfc-translater/html/rfc8446.html

ドキュメント：https://www.wolfssl.jp/docs/
英語サイト：https://www.wolfssl.com
日本語サイト：https://www.wolfssl.jp
Twitter: https://twitter.com/wolfSSL_Japan