セキュアなIoTデバイス通信をやってみた(MbedTLS移植編-httpsテスト-接続)

#はじめに#
2019年5月に[IoTLT](https://iotlt.connpass.com/)にてLTをさせていただきました。
その内容のフォローを記入しながら自分なりに整理していきたいと思います。

発表内容：
[スタートアップIoTデバイスのセキュリティを考える](https://www.slideshare.net/KentaroMitsuyasu1/iot-144602008)

#前回までのあらすじ#
[セキュアなIoTデバイス通信をやってみた(MbedTLS移植編-httpsテスト-サーバー構築)](https://qiita.com/kmitsu76/items/e3f1725d3c013bdea163)で接続先のapacheサーバーの構築と、自己認証局でサーバー証明書の作成と、準備した証明書の組み込みを行いました。

今回の記事に関連するソースコードは下記にて公開中。
[kmwebnet/ECC608-httpsconnection](https://github.com/kmwebnet/ECC608-httpsconnection)

#https接続のためのmbedtlsへのポーティング#

デバイス側から、"GET / HTTP/1.0\r\nHost: <ホストURL>\r\n\r\n"を送信します。
main.cの内容からmbedtlsへのポーティングのポイントを整理します。

■初期化
下記にて、必要な構造体の初期化を行っている。

```
    mbedtls_net_init(&server_fd);
    mbedtls_ssl_init(&ssl);
    mbedtls_ssl_config_init(&conf);
    mbedtls_x509_crt_init(&cacert);
    mbedtls_x509_crt_init(&cert);
    mbedtls_ctr_drbg_init(&ctr_drbg);

    printf("\n  . Seeding the random number generator...");
    fflush(stdout);

    mbedtls_entropy_init(&entropy);

    if ((ret = mbedtls_ssl_config_defaults(&conf,
        MBEDTLS_SSL_IS_CLIENT,
        MBEDTLS_SSL_TRANSPORT_STREAM,
        MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
    {
```

■証明書の設定
以下のように構造体が初期化されている
mbedtls_x509_crtが証明書の構造体で、CA証明書用にcacert、デバイス証明書用にcertを作成している。
pkeyは秘密鍵を取り扱う構造体で、certと合わせて後ほど使用する。

```
    mbedtls_x509_crt cacert;
    mbedtls_pk_context pkey;
    mbedtls_x509_crt cert;
```

238行から、mbedtls_x509_crt_parse(&cacert, rootcacert , sizeof(rootcacert)でルートCA証明書をcacertへ設定している。

246行からATECC608Aから証明書情報を抜き出して、cert構造体へ設定をかけている

```
//秘密鍵の構造体pkeyを初期化、ATECC608Aのスロット0で処理する設定
    if (0 != atca_mbedtls_pk_init(&pkey, 0))
//デバイス証明書をATECC608Aから抜き出してcertへ追加
    if (0 != atca_mbedtls_cert_add(&cert, &g_cert_def_2_device))
//中間CA証明書をATECC608Aから抜き出してcertへ追加
    if (0 != atca_mbedtls_cert_add(&cert, &g_cert_def_1_signer))
//client verifyを行うため、上記certとpkeyをペアとして設定
    if(0 != (ret = mbedtls_ssl_conf_own_cert(&conf, &cert, &pkey)))
```

それぞれ内部で、ATECC608Aをフックする処理に飛ぶ。
それらを設定するのがソース内src/port内の下記ファイル。

```
atca_mbedtls_wrap.h
atca_mbedtls_wrap.c //　pkey構造体の初期化、証明書作成にATECC608Aを関与させる
atca_mbedtls_ecdsa.c // 署名と検証処理をATECC608Aへ飛ばす
atca_mbedtls_ecdh.c //　ECDH処理（公開鍵作成、プリマスターシークレット計算）をATECC608Aで行う
```
■mbedtls認証設定

287行でSSLベリファイ必須にしてセキュリティが確保できる設定にし、
サーバー証明書を検証するルートCA証明書を設定。

```
    mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED);
    mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
```

■
これらを経て、ハンドシェイクを開始し、成功すればはじめてGETリクエストが出せる。

#個別設定#
main.c内の下記項目を環境に合わせて設定する。
今回で言えば、下記のようになる。

```
// your SSID and PASS
#define EXAMPLE_WIFI_SSID ""
#define EXAMPLE_WIFI_PASS ""

// Trusted CA certificate for verifying HTTPS server
const unsigned char rootcacert[]={
"-----BEGIN CERTIFICATE-----\n"
//root-ca.crtの中身
"-----END CERTIFICATE-----\n"
};

// URL , port number which you want to connect
status = atca_connect("iot.testcorp.com" , "4689", &cfg);
```

#接続#

デバイス側からの接続をシリアルコンソールから確認したところ。
多くのTLSハンドシェイクログが表示される中で、下記の表示が現れると成功。

```
HTTP/1.1 200 OK
Date: Thu, 13 Jun 2019 08:35:11 GMT
Server: Apache/2.4.39 (Unix) OpenSSL/1.1.1
Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT
ETag: "2d-432a5e4a73a80"
Accept-Ranges: bytes
Content-Length: 45
Connection: close
Content-Type: text/html

<html><body><h1>It works</h1></body></html>
```