NXP SE050検証(AWS IoT Multi-Account Registration接続テスト)(NXP SE050 AWS IoT connection test by using Multi-Account Registration)

#はじめに#
2019/12/14に開かれた　IoTSecJPにてお時間をいただき
[セキュアエレメントとIoTデバイスセキュリティ](https://www.slideshare.net/KentaroMitsuyasu1/secure-element-for-iot-device)
と題してお話させていただきました。
その内容をベースにまとめていきたいと思います。

#AWS IoTのMulti-Account Registrationとは#
2019年9月にベータリリースの機能となる。
概要は[リンク先](https://pages.awscloud.com/iot-core-early-registration.html)にあるが、以下のように証明書を使った安全なデバイス接続を簡単に行える機能らしい。

「コンポーネント/デバイスメーカーは、固有の顧客固有のCAを維持する必要なく、デジタルID（証明書）が事前にプロビジョニングされたコンポーネントを提供できます。
お客様は同じデバイス証明書を使用して、同じリージョン内の複数のAWSアカウントにデバイスを登録できるようになりました。たとえば、顧客は同じ証明書を同じリージョンのテスト用アカウントと本番用アカウントに登録できます。その後、お客様は、デバイスをAWS IoTに初めて接続するときにアカウントを指定することにより、これらのAWSアカウント間でデバイスを簡単に移動できます。」

CAの管理をせずに、デバイスが安全に接続できるかどうか、
NXP　SE050 でこの機能を利用したサンプルプログラムが利用できるようなので、一度整理してみる。

#Multi Account Registrationの概要#

いわゆる通常のCAを利用したデバイスの自動登録は、AWSではJust-In-Time-Registrationといい、下記の図のようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/ccb9f891-0648-bfe9-15c1-34fc1bc49adb.png)
①、は、ユーザー用意のCAが存在し、正しいユーザーがCA秘密鍵を持っていることの証明をするために
CAごとに1回発生する登録作業。
②、ではユーザー用意のCAを使い、デバイス毎にSE050からPublic keyを抜き出し証明書を作成し、書き戻してスタンバイする
③、でAWS IoTに接続する前に作成したデバイス証明書を提示し、Just In Time Registrationに登録された証明書チェーンを確認し、問題なければ④で通信開始
といった流れになる。
「ユーザー用意のCA」とは、いわゆる自己認証局でもいいが、CA秘密鍵の保護など、セキュアな運用は難しいと考えられる。それをなくそうというのがMulti-Account Registrationのようだ。

NXP SE050実チップとESP32を3セット程使っていろいろ試した結果以下のような動きになりそうだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/aab9a2c2-f33d-6684-76d6-c79cf4eb2b68.png)
ユーザーの設定とは関係なく、各チップに固有のデバイス証明書がSE050に書き込まれている。署名者はチップメーカーのCAとなる。
①、でそのデバイス証明書を抜き出し、AWS CLIで登録をする。
②、でAWS IoTに接続する前にデバイス証明書を提示し、Multi-Account Registrationに登録された証明書を確認及びSNIを確認し、問題なければ③で通信開始

#準備#
まず、上記ベータ版のページからベータ版アクセスの登録を行う。
AWSリージョンとAWSアカウントIDの指定が必要。自分がAWS IoT Coreを立ち上げている、立ち上げる予定のリージョンを選択する。

数日でメールでMulti-Account Registrationが有効になった旨のメールが来る。そのリンクにMulti-Account Registrationを有効にする手順と必要になるファイルがダウンロードできるリンクが記載されている。

流れとしてはAWS CLIをセットアップした後、（AWS CLI バージョン1(1.18.31)でもバージョン2(2.0.5)でも問題なかった）Multi-Account Registrationを有効にしたAWSアカウントIDのユーザーで接続し、

```
aws configure add-model --service-model file:///path/to/iot-2015-05-28.normal.json --service-name iot
```
上記でAWS CLIにMulti-Account Registrationの追加機能をインストールする。

これを行うことで、aws iot register-certificate-without-caというコマンドが使えるようになる。
上記をインストールしないと、

```
aws: error: argument operation: Invalid choice, valid choices are:

accept-certificate-transfer              | add-thing-to-billing-group
add-thing-to-thing-group                 | associate-targets-with-job
………
```
当然ベータ版の機能なので、AWS CLIが理解できずエラーが出る。

#デバイス毎のデバイス証明書の準備#

上記①を行うためのデバイス証明書を抜き出す。
[NXP SE050検証(証明書読み出し)(NXP SE050 cerificate extraction by using ESP32)](https://qiita.com/kmitsu76/items/91829a15025ee2afa925)で記事にした内容を実行すると、シリアルコンソールにデバイス証明書がpemフォーマットで表示される。
これに適当な名前を付けてファイル保存する。

これでやっている内容は、
Cloud Connectivity Certificate 0, ECC signed
Cert: 0xF0000101
SE050内に上記のオブジェクトIDで保存されている証明書を読み出す作業となる。
3つのデバイスで同様に抜き出したところ、NXP社署名でECC P256の証明書となり、下記のようになっていた。

CAのコモンネーム：共通
Subject Alt Name(SAN)：共通
当然ながら署名者は同一のCAとなり、デバイスCN等のその他の値はユニークとなっていた。

上記が準備できたらAWS CLIで登録を行う。

```
aws iot register-certificate-without-ca --certificate-pem file:///path/to/com6trustedcert.crt --status ACTIVE

{
    "certificateArn": "arn:aws:iot:ap-northeast-1:1XXXXXXXX04:cert/7e5…………..deb28a",
    "certificateId": "7e5…………deb28a"
}

```
上記で登録できたが、ポリシーと紐付けしなくてはならないらしい。
ポリシーのテンプレートファイルが用意されているので登録してみる。

```
aws iot create-policy --policy-name wildCardPolicy --policy-document file:///path/to/wildCardPolicy"
{
    "policyName": "wildCardPolicy",
    "policyArn": "arn:aws:iot:ap-northeast-1:14XXXXXXXX04:policy/wildCardPolicy",
    "policyDocument": "{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"iot:Connect\",\n                \"iot:Publish\",\n                \"iot:Receive\",\n                \"iot:Subscribe\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        }\n    ]\n}\n",
    "policyVersionId": "1"
}
```

登録できたポリシーへデバイス証明書を紐づけ。

```
aws iot attach-policy --target "arn:aws:iot:ap-northeast-1:14XXXXXXX04:cert/7e5………deb28a" --policy-name wildCardPolicy
```

接続先エンドポイントアドレスを入手する。これがデバイス側からの接続URLとなり、今回のAWS IoT Coreに接続するデバイス共通の値となる。

```
aws iot describe-endpoint --endpoint-type iot:Data-ATS
{
    "endpointAddress": "XXXXXXXXXX-ats.iot.ap-northeast-1.amazonaws.com"
}
```

これを3つのデバイス分行うと下記の通りとなった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/e7bc4d38-5066-bc9e-e7d9-3d39ef75f50c.png)

#デバイス証明書を提示するESP32のコード作成#

上記で必要になる登録が済んだが、ESP32からこのAWSに接続するためのコードを作成した。
[NXP-SE050-AWS-IoT-Multi-Account-Registration-Test](https://github.com/kmwebnet/NXP-SE050-AWS-IoT-Multi-Account-Registration-Test)

ポイントは、デバイス証明書を提示する、mbedtls_ssl_conf_own_certへ与える証明書を、
上記で読み出したCert: 0xF0000101のオブジェクトIDから読み出すこと、
この証明書の秘密鍵を、

```
sss_mbedtls_associate_keypair(&(tlsDataParams->pkey), &pex_sss_demo_tls_ctx->obj);
```

で登録すること。

CA証明書はSE050内にも十分入るが、ひとまずAmazonRootCA1.pemをコード内にべた張りし、読み込ませた。

また、MQTTクライアントIDがかぶると接続クローズされるので、ユニークな値としてSE050のUIDをBase64にして作成、代入した。

そうして同時に3つのデバイスから接続テストを行った。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/ef35b909-f173-50b9-1991-64d8ff6a41b3.png)

3つのデバイスからのトピックの受信、AWS IoTからのトピックへのパブリッシュ内容を3つのデバイスで受信が行えた。

#考察#
①の手順のデバイスごとにデバイス証明書を登録する作業について、デバイス証明書は製品出荷時に決まっている値なので、別で台帳でもらって自分の契約AWSアカウントIDへ一括登録をかけることができれば、デバイスに個別に行う作業はなくなるので都合がいい。
そういう契約もあるそうなので、利用すればよりAWS IoTへの安全な接続が楽になるだろう。

Microchip社のATECC608Aの新しいTrust&Goという仕掛けもどうも同じ仕組みを使うもののようだ。