ESP32-WROOM-32Eについて、従来品との違い

#はじめに

ESP32搭載のデバイスはM5stackをはじめ大変注目されているが、搭載されているEspressif社モジュール単体も簡単にWifi,Bluetoothを含んだプロトタイピングができることで注目を集めている。

ここ数か月で新製品の一つであるESP32-WROOM-32Eについて流通が活発になっている動きがあるので、違いについて整理する。

#従来品との違い

[espressif_products_ordering_information](https://www.espressif.com/sites/default/files/documentation/espressif_products_ordering_information_en.pdf)によると、2020/11/3時点で以下の通りである。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/16c2a99f-11f7-561e-16cf-24bf77c28bd4.png)

ESP32-WROOM-32EはESP32 ECO V3というリビジョンのチップを搭載していることと、従来店頭で買えたESP32-WROOM-32D、ESP32-WROOM-32はいずれも新規設計非推奨、つまり終売が近いことを表している。

ESP32 ECO V3のリビジョンの違いについて調べてみる。

[ESP32_ECO_V3_User_Guide](https://www.espressif.com/sites/default/files/documentation/ESP32_ECO_V3_User_Guide__EN.pdf)が詳細資料となる。

"Design Chanage in ECO V3"項目は下記の通り。

* 1.PSRAMキャッシュのバグ修正：「CPUが特定の順序で外部SRAMにアクセスすると、読み取りおよび書き込みエラーが発生する可能性がある」を修正しました。この問題の詳細は、ESP32ECOおよびバグの回避策の項目3.9に記載されています。   

* 2.「各CPUが特定の異なるアドレス空間を同時に読み取ると、読み取りエラーが発生する可能性がある」を修正しました。この問題の詳細は、ESP32ECOおよびバグの回避策の項目3.10に記載されています。 

* 3.最適化された32.768KHz水晶発振器の安定性。ECOV1ハードウェアでは、32.768KHz水晶発振器が正しく起動できない可能性が低いという問題がクライアントから報告されました。 

* 4.セキュアブートとフラッシュ暗号化に関するフォールトインジェクションの問題が修正されました。参照：フォールトインジェクションとeFuse保護に関するセキュリティアドバイザリ（CVE-2019-17391）およびフォールトインジェクションとセキュアブートに関するEspressifセキュリティアドバイザリ（CVE-2019-15894）

* 5.改善：CANモジュールでサポートされる最小ボーレートを25kHzから12.5kHzへ変更。 

* 6.新しいeFuseビットUART_DOWNLOAD_DISをプログラミングすることにより、ダウンロードブートモードを永続的に無効にすることができます。このビットが1にプログラムされている場合、ダウンロードブートモードは使用できず、ストラップピンがこのモードに設定されているとブートは失敗します。ソフトウェアは、EFUSE_BLK0_WDATA0_REGのビット27に書き込むことによってこのビットをプログラムし、EFUSE_BLK0_RDATA0_REGのビット27を読み取ることによってこのビットを読み取ります。このビットの書き込み無効化は、flash_crypt_cnteFuseフィールドの書き込み無効化と共有されます。

この中で特に、4.セキュアブートとフラッシュ暗号化に関するフォールトインジェクションの問題　について詳細を調べてみる。

#セキュアブートとフラッシュ暗号化に関するフォールトインジェクションの問題
フォールトインジェクションとeFuse保護に関するセキュリティアドバイザリ（CVE-2019-17391）について確認する。
[Security Advisory concerning fault injection and eFuse protections (CVE-2019-17391)](https://www.espressif.com/en/news/Security_Advisory_Concerning_Fault_Injection_and_eFuse_Protections)によると、

> フォールトインジェクションを使用して、リセット直後にESP32 CPUを物理的に中断する攻撃者は、内部ハードウェアによって読み取られているときにeFuseビットを破損する可能性があります。これには、eFuseの他の部分へのソフトウェア読み取りアクセスを制御する読み取り保護eFuseビットの破損が含まれます。

> このフォールトインジェクション攻撃により、eFuseに保存されているフラッシュ暗号化およびセキュアブートキーの読み取り保護をバイパスできます。多くの場合、キーは障害によって破損していますが、攻撃を繰り返して結果を分析することにより、完全なeFuseキー値が回復される可能性があります。

> 執筆時点では、現在利用可能なESP32チップ（ESP32-D0WD、ESP32-D2WD、ESP32-S0WD、ESP32-PICO-D4、および関連モジュール）はこの攻撃に対して脆弱です。 ESP32-D0WD-V3チップには、この攻撃を防ぐROMのチェックがあります。このチップと関連モジュールは2019年第4四半期に利用可能になります。ESP32-D0WD-V3の詳細はまもなくリリースされます。

> この問題は、LimitedResultsによって発見され、Espressifに開示されました。 Espressifは、この問題を責任を持って開示してくれたLimitedResultsに感謝します。」

ここで紹介されている[LimitedResults](https://limitedresults.com/posts/)氏というのは、バグハンターのようで数多くのSoC、チップの脆弱性について独自の調査結果を公開している。

[CVE-2019-17391に関するLimitedResults氏の投稿](https://limitedresults.com/2019/11/pwn-the-esp32-forever-flash-encryption-and-sec-boot-keys-extraction/)に詳細が記されている。

ESP32に搭載されている、セキュアブートとフラッシュ暗号化機能を有効にした状態で、電圧グリッチングを発生させ、両方の秘匿情報を読み出すというものだ。
日本語の記事でも過去に紹介されている。
[ESP32 IoTデバイスに永久ハック可能な脆弱性](https://www.infoq.com/jp/news/2020/02/esp32-fatal-fury/)

ESP32でのセキュアブートとフラッシュ暗号化は、それぞれ32バイト(256ビット)のSBK(セキュアブートキー),FEK(フラッシュ暗号化キー)をeFuseというOTP(1回のみプログラム可能)領域に書き込み、起動時にブートローダーがSBKを参照し、収められているパーティションイメージの署名を検証し、問題がなければパーティションの内容をFEKを使って復号しプログラムを実行させる流れとなる。
手元のESP32のefuseを読んでみた。

```
python espefuse.py --port COM3 summary
espefuse.py v2.9-dev
Connecting.....
EFUSE_NAME             Description = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Security fuses:
FLASH_CRYPT_CNT        Flash encryption mode counter                     = 0 R/W (0x0)
UART_DOWNLOAD_DIS      Disable UART download mode (ESP32 rev3 only)      = 0 R/W (0x0)
FLASH_CRYPT_CONFIG     Flash encryption config (key tweak bits)          = 0 R/W (0x0)
CONSOLE_DEBUG_DISABLE  Disable ROM BASIC interpreter fallback            = 1 R/W (0x1)
ABS_DONE_0             secure boot enabled for bootloader                = 0 R/W (0x0)
ABS_DONE_1             secure boot abstract 1 locked                     = 0 R/W (0x0)
JTAG_DISABLE           Disable JTAG                                      = 0 R/W (0x0)
DISABLE_DL_ENCRYPT     Disable flash encryption in UART bootloader       = 0 R/W (0x0)
DISABLE_DL_DECRYPT     Disable flash decryption in UART bootloader       = 0 R/W (0x0)
DISABLE_DL_CACHE       Disable flash cache in UART bootloader            = 0 R/W (0x0)
BLK1                   Flash encryption key
  = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
BLK2                   Secure boot key
  = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
BLK3                   Variable Block 3
  = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W

Identity fuses:
MAC                    Factory MAC Address
  = 30:ae:a4:ee:ba:64 (CRC 0x09 OK) R/W
CHIP_VER_REV1          Silicon Revision 1                                = 1 R/W (0x1)
CHIP_VER_REV2          Silicon Revision 2                                = 0 R/W (0x0)
CHIP_VERSION           Reserved for future chip versions                 = 2 R/W (0x2)
CHIP_PACKAGE           Chip package identifier                           = 0 R/W (0x0)

Efuse fuses:
WR_DIS                 Efuse write disable mask                          = 0 R/W (0x0)
RD_DIS                 Efuse read disablemask                            = 0 R/W (0x0)
CODING_SCHEME          Efuse variable block length scheme                = 0 R/W (0x0)
KEY_STATUS             Usage of efuse block 3 (reserved)                 = 0 R/W (0x0)

Config fuses:
XPD_SDIO_FORCE         Ignore MTDI pin (GPIO12) for VDD_SDIO on reset    = 0 R/W (0x0)
XPD_SDIO_REG           If XPD_SDIO_FORCE, enable VDD_SDIO reg on reset   = 0 R/W (0x0)
XPD_SDIO_TIEH          If XPD_SDIO_FORCE & XPD_SDIO_REG, 1=3.3V 0=1.8V   = 0 R/W (0x0)
CLK8M_FREQ             8MHz clock freq override                          = 49 R/W (0x31)
SPI_PAD_CONFIG_CLK     Override SD_CLK pad (GPIO6/SPICLK)                = 0 R/W (0x0)
SPI_PAD_CONFIG_Q       Override SD_DATA_0 pad (GPIO7/SPIQ)               = 0 R/W (0x0)
SPI_PAD_CONFIG_D       Override SD_DATA_1 pad (GPIO8/SPID)               = 0 R/W (0x0)
SPI_PAD_CONFIG_HD      Override SD_DATA_2 pad (GPIO9/SPIHD)              = 0 R/W (0x0)
SPI_PAD_CONFIG_CS0     Override SD_CMD pad (GPIO11/SPICS0)               = 0 R/W (0x0)
DISABLE_SDIO_HOST      Disable SDIO host                                 = 0 R/W (0x0)

Calibration fuses:
BLK3_PART_RESERVE      BLOCK3 partially served for ADC calibration data  = 0 R/W (0x0)
ADC_VREF               Voltage reference calibration                     = 1135 R/W (0x5)

Flash voltage (VDD_SDIO) determined by GPIO12 on reset (High for 1.8V, Low/NC for 3.3V).
```

上記の通り、SBK,FEKが未設定のESP32は、

```
BLK1                   Flash encryption key
  = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
BLK2                   Secure boot key
  = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
```
のように全部0で表される。

電圧グリッチングとは、プロセッサに対し、特定のタイミングで供給電圧を変化させ、外から操作できないプロセッサの内部ロジック状態を反転させるハッキング手法になる。

LimitedResults氏のサイトでは、以下のように起動後にμsecオーダーのタイミングで電圧を上下させるセットアップを行っている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/70da7bd6-fa9f-749b-1a7c-9031402c0bde.png)

ESP32は金属シールドをはがし、プローブを当ててオシロで動作を観測させている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387653/0cb2b012-7ea9-148c-0a69-0a74eeb0fb38.png)

この状態で、数十回efuseを読みだすコマンドを行い結果を集計し、いくつかばらつきがあるビットはブルートフォースアタックで鍵を特定することができたとのことである。

ポイントはこの脆弱性が、ソフトウェア起因でなくハードウェア起因であることで、これが直接今回のデザインチェンジにつながっていることが推測される。

#対策
[Security Advisory concerning fault injection and eFuse protections (CVE-2019-17391)](https://www.espressif.com/en/news/Security_Advisory_Concerning_Fault_Injection_and_eFuse_Protections)によると、


>2019年5月、EspressifはRiscureのセキュリティアナリストと協力して、フォールトインジェクションに対して強化する変更を含んだESP32ブートROMコードをレビューしました。

>その過程で、リセット後にハードウェアによって読み取られたときに、フォールトインジェクションによってeFuse値が破損する可能性があることが確認されました。この可能性から保護するためにROMコードに追加のチェックが追加され、これらのチェックはESP32-D0WD-V3チップに含まれています。

>ESP32-D0WD-V3は、非対称暗号化に基づく新しいセキュアブートV2スキームのサポートも追加します。セキュアブートV2は、読み取り保護されたセキュアブートキーを必要としません。 Secure Boot V2のESP-IDFソフトウェアサポートは2019年第4四半期にリリースされます。SecureBootV1はESP32-D0WD-V3でもサポートされており、フォールトインジェクション攻撃を防ぐためにROMがチェックされています。

つまり、

 * ESP32を使用するユーザーはESP32-D0WD-V3チップを搭載するデバイスの使用を推奨する
 * ESP32-D0WD-V3チップを搭載するデバイスにはより強化されたSecure Boot V2が使用できる。
 * V3でないチップはこの脆弱性に対して対策がない

ということになり、ESP32を使用するユーザーでフラッシュ内容を秘匿する必要がある場合はESP32-D0WD-V3チップを搭載するデバイス、つまりESP32-WROOM-32Eを使う必要があるということになる。