組込み向けDTLSを試してみる

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

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

### 1. DTLSとは
まずは、DTLSというプロトコル、wolfSSLのAPIについて簡単に説明します。すでにご存じの方は次のセクションにスキップしてください。


DTLS(Datagram Transport Layer Security)はUDP(User Datagram Protocol)のセキュリティを実現するためのトランスポート層のプロトコルです。UDPはTCPのような接続の概念がなく、単純にパケットを送受することができる軽量で簡単に使えるプロトコルとして広く使われてきましたが、この分野でも本格的な応用ではセキュリティが求められることも多々あります。そのような場合に活躍するのがDTLSです。

![DTLS-TLS.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263939/b8d6e855-1c80-07a6-81e6-5a8d4ed016a1.jpeg)

IETFでのDTLSの標準化は当初TLSとは比較的独立に行われていたのですが、最近はTLSと歩調をあわせるようになってきています。DTLS1.0の次の検討ではTLS1.2と歩調を合わせるために、プロトコルのバージョン名も一つスキップしてDTLS１.２としています。IETFのワーキンググループでは次のバージョンDTLS1.3の内容が議論されていますが、DTLS1.3の内容も先行しているTLS1.3で実現した多くの強化、改善が取り込まれていく見込みです。とはいえDTLS１.３についてはまだ不確定要素も多くあるので、今回はすでに広く使われておりwolfSSLでも利用可能なDTLS1.2に基づいて紹介していくことにします。

UDPは軽量のプロトコルである一方で、パケットロスや転送順序の保証がなかったりといった暗号処理には少々やっかいな問題をかかえています。そこで、DTLSの処理の下層部分ではパケットロスや順序保障といったTCPに似たような処理を行わせています。ただし、TCPとは違って安全な接続を確立するための準備(ハンドシェークプロトコル)の間だけそうした不安定要素を取り除くようにし、接続が確立したあと上位のアプリケーションに対して順序性を保証したりロストパケットを再送要求して補ったりするわけではありません。

![DTLS.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263939/76fc5566-d266-c476-523b-898b371a24d6.jpeg)


DTLSではそのような管理の上にセキュリティプロトコルを実現します。一方、DTLSのプロトコル自身はTLSによく似たプロトコルになっています。TLSと同様に通信ノードの役割はクライアントとサーバに分かれていて、接続の概念もTLSと同様です。DTLSの通信はクライアントからの接続要求からはじまり、クライアントとサーバの間で一連のハンドシェークが行われ安全な接続を確立し、実際のアプリケーションデータの転送が行います。そのために、通信するノードはUDPではなかったサーバ、クライアントの区別が導入されています。接続要求をするほうがクライアント、要求を待つほうがサーバです。

### 2. ダウンロード、ビルド
では、wolfSSLを入手して実際に実行させてみることにします。まず、ダウンロード、ビルドします。

１） ソースコード一式のダウンロード
正式版は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コマンドではDTLS機能を有効化指定（"--enable-dtls"）してビルドします。make checkのように指定するとコンパイル完了後、ローカルテストを実行するのですべてのテストが正常終了することを確認します。

```
$ ./configure --enable-dtls
...
   * DTLS:                       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
============================================================================
```

### 3. 実行
DTLS通信の様子をみるために、まずWiresharkを立ち上げます。Wiresharkのメニューバーの　Analyze -> Decode As　でIP ProtocolにUDPを登録しておき、FIlterに"dtls"を指定します。

サーバ用、クライアント用の二つのコマンドウィンドウを開いておいて、サーバ、クライアントそれぞれに"-u"を指定してDTLSで通信させてみます。サーバ、クライアント双方に使用された暗号スイートや送られたサンプルメッセージなどが表示されます。

サーバ側：

```
$ ./examples/server/server -u
SSL version is DTLSv1.2
SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
SSL curve name is SECP256R1
Client message: hello wolfssl!
```

クライアント側：

```
$ ./examples/client/client -u
SSL version is DTLSv1.2
SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
SSL curve name is SECP256R1
I hear you fa shizzle!
```

Wiresharkを使ってDTLSの簡単な通信の様子を見てみます。
![PacketCapture.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263939/9e06f12b-44f8-1c77-a1b7-5ee31077eb7e.jpeg)

DTLSもTLSと同様にアプリケーションデータの送受信に先立って、安全な接続のためのハンドシェークが行われていることがわかります。TLSと異なるのは、DoS攻撃の防衛のために最初のClientHelloに対して、HelloVerifyRequestと呼ばれるレコードでサーバからクライアントに対してクッキーが渡され、クライアントはこれを以後の通信で引き継がないといけないようになっている点です。ハンドシェークのあとは暗号化されたアプリケーションデータの通信が行われます。この部分はアプリケーションの必要に応じて、必要なレコードを必要な回数往復させることができます。

この時、一度確立したセッションは継続されるので、ハンドシェークは最初の一回のみ行われます。

### まとめ
以上、wolfSSLのDTLS機能をインストールして、簡単な動作を試してみました。詳細についてはinfo@wolfssl.jpにお尋ねください。

参考資料：
IETF RFC-6347(DTLS1.2)：https://tools.ietf.org/html/rfc6347
IETF RFC-6347(日本語訳、インターネット協会)：https://tex2e.github.io/rfc-translater/html/rfc6347.html

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