セキュアブートの仕組みと実装
セキュアブートとは、ソフトウェアの真正性と完全性を確かめたうえで起動する仕組みです。OSが起動する前の段階で、コンピュータを脅威から守ります。その中核が、Root of Trustを起点にChain of Trust(信頼の連鎖)で検証を積み上げる点です。
この記事の主役は、「検証して、必要なら止める」仕組みそのものです。読み終えるころには、実装の勘所まで見えてくるでしょう。
セキュアブートが解決する「OS以前」の脅威
コンピュータの電源を入れた瞬間、OSはまだ動作を始めていません。電源の投入からOSが起動するまでのプロセスにおいて、有効となるセキュリティ対策は限られます。アンチウイルスソフトやOSによるアクセス制御は、OSの起動後に動作するためです。
ブートキットやファームウェアルートキットは、OSの前に動作するMBR(マスタブートレコード)やUEFIファームウェアを改ざんして制御を奪う悪意あるプログラムです。OSよりもハードウェアに近い部分で動作するため、OSによるセキュリティ対策には限界があります。
メジャードブートは、起動コンポーネントのハッシュ値をTPMのPCR(プラットフォーム構成レジスタ)へ順次extend(拡張)し、計測ログとして積み上げる仕組みです。その記録を、ローカルまたはリモートでアテステーション評価し、正しい状態で起動したかを後から確かめます。一方、セキュアブートは、Root of Trustを起点に、各段で次段の署名を検証して起動します。
信頼の連鎖(Chain of Trust)の仕組み
コンピュータの起動は、決められた順番で進められます。ステップごとに、次のステップで用いられる情報の正当性をチェックする「Chain of Trust」の考え方が生かされています。
Root of Trust(信頼の基点)を起点とした段階検証
Root of Trust(信頼の基点)は、デバイスの信頼性を保証するためのハードウェアやソフトウェアです。変更できないマスクROMやOTP、ロック済みのコードフラッシュに置き、出荷後の改変を防ぎます。
Root of Trustは、一連の起動プロセスの最初の段階で実行されます。ここで確立した信頼を土台に、後続の各段が次段のコードを検証していきます。この検証の連鎖こそが、セキュアブートの中核です。
次のステップを署名検証してから実行する
Chain of Trustは、複数のステップを踏んで実現されます。起点となるRoot of Trustは、次に動かすコードのデジタル署名を公開鍵で検証します。合格なら次のステップを実行して、その次のステップで用いられるコードのデジタル署名を検証するプロセスに進みます。このプロセスをOSの起動まで繰り返すことが、Chain of Trustです。検証に失敗したステップがあれば、起動プロセスは途中で停止します。
署名検証の技術要素
署名の検証は、ハッシュ・公開鍵署名・検証鍵の保護がそろってはじめて成り立ちます。ハッシュや公開鍵署名は、署名の正当性をチェックするために用いられます。また鍵の種類を把握し、適切に用いることも押さえておきたいポイントです。
公開鍵・ハッシュ・電子署名による完全性と真正性の検証
完全性と真正性は、ハッシュと公開鍵暗号を用いた電子署名を組み合わせて確かめます。
まず開発元が配布するコードからハッシュ値を算出し、秘密鍵で電子署名を作ります。デバイス側は受け取ったコードからハッシュ値を計算し、公開鍵で署名を検証します。両者が整合すれば、改ざんされていないこと(完全性)と署名者が正当であること(真正性)を確認できます。
検証鍵の保護
検証に使う鍵そのものが守られていなければ、署名検証は意味を持たなくなります。攻撃者がこの公開鍵やハッシュを自分のものにすり替えれば、不正なコードも「正規」とみなされてしまいます。
このため、検証鍵を書き換え不可の領域に置くことが重要です。マスクROMや一度しか書き込めないOTP(One-Time Programmable。OTP ROMやeFuseなどを含む書き換え不可領域)に焼き込み、出荷後の変更を封じます。実装によっては、公開鍵そのものではなく公開鍵のハッシュ(指紋)や、信頼する証明書のハッシュを不変領域に保持する方式もあります。
鍵の種類と署名鍵の階層
署名に用いられる鍵は、複数あります。UEFI Secure Bootでは、4つの役割に分かれています。
頂点はPK(プラットフォーム鍵)です。プラットフォームの最上位権限であり、KEK・db・dbxといった鍵データベースの更新を認可するルート鍵、いわば実印にあたります。ここで押さえたいのは、PKが実行バイナリの署名検証に直接使われるわけではない点です。PKの役割は、あくまで鍵の更新を認可することにあります。db・dbxの更新を実際に認可するのは、PK直下のKEK(鍵交換鍵)です。
実行可否そのものは、原則としてdb(許可)とdbx(拒否)で判定します。実行許可は、対象バイナリの署名(証明書)またはハッシュなどがdbで許可され、dbxで拒否されていないことが条件です。
実装方式の選択
セキュアブートを検証する方法は、複数あります。選択する方法によって起動時間が変わる点に、注意が必要です。速度と確実な検証を両立できる方式を選びましょう。
モノリシック/段階的/マルチコア並列の使い分け
セキュアブートにおける検証には、3つの方式があります。モノリシック方式は、起動前にすべてのイメージをまとめてチェックする方式です。シンプルでわかりやすく、確実性が高い一方で、起動に要する時間は長くなりがちです。
段階的方式は、ステップごとに検証しながら起動を進めます。マルチコア並列方式では、複数のコアを用いて検証を並列に実行することで、起動時間を短縮できます。短い起動時間が求められるシステムでは、段階的方式やマルチコア並列方式が採用される場合もあります。
ブート時間要件と暗号ハードウェアアクセラレータ
起動には「何秒以内」というブート時間の要件があります。一方でソフトウェアの大規模化により、ハッシュや署名検証の負荷は増大しがちです。汎用CPUだけで処理すると、ブート時間の要件を満たさない場合もあります。
暗号処理に用いるハードウェアアクセラレータは、この課題を解決する方法の1つです。RSAやECDSAなどの署名検証、SHA-256などのハッシュ計算を専用回路に任せ、検証に要する時間を削減します。起動プロセスの安全性を確認しつつ、起動時間を短縮できる方法です。
実装時の落とし穴と設計における注意
セキュアブートの仕組みが正しくても、適切に実装しないとシステムの保護には結びつきません。また、鍵の更新や旧版への差し戻しにも、押さえておきたいポイントがあります。
検証失敗時のフェイルセーフ
セキュアブートの検証に失敗した場合、無理に起動させる対応は推奨されません。「ひとまず動かす」対応は、不正なコードや悪意ある者の侵入を許すおそれがあるためです。
そのため設計する際は、「フェイルセーフ」を基本にします。フェイルセーフとは、セキュアブートの検証が失敗した場合に安全な状態へ遷移する設計思想です。暗号鍵や周辺機能へのアクセス遮断、CPUのリセットといった対応が、その具体例です。システムを復帰させたい場合は、正規のリカバリ処理へ導く方法もあります。
鍵ロールオーバーとダウングレード攻撃対策
暗号鍵は、設定後も永続的に使い続けられるわけではなく、状況に応じた更新が必要です。脆弱性が見つかれば、鍵を新しくして古い鍵を失効させます。この鍵ロールオーバーでは、新しい鍵を安全な経路で配布することが重要です。
古い版へ戻すダウングレード攻撃(バージョンロールバック攻撃/anti-rollback)への対策も必要です。攻撃者の狙いは、既知のバグが残る旧版への差し戻しにあります。対策の1つは、バージョン番号を単調に増加させ、その値をOTPや電気的ヒューズ(eFuse)に刻んで、システムが旧版へ逆戻りするのを防ぐ方法です。


