14.3.4. フラッシュ読み出し保護に関する注意

出荷状態では、出荷された OpenMV cam 上のファームウェアは、デバイスへ物理的にアクセスできる人物であれば誰でも 読み出し可能 です。cam を手にした攻撃者は、デバッグヘッダに SWD プローブを接続し、MCU のデバッグインターフェイスと通信してフラッシュをダンプできます。これにはすべてのフリーズされた Python モジュールと ROMFS パーティションの内容が含まれます。標準の OpenMV ファームウェアは、デフォルトではフラッシュ読み出し保護を 有効にしていません

製品を出荷するチームが責任の所在を把握できるよう、このページではその点を明示的に説明します。

14.3.4.1. cam がデフォルトで行うこと

cam のブートローダーとランタイムは、基盤となる MCU の読み出し保護機能を一切有効にしません。デバッグインターフェイスは開いたままで、フラッシュは読み出し可能なままであり、ビルドは開発者の作業台上と同じように動作します。これはチュートリアルの読者にとって正しいデフォルトです。読み出し保護を有効にして出荷される cam は、IDE 経由で再フラッシュできず、デプロイ失敗後に再イメージ化できず、ビルドチーム以外の誰によっても復旧できない cam だからです。

cam が「開発者向けデバイス」から「製品」へと変わると、このトレードオフも変化します。アプリケーションコードが非公開に保たれることに価値が依存する製品では、その保護を製品自身が有効にしなければなりません。OpenMV ファームウェアはそれを行いません。

14.3.4.2. 製品チームが行うこと

あらゆる MCU ベンダーが読み出し保護メカニズムを提供しています。詳細はさまざまです。ビットレベルのヒューズ、一度きりのライフサイクル遷移、署名付きフラッシュイメージなどがありますが、共通する形は次のとおりです。

  • ベンダー固有のビット(または一連のビット)がシリコンに書き込まれます。これは通常、MCU のデバッグポートと最後に一度通信するベンダーツールを介して行われます。

  • 書き込み後、デバッグポートはフラッシュの読み出しを拒否します。cam は依然として起動してアプリケーションを実行しますが、もはやプローブにその内容を公開しません。

  • この書き込みは 不可逆 です。cam を破壊せずにデバッグ可能な状態へ戻す方法はありません。

このセットアップは MCU 固有であり、手順は保護対象となる cam 上の部品に依存します。ベンダーのリファレンスマニュアルが信頼できる情報源であり、製造ラインで正しく行うための窓口はベンダーサポートです。

これは簡単な部分です。

難しい部分は、cam 上でコードを実行したり、アプリケーションが何を行っているかを読み取ったりするために攻撃者が利用できる その他のすべての 経路を塞ぐことです。読み出し保護は、デバッグプローブがフラッシュをダンプするのを防ぐだけです。cam は依然として次の経路を塞ぐ必要があります。

  • MicroPython REPL。 USB 接続の REPL は任意の Python を受け付けます。読み出し保護はそれを変えません。REPL セッションは RAM を読み取り、関数を呼び出し、実行中のアプリケーションが見られるものを何でも持ち出せます。実質的に、到達可能な REPL は読み出し保護で得られるものすべてを回避します。REPL アクセスの無効化は、製品チームが担うファームウェアビルドの変更です。

  • IDE スクリプトのアップロード。 IDE の「このスクリプトを cam 上で実行する」経路は、REPL と同じ USB プロトコルの面を利用します。REPL を塞げばこれも一緒に塞がれます。どちらかを開いたままにすると、cam への任意コード実行チャネルが残ります。

  • ファイルシステムからのエントリポイントの乗っ取り。 アプリケーションを スクリプトをファームウェアにフリーズする を通じて出荷した時点ですでに塞がれています。ランタイムは、いかなるファイルシステム上のコピーよりも先にフリーズされた boot.pymain.py を解決するため、フラッシュや SD に置かれたものがそれらを上書きすることはできません。この保護は、アプリケーションがビルドに含まれていれば無償で得られます。

  • 新しい cam の外部フラッシュ。 アプリケーションイメージを外部フラッシュに保存する cam は、そのイメージを PCB 上に丸見えの状態で載っているチップに置きます。このチップは市販のツールではんだ付けを外して直接読み取ることも、バスをプローブして基板上で読み取ることもできます。これを保護するには、読み出し時にフラッシュ内容を復号するオンチップハードウェアを有効化し、暗号鍵を生成し、その鍵を cam にプロビジョニングし、MCU のワンタイムプログラマブルストレージに不可逆的に焼き込む必要があります。これらはそれぞれ独立した一度きりの操作であり、量産ユニット上でいずれか一つでも誤って行うと、そのユニットは文鎮化します。

このリストの各項目は、それぞれが独自のファームウェアビルド作業、製造ライン手順、不可逆的な書き込みの積み重ねです。真にロックダウンされた製品とは、カスタマイズされたファームウェアビルド、カスタマイズされたブートローダー、ユニットごとに鍵をプロビジョニングする製造フロー、そしてユニットがラインを離れる前にロックが実際に閉じていることを証明する一連のテストです。これは数日ではなく数か月の作業であり、不可逆性ゆえにミスはユニットを犠牲にします。

なぜデフォルトが開いているのか

このリストは、標準の OpenMV ファームウェアが読み出し保護を有効にせず 出荷される理由でもあります。REPL を閉じ、IDE スクリプトのアップロードを無効化し、ファームウェアをロックした cam は、まったく開発できない cam です。そもそも OpenMV cam を使えるものにしているワークフローが、丸ごと失われてしまうのです。デフォルトではすべてが開いたままにされており、製品チームは出荷ユニットへ向かう過程でどの部分を閉じるかを選択します。

14.3.4.3. 物理アクセスでなお得られるもの

読み出し保護を有効にしていても、cam を手にした攻撃者はかなり多くのことができます。

  • 出力を盗聴して cam のネットワークトラフィックをリプレイする。

  • 目に見える挙動を観察し、入力に対してどう反応するかを推測する。

  • 場合によっては、保護された MCU を狙ったフォールトインジェクションやサイドチャネル攻撃によって秘密情報を復元する。

読み出し保護は、アプリケーションのソースに到達するコストを引き上げます。コストをなくすわけではありません。「物理アクセス = 侵害」というのが、セキュリティレビューが出発点とすべき作業上の前提です。保護メカニズムは、その侵害が時間と機材の面でどれだけのコストになるかを決めるにすぎません。

14.3.4.4. OpenMV ファームウェアの出荷状態

具体的に示すための要約です。

  • デフォルトでは読み出し保護は有効になっていません。

  • 標準ファームウェアには、それを有効にするビルドフラグはありません。

  • MicroPython から呼び出せるアプリケーションレベルの API はありません。

保護を必要とする製品は、カスタマイズされたファームウェアを出荷します。そのカスタマイズはボードのブートローダーと製造フローに存在し、OpenMV のコードベースの外側にあります。これを初めて行うチームは、最後に付け足すものとしてではなく、独立した作業として開発スケジュールに織り込んで計画すべきです。不可逆性ゆえに「後で追加する」のはコストが高くつきます。