reTerminalのハードウェアセキュリティ - Azure IoT Hubと繋ぐ

Seeed K.K.の松岡です。
我が家にSenseCAP M1 LoRaWAN Indoor Gatewayを設置しました。SeeedのLoRaWANゲートウェイモジュールとRaspberry Pi 4が入ったLoRaWANゲートウェイなのですが、Heliumに参加させるとコツコツとマイニングしちゃうという製品です。いろんなことを考える人がいますね。

さて、前回にreTerminalに内蔵されているハードウェアセキュリティモジュールATECC608Aをプロビジョニングして使えるようになりました。
今回は、ATECC608Aに隠蔽している秘密鍵を使って、Azure IoT Hubと接続してみましょう。

3つの認証方法

マイクロソフトのクラウドサービスAzureでは、IoTデバイスからのデータ受け取りはAzure IoT Hubが担っています。そして、Azure IoT HubからAzureのデータ保管や分析といった各種サービスに繋ぐことで全体のシステムを構築します。
Azure IoT Hubでは、個々のデバイスを認証する方法が3つあります。

  • 対称キー(Symmetric Key)
  • 自己署名X.509証明書(X.509 Self-Signed)
  • CA署名X.509証明書(X.509 CA Signed)

ATECC608Aで隠蔽している秘密鍵を使えるのは、自己署名X.509証明書とCA署名X.509証明書です。今回は、パッと試しやすい自己署名X.509証明書にしたいと思います。

自己署名X.509証明書でAzure IoT Hubと接続しよう

Azure IoT Hubの自己署名X.509証明書による認証は、次のように準備、動作します。
あらかじめ、デバイス証明書の拇印(Finger Print)をAzure IoT Hubのデバイスに設定しておきます。この拇印(Finger Print)は、ATECC608A内の秘密鍵(Private Key)から証明書(Certificate)を作成して、さらに証明書(Certificate)から拇印(Finger Print)を算出することで得ることができます。アプリケーションは証明書(Certificate)とATECC608A内の秘密鍵(Private Key)を使って、Azure IoT Hubに相互認証(Mutual Authentication)で接続します。接続されたAzure IoT Hubは、受け取った証明書(Certificate)とデバイスに設定された拇印(Finger Print)が一致するかチェックします。

図示するとこちら。文章だと理解しにくいですが、図にするとすぐに把握できるのではないでしょうか。

それでは、ステップバイステップで説明します。

環境構築

Azure IoT Hubを作成

AzureにAzure IoT Hubを作成します。
特に注意すべきことはありません。ちょっと試すだけなら、F1(無料プラン)でOKです。


デバイス証明書を作成

opensslコマンドで、ATECC608A内の秘密鍵から証明書ファイル(reterminal.cer)を作成します。
ここでは、証明書の有効期限を365日後にしています。

$ openssl req -engine pkcs11 -key "pkcs11:token=MCHP;object=device;type=private" -keyform ENGINE -new -x509 -days 365 -out reterminal.cer -subj "/CN=reterminal"

Azure IoT Hubにデバイスを作成

Azure IoT Hubにデバイスを作成します。
その際、証明書の拇印が必要なので、先に、opensslコマンドで証明書ファイル(reterminal.cer)から算出しておきます。

$ openssl x509 -sha1 -fingerprint -noout -in reterminal.cer | sed -e 's/://g'

環境の確認

以上でAzure IoT Hubの準備が整いました。
アプリケーションから接続する前に、正しく環境が出来ているかcurlコマンドで確認しましょう。

curlコマンドで、Azure IoT HubへHTTPSでメッセージを送信します。下記curlコマンドの{fully-qualified-iothubname}{device-id}は適切に変更してください。

curlコマンド 説明
{fully-qualified-iothubname}.azure-devices.net ホスト名 SeeedJPIoTHub.azure-devices.net
{device-id} デバイスID reterminal
$ curl --cert reterminal.cer --key "pkcs11:token=MCHP;object=device;type=private" https://{fully-qualified-iothubname}.azure-devices.net/devices/{device-id}/messages/events?api-version=2020-03-13 -X POST -d '{"message":"hello world"}'

Azure IoT Hubにメッセージが到達しているか否かは、Azure IoT Explorerなどで確認してください。

Azure IoT Device SDK for Cを使って接続

次は、アプリケーションから自己署名X.509証明書でAzure IoT Hubに接続してみましょう。
マイクロソフトから便利なSDK、Azure IoT Device SDK for Cが提供されているので、こちらを使用します。

言語はPythonにしたかったのですが、、、
Python用にAzure IoT SDK for Pythonが提供されていますが、これを使ってATECC608A内の秘密鍵を利用することはできませんでした。

ツールをインストール

Azure IoT Device SDK for Cの前提条件のツールをインストールします。

$ sudo apt update
$ sudo apt install -y git cmake build-essential curl libcurl4-openssl-dev libssl-dev uuid-dev ca-certificates

Azure IoT Device SDK for Cをダウンロード

GitHubから、Azure IoT Device SDK for Cをダウンロードします。
現時点の最新リリースはLTS_01_2022_Ref01でした。

$ git clone -b LTS_01_2022_Ref01 https://github.com/Azure/azure-iot-sdk-c.git
$ cd azure-iot-sdk-c
$ git submodule update --init

サンプルコードがコンパイルできるか確認

動かすアプリケーションはAzure IoT Device SDK for Cに入っているiothub_ll_client_x509_sampleです。
とりあえず、未修正でコンパイルが通るか確認します。

$ mkdir cmake
$ cd cmake
$ cmake -Dbuild_service_client=OFF -Dbuild_provisioning_service_client=OFF -Duse_amqp=OFF -Duse_http=OFF ..
$ make iothub_ll_client_x509_sample

サンプルコードを編集

iothub_client/samples/iothub_ll_client_x509_sample/iothub_ll_client_x509_sample.cを4箇所、変更します。

  • #define SAMPLE_OPENSSL_ENGINE "pkcs11"をコメント解除
  • connectionStringの値をHostName={fully-qualified-iothubname}.azure-devices.net;DeviceId={device-id};x509=trueに変更
  • x509certificateの値をデバイス証明書(reterminal.cer)の中身に変更
  • x509privatekeyの値をpkcs11:token=MCHP;object=device;type=privateに変更

サンプルコードをコンパイル、実行

コンパイルして実行します。

$ make iothub_ll_client_x509_sample
$ iothub_client/samples/iothub_ll_client_x509_sample/iothub_ll_client_x509_sample

変更履歴

日付 変更者 変更内容
2022/4/19 松岡 作成