#はじめに#
2019年5月にIoTLTにてLTをさせていただきました。
その内容のフォローを記入しながら自分なりに整理していきたいと思います。
発表内容:
スタートアップIoTデバイスのセキュリティを考える
#前回までのあらすじ#
セキュアなIoTデバイス通信をやってみた(MbedTLS移植編-httpsテスト-サーバー構築)で接続先のapacheサーバーの構築と、自己認証局でサーバー証明書の作成と、準備した証明書の組み込みを行いました。
今回の記事に関連するソースコードは下記にて公開中。
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>