セキュアなIoTデバイス通信をやってみた(ATECC608A基本編)

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

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

#前回までのあらすじ#
[セキュアなIoTデバイス通信をやってみた(環境構築編)](https://qiita.com/kmitsu76/items/768d320069d9a2e764fa)でセキュアエレメントを選定、環境を構築し、Arduinoのサンプルプログラムで、ESP32からI2C上でATECC608Aが認識できたところまで行いました。

#開発環境構築#
[ESP-IDF](https://github.com/espressif/esp-idf)というESP32用に準備された開発環境を使用します。
MSYS32環境でターミナル上から開発する環境が標準だが、VScodeが使いたいということで、VSCode上でIoTデバイスの開発を可能にするPlatformioをセットアップします。

セットアップに関しては詳しい説明をしていただいている方を参考にセットアップ。
[PlatformIO IDE for VSCode でESP-IDF を利用したESP32プログラムの開発](https://kunsen.net/2018/09/04/post-1052/)

#ATECC608Aとの基本的な通信#
ATECC608Aは、内蔵されているEEPROMの領域の使い方の設定をコンフィグとして書き込み、初期化する必要があるようだ。また、いったんコンフィグを書き込んだ後はロックがかかり変更ができなくなる仕組みを備えている。

まず、コンフィグを触る前にATECC608Aとの通信を試してみる。
コードを下記リンクにて公開。
[ECC608-Simple-Connection-Test](https://github.com/kmwebnet/ECC608-Simple-Connection-Test)

まず、Platformioで新規プロジェクトを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/95de20cb-810c-824c-7182-fb53cb6d5ef6.png)
BoardはEspressif ESP32 Dev Moduleを選択。
FrameworkはESP-IDFを選択。

プロジェクトが完成後、以下のような構造のプロジェクトが出来上がるので、
src以下にコーディングを行っていく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/ae810d63-f239-9a04-869a-55b95c8d4d12.png)

■cryptoauthlibの組み込み
コマンドプロンプトからプロジェクトディレクトリで、gitを有効にし、サブモジュールとして組み込みさせる。

```
Microsoft Windows [Version 10.0.17134.765]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Users\johndoe>cd C:\Users\johndoe\Documents\PlatformIO\Projects\test

C:\Users\johndoe\Documents\PlatformIO\Projects\test>git init
Initialized empty Git repository in C:/Users/johndoe/Documents/PlatformIO/Projects/test/.git/

C:\Users\johndoe\Documents\PlatformIO\Projects\test>cd src

C:\Users\johndoe\Documents\PlatformIO\Projects\test\src>git submodule add https://github.com/MicrochipTech/cryptoauthlib
Cloning into 'C:/Users/johndoe/Documents/PlatformIO/Projects/test/src/cryptoauthlib'...
remote: Enumerating objects: 1172, done.
remote: Counting objects: 100% (1172/1172), done.
remote: Compressing objects: 100% (508/508), done.
remote: Total 11297 (delta 676), reused 990 (delta 664), pack-reused 10125
Receiving objects: 100% (11297/11297), 18.26 MiB | 4.20 MiB/s, done.
Resolving deltas: 100% (8698/8698), done.
warning: LF will be replaced by CRLF in .gitmodules.
The file will have its original line endings in your working directory
```

以降、platformio.iniに必要なコンパイラオプションを追記する。
特にCryptoauthlib内のhalフォルダに、各デバイス向けの移植を可能にする
コードが置かれている。
以下は最終のplatformio.ini。

```
; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = espidf
src_filter = 
    +<*>
    -<.git/> 
    -<svn/> 
    -<example/> 
    -<examples/> 
    -<test/> 
    -<tests/>
    -<cryptoauthlib/app/>
    -<cryptoauthlib/test/>
    -<cryptoauthlib/python/>
    -<cryptoauthlib/third_party/>
    -<cryptoauthlib/lib/hal/>
    -<cryptoauthlib/lib/basic/atca_helpers.c>
    +<cryptoauthlib/lib/hal/atca_hal.c>
    +<cryptoauthlib/lib/hal/atca_hal.h>
    +<cryptoauthlib/lib/hal/hal_esp32_timer.c>
    +<cryptoauthlib/lib/hal/hal_freertos.c>
build_flags = 
    -I "src/cryptoauthlib/lib"
    -I "src/cryptoauthlib" 
    -I "$PIOHOME_DIR/packages/framework-espidf/components/freertos/include/freertos" 
    -DESP32 
    -DATCA_HAL_I2C 
    -DATCA_PRINTF 
    -DATCA_USE_RTOS_TIMER 
upload_port = COM7
monitor_speed = 115200
```

ESP32で必要なのは、
cryptoauthlib/lib/hal/atca_hal.c
cryptoauthlib/lib/hal/atca_hal.h
cryptoauthlib/lib/hal/hal_esp32_timer.c
cryptoauthlib/lib/hal/hal_freertos.c
cryptoauthlib/lib/hal/hal_esp32_i2c.c

が必要となる。
しかし、hal_esp32_i2c.cはカスタマイズが必要なので、サブモジュールから取り出して、src直下のportフォルダを作り、そこにおいてカスタマイズをかける。

元のcryptoauthlib/lib/hal/hal_esp32_i2c.cはコンパイルに含めないようにしておく。

hal_esp32_i2c.cの変更ポイントは下記。

```
#define SDA_PIN                            21
#define SCL_PIN                            22
//ATECC608A の接続先ピン番号

            conf.mode = I2C_MODE_MASTER;
            conf.sda_io_num = SDA_PIN;
            conf.scl_io_num = SCL_PIN;
            conf.sda_pullup_en = GPIO_PULLUP_DISABLE;　//ピンのプルアップ指定
            conf.scl_pullup_en = GPIO_PULLUP_DISABLE;　//ピンのプルアップ指定
            conf.master.clk_speed = 100000; //cfg->atcai2c.baud;　//ポートの動作クロック

```

もう1か所、コンパイルでエラーが出るファイルがあるため、これも手元に持ってきて修正。
cryptoauthlib/lib/basic/atca_helpers.c

```
static void hex_to_lowercase(char *buffer, size_t length)
{
    if ((buffer != NULL) && (length > 0))
    {
        for (size_t index = 0; index < length; index++)
        {
            buffer[index] = tolower(buffer[index]);
        }
    }
}


static void hex_to_uppercase(char *buffer, size_t length)
{
    if ((buffer != NULL) && (length > 0))
    {
        for (size_t index = 0; index < length; index++)
        {
            buffer[index] = toupper(buffer[index]);
        }
    }
}

In file included from src\atca_helpers.c:30:0:
src\atca_helpers.c: In function 'hex_to_lowercase':
C:/Users/johndoe/.platformio/packages/framework-espidf/components/newlib/include/ctype.h:57:54: error: array subscript has type 'char' [-Werror=char-subscripts]

```
toupper,tolowerへ代入する型が違うらしい。
キャストを追加し修正。

```
static void hex_to_lowercase(char *buffer, size_t length)
{
    if ((buffer != NULL) && (length > 0))
    {
        for (size_t index = 0; index < length; index++)
        {
            buffer[index] = tolower((unsigned char)buffer[index]);
        }
    }
}


static void hex_to_uppercase(char *buffer, size_t length)
{
    if ((buffer != NULL) && (length > 0))
    {
        for (size_t index = 0; index < length; index++)
        {
            buffer[index] = toupper((unsigned char)buffer[index]);
        }
    }
}

```

元のファイルがコンパイルされないようにplatformio.iniに記載をする。

```
    -<cryptoauthlib/lib/basic/atca_helpers.c>
```

このままだとなぜか、ESP-IDF内のFreeRTOS.hを見つけられないので、
インクルードパスを記載、必要なコンパイルオプションを記入する

```
    -I "$PIOHOME_DIR/packages/framework-espidf/components/freertos/include/freertos" 
    -DESP32 
    -DATCA_HAL_I2C 
    -DATCA_PRINTF 
    -DATCA_USE_RTOS_TIMER 
```
これで大まかな組み込みが完了。
#コマンド内容#

■atcab_init()
ATECC608Aの初期化を行い、その他コマンドを受け付けられるようにする。

■atcab_release()
すべてのATECC608Aの使用を終了する。

上記の間にコマンドを実行する形。

■ATCA_STATUS atcab_read_serial_number(uint8_t* serial_number);
ATCA_STATUSはエラーを定義する構造体。
9バイトのシリアルナンバーを得るコマンド

■ATCA_STATUS atcab_info(uint8_t* revision)
4バイトのリビジョンナンバーを得るコマンド

■ATCA_STATUS atcab_read_config_zone(uint8_t* config_data)
128バイトのコンフィグデータを得るコマンド

これらをmain.cとして実行させ、シリアルコンソールの内容を確認する。

```
ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:5804
load:0x40078000,len:7924
load:0x40080000,len:5916
entry 0x40080314
I (29) boot: ESP-IDF 3.30103.190221 2nd stage bootloader
I (29) boot: compile time 19:29:47
I (29) boot: Enabling RNG early entropy source...
I (34) boot: SPI Speed      : 40MHz
I (38) boot: SPI Mode       : DIO
I (42) boot: SPI Flash Size : 4MB
I (46) boot: Partition Table:
I (50) boot: ## Label            Usage          Type ST Offset   Length
I (57) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (65) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (72) boot:  2 factory          factory app      00 00 00010000 00100000
I (80) boot: End of partition table
I (84) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x078ec ( 30956) map
I (103) esp_image: segment 1: paddr=0x00017914 vaddr=0x3ffc0000 size=0x02028 (  8232) load
I (107) esp_image: segment 2: paddr=0x00019944 vaddr=0x40080000 size=0x00400 (  1024) load
I (111) esp_image: segment 3: paddr=0x00019d4c vaddr=0x40080400 size=0x062c4 ( 25284) load
I (129) esp_image: segment 4: paddr=0x00020018 vaddr=0x400d0018 size=0x132b8 ( 78520) map
I (157) esp_image: segment 5: paddr=0x000332d8 vaddr=0x400866c4 size=0x029b8 ( 10680) load
I (167) boot: Loaded app from partition at offset 0x10000
I (167) boot: Disabling RNG early entropy source...
I (168) cpu_start: Pro cpu up.
I (172) cpu_start: Starting app cpu, entry point is 0x400816dc
I (0) cpu_start: App cpu up.
I (183) heap_init: Initializing. RAM available for dynamic allocation:
I (189) heap_init: At 3FFAFF10 len 000000F0 (0 KiB): DRAM
I (195) heap_init: At 3FFC30B8 len 0001CF48 (115 KiB): DRAM
I (202) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
I (208) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (214) heap_init: At 4008907C len 00016F84 (91 KiB): IRAM
I (221) cpu_start: Pro cpu start user code
I (239) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (799) ECC608: Serial Number:
0123xxxxxxxxxxxxee
I (799) ECC608: Revision Number:
I (799) ECC608: 00
I (799) ECC608: 00
I (799) ECC608: 60
I (799) ECC608: 02
I (799) ECC608: Config Zone data:
01 23 xx xx 00 00 60 02
xx xx xx xx ee 01 35 00
c0 00 00 01 8f 20 c4 44
87 20 87 20 8f 0f c4 36
9f 0f 82 20 0f 0f c4 44
0f 0f 0f 0f 0f 0f 0f 0f
0f 0f 0f 0f ff ff ff ff
00 00 00 00 ff ff ff ff
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
ff ff 00 00 00 00 00 00
33 00 1c 00 13 00 13 00
7c 00 1c 00 3c 00 33 00
3c 00 3c 00 3c 00 30 00
3c 00 3c 00 3c 00 30 00


```
問題なく通信できていることが確認できた。