AWS IoT EduKit通して学ぶ「クライアント証明書入りセキュアエレメント」の使い方

こんにちは、[AWS IoT Hero](https://aws.amazon.com/developer/community/heroes/kohei-matsushita/)のソラコム松下(ニックネーム:Max)です。

このブログでは、AWS re:Invent 2020 で新たに発表されたAWS製のリファレンスデバイス「[AWS IoT EduKit](https://aws.amazon.com/jp/about-aws/whats-new/2020/12/introducing-aws-iot-edukit/)」について、このキットから何が学べるのかを紹介します。

ちなみに、AWS IoT EduKitの開発環境の作り方は[AWS IoT EduKitのページ](https://edukit.workshop.aws/jp/getting-started.html)、もしくは[Ubuntu 20.04 + VirtualBox 6.1でAWS IoT EduKitの開発環境を作る](https://qiita.com/ma2shita/items/164fdf8f30e41f01540e)をご覧ください。

また、AWS IoT EduKit を含め AWS re:Invent 2020の新発表の中で IoT で注目したい新発表や新サービスは「[IoTに関わるなら押さえておきたい「AWS re:Invent 2020の新サービスと新発表](https://blog.soracom.com/ja-jp/2021/01/14/new-services-at-aws-reinvent-2020-by-viewpoint-of-iot/?utm_source=qiita&utm_medium=ext&utm_campaign=blog)」にまとめておきました。

## AWS IoT EduKit とは？

AWS IoT EduKitは、マイコンと[AWS IoT Core](https://aws.amazon.com/jp/iot-core/)(以下、IoT Core)との連携について学ぶことができるデバイスです。オレンジ色がかわいいですね。
AWS IoT EduKit(以下、EduKit)とは、[Microchip社製のATECC608A Trust&GOセキュアエレメント](https://www.microchip.com/en-us/products/security-ics/trust-platform/trust-and-go)を搭載した [M5Stack Core2](https://www.switch-science.com/catalog/6530/)です。
![AWS IoT EduKit](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/29e436cb-24e8-2f57-96b3-ebcac344e1e5.png)
Bottom(下側の部品)のU4の位置に実装されているのがATECC608A Trust&GOセキュアエレメントです。回路図は[スイッチサイエンスさんの商品ページ](https://www.switch-science.com/catalog/6784/)からリンクされています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/957f8ddb-2aa5-bffc-d703-dbf49d828d7d.png)
[日本でも販売されており](https://www.switch-science.com/catalog/6784/)、[オンラインのワークショップテキストも公開](https://edukit.workshop.aws/jp/getting-started.html)されています。
このテキストには[定番のLチカ](https://edukit.workshop.aws/jp/blinky-hello-world.html)[^1]から、[エアコン制御の実装例](https://edukit.workshop.aws/jp/smart-thermostat.html)、機械学習サービスであるAmazon SageMakerを取り入れた[自動空調管理](https://edukit.workshop.aws/jp/smart-spaces.html)に加え、[Alexa Voice Service Integration for AWS IoTからの制御](https://edukit.workshop.aws/jp/intro-to-alexa-for-iot.html)が盛り込まれていて、AWSを活用したIoT学習ができるようになっています。

(**2/12追記**) EduKitのサンプルはFreeRTOSで書かれているため、FreeRTOSの実装例として学ぶことができます。また、マイコンでAlexaの機能を実現できるといった面においても、小型／省電力なAlexaデバイス作りの実際を知ることができるわけです。

ただ、これらの例は、**IoT Core + Raspberry Piでも実現できる**わけですが、では、EduKitからは何が学べるのかを考えていきたいと思います。

[^1]: 「LEDをチカチカ点灯させる」からLチカ。デバイスを使ったプログラミングのHello Worldです。

## 先に結論

EduKitは、ハードウェアの開発者が**クライアント証明書入りのセキュアエレメントを(ATECC608A Trust&GO)使った、AWS IoT Coreとの連携方法を学ぶためのキット**です。

クライアント証明書入りセキュアエレメントを使うことで以下の利点があります。

1. **IoT Core接続時に使うクライアント証明書の作成やCA運用が不要**
2. **ハードウェア内に格納した秘密鍵の漏洩対策が不要**

この利点は、EduKitの以下2点を通じて学ぶことができます。

1. ATECC608A Trust&GO内のクライアント証明書でIoT Coreへ登録する方法
2. IoT Coreへの接続時にATECC608A Trust&GO内の秘密鍵を使用する方法

ちなみにこの仕組みは、以下2つによって成立しています。

1. Microchip社のプロビジョニング済みセキュアエレメントソリューション「[Trust Platform](https://eetimes.jp/ee/articles/1910/01/news117.html)」
2. IoT Coreの「[CAを使用しないクライアント証明書登録の仕組み](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/manual-cert-registration.html#manual-cert-registration-noca-cli)」

## 利点1. IoT Core接続時に使うクライアント証明書の作成やCA運用が不要

IoT Coreへの接続には認証が必須です。
認証には[いくつか方法があります](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/client-authentication.html)が、中でも[X.509 クライアント証明書を利用した方法](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/x509-client-certs.html)では、クライアント証明書と対となる秘密鍵の2つが必要です。

この対を作る/準備する方法は4つあります。

| # | 方法                  | 概要とPros/Cons |
|---|-----------------------|-------------|
| 1 | [1-Click 証明書作成](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/device-certs-create.html)    | AWS IoT Core の管理画面で作成可能。最も手軽だが、得られた秘密鍵とクライアント証明書をデバイスに転送する必要あり。 |
| 2 | [CSR による作成](https://dev.classmethod.jp/articles/aws-iot-create-certificate-with-csr/)        | 手元の秘密鍵を利用できる。秘密鍵から署名リクエスト(CSR)を作成し、IoT Coreに署名依頼をするとクライアント証明書が得られる。クライアント証明書をデバイスに転送する必要あり。 |
| 3 | [独自CAの運用](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/device-certs-your-own.html)          | 手元の秘密鍵とクライアント証明書を利用できる。大量デバイスの管理に適してはいるが、初期設定として独自CAをIoT Coreへ登録する事と独自CA自体の適切な運用が必要。さらに、デバイスの接続前にデバイス毎のクライアント証明書をIoT Coreへ登録する必要あり。クライアント証明書の接続前登録は、[ジャストインタイム](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/auto-register-device-cert.html)で軽減は可能。 |
| 4 | [CAを登録せずにクライアント証明書を登録する](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/manual-cert-registration.html#manual-cert-registration-noca-cli) | 手元の秘密鍵とクライアント証明書を利用できる。クライアント証明書へ署名しているCAがIoT Coreに登録されて無くても良いが、デバイスの接続前にはクライアント証明書をIoT Coreに登録する必要あり。 |

2~4は秘密鍵、もしくは対となるクライアント証明書が手元に存在する前提の仕組みです。これは例えばopensslコマンドで作成できます。(openssl を使った方法は [opensslとmosquittoでAWS IoT Coreの "CAを登録せずにクライアント証明書を登録する" を試す](https://qiita.com/ma2shita/items/23b91de6df70711119c7) で解説しています。)

一方、ATECC608A Trust&GOは "プロビジョニング済み" 即ち、秘密鍵とクライアント証明書が格納された状態で出荷されるため、**秘密鍵やクライアント証明書の作成が不要**です。これが[Trust Platform](https://eetimes.jp/ee/articles/1910/01/news117.html)と呼ばれるソリューションです。
ちなみにですが、一般的にはセキュアエレメントにはクライアント証明書は入っていません。そのため、セキュアエレメント内のコマンド(opensslコマンド相当)で作成することになります。Trust Platformはここを軽減してくれるわけです。

ATECC608A Trust&GOから取り出したクライアント証明書の署名者を確認すると `Microchip Technology Inc.` となっています。(取出しや署名者確認は後半で紹介しています。)
これまではIoT CoreにCA登録されていない署名者のクライアント証明書は登録に使えなかったのですが、「[CAを登録せずにクライアント証明書を登録する](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/manual-cert-registration.html#manual-cert-registration-noca-cli)」によって、 **IoT CoreのCAとして登録されていないMicrochip社のCAによって署名されたクライアント証明書でも、IoT Coreに登録できるようになった** わけです。

## 利点2. ハードウェア内に格納した秘密鍵の漏洩対策が不要

これまで解説してきた利点は、クライアント証明書と秘密鍵が入ったmicroSDを配布しても同様のことが実現できます。ここにセキュアエレメントを利用する理由は、**秘密鍵の漏洩対策が不要になる** という面があるからです。

ここでIoT Coreに接続するための情報を再確認すると、これまで解説していた「クライアント証明書」「秘密鍵」の他に「サーバー証明書」と「エンドポイントアドレス」と、計4つの情報を使います。
このうち秘密鍵以外は読もうと思えば読めてしまう情報であるため、**秘匿すべき情報は「秘密鍵」**となります。

秘密鍵をmicroSDといった読み書きが容易なストレージに入れておくのは、セキュリティリスクです。そのため、例えばファイルシステムを暗号化したりといった漏洩対策を行うわけですが、正直手間です。
**ATECC608A Trust&GO内の秘密鍵は、セキュアエレメントの特徴によって保護されているため、面倒な漏洩対策が不要になります。**

### セキュアエレメントの特徴

セキュアエレメントとは、情報を安全に格納するストレージと、暗号化を補助するロジックや乱数生成が実行できるコプロセッサが一体化したハードウェアモジュールです。メインのCPUやMCUからはI2C等を利用して接続してアクセス(読み/書き/実行)します。

特徴は、内部情報には決められた手続きのみでアクセスが可能で、それ以外の手続きを用いたアクセスや回路解析といった事が困難なように作られています(耐タンパー性が高いと表現されます)。
読むのも書くのも大変なので**複製が極めて困難で、信頼性を保証するための要素(Root of Trust(RoT); 信頼の基点)して利用されます。**

身近な例としてはクレジットカードのICチップ部分やおサイフケータイ(NFC)、スマートフォンの通信で使われるSIMもセキュアエレメントです。

- 資料
  - [IoTデバイスにおける ハードウエア・セキュリティ機能の活用](https://emb.macnica.co.jp/articles/9142/)
  - [SORACOM Technology Camp 2018 アドバンストラック2 | 売れば売るほど大変"を防ぐ！「IoT デバイス初期設定の工数削減」手法 P16より](https://www.slideshare.net/SORACOM/soracom-technology-camp-2018-2-iot-123686996/16)

以上2点の利点を踏まえたうえで、学習ポイントを実装から見ていきます。

## 学習ポイント1. ATECC608A Trust&GO内のクライアント証明書でIoT Coreへ登録する方法

まず最初はATECC608A Trust&GO内からクライアント証明書を取り出し、IoT Coreへ登録している部分です。実はIoT Coreへの登録はM5Stack Core2ではなく、開発PC上で動かすPythonが担当しています。

具体的には [registration_helper.py](https://edukit.workshop.aws/en/blinky-hello-world/device-provisioning.html#retrieving-the-device-certificate-and-registering-your-aws-iot-thing) です。中身は[ここ](https://github.com/m5stack/Core2-for-AWS-IoT-EduKit/blob/master/Blinky-Hello-World/utilities/AWS_IoT_registration_helper/registration_helper.py)です。

このスクリプトで注目すべき点は2つです。

- セキュアエレメントからクライアント証明書を取り出す  ([該当部分](https://github.com/m5stack/Core2-for-AWS-IoT-EduKit/blob/8abc337aed317e306a3acd89dc2bb72901f77cfd/Blinky-Hello-World/components/esp-cryptoauthlib/esp_cryptoauth_utility/helper_scripts/manifest.py#L195))
- `register_certificate_without_ca` APIを使いIoT Coreへ登録 ([該当部分](https://github.com/m5stack/Core2-for-AWS-IoT-EduKit/blob/ccf065cfaec97dfa08c1fff035ee9c54b76037c8/Blinky-Hello-World/utilities/trustplatform/TrustnGO/Microchip_manifest_handler.py#L115))
    - 使用している API
        - register-certificate-without-ca
        - attach-policy
        - update-certificate
        - create-thing
        - attach-thing-principal

ATECC608A Trust&GOからクライアント証明書が取り出せたら、あとは上記のAPIをAWS CLIで叩いても同じことができます。クライアント証明書の取出しは、後述の「対話shell」で直接行えます。

※ registration_helper.py は途中で `Manifest.json` を生成しています。EduKitという点ではあまり関係ありませんが、ATECC608A Trust&GOを用いて量産する時には重要です。量産時にいちいちデバイスからクライアント証明書を抜き出すのは非現実的です。そこで、ATECC608A Trust&GOは部品購入するとクライアント証明書が入った `Manifest.json` が入手でき、これを使ってIoT Coreへ一括登録できます。

### ATECC608A Trust&GOとの対話shell

registration_helper.py を基に、ATECC608A Trust&GOとの対話shellを作りました。([ATECC608A_shell.py](https://gist.github.com/ma2shita/37f5b68f4a7e1829220a7702ac082ae4))
EduKit の開発環境が揃った環境で実行できます。

```console:ATECC608A_Trust&GOとの対話shell
$ cd Core2-for-AWS-IoT-EduKit/Blinky-Hello-World/
$ curl -O https://gist.githubusercontent.com/ma2shita/37f5b68f4a7e1829220a7702ac082ae4/raw/12bba55527b3d5b2c1e3b7ce04eb605e0caabb36/ATECC608A_shell.py
$ source ~/esp/esp-idf/export.sh
$ PYTHONSTARTUP=ATECC608A_shell.py python
```

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/90ef9b2e-287e-24dc-847a-605e3e8435a6.gif)
※動画では証明書の一部のみ表示するように手を加えています

得られたクライアント証明書はopensslコマンドで検証できるほか、AWS IoT Core への登録に(もちろん)利用できます。

```console
$ openssl x509 -issuer -noout -in fetched_client.crt.pem
issuer=O = Microchip Technology Inc, CN = Crypto Authentication Signer 2A00
```

## 学習ポイント2. IoT Coreへの接続時にATECC608A Trust&GO内の秘密鍵を使用する方法

クライアント証明書をIoT Coreへ登録したら、接続の準備は完了です。実際にEduKitから接続する部分を見ていきます。

EduKit からIoT Coreへの接続については、`#if defined(CONFIG_AWS_IOT_USE_HARDWARE_SECURE_ELEMENT)` によるブロックが該当します。
サンプルコード内を [`CONFIG_AWS_IOT_USE_HARDWARE_SECURE_ELEMENT` でgrep](https://github.com/m5stack/Core2-for-AWS-IoT-EduKit/search?q=path%3ABlinky-Hello-World%2F+CONFIG_AWS_IOT_USE_HARDWARE_SECURE_ELEMENT)すればすぐ見つかります。

注目すべき点は [`network_mbedtls_wrapper.c` の 204行目](https://github.com/m5stack/Core2-for-AWS-IoT-EduKit/blob/1c791321848c12ef859d44ae130b12368d4278d1/Blinky-Hello-World/components/esp-aws-iot/port/network_mbedtls_wrapper.c#L204)の [`atca_mbedtls_pk_init()`](https://microchiptech.github.io/cryptoauthlib/a01526.html#ga72da31831a3647e287543634e3f78aca)と、[218行目](https://github.com/m5stack/Core2-for-AWS-IoT-EduKit/blob/1c791321848c12ef859d44ae130b12368d4278d1/Blinky-Hello-World/components/esp-aws-iot/port/network_mbedtls_wrapper.c#L218)の [`mbedtls_pk_parse_key()`](https://tls.mbed.org/api/pk_8h.html#a072d27dc4143bfd600786232f9417e08)です。ここで ATECC608A Trust&GO 内の秘密鍵を使ってTLSクライアント認証に必要な情報を取り出しています。

ちなみに `CONFIG_AWS_IOT_USE_HARDWARE_SECURE_ELEMENT` の前後を見ると、ATECC608A Trust&GOを使わずに別途作成したクライアント証明書と秘密鍵でも動くように作られています。
即ち、クライアント証明書と秘密鍵の部分以外は、一般的な[mbed TLS](https://tls.mbed.org/api/index.html)を使ったTLS接続の実装で良いことがわかります。

## まとめ

AWS IoT EduKiTは、ハードウェアを作る人に「セキュアエレメント使うといいよー」というのを感じてもらうためのキットです。
そういった意味ではBlinky-Hello-Worldさえ動けば、EduKitの意義は達成です。IoT EventsやAlexaと連携出来なくても気にしないでください。というか、そういうのはRaspberry Piとかでやった方が楽で面白いです。

ATECC608A Trust&GOに話を戻すと、MCUとの通信はI2Cですので実装も容易にできそうですし、MOQ(最小発注単位)が10と小規模でも始められるようになっているのは、やはり「セキュアエレメント使ってねー」というメッセージでしょう。

一方で、クライアント証明書の登録作業はパソコンからとなります。
デバイス自身で登録も行わせたい場合は、現時点では独自CAによる[ジャストインタイム登録](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/auto-register-device-cert.html)となります。セキュアエレメント内のクライアント証明書で直接登録できるようになるソリューションを期待したいところです。

### ちなみに: SIM を使ったプロビジョニングサービス「SORACOM Krypton」のご紹介

IoT プラットフォーム「SORACOM」では、SIMを使ってIoT Coreの秘密鍵とクライアント証明書を得ることができる「[SORACOM Krypton](https://soracom.jp/services/krypton/?utm_source=qiita&utm_medium=ext&utm_campaign=blog)」というサービスがあります。
最大の利点は、独自CAやジャストインタイム登録の仕組みを持つことなく、デバイス完結型ソリューションを実現できることにあります。

![](https://soracom.jp/img/fig_krypton-image01.png)

これは、SIMがユニークなIDを持つセキュアエレメントである事と、そのSIMによる3G/LTE通信(SORACOM Air)をSORACOMプラットフォームで一意に識別することができることで実現しています。具体的にはデバイスからの要求に応じてKryptonはIoT Coreに対して1-Click 証明書作成を代行します。そして得られた秘密鍵とクライアント証明書を3G/LTEの暗号化通信でデバイスに転送します。

得られた秘密鍵とクライアント証明書は、Wi-Fi経由でも利用可能です。よって、秘密鍵とクライアント証明書の取得にだけ3G/LTE(SORACOM Air)とKryptonを使い、普段のIoT Coreとの通信はWi-Fiを利用するといった構成も可能となります。

秘密鍵とクライアント証明書の保管先自体は管理する必要がありますが、Kryptonは要求毎に新しい秘密鍵とクライアント証明書が発行されます。そのため、例えば周期を短くして過去の秘密鍵を無効化していくアプローチでセキュリティリスクを軽減できます。

SORACOM KryptonはAWS IoT Coreだけでなく、Amazon CognitoによるSTS(AWS Security Token Service)も対応しています。ご興味があれば[SORACOM Krypton ユーザーガイド](https://dev.soracom.io/jp/krypton/what-is-krypton/?utm_source=qiita&utm_medium=ext&utm_campaign=blog)をご覧ください。

## あとがき

一時はどうなるかと思いましたが、かき揚って良かった。
参考資料にかなり助けられました、ありがとうございましたー。
※間違ってるところがある気がする。修正依頼はお気軽に、というかお願いします！

### 参考資料

- [図解 X.509 証明書 / Qiita](https://qiita.com/TakahikoKawasaki/items/4c35ac38c52978805c69)
- [opensslとmosquittoでAWS IoT Coreの "CAを登録せずにクライアント証明書を登録する" を試す / Qiita](https://qiita.com/ma2shita/items/23b91de6df70711119c7)
- [NXP SE050検証(AWS IoT Multi-Account Registration接続テスト) / Qiita](https://qiita.com/kmitsu76/items/b7bb4146117a9a59412e)
- [ATECC608A-TNGTLS検証(AWS IoT Multi-Account Registration接続テスト) / Qiita](https://qiita.com/kmitsu76/items/4959859c02da479c26c1)
- [Secure element for IoT device](https://www.slideshare.net/KentaroMitsuyasu1/secure-element-for-iot-device)
- [SE050 を使用して AWS IoT Core へ接続する / Armadillo HowTo](https://armadillo.atmark-techno.com/howto/aiot_g3m1-se050-demo_connect_aws_iot_core)
- [AWS IoT サービス アップデートのご紹介](https://www.slideshare.net/AmazonWebServicesJapan/aws-iot-238410946/25)
- [マルチアカウント登録による複数の AWS アカウントでの X.509 クライアント証明書の使用](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/x509-client-certs.html#multiple-account-cert)

EoT