TPM 2.0のPCRとハードウェア信頼起点のリアル
エンジニアの多くは、暗号理論を「数学的に綺麗な抽象概念」として捉えたがる。AESのSボックス、RSAの素因数分解、ECCの群演算。だが、現実のインフラストラクチャにおいて、暗号鍵の安全性は数学だけで担保されているわけではない。どれほど強固なアルゴリズムを採用しようとも、それを保持するメモリやストレージが平文で露出していれば、物理的なプローブ攻撃やコールドブート攻撃の前には無力だ。
ここで「ハードウェア信頼起点(RoT: Root of Trust)」の出番となる。マザーボード上の小さなセキュリティ・コプロセッサ、すなわちTPM 2.0(Trusted Platform Module)が、その要塞の門番だ。本稿では、TPM 2.0の中核をなすPCR(Platform Configuration Register)の挙動、ハッシュ伸長(Extend)の数学的意味、そして鍵の封印(Sealing)が破られる境界線について、現場のインシデントハンドリングの視点から紐解いていく。
—
PCR(Platform Configuration Register)の正体とハッシュ伸長の罠
TPM 2.0には、一般的に24個のPCRが存在する。これらは「データを自由に読み書きできるストレージ」ではない。もし自由に書き換えられるのであれば、ハイパーバイザーやカーネルを改ざんした攻撃者がPCRの値を書き換えて「安全です」と偽装できてしまうからだ。
PCRの本質は、「過去の測定値の累積(履歴)を不可逆的に保持するアキュムレータ(累積器)」である。
ハッシュ伸長(Extend)アルゴリズムの仕組み
PCRに対する書き込み操作は、厳密には TPM2_Extend と呼ばれるコマンドを通じて行われる。これは単純な代入(Register = Value)ではなく、以下のハッシュ演算による更新(Extend)だ。
$$PCR_{new} = Hash(PCR_{old} \parallel Measurement)$$
ここで $\parallel$ はバイト列の連結を意味し、$Hash$ には通常 SHA-256 が使用される(TPM 2.0ではバンクごとにSHA-1やSHA-384も選択可能だが、セキュリティ要件からSHA-256以上が必須となる)。
この仕組みが生み出す重要な特性が二つある。
1. 可換性の欠如: 測定値が投入される順序が異なれば、最終的なPCRの値も完全に変わる。
2. 不可逆性(履歴の隠蔽不可能): 一度投入された測定値を特定の順序で「巻き戻す」ことは、ハッシュ関数の原像計算困難性により不可能である。
ブートプロセスにおける測定の連鎖(Chain of Trust)
UEFIセキュアブートからOSカーネルの初期化に至るまで、システムは「次に実行するコードのハッシュ」を計算し、それを適切なPCRに Extend していく。
- PCR[0]: デバイスのファームウェア(UEFI Core)の測定値
- PCR[2]: UEFIドライバやオプションROMの測定値
- PCR[7]: セキュアブートのポリシー変数(PK, KEK, db, dbx)の状態
攻撃者がストレージ内のカーネルイメージやブートローダー(grubx64.efi など)を巧妙に改ざんしたとする。CPUがそのコードを読み込んで実行しようとする瞬間、あるいはその直前に、UEFI環境やハードウェアはそのコードのハッシュを算出する。改ざんされたコードのハッシュは正当なものとは異なるため、PCRに Extend された瞬間に、PCRの最終的なハッシュ値は正規の状態から大きく逸脱することになる。
—
鍵の封印(Sealing)と復号条件の紐付け
PCRが改ざんを検知したとして、システムはどうやって防御行動に移るのだろうか。ここで登場するのが「鍵の封印(Sealing)」と「複合条件(Policy)」のメカニズムである。
ディスク暗号化(BitLockerやLUKSなど)において、マスターキーをそのままストレージのヘッダ領域に保存するわけにはいかない。鍵は暗号化された状態で保護されなければならないが、その鍵を復号するための「パスワード」や「リカバリキー」を人間が毎回入力するのはUXを損なう。
そこで、TPM内部の不揮発性メモリに暗号鍵を閉じ込め、「特定のPCR値が一致している時のみ、TPMがその鍵を復号してOSに引き渡す」という設計をとる。これがSealingだ。
TPM Policyによる条件分岐
単に「現在のPCR値が一致するか」だけでなく、TPM 2.0では TPM2_PolicyAuthorize や TPM2_PolicyPCR を用いて、より柔軟かつ厳密なポリシーを構築できる。
以下に、Linux環境(tpm2-tss ライブラリ群を使用)で、特定のPCR状態(例: PCR[7] が特定の値であること)に鍵を紐付けて封印する際の手順を、シェルスクリプトの概念コードとして示す。
#!/bin/bash
# 厳格なエラーハンドリングの設定
set -euo pipefail
# 1. 現在のPCR[7]の値をファイルに保存(これが「正常な状態」の基準となる)
tpm2_pcrread sha256:7 -o pcr7_val.bin
# 2. PCR[7]の期待値を満たすためのTPMポリシーバイナリを生成
# -l: ハッシュアルゴリズム
# -F: 期待するPCR値のファイル
# -p: ポリシーファイル出力先
tpm2_createpolicy --policy-pcr -l sha256:7 -F pcr7_val.bin -p policy.dat
# 3. プライマリーキー(SRK: Storage Root Key)のコンテキストを作成
tpm2_createprimary -C o -g sha256 -G rsa -c primary.ctx
# 4. 秘密鍵(または暗号化キー)をTPM内で生成し、生成したポリシー(policy.dat)で封印する
# -C: プライマリーキーのコンテキスト
# -u: パブリック部分の出力
# -r: プライベート部分の出力(これが封印された実データ)
# -L: 適用するポリシーファイル
tpm2_create -C primary.ctx -g sha256 -G aes -u key.pub -r key.priv -L policy.dat \
-a "decrypt|encrypt|fixedtpm|fixedparent|sensitivedataorigin"
# 5. TPMにオブジェクトをロードしてハンドルを取得
tpm2_load -C primary.ctx -u key.pub -r key.priv -c unseal.ctx
# 【復号時の処理(OSブート時)】
# ブート時のPCR状態が一致している場合のみ、以下のコマンドで平文の鍵を取り出すことができる
# 改ざんされていればTPMはエラーを返し、鍵の復号は失敗する
tpm2_unseal -c unseal.ctx -p pcr:sha256:7=pcr7_val.bin
このアーキテクチャの強さは、「CPUやOSがどれほどマルウェアに感染していようとも、TPM内部の暗号回路およびプロセッサは外部からの直接的なメモリ読み取りを物理的に拒絶する」という点にある。OSが乗っ取られていれば、OS層からのAPIコールによる復号は失敗するか、あるいはTPM自体がロックアウトされる。
—
現場のエンジニアが知るべき「突破口」と監査の盲点
理論上は完璧に見えるTPMとPCRによる改ざん検知だが、実際のインシデント現場やセキュリティ監査においては、いくつかの「設計の隙間」や「実装上の脆弱性」が突かれるケースが存在する。
1. ローカル・トランスポート層(LPC / SPIバス)の盗聴
TPMチップは、多くの場合マザーボード上に独立して存在し、CPUやPCH(Platform Controller Hub)とはLPCバスやSPIバスで通信している。初期の設計では、このバス上の通信が暗号化されておらず、ロジックアナライザや高精度なプローブを用いてバス上のデータを直接キャプチャし、PCRの測定値や通信内容をリプレイ・解析する物理攻撃(Bus Snooping)が成立した。
- 現代の対策: TPM 2.0の規格および近年のプラットフォームでは、CPUとTPM間の通信暗号化(Parameter Encryption / Session Encryption)が必須、あるいは強く推奨されている。監査時には、BIOS/UEFI設定でTPMバスの暗号化が有効かを確認する必要がある。
2. ダイナミック・ローディングとPCR[0]-[7]の死角
「カーネルの起動までは測った」としても、その後にロードされる内核モジュール(Kernel Modules)、サードパーティ製ドライバ、あるいはコンテナランタイムが動的にロードするバイナリまでは、デフォルトのPCR[0]-[7]のスコープ外である。
攻撃者が正規のブートプロセスをバイパスせずとも、起動後のOS上で特権昇格(LPE)に成功し、カーネル空間のメモリを直接書き換えてしまえば、TPMは「起動時は安全だった」と判断したまま、暗号鍵をホストに渡してしまう。
- 現代の対策: Linux環境であれば IMA(Integrity Measurement Architecture)を活用し、ファイルシステム上のファイルオープンや実行時にハッシュを計算してPCR[10]等に継続的に
Extendさせる動的測定の導入が不可欠だ。
3. コールドブートアタックと物理的残留
RAMのデータが電源断後数秒〜数分間残留する特性を利用し、物理的に冷却スプレーなどで冷却してメモリ内容を抜き取る攻撃。これに対してTPMは直接の防御策を持たないため、フルディスク暗号化の鍵がメモリ上にプレーンテキストとして長く存在する時間を最小化する設計(Ephemeral Keysの徹底など)が求められる。
—
結び:トラスト(信頼)をコードに落とし込むということ
セキュリティアーキテクチャにおける「信頼(Trust)」とは、感情的なものではなく、「検証可能であること(Verifiable)」と同義である。
TPM 2.0のPCRとSealingメカニズムは、システムが「自分が自分であること」「誰も改ざんしていないこと」をハードウェアの根底から証明するための数少ない現実的な武器だ。しかし、それは魔法の弾丸ではない。ファームウェアの設定不備、バス暗号化の欠落、動的測定(IMA等)の未導入といった「レイヤーの隙間」を突かれれば、要塞は内側から崩壊する。
チーフホワイトハッカーやセキュリティアーキテクトに求められるのは、暗号アルゴリズムの選択に留まらず、ハードウェアの物理的制約からOSのメモリ管理、そしてブートチェーン全体の測定フローまでを一本の線として貫く、徹底的なローレイヤの洞察力に他ならない。
コメント