ファームウェアの暗号化と鍵管理
ファームウェアは、暗号化しただけでは守り切れません。鍵をどう生成し、どこに保管し、どうローテーション(更新)するか。ここまで設計して、ようやく改ざんや模倣を防げます。鍵の扱いが甘ければ、暗号方式そのものではなく、鍵漏洩によって防御が無効化されるでしょう。
この記事では、暗号化と署名の使い分けから、鍵の生成・保管、OTA更新への組み込みまでを、組み込み機器の現実に沿って解説します。
ファームウェアを暗号化する目的と脅威
ファームウェアを暗号化する狙いは、はっきりしています。中身を吸い出されたとしても、設計や制御ロジックの漏洩を防ぐことです。
組み込み機器は、攻撃者が現物を手にできる前提の世界です。基板に残るJTAGやUARTのデバッグ端子につながれたり、フラッシュメモリをはずして吸い出されたりします。そのため「競合に中身をコピーされた」という相談が持ち込まれることも、実際に珍しくありません。
やっかいなのは、暗号化と署名を混同したまま進めてしまうことです。守る対象がぼやけ、対策がちぐはぐになります。まず何を守るのか、脅威とセットで決めるのが先です。
機密性(解析・模倣防止)と完全性(改ざん防止)の違い
暗号化と署名は、守る対象がはっきりわかれます。暗号化が受け持つのは機密性です。AESなどで中身を隠し、解析や模倣品づくりの手間を大きく引き上げます。
一方で、署名が守るものは真正性と完全性です。つまり「書き換えられていないか」「正規の発行元から届いたか」を保証します。
暗号化は「読まれない」ためにあり、署名は「すり替えられない」ためにあります。狙いがそもそも別なので、片方だけでは足りません。この点は取り違えやすいポイントです。
OTA更新経路で想定する攻撃
OTA更新では、配信経路そのものが狙われます。実際、2018年にPC向け更新機構が悪用され、正規のコード署名が付いた形(署名が正規ベンダ由来に見える状態)でマルウェアが配られました(2019年に公表)。このマルウェアは、全世界で100万人以上の利用者に影響した可能性があると報告されています。
まず怖いのは盗聴です。平文で流れる更新イメージは、途中で丸ごと抜き取られます。また、データのすり替えも重大な脅威です。中間者攻撃で不正なファームウェアをつかまされれば、機器はそのまま乗っ取られます。さらに、経路上で拾ったイメージからロジックを読み解くリバースエンジニアリングも、現実的な脅威です。
ネットワーク経由だから安全、とはいえません。どの段階でも盗聴・改ざん・複製は起こりうる、と構えておくほうがよいでしょう。
暗号化と署名の使い分け
暗号化と署名は、片方では役目を果たせません。ただ、使い分けの軸は明確です。暗号化は中身を隠す担当です。AESなら鍵長を128・192・256ビットから選び、用途に応じてCTR・CBC・GCMなどのモードを決めます。現場では、まずGCMが候補にあがることが多いです。認証付き暗号として、機密性に改ざん検知(完全性)まで一手で乗せられるからでしょう。ただし、ここでの改ざん検知は伝送経路でデータが書き換えられていないかを確かめるものです。共有鍵を前提とする以上、発行元(配信元)が正規かどうかまでは保証しません。
一方、署名が担うのは真正性と完全性です。公開鍵署名で発行元と改ざんの有無を裏付け、暗号化と重ねる構成が基本になります。
ただし、暗号化が常に必要とはかぎりません。設計や鍵などの秘匿情報を含むなら暗号化し、中身が読まれても困らないなら署名だけ、と切り分けることもできます。ここは案件ごとに判断が割れるところです。
鍵管理の設計
暗号化や署名の強度は、突き詰めれば鍵の扱いで決まります。アルゴリズムをどれだけ堅牢にしても、鍵が漏れれば守りは一気に崩れてしまうためです。ここが組み込みで特につまずきやすい部分でしょう。鍵は作って終わりではありません。配布して、保管して、漏洩すれば失効させる。この運用が続くかぎり付き合う相手です。まずは役割ごとに分けるところから設計を始めましょう。
鍵の種類(暗号鍵・署名鍵)と役割分離
鍵は用途ごとに分けるのが原則です。暗号鍵は中身を隠すために、署名鍵は真正性と完全性を証明するために使い、両者を兼ねさせません。理由は単純です。1本の鍵に役割を集めると、その鍵が漏れた瞬間、機密性も真正性・完全性も同時に失われるからです。
あらかじめ権限を絞っておけば、危殆化(鍵の漏洩などで安全性が崩れること)したときでも、被害をその鍵1本の範囲にとどめられます。役割を分けておく意味は、このリスクの局所化にあります。
鍵のライフサイクル
鍵には生成から失効までの流れがあり、工程ごとに守り方が変わります。特に怖いのが、更新忘れです。過去には、ネットワーク機器ソフトウェア内の証明書期限切れが大規模障害につながった例があります。
このような事態を回避するためには、生成した鍵をどう配り、どこに保管し、漏洩時にいつ失効させるのかを、事前に定義しておく必要があります。運用が始まってからでは慌ててしまうでしょう。
IPA/CRYPTRECの『暗号鍵管理システム設計指針(基本編)』では、チェックシートとして250項目を超える検討事項が整理されています。再発行の手順まで含めて、始まりと終わりを一続きで設計しておきたいところです。
鍵生成と乱数品質・エントロピー源の確保
鍵の強さは、アルゴリズムより先に乱数の質で決まります。有名なのが2008年のDebian OpenSSL問題(CVE-2008-0166)です。乱数の種が事実上絞り込まれ、生成される秘密鍵が予測可能になり、世界中で鍵の作り直しに追われました。
長い鍵を選んでも種が偏れば探索は容易に進むため、鍵の生成には熱雑音やクロックジッタを源にするTRNGを使いましょう。電源投入直後はエントロピーが不足しがちです。十分にたまるまで鍵を作らない設計にしておきます。
NIST SP800-90BやAIS-31が求めるのも、エントロピー源が予測不可能であることの証明です。鍵長を伸ばす前に、まず乱数品質を確認するのが有効です。
危殆化時の失効・鍵ローテーション運用
鍵はいつか危殆化します。2017年のROCA(CVE-2017-15361)はその典型でした。特定ベンダ実装の欠陥により、世界中の多くのTPMが影響を受け、各社は鍵の作り直しと再登録に追われました。鍵はいつか漏れる前提で、失効と切り換えを止めずに回せる運用を組みます。危殆化を検知したらその鍵を無効にし、新しい鍵へ差し替え、必要なら過去のリリースにも再署名しましょう。ここで更新が止まれば、機器は現場で立ち往生してしまいます。
暗号鍵管理では、生成・使用・保管・更新に加えて失効・破棄までをライフサイクルとアクセス管理の両面で扱うべきです。事故をゼロにするより、起きても回復できる形にしておくほうが現実的でしょう。
デバイス側の鍵保護(セキュアストレージ)
端末に鍵を置くしかないなら、ソフトウェアの外へ追い出すのが基本です。
セキュアエレメントやHSMは、耐タンパー性のある閉じた領域で鍵を保管し、外部からは署名や復号の指示しか受け付けません。鍵そのものは取り出せない構造です。ブート検証用の公開鍵ハッシュは、OTP(One-Time Programmable:一度だけ書き込み可能な領域)やeFuse(電気的ヒューズ。OTP用途で使われることが多い)へ焼き付け、書き換えを防ぎます。
やってはいけないのは、ソースやバイナリに鍵を平文で埋め込むことです。ハードコードした鍵は、解析されればそのまま抜かれます。鍵はコードに書かず、セキュアストレージに預けましょう。読み出しと複製をどれだけ難しくできるかが、勝負どころです。
OTA更新フローへの組み込み
要素技術は、実際の更新処理に組み込んではじめて働きます。2015年には、車載システムへの遠隔攻撃が公表されました。これは大規模リコールとソフトウェア更新で対策された事例です。裏を返せば、更新の仕組みそのものが安全でなければ話になりません。
OTA更新は、配信からダウンロード、検証、書き込み、再起動へと工程が続く流れです。どこか1つ順序を誤れば、そこが穴になります。特に効くのは2つ。検証と復号をどの順で回すか、そして更新に失敗したときどう戻すかです。ここを設計で固めましょう。
暗号化・署名・検証・復号の処理順序
処理の順序において、特に重要な原則は「使用前の検証」です。配信側はファームウェアを暗号化し、そのうえで署名を付けて送り出します。デバイスは受け取った更新をまずバッファ面へ書き込み、署名を検証。真正性と完全性を確認できてから、はじめて復号に進みます。
再起動後はブートローダが同じ署名をもう一度確かめ、通ったものだけをメイン面へ展開します。検証を実行前におこなうという一方通行を崩さないことも大切です。この順番を入れ替えてしまうと、未検証のコードが動く隙が生まれます。
失敗時ロールバックとダウングレード防止
更新は失敗する前提で組みます。A/B2面やバッファ面を用意し、新しい面の起動確認が取れるまで元の面を残すのが基本です。書き込み中に電源が落ちても、有効なファームウェアは必ず片側に残ります。起動に失敗すれば自動で旧面に戻り、機器は立ち往生しません。
ただし、戻せること自体が新たな穴になることもあります。攻撃者は、脆弱性の残る旧版へわざと差し戻す「ダウングレード攻撃」を狙ってくるでしょう。そこでバージョンを単調増加で管理し、古い署名済みコードは正規の署名でも拒否します。このバージョン管理の仕組みがアンチロールバックという守りです。


