株式会社AcompanyでTEE Debugging OfficerR&Dエンジニアをしている今村です.今年5月にプライバシーテックスタートアップのAcompanyにR&Dエンジニアとして中途採用され,TEE(後述)周りの研究開発に携わっています.その流れでプライベートでもTEE関係のOSSに継続的にコントリビューションするようになったので,そのあたりの活動を紹介します.
本記事はAcompany😎 Advent Calendar 2025 (Part 2)の16日目の記事です.Acompany😎 Advent Calendar 2025 (Part 1)もあるので興味があれば.
はじめに
最初は入社エントリを依頼されたのですが,本音を書くと多方面への呪詛がまろび出てしまうリスクがあったため,社会性フィルタを発揮して技術関連の記事を書くことにする.[註:社会性のある者はこのようなことを書かない.]とはいえ入社エントリ代わりにAcompanyに入社した理由に少しだけ触れることにします.
Acompanyは秘密計算を中心としたサイバーセキュリティ技術を扱うスタートアップ企業です.私はこれまで大学・研究機関で数学の研究(所謂数学者)をしていました.詳細な経歴・専門はresearchmapに載っているので割愛しますが,秘密計算も暗号理論もITエンジニアの経験も何もかもありません.数学の研究に飽いたわけでもありません.(何なら現在も個人的に研究は継続しています.)それにも拘らず業界も分野も全く異なるAcompanyに入社したのは,Acompanyが「Be Cool」をValueとして掲げ,その中で「邪悪な人は(どれだけ優秀でも)受け入れない」ことを明言していたことにあります.
邪悪なこと(の一部)を懲戒規程等の内規で縛ることは普通のことです.しかしそれを対外的な資料として大々的に掲げるということは普通はやりません.例えばパワハラが法令や内規に違反することは自明ですが,会社説明資料に「パワハラする人は採用しません」などと書くのは異様に思われます.そのような異様なことをしているからには,このValueには相当な拘りがあるのであろうと察し,ここならば人間関係に煩わされMPが削られるようなことはないだろうと期待して(面接でも確認でき)入社を決めました.結果としてTEEの闇によってMPが削られることと相成りました.
いささか後ろ向きな入社理由ではあるものの,秘密計算は技術的にも事業的にも非常にエキサイティングな領域であり,社内の雰囲気も想像を超えて良好であり,現在は非常にポジティブに仕事をしています.
私は「少しでも触れた分野には必ず爪痕を残す」ルールを自らに課しているため,自社の事業は当然ながら,秘密計算領域自体へも何かしら貢献する責務があります.TEE関係のOSSへのContributionもこの一環という側面があります.ようやく本題に到達しました.(敬体で書くのがむず痒いので以下常体で書く.)
秘密計算とは何か
TEE関係のOSSといっても,現状のTEEは知名度が絶望的に低いので,まずTEEとは何かを説明した方がいいだろう.共通鍵暗号方式と公開鍵暗号方式の概要は前提とするが,具体的なアルゴリズムは前提としない.
In Transit — Encrypted Communication
我々(クライアント)がWebページを閲覧したりパスワードやクレジットカード番号をフォームに入力して送信したりするとき,クライアントとサーバの間の通信は(そう意識していなくても)SSL/TLSなどの暗号プロトコルによって暗号化され機密性・完全性が保護されている.メールを送受信する際も同様(S/MIME・PGP).データ転送時の機密性・完全性は暗号化・署名などにより保護されているということである.
At Rest — Storage Encryption
我々がクラウドストレージにデータを送信して保管する状況を考えよう.E2EE(End-to-End Encryption)を銘打っているサービスであれば,データはクライアントサイドで暗号化してから送信され,クラウドストレージには暗号文のみが保管され,クライアントしか平文にアクセスすることはできない1.クライアントアプリケーションを解析すればE2EEで保護されていることを検証することもできる.外部主体にデータを預ける場合に限らず,自身のローカルストレージにデータを保存する際にも暗号化は有効である.例えばWindows PCはストレージ暗号化機能であるBitLockerを標準搭載している2.これによりローカルデバイスが侵害(紛失・盗難)された場合であってもデータ漏洩を防ぐことができる.いずれにせよデータ保管時の機密性(実装次第では完全性も)は暗号化で保護されている.
In Use — Confidential Computing
データを移動したり保管したりする際に暗号化によって保護されているのは分かった.それならデータ利用中はどうやって保護すればいいだろうか?物理的なアナロジーで言えば,機密文書は鍵付きのアタッシュケースに入れて持ち運べばいいし,鍵付きの金庫に入れて保管すればいいが,その機密文書自体を使う時には鍵を開けて取り出して見ないといけないのではないか?自分だけがその機密文書を使うなら構わないが,機密文書を他者に預けて仕事を任せたい場合もあり,その際にその他者が機密を漏らさないことをどう保証できるだろうか?
例えば,我々がSaaSに対してデータを送信する際,クライアントとサーバ間で共通鍵を作り,クライアント側で暗号化したデータをサーバに送り,サーバはそれを復号してから処理を行い,結果を暗号化してクライアントに返送し,クライアントはそれを復号して結果を取得する.よってサーバ管理者はクライアントの送信したデータの平文にアクセスできる.
次にサービスがクラウドインフラの上に乗っかっている状況を考えてみよう.サーバは自身の管理する暗号鍵(から導出された鍵)を使って永続化したいデータ(ユーザ情報等)を暗号化し,それをストレージに記録すれば,ストレージからデータが漏れることはない.しかしサーバが計算時に利用するメモリは通常暗号化されていないため,クラウド管理者はメモリからサーバの処理内容を平文で窃取できる.
このデータ利用時の機密性保護を実現する技術の総称が秘密計算(Confidential Computing)である.ただし英語のConfidential Computingはハードウェアベースという含意がある場合もあるので注意.
秘密計算技術の例
TEE — ハードウェアベース秘密計算
秘密計算をハードウェアベースで実現する技術がTEE (Trusted Execution Environment)である.アイデアは非常に明快で,プロセッサ(CPU/GPU)だけが暗号鍵を持っている状況を作り出し,メモリ内のコード及びデータをプロセッサ固有の鍵で透過的に暗号化することで,平文が露出する範囲をプロセッサ内部に絞るというものである.
先程の機密文書のアナロジーで言えば,自分だけが解読できる暗号を用意しておいて,機密文書も作業中のメモ書きも全て暗号文で書く,という状況である.機密文書の内容(平文)はその人の脳内にしか存在しないから,脳内の情報処理自体を解読しない限り機密は漏洩しない3.
TEEのアドバンテージは「実装の簡単さ」と「計算の速さ」にある.暗号・復号処理はプロセッサ内のハードウェアモジュールによって透過的に実行されることから,基本的に既存コードに修正を加えることなくTEE内で実行することができる.このことは計算の速さの理由でもある.コードが変わらないということは,アルゴリズムが変わらないということだから,したがって計算量オーダーは不変である.暗号化オーバーヘッドは計算量に対して定数倍(数割増)でかかるのみである.
TEEのデメリットはハードウェアベースであることである.TEEに対応したハードウェアでなければ利用できない.現時点ではIntel Xeon Scalable ProcessorのSGX2や,AMD EPYC ProcessorのSEV/SEV-ES/SEV-SNPなど,もっぱらサーバ向けCPUのみTEEに対応している4.
MPC/FHE — ソフトウェアベース秘密計算
プロセッサ(脳)から平文が漏れ出す脅威さえ排除するものが秘密分散型マルチパーティ計算(Multi-Party Computation; MPC)や準同型暗号(Homomorphic Encryption; HE)である.MPCはデータを「一部から全体を復元することが暗号学的に困難」であるようなピース(share)に分割してから複数パーティに分散させ,それぞれが処理を行い,結果のピースを全て集めると計算結果の平文が復元できるというものである.パーティ全員が共謀しない限り機密性が保たれる.
特定の演算が(現実的な時間で)実行できる特殊な暗号方式(の総称)がHEである.数学的にいえば,$P$ を平文集合, $K$ を鍵集合,$C$ を暗号文集合,$e\colon P \times K \to C$ を暗号化写像,$f\colon P^{n}\to P$ を目的の演算としたときに,
$$
e(f(x_{1}, \ldots, x_{n}), \mathit{sk}) = g(e(x_{1}, \mathit{sk}), \ldots, e(x_{n},\mathit{sk}))
$$
となるような演算 $g\colon C^{n}\to C$ が「リーズナブルな時間で計算できる」ような暗号方式である.ここで $g(-,\mathit{sk})\colon (P, f) \to (C, g)$ が準同型になっていることから準同型暗号と呼ばれている.私は一般論が好きであるため過度に一般的な設定でHEを導入したが,典型的には $P$ は $\mathbb{Z}/m\mathbb{Z}$ であって $f$ が環演算である場合のみを考える.
ただし,MPCもHEも,どちらも途轍もなく大きな障害がある.それは「実装の複雑さ」と「計算量」である.第一に,実行したい処理をMPC/HE専用のアルゴリズムに書き換える必要がある.MPCに固有な問題としては,秘密分散プロトコルに参加してくれるパーティを用意する必要がある,という点も挙げられる.何より問題なのは計算量である.たとえ実装ができたとしても,計算時間が数十倍,数百倍,下手をすると数万倍にもなる.例えば次の論文
はGPUを利用したFHEのブートストラッピング5を100倍以上高速化するものだが,つまり100倍以上も高速化できるくらい遅いということである.
MPCやHEはセキュリティのコアとなる小さなモジュールを置き換えるために使うことはできるが,アプリケーション全体をMPCやHEによって保護することは現実的には不可能といってよい.
リモートアテステーション
MPCやHEには圧倒的なメリットがひとつある.クライアントアプリケーションを解析し,秘密分散なりHEによる暗号化処理なりが適切に実行されていることを検証しさえすれば,サーバサイドがどうなっていようとデータの機密性を保証できるという点である.
一方でTEEについてはどうだろうか.クラウドの計算環境がTEEを標榜していたところで嘘かもしれない6.それではどうやって機密性を検証できるだろうか?データセンタに赴いてホストマシンを特定してマザーボードを引っこ抜いてプロセッサを調べるなどということはどだい不可能である.もしそんなことができるようなら寧ろデータセンタのセキュリティが疑われる.
実はTEEにおいても次のように検証可能性が担保されている.TEE対応プロセッサは,製造時に耐タンパ性の記憶領域にシークレットが焼き込まれており,ここから派生する署名鍵を用いて自分自身の構成情報(Chip ID,マイクロコードバージョン,Mitigation Status,初期メモリ配置のハッシュ値など)を含む署名付きの「身分証明書」(Attestation Report)を発行する命令を提供する7.当該署名鍵はチップベンダのルートCA証明書まで遡ることができ,チップベンダへの信頼を前提として「身分証明書」の真正性を検証可能である.あとはAttestation Reportに期待された内容が記載されているか見分すればよい.このリモート検証プロセスをRemote Attestation(構成証明とも訳される)と呼ぶ8.
ただしこれらの手順を自前で実装するとなると,ハードウェア〜ファームウェアレベルに突っ込む必要があり,かなりハードルが高い.幸いにも低レベルの詳細をうまい具合に抽象化してくれるラッパーライブラリ・CLIツールがオープンソースで公開されているので,それらを使えばTEEの低レイヤーと格闘する苦しみから逃れることができる.そのはずであった.
後の記述を簡単にするため用語の整理をしておく.用語法はRFC 9334に概ね従う.
| 用語 | 役割 |
|---|---|
| Attester | 自身の構成情報を証明する主体.Evidenceを生成する役割を担う.TEEによる秘密計算環境. |
| Verifier | EvidenceをEndorsementsを用いて検証し,検証結果(Attestation Results)を発行する主体.ローカル検証ツールや検証サービスなど. |
| Relying Party | Attesterを信頼して利用するリモートピア.秘密計算環境の利用者(側のアプリケーション).Attestation Resultsの結果からAttesterを信頼するかどうか判断する. |
| Endorser | Evidenceにお墨付き(endorsement)を与える主体.チップベンダ. |
| Evidence | Attesterの構成情報を証明する証拠.Attestation Report. |
| Endorsements | お墨付き.Attestation Reportの署名検証に使う証明書チェーンや証明書失効リスト(CRL)などのことと思ってよい. |
TEE OSSの惨状
現実は厳しい.TEE関係のOSSは例外なく次のいずれかに該当する.
- 動作しない
- 動作するけれども
- ドキュメントが終わっておりコードもぐちゃぐちゃで使い方が分からない
- ドキュメントは整備されているしコードもまともだが,TEE側の仕様変更で突然動かなくなる
したがってOSSを使うのを諦めて低レベルと格闘する覚悟を決めるか,OSSの闇と格闘し続ける覚悟を決めるか,いずれかを決断する必要がある.
私は後者を選択してしまった.結果,OSSのバグを修正するためにバージョン毎のファームウェア仕様書を読み漁るなど,低レベルの詳細と格闘する羽目になる.本末転倒.
なれそめ
私がTEE OSS Contributorとして最初に関わることとなったOSSがsnpguestである.
snpguestはVirTEEというOSSコミュニティによってホストされているプロジェクトである.VirTEEはVirtualization-based TEE(VMレベルでの隔離を実現するTEE)のことで,AMD SEV/SEV-ES/SEV-SNP,Intel TDX,Arm CCA(Realm),Hygon CSVなどが該当する.snpguestはこのうちAMD SEV-SNPに対応したCLIツールであり,Attestation Report発行,証明書チェーン及びCRL取得,トラストチェーン検証などの機能を提供する.名目上はサードパーティ製であるが,AMDの公式ドキュメントで利用されていたり,クラウドベンダが公開しているチュートリアルでも使われるような,デファクトスタンダードのツールである.
入社早々AMD SEV-SNPベースのConfidential VM(CVM)のキャッチアップ兼調査を任されたので,AWS/Azure/GCPでそれぞれSEV-SNP CVMを立てて9,それのRemote Attestationを試すことにした.
AMD SEV-SNPにおけるRemote Attestationの基本的な流れは以下の通り.これをOSSでやればよい.
- Attester(Guest OS)は
/dev/sev-guestドライバへのioctlによりASP(AMD Secure Processor)というコプロセッサにAttestation Reportの発行を依頼 - ASPはVCEK(Versioned Chip Endorsement Key)秘密鍵で署名されたAttestation Reportを発行
- VCEK秘密鍵にはプロセッサモデル(Milan, Genoa, Turinなどのコードネーム)・Chip ID・TCB Version(microcodeバージョンなど)がmixされている
- したがってハードウェアが同一であってもTCB Versionが違えば署名鍵が変わる
- AttesterまたはVerifierは,Attestation Reportに記載のプロセッサ情報及びReported TCBを用いて,それに対応するVCEK証明書をAMD Key Distribution Service(KDS)から取得
- Host OS(Hypervisor)が予めVCEK証明書をフェッチしておき,Guest OSがこれをASP経由で取ってくるというプロトコルも存在する(Extended Attestationと呼ばれる)
- VerifierはAttestation Report記載内容からプロセッサモデルを判定し,それに対応する中間CA証明書(ASK)とルートCA証明書(ARK)をAMD KDSから取得
- VerifierはARK→ARK→ASK→VCEK→Attestation Reportと署名されていることを検証し,Attestation ResultsをRelying Partyに送る
- Relying Party(Remote User)はAttestation Resultsに基づいてAttesterが信頼可能か判断
GCPで問題発生
まず,Googleの公式ドキュメントに従いgo-sev-guestという類似のCLIツールを用い,上記の手順を実行したところ,Reportの発行から検証まで首尾よくいった.次にデファクトのsnpguestでも試してみよう.するとまずREADME.mdに記載のコマンドライン引数の順序が実際と違うというトラップに引っかかる.Rustのソースコードを読んで正しい引数順序を把握し,プルリクを出して修正し,再度試してみた.
# ランダムnonceを使ってレポートを発行
sudo snpguest report report.bin report-data.bin -r
# レポート記載のChip IDとTCB Versionに対応するVCEK証明書をAMD KDSからフェッチ
snpguest fetch vcek pem . -r report.bin
# レポート記載のChip ID(or Family iD)からプロセッサファミリを判定
# プロセッサファミリに対応するARK証明書とASK証明書をKDSからフェッチ
snpguest fetch ca pem . -r report.bin -e vcek
# 証明書チェーン検証
snpguest verify certs .
# レポートとVCEK証明書のTCB Versionを照合 → 署名検証
snpguest verify attestation . report.bin -t
snpguest verify attestation . report.bin -s
するとうまくいかない.Reportの発行から証明書チェーン検証までは成功するのだが,Report署名の検証で失敗する.
ERROR: VEK did NOT sign the Attestation Report
地獄の原因究明
まず考えられるのはsnpguestの検証ロジックにバグがある可能性である.そこで「snpguestで発行したReportをgo-sev-guestで検証」することを試みた.するとこれも失敗する.snpguestから取得したReportが間違っているというおかしな可能性が浮上する.
反対も試してみよう.すなわちgo-sev-guestで取得したReportをsnpguestで検証してはどうか.これは成功することが期待できる.ところがこれも失敗する.正確にはTCB Version照合に成功するのだが,署名検証に失敗する.何事だろう?
| 発行 \ 検証 | snpguest | go-sev-guest |
|---|---|---|
| snpguest | ❌ | ❌ |
| go-sev-guest | ❌ | ✅ |
念のため,AMD KDSから取得したVCEK証明書ではなく,GCPのホストがキャッシュしているVCEK証明書を利用する手順(Extended Attestation)も試してみた.
# ホストがキャッシュしているVCEK証明書をASP経由で取得
sudo snpguest certificates pem .
# 検証
snpguest verify attestation . report.bin -t
snpguest verify attestation . report.bin -s
すると今度はTCB Version照合と署名検証の両方に失敗する.
ERROR: Report TCB Boot Loader and Certificate Boot Loader mismatch encountered.
ERROR: VEK did NOT sign the Attestation Report!
これは「Report記載のChip ID & TCB Versionに紐付いたVCEK証明書」と「ホストがキャッシュしているVCEK証明書」が一致しないことを意味する.何事だろう?
どうもTCB Version周りが怪しいので,それぞれのツールで取得したReportをパースして表示したところ,次のようになった.
| 項目\発行 | snpguest | go-sev-guest |
|---|---|---|
| Microcode | 219 | 219 |
| SNP | 0 | 25 |
| TEE | 4 | 0 |
| Boot Loader | 0 | 4 |
| FMC | None | None |
一部項目が一致しない.これは通常考えられないことである.念のために,SEV-SNPファームウェアABI仕様書を片手に,Reportのバイナリを読むことにした.するとReported TCB Versionフィールドのバイト列に食い違いがある.具体的には
-
00 04 00 19 00 00 00 db(snpguest) -
04 00 00 00 00 00 19 db(go-sev-guest)
どうもバイト列の順番がシャッフルされていることが原因ではないかと思えてきた.ABI仕様書をよく読むと,このTCB Versionフィールドの仕様が,プロセッサファミリによって異なり,次のようになっているという記述を見つける.なぜReserved領域を払い出さずにフィールドの順番を変えたのか?
| byte offset | pre-Turin | Turin |
|---|---|---|
| 0 | Boot Loader | FMC |
| 1 | TEE | Boot Loader |
| 2 | (Reserved) | TEE |
| 3 | (Reserved) | SNP |
| 4 | (Reserved) | (Reserved) |
| 5 | (Reserved) | (Reserved) |
| 6 | SNP | (Reserved) |
| 7 | Microcode | Microcode |
さて,このとき使っていたマシンのプロセッサファミリはMilan(pre-Turin)である.snpguestのReportはreserved領域がnon-zeroになっているので,間違っているのはsnpguestの方だと確定した.
しかもMilanの方のTCB Versionフィールドを,Turinの区切り方で読むと,go-sev-guestの方のTCB Versionの値と一致することにも気付く.
FMC:0 BL:4 TEE:0 SNP:25 (Reserved) uC:219
| | | | | | | ← AMD Turin
00 04 00 19 00 00 00 db
| | | | | | ← AMD Milan
BL:0 TEE:4 (Reserved) SNP:0 uC:219 FMC:None
つまり,snpguestは何故かは分からないが,Milanマシンから取得してきたReportのTCB VersionをTurinのものとして読み直してから出力する,というまことに変なことをしている疑いが出てきた.
この仮説を検証するため,snpguestから取ってきたReportのTCB Versionのみ全て正しいTCB Versionに挿げ替えたファイルを作成し,これをgo-sev-guestで検証させてみた.すると予想通り検証に成功.
$ go-sev-guest-check -in report-modified.bin -guest_policy 0x030000
$ echo $?
0
最後にsnpguestとgo-sev-guestがそれぞれReportをどう扱っているのかをソースコードを読んで確認することにした.すると次のような違いがあることが分かった.
- go-sev-guestは必要がない限りバイト列のまま取り回す.ファイルに書き出す際は取得したバイト列をそのまま書き出す.
- snpguestは
AttestationReport構造体に入れてから取り回す.ファイルに書き出す際はAttestationReportからシリアライズして書き出す.
snpguestの不可解なバグは「pre-TurinマシンのReportを誤ってTurinフォーマットでシリアライズした」ことによって生じていたわけである.
解決
ではなぜそんな誤りが起きてしまったのか.その原因はsnpguestが依存するsevライブラリにあり,Reportフォーマットを判定する箇所のロジックが以下のようになっていたことに由来する.
- Report Version 2ならV2フォーマット
- Report Version 3かつChip IDがpre-Turin CPUのものならV3PreTurinフォーマット
- それ以外はV3Turinフォーマット
なぜ実装時点では存在しなかったFormat Version(V4以降)をエラーではなくV3Turinにフォールバックしているのだろうか?
GCPのSEV-SNP VMから取得されたReportはReport Version 4という謎のフォーマットであった.ちなみにVersion 4が何者なのかはABI仕様書にも載っていない.SEV-SNPファームウェアがアップデートされた結果,既存の仕様書には載っていないReport Version 4が入力されてしまったが故に「V4かつMilan (pre-Turin)」が「V3かつTurin」の場合分けに飛んでしまって,このような惨劇が発生したのであった.
この原因を特定した後になって,ほんの数日前にsevライブラリ側のバグが修正されたことを知った.感情を喪失しながらsnpguestに修正pull requestを出し(えらい),ここからsnpguest――そしてTEE OSSの闇との長い付き合いが始まる.
AWSで問題発生
AWSでは上記のような問題は起こらなかった.というのも当時のAWSのSEV-SNP CVMでは,発行されるReportがVersion 3だったからである.前述の通りバグは修正済みであるから,仮にファームウェアアップデートでVersion 4になっても問題は起きない.そのはずであった.しかしAWSのSEV-SNP CVMは無慈悲にもVersion 5のレポートを吐き出すようになり,レポートのパースエラーが発生することとなる.
原因究明
再びABI仕様書を眺めていると,ABI Revisionが1.57→1.58に上がっていて,Attestation Report構造体に見覚えのない項目がいくつか増えていることに気付く.脆弱性対応状況を管理するフィールドを追加したようだ.
| Bytes | V3 or V4 | V5 |
|---|---|---|
| … | … | … |
| 0x1f0—0x1f7 | LAUNCH_TCB |
LAUNCH_TCB |
| 0x1f8—0x1ff | Reserved | LAUNCH_MIT_VECTOR |
| 0x200—0x208 | Reserved | CURRENT_MIT_VECTOR |
| 0x208—0x29f | Reserved | Reserved |
| 0x2a—0x49f | SIGNATURE |
SIGNATURE |
さらに GUEST_POLICY (ハイパースレッディングなど攻撃に利用可能なfeatureを許可するか等を指定するビットフィールド)にも見覚えのない項目が増えている.この PAGE_SWAP_DISABLE というのはページスワップを利用したHeracles AttackのMitigation statusとして導入されたもののようであった.
| Bits | V3 or V4 | V5 |
|---|---|---|
| 63:26 | Reserved | Reserved |
| 25 | Reserved | PAGE_SWAP_DISABLE |
| 24 | CIPHERTEXT_HIDING_DRAM |
CIPHERTEXT_HIDING_DRAM |
| … | … | … |
他にも PLATFORM_INFO フィールドにSEV-TIO関係のビットフィールドが追加されていた.なぜ6ビット目を飛ばして7ビット目を払い出したのか?
| Bits | V3 or V4 | V5 |
|---|---|---|
| 63:810 | Reserved | Reserved |
| 7 | Reserved | TIO_EN |
| 6 | Reserved | Reserved |
| 5 | ALIAS_CHECK_COMPLETE |
ALIAS_CHECK_COMPLETE |
| … | … | … |
ちなみにReport Version 4が何者なのかは未だ公開されていない.
解決
幸いにもsevライブラリ側では当該フィールドの追加に対応していたようなので,早速snpguestが依存しているsevのバージョンをupstreamに上げて試してみたところ,派生鍵生成関数のビルドで失敗している.何事かと思ったら,Attestation Report構造体だけでなく,派生鍵を生成するためのioctlリクエスト構造体の仕様にも変更が入っており,派生鍵にLaunch Mitigation Vector情報をmixできるようになっていた.これに対応して派生鍵生成関数の実装に修正が必要となった.悲鳴をあげながら修正しpull requestを投げてこれを解決.
そしてこの過程でABI Rev 1.58未対応のCVM上でLaunch Mit Vectorを含む派生鍵リクエストを投げるとSEV-SNP Guest Firmwareがhangし,rebootするまで復旧しないという,Linux Kernelのバグなのか何なのかよく分からない挙動に遭遇することとなる11.
まとめ
TEE OSSと関わっていると,このような意味不明なバグに遭遇することは日常であり,ドキュメントの不在やドキュメントの嘘に翻弄され,人間の尊厳が削られてゆきます.くれぐれもお気をつけください.
Acompanyでは闇の技術であるTEEと悶え苦しみながら戦う戦闘員AI時代のプライバシー保護技術であるTEEと悶え苦しみながら戦うR&Dエンジニアを募集中です.
Disclosure
本記事は株式会社Acompanyの依頼のもと執筆したものである.
-
実際には,ファイル毎に暗号鍵を生成→ファイル暗号鍵でファイルを暗号化→ファイル暗号鍵をマスタ鍵で暗号化(ラッピング)→暗号化されたファイルとラッピングされたファイル暗号鍵をクラウドストレージに保管,というプロセスになっている.クラウド上のファイルにアクセスする際は,暗号化されたファイルとラッピングされたファイル暗号鍵をダウンロードし,クライアント側のマスタ鍵でファイル暗号鍵を復号(アンラップ)した後,ファイル暗号鍵でファイルを復号する.例えばMEGA Cloudはその様な構造になっている.とはいえクライアントしか平文にアクセスできないという事情は変わらない. ↩
-
BitLockerは暗号周りの処理にTPM(Trusted Platform Module)というハードウェアモジュールを(利用可能な場合には)用いる.ソフトウェアベースの暗号化機能と比較して攻撃面が極小化されている.TPMはTEEと同じくHIEE(Hardware-assisted Isolation Execution Environment)の一種である.Microsoftによる解説を参照. ↩
-
もっとも医療計測技術・脳情報学の発展によって脳内の情報処理を解読することは現実に可能となってきている.例えばこの論文ではfMRIによって計測された脳活動イメージを事前学習されたDNNモデルで解読することが試みられている.こうした研究の発展は進行したALS患者等にとって多大な利益を齎す一方,脳のプライバシーが侵害されるという新たな脅威をも齎すものである. ↩
-
かつてはIntelのコンシューマ向けCPUにもSGXが搭載されていたが,SGXが完全にぶっ壊されたことなどもあり,11th Gen以降のコンシューマ向けCPUはSGX非対応となっている.このお陰でSGXを利用してDRMを実装していたUltra HD Blu-rayが再生不能となった.
私有財産権の不当な侵害ではないか.↩ -
演算のたびに蓄積していくノイズを取り除く処理.これをしないといずれ復号できなくなる. ↩
-
TEEを詐称する動機についてはプライバシーテック研究所の連載記事に書いたので割愛するが,これは陰謀でも何でもなく,現実的にありうる話である.詐称とは違ってmaliciousではないものの,TEE周りの致命的な脆弱性をmitigateしないまま使い続けている,という可能性もある.例えば,AMD SEV-SNPでは最近ページスワップを利用したHeracles Attackという脆弱性が発見されたが,本記事執筆時点で主要クラウドベンダの提供するSEV-SNP VMはmitigateしていない又はmitigation statusを確認できない.(SEV-SNP FW Ver. 1.58以降であればSNP reportの
PAGE_SWAP_DISABLEフィールドを見ることで確認できる.) ↩ -
SGX及びTDXにおいてReportには署名ではなくMACが打たれる.このままではReportを検証できないので,同一ホストマシン内に存在するQuoting Enclave(QE)やProvisioning Certification Enclave(PCE)などの謎のTEEが連携して,Quoteという検証可能な形に変換する必要がある.SGXのプロによる詳細な解説を参照. ↩
-
正確には検証対象をSubjectと見做して「自身の構成情報を証明する」ことをAttestationと呼ぶ.なお,同一物理マシン上にいる相手に対し,自分が同一ホストマシン上にいることを証明するのがLocal Attestationであり,Intel SGX/TDXではQEがPCEとの間で行ったり,検証対象TEEがQEに対して行ったりしている. ↩
-
当時のGCPのWebコンソールはレガシーSEVしか対応しておらず,GUI上ではSEV-SNPが有効なVMを作成できないといった災難にも見舞われた.なお,現在もフロントエンドとバックエンドに齟齬が存在し,インスタンステンプレート経由でSEV-SNP VMを作成すると,インスタンスメタデータ上はCVM機能が無効だが実際には有効といった不整合が起きる. ↩
-
仕様書には "63:7" と書かれているが間違いである.もしかすると当初は6ビット目を
TIO_ENに払い出す予定だったのかもしれない. ↩ -
より詳細に言えば,ASPとGuest OSがやりとりする際のセッション鍵であるVMPCK(VMPL Communication Key)がフェールセーフで無効化される,という挙動をする.古いFirmwareにとっては無効なリクエストが飛んできているのだからエラーを返すのは分かるが,同じく無効なリクエストでも「64ビットフィールド
GUEST_FIELD_SELECTの未使用予約領域をnon-zeroにした場合」はエラーを吐くだけでhangしない. ↩
