IoT Security 20 · Espressif — ESP32 系

Chapter 20

Espressif — ESP32 系

この章の位置づけ.

ESP32 系は、Wi-Fi / BLE 一体型で圧倒的に安価なため、 IoT 製品で非常に広く使われている。

だが——セキュリティ機能は「既定で無効」であり、 有効化しないまま出荷される事例が極めて多い。

機能自体は充実している。問題は「使われていない」ことである。

注意: ESP32 系は品種(ESP32 / S2 / S3 / C3 / C6 / H2 / P4 など)と シリコンリビジョンで機能が大きく異なる。 必ず対象品種の Technical Reference Manual と ESP-IDF の Security ドキュメントで確認すること。

この章で使う既出の用語(定義は各リンク先). セキュアブート(02 章 3 節)、物理攻撃(04 章 6 節)、署名検証(04 章 4 節)、RSA-3072(05 章 3 節)、eFuse(06 章 2 節)、不可(06 章 1 節)、完全性(06 章 6 節)、機密性(06 章 6 節)、起動時間(06 章 3 節)、Non-secure(07 章 3 節)、Secure(07 章 3 節)、サイドチャネル(07 章 8 節)、AES(08 章 8 節)、Nordic(11 章 4 節)、Espressif(12 章 3 節)、Renesas(12 章 3 節)、量産(14 章 5 節)、開発(14 章 5 節)、運用(15 章 8 節)、RAM(16 章 3 節)、フラッシュ(16 章 3 節)、TrustZone-M(17 章 1 節)、TEE(19 章 8 節)

1. ファミリの整理

ESP32 のセキュリティ機能を調べる

品種を選ぶと、対応する機能と設定手順の要点が表示される。

品種コア特記事項
ESP32(初代)Xtensa LX6 ×2Secure Boot v1(旧)/ v2 はリビジョン 3 以降
ESP32-S2Xtensa LX7 ×1Secure Boot v2、Flash Encryption(XTS)
ESP32-S3Xtensa LX7 ×2上記 + AI 命令。HMAC / DS ペリフェラル
ESP32-C3RISC-V ×1低コスト。Secure Boot v2、DS ペリフェラル
ESP32-C6RISC-VWi-Fi 6、Thread/Zigbee。ESP-TEE 対応(ESP-IDF v5.4 以降)
ESP32-H2RISC-VThread/Zigbee 専用(Wi-Fi なし)
ESP32-P4RISC-V ×2高性能。無線なし

「ESP32」と一括りにしないこと.

初代 ESP32 のリビジョン 1 では Secure Boot v2 が使えない。 新規設計では、S3 / C3 / C6 など新しい世代を選ぶことを強く推奨する。

2. eFuse — すべての土台

ESP32 のセキュリティ設定は、すべて eFuse で制御される(06 章)。

eFuse ブロック用途
BLOCK0各種の設定ビット(機能の有効/無効、保護フラグ)
BLOCK1システム用(キャリブレーションなど)
BLOCK2システム用
BLOCK3 / BLOCK_KEYnユーザ鍵の格納(S2/S3/C3 などは KEY0〜KEY5 の 6 ブロック)

各ブロックには「読み出し保護」と「書き込み保護」のビットがある。

eFuse に鍵を焼く手順BLOCK_KEYn に鍵を書き込むKEY_PURPOSE_n に用途を設定するSecure Boot 用、Flash Encryption 用など★ 読み出し保護ビットを焼くCPU からも読めなくなる★ 書き込み保護ビットを焼く二度と変更できなくなる3 と 4 を焼き忘れたまま出荷する事故が多い。焼いたことを製造検査で確認する
機能はあるが、有効化されないまま出荷されるのが最大の問題。工程に組み込んで検査する

espefuse.py の操作は、すべて不可逆である.

# 必ず --do-not-confirm なしで、内容を確認してから実行する
espefuse.py -p /dev/ttyUSB0 burn_key BLOCK_KEY0 secure_boot_key.pem SECURE_BOOT_DIGEST0
espefuse.py -p /dev/ttyUSB0 summary        # ← 状態を確認する

間違えたチップは廃棄するしかない。 量産前に、捨ててよいチップで手順を通しで検証すること。

用途ビット(KEY_PURPOSE)

鍵ブロックに「何に使うか」を宣言するのが優れた設計である。

用途内容
SECURE_BOOT_DIGEST0/1/2セキュアブートの公開鍵ダイジェスト(3 個持てる)
XTS_AES_128_KEY / XTS_AES_256_KEY_1/2Flash Encryption 用
HMAC_UP / HMAC_DOWN_*HMAC / DS ペリフェラル用
USERアプリケーションが自由に使う

セキュアブートのダイジェストが 3 個持てるのは重要である(12 章)。

署名鍵が漏洩したら、その鍵を失効させて、残りの鍵で運用を継続できる。 SECURE_BOOT_KEY_REVOKE0/1/2 の eFuse で個別に失効できる。

鍵の失効機構を持つのは、この価格帯の MCU では特筆すべき点である。

3. Secure Boot v2

項目内容
署名アルゴリズムRSA-PSS 3072(全世代)。ECDSA(P-192/P-256、対応品種)
eFuse に焼くもの公開鍵のダイジェスト(SHA-256)。鍵本体はブートローダに含まれる
検証の連鎖ROM → 第 2 段ブートローダ → アプリケーション
鍵の失効3 個のダイジェストを個別に失効可能
ESP32 系のブートの流れROM ブートローダImmutable RoT(04 章)第 2 段ブートローダ(フラッシュ上)同じ鍵でアプリの署名を検証するアプリケーションROM は焼き切り。第 2 段以降は更新できる——04 章の 2 段構えそのもの
構成は他社と同じ。違うのは「デフォルトでは何も有効になっていない」こと

有効化の手順

# menuconfig で設定
idf.py menuconfig
  → Security features
      → [*] Enable hardware Secure Boot in bootloader
      → Secure Boot: Signing scheme = RSA-3072
      → [*] Sign binaries during build
      → Secure bootloader mode = One-time flash(★推奨)

# 署名鍵を生成(★ HSM 管理を推奨。ここでは例示)
espsecure.py generate_signing_key --version 2 secure_boot_signing_key.pem

# ビルド・書き込み
idf.py build
idf.py -p /dev/ttyUSB0 flash

「Reflashable」モードを量産で使わないこと.

ESP-IDF には 2 つのモードがある。

モード内容
One-time flasheFuse にダイジェストを焼き、以後は署名済みイメージしか書けない
Reflashable開発の利便性のため、鍵を再利用できる

Reflashable は開発専用である。 量産では One-time flash を使う。

見落としがちな設定

eFuse意味
SECURE_BOOT_ENセキュアブート有効
DIS_DOWNLOAD_MODEシリアルダウンロードモードの無効化
DIS_DIRECT_BOOT / DIS_LEGACY_SPI_BOOT代替ブート経路の無効化
SOFT_DIS_JTAG / HARD_DIS_JTAGJTAG の無効化
DIS_USB_JTAG / DIS_USB_SERIAL_JTAGUSB 経由の JTAG 無効化

これが 11 章のチェックリストそのものである.

Secure Boot を有効にしても、 シリアルダウンロードモードや JTAG が開いていたら意味がない。

ESP-IDF の menuconfig には Security features → UART ROM download mode の設定があり、 Permanently disabled を選べる。

量産では必ず無効化すること。

4. Flash Encryption

外付け SPI フラッシュの内容を暗号化する(06 章)。

項目内容
アルゴリズムAES-256 XTS(S2/S3/C3 以降)/ ESP32 初代は AES-256(tweak 付き ECB 相当)
鍵の場所eFuse の鍵ブロック。読み出し保護をかける
透過性フラッシュコントローラが自動で復号する。XIP のまま動く
暗号化される範囲ブートローダ、パーティションテーブル、アプリ、NVS 鍵など(設定による)

Development モードと Release モード

この違いが決定的に重要である。

モード内容用途
Development平文のイメージを書き込める(チップが暗号化してくれる)。UART ダウンロード可開発中のみ
Release平文の書き込みを禁止。UART ダウンロードで復号もできない量産必須

Development モードのまま出荷する事故が実際にある.

Development モードでは、攻撃者が UART 経由で平文を書き込める。 つまり任意のファームウェアを動かせる。Flash Encryption の意味がない。

Security features
  → Enable flash encryption on boot
  → Enable usage mode = Release   ★ 必ず Release

一度 Release にすると Development には戻せない。 だからこそ、量産前に Release モードで全機能を検証すること(14 章)。

Flash Encryption が守るもの・守らないもの

守る守らない
フラッシュを外して読まれる(機密性)完全性(改ざんの検出)← Secure Boot が担当
SPI バスの盗聴実行中の RAM の内容
クローン(鍵がチップ固有)サイドチャネル攻撃

Secure Boot と Flash Encryption は、必ず両方有効にすること.

有効にしたもの残る穴
Secure Boot のみフラッシュを読める → 鍵やロジックが漏れる
Flash Encryption のみ改ざんを検出できない(06 章の「暗号化 ≠ 完全性」)
両方実用上の防御が成立する

5. HMAC と DS ペリフェラル

ESP32-S2/S3/C3 以降が持つ、非常に有用な機能である。

HMAC ペリフェラル

HMAC ペリフェラル — 鍵を CPU に見せないeFuse に HMAC 鍵を焼く(読み出し保護をかける)ソフトウェアは「この HMAC を計算して」と依頼するだけ★ 鍵は CPU に一度も現れない(06 章の鍵の不可視化)同じ考え方が DS ペリフェラル(RSA/ECDSA の秘密鍵)にも適用されている
06 章で述べた原則が、そのまま製品機能になっている例
用途内容
チャレンジ・レスポンス認証サーバとの相互認証
鍵導出HMAC を KDF として使い、用途別の鍵を派生させる
JTAG の一時的な有効化HMAC でトークンを検証して JTAG を開く(認証付きデバッグ相当)

DS(Digital Signature)ペリフェラル

これが最も特徴的な機能である。

DS ペリフェラル — 秘密鍵をソフトウェアに見せずに署名する1秘密鍵を、eFuse の HMAC 鍵から導出した鍵で暗号化してフラッシュに保存する2署名するとき、DS ペリフェラルに暗号化されたパラメータを渡す3★ ペリフェラルが内部で復号し、署名を計算する4平文の秘密鍵は CPU バスに現れないTLS クライアント認証の秘密鍵をこの形で持てば、ファームウェアを吸い出されても機器になりすませない= 12 章の「機器固有鍵」を安価な MCU で実現できる
外付けのセキュアエレメントを使わずに、鍵の不可視化を実現する仕組み。コスト面での意味が大きい
効果内容
TLS クライアント認証の秘密鍵を保護できるファームウェアを読まれても鍵が取れない
鍵がチップに縛られる別のチップにコピーしても使えない
外付け SE なしで、ある程度の鍵保護が得られるBOM コストが上がらない

これは ESP32 系の大きな価値である.

06 章で述べた「鍵の不可視化」を、 追加のチップなしで実現できる。

ESP-IDF には esp_secure_cert_mgr というコンポーネントがあり、 DS ペリフェラルを使った TLS クライアント認証が AWS IoT / Azure IoT との接続で使える。

ただし——物理攻撃(クラス 4 以上)への耐性は、 専用のセキュアエレメントには及ばないことを理解しておくこと(22 章)。

6. NVS 暗号化

設定値やユーザデータを保存する NVS(Non-Volatile Storage)も暗号化できる。

項目内容
鍵の保管専用パーティションに保存し、Flash Encryption で保護する
またはHMAC ペリフェラルから導出する(対応品種)
暗号化方式AES-XTS

Wi-Fi のパスワードやクラウドのトークンは、NVS に保存されることが多い.

NVS 暗号化を有効にしないと、フラッシュを読むだけでこれらが取れる。 Flash Encryption を有効にしていれば間接的に守られるが、 NVS 暗号化も併せて有効にするのが正しい構成である。

7. ESP-TEE(新しい取り組み)

ESP-IDF v5.4 以降、ESP32-C6 向けに ESP-TEE が導入された。

項目内容
仕組みAPM(Access Permission Management)による、Secure / Non-secure の分離
提供するものセキュアサービス(暗号、ストレージ、アテステーション)
位置づけTrustZone-M に相当する機能を、RISC-V + APM で実現する

RISC-V には標準の TrustZone 相当がない(07 章)ので、 ベンダ独自の機構で埋めているという構図である。

対応品種と成熟度は発展途上なので、 採用を検討する場合は、最新の ESP-IDF ドキュメントで 対応状況を確認すること。

8. ESP32 の設定チェックリスト

この章の内容を、実行可能な形にまとめる。

#確認項目設定場所
1Secure Boot v2 が有効かmenuconfig → Security features
2One-time flash モードか(Reflashable でないか)同上
3署名鍵は HSM で管理されているか(12 章)運用
4Flash Encryption が有効かmenuconfig
5Release モードか(Development でないか)menuconfig
6NVS 暗号化が有効かmenuconfig + パーティションテーブル
7UART ダウンロードモードが無効化されているかeFuse DIS_DOWNLOAD_MODE
8JTAG が無効化されているかeFuse SOFT/HARD_DIS_JTAG、DIS_USB_JTAG
9eFuse の読み出し保護・書き込み保護が焼かれているかespefuse.py summary
10鍵の失効機構を理解し、予備の鍵を準備しているか運用
11秘密鍵は DS ペリフェラルで保護されているかesp_secure_cert
12OTA が署名検証つきか、ロールバック防止が有効か(13 章)menuconfig Enable app rollback support
13TLS の証明書検証が有効か(16 章)コード
14ファームウェアに秘密が埋まっていないか(11 章)CI の strings チェック
# 出荷前に必ず実行する確認コマンド
espefuse.py -p /dev/ttyUSB0 summary
# → SECURE_BOOT_EN = True
# → SPI_BOOT_CRYPT_CNT が Release 相当の値
# → DIS_DOWNLOAD_MODE = True
# → 鍵ブロックが読み出し保護されている

9. 実務上の注意点

注意点内容
ブートローダのサイズ制限Secure Boot 有効時にブートローダが大きくなり、パーティションに収まらないことがある
起動時間の増加署名検証と復号で数十〜数百 ms 増える
OTA イメージのサイズ署名が付く分、パーティション設計に余裕を持たせる
一度きりの設定eFuse は不可逆。捨ててよいチップで全手順を検証する
モジュール品ESP32-WROOM などのモジュールでも、eFuse の操作は同じ
Espressif の事前プロビジョニングモジュールに鍵と証明書を事前注入するサービスがある(12 章)

「起動時間が伸びる」は製品要件に影響する.

電池駆動で「ボタンを押したら即座に反応する」製品では、 Secure Boot + Flash Encryption の起動時間増加が問題になりうる。

企画段階で実測し、要件に織り込むこと。 後から「起動が遅いのでセキュリティを切る」は最悪の判断である。

10. この章のまとめ

ポイント内容
最大の問題機能はあるが、既定で無効。有効化されないまま出荷される
品種差初代 ESP32 のリビジョン 1 では Secure Boot v2 が使えない
eFuseすべての設定の土台。不可逆。捨てチップで手順を検証する
鍵ブロック用途ビット(KEY_PURPOSE)で宣言する。優れた設計
Secure Boot v2RSA-PSS 3072 / ECDSA。ダイジェストを 3 個持て、個別に失効できる
量産設定One-time flash。Reflashable は開発専用
Flash EncryptionRelease モード必須。Development のままだと平文を書き込める
両方必須Secure Boot(完全性)と Flash Encryption(機密性)は片方では不十分
DS ペリフェラル秘密鍵を CPU に見せずに署名できる。外付け SE なしで鍵を保護できる
忘れがちな設定UART ダウンロードモードと JTAG の無効化(11 章)
NVS 暗号化Wi-Fi パスワードやトークンを守るために併せて有効化する
ESP-TEEESP32-C6 以降。RISC-V での分離機構(発展途上)
起動時間数十〜数百 ms 増える。企画段階で織り込む

次章は、その他の主要ベンダをまとめて見る。