
署名なしのファームウェアでBluetoothモジュールを出荷するということは、フラッシュできれば誰でも信頼することを暗に認めるということです。競合が製品をクローンし、攻撃者がバックドアを仕掛け、悪意のあるOTAが現場を死活させても、起動時にあなたのイメージと他人のイメージを見分けられません。セキュアブートはこの隙間を塞ぎます。ハードウェアが、任意のコードを実行許可する前に暗号的に署名を検証します。この記事はそのエンジニアリング側、すなわちルートオブトラスト、署名チェーン、鍵プロビジョニング、ロールバック防止、セキュアOTA、デバッグロックダウン、そして引き受けるトレードオフです。
セキュアブートが存在する理由
脅威は具体的です。
- クローン。 署名なしのイメージは1台から読み出し、何千台もの偽物に焼けます。
- 悪意のOTA。 更新チャネルが認証されていなければ、そこに届く者がデバイスを所有します。
- サプライチェーンの改ざん。 侵害されたビルドサーバや委託先が、あなたの書かなかったコードを出荷します。
- 永続的インプラント。 ブートローダレベルのインプラントは、検証機がその*配下*で動くためアプリ更新では消えません。
セキュアブートなしでは、唯一の境界は「攻撃者が物理的にフラッシュできるか、ポートに届くか」です。それありでは境界は「攻撃者が秘密署名鍵を握っているか」になります。
ルートオブトラスト
すべては製造時にシリコンへ焼かれた不変のROMブートローダに依拠します。そこにはベンダの検証ロジックと、あなたの*公開鍵のハッシュ*(決して秘密鍵ではない)を収めるワンタイムプログラマブル領域(OTP/eFuse)が含まれます。
- 秘密鍵はオフラインの署名サーバにのみ存在し、デバイスには決して触れません。
- 信頼のチェーンは ROM -> ブートローダ -> アプリケーション と続きます。各段は制御を渡す前に次段の署名を検証します。
標準的な構成:
ROM (固定) --検証--> ブートローダ (署名済) --検証--> アプリケーション (署名済)
署名方式
仕組みは非対称署名です。
1. イメージをハッシュ(SHA-256)し、そのハッシュをオフラインで秘密ECDSA P-256(またはEd25519)鍵で署名します。
2. ブートローダは電源投入時にハッシュを再計算し、信頼する公開鍵で署名を検証します。
3. 検証が通ったときのみ、そのイメージへジャンプします。
公開鍵をeFuseに丸ごと収めるのは希少なビットの無駄なので、ほとんどの設計は公開鍵のSHA-256を格納します。ブートローダはまずイメージ内の鍵がeFuseダイジェストと一致するか確かめ、その鍵で署名を検証します。
最小の検証:
def verify_image(img, pk_digest, sig):
if sha256(img.public_key) != pk_digest:
return FAIL # 鍵が違う
if not ecdsa_verify(img.public_key, sig, sha256(img.code)):
return FAIL # 署名が不正
return OK
ロールバック防止
署名済みイメージでも、攻撃者が昨年出荷した*古く脆弱な*署名済みイメージを焼くことを許せば意味がありません。解決はeFuse内の単調増加バージョンカウンタです。
- イメージはバージョン番号を持ち、デバイスは実行済みの最高バージョンを保存します。
- 保存カウンタより低いバージョンのイメージの起動を拒否します。
- eFuseビットは一方向なので、カウンタ計画は量産前に固定必須です。後から「増やす」ことはできません。
セキュアOTA
工場イメージを守る署名と同じものが更新も守らなければなりません。流れ:
1. CIがオフライン鍵で新イメージに署名し、デバイスはダウンロード時に検証します。
2. デュアルバンク構成を使います。更新をスロットBに書き、検証してからスワップ。検証失敗ならスロットAが動き続け、死活しません。
3. OTA署名鍵はeFuse鍵と一致しなければならず、更新チャネルは端から端まで認証されます。
デバッグインタフェースのロックダウン
SWD/JTAGを開いたままのBluetoothモジュールは開いた本です。コードの完全読出しと再書込みが可能。セキュアブートはデバッグポートと同じ強さしかありません。
- プロビジョニング後にデバッグインタフェースをロックします。
- 「全消去でアンロック」やチャレンジレスポンスといった制御された再オープンを用意し、返品/RMAは消去できるが読出しはできないようにします。
- 一般的な実装の比較:
| 制御 | nRF Secure Boot (NSIB) | ESP32 Secure Boot v2 | 汎用eFuse SoC |
|---|---|---|---|
| 鍵格納 | eFuseの公開鍵ハッシュ | eFuse公開鍵ダイジェスト | OTPハッシュ |
| 署名 | ECDSA P-256 | RSA-3072 / ECDSA | ECDSA |
| ロールバック防止 | 単調カウンタ | eFuse内バージョン | 手動 |
| デバッグロック | CTRL-APロック | JTAG無効eFuse | SWDロック |
| セキュアOTA | MCUBoot / SUIT | ネイティブ | カスタム |
モジュール上の暗号ハードウェア
最近のBLE SoCは必要な基礎を備えます。TRNG、AES、ECDSAアクセラレータ(nRF52/53、ESP32、DA1459x)です。Cortex-M4での署名検証は数十ミリ秒、そのバーストでmA級を消費しますが、一度きりの起動なら取るに足りません。ベンダのブートローダライブラリを使い、暗号を自作してはいけません。
トレードオフと故障モード
セキュアブートはタダではありません。
- 死活リスク。 秘密鍵を失えば二度と署名できず、現場更新は不可能に。鍵の保管が最も重要な資産です。
- ダウングレード不可。 悪い新バージョンは旧版を焼けば逃げられません(カウンタが阻止)。*より新しい*修正ビルドを押し込む必要があります。
- プロビジョニング歩留り。 eFuse焼きは一方向。焼きミスはラインでユニットを死活させます。大量焼き前にゴールデン機で検証を。
- リカバリ。 署名済み「リカバリ」イメージ経路を最初に計画を。後付けは困難です。
OEMがなすべきこと
工場を出るBluetoothモジュールを作るなら最低限:
1. 鍵ペアをオフラインHSM/署名サーバで生成。 秘密鍵は開発者PCやCIランナーに置かない。
2. 公開鍵ハッシュをeFuseに焼く — 保護されたプロビジョニング工程で。量産前にゴールデン機で検証。
3. すべての成果物に署名 — ブートローダ、アプリ、OTA — をオフライン��でCI内で。
4. ロールバック防止を有効化し、デバッグポートをロック。
5. リカバリ経路(署名済みリカバリイメージ)と鍵ローテーション/失効計画を保持。
まとめ
セキュアブートは信頼を「誰がフラッシュできるか」から「誰が鍵を握っているか」へ移します。設計時に追加は安く、後付けはほぼ不可能です。組み込み、デバッガをロックし、秘密鍵を王家の宝石のように守れ。なぜなら攻撃者にとって、あなたのファームウェア署名こそが彼らと製品の間に立つ唯一の壁だからです。
