# TEEビルド&スクラップゼミ応募課題 * 本応募課題では、各問難易度を高めに設定しており、(コード実装含め)完答を前提としてはおりません。 同時に、ゼミの主題であるTEEへの(スタンス的な)適性や、解答までのプロセス、熱意を測る意味合いを多分に含めています。 完答が難しい場合、途中までの調査結果や思考内容、自らの意見等を記述していただければ、そちらも大きく加点対象といたします。 * 文字数が多い事により採点に有利になることはありません。 * フォームの文字数制限を超過する場合は、外部サービスを利用し限定共有の形で共有いただいて構いません。 * 解答を作成する上で、各種参考文献やサービス(生成系AI等)を参照するのは全く減点要素にはならず、寧ろ大歓迎です。 ただし、文献やサービスを参照した際には必ず参考文献を記載してください。 TEEやその実装例の1つであるSGXについての基本的な前提知識については、例として以下の文献を参考にしてください(勿論以下の文献に限りません)。 * https://www.ieice.org/~dpf/wp-content/uploads/2021/08/DFS研究会産総研須崎.pdf * http://www.ipsj.or.jp/sig/os/index.php?plugin=attach&refer=ComSys2020&openfile=ComSys2020-Suzaki.pdf * https://acompany.tech/privacytechlab/author/ao-sakurai * https://qiita.com/Cliffford/items/2f155f40a1c3eec288cf * https://qliphoth.io/seccamp/ # 簡易的な前提知識 TEEとは、ハードウェア(主にCPU)により厳重に隔離された領域にデータを保持し、その状態で隔離保護領域用に定義された コードを実行する事で、終始データを保護しながらそのデータを利用した処理を可能とする技術です。 特に、Intel SGXにおいてはこの隔離保護領域を「Enclave」と呼びます。SGXのEnclaveは、CPUの極めて特権的な制御により 隔離されている上、その全域がAESベースで暗号学的に保護(暗号化)されているという特長を有しています。 # 問題 ## Q1. あなたがTEEを使用して実現してみたいプロダクト(アプリケーションやシステムなど)を、理由と共に紹介してください。 セキュリティに対する興味を交えて紹介いただけるとベターです。 その上で、本ゼミでメインとして取り上げるIntel SGXは、その利用・開発の際にC/C++に強く依存するため、最低限のC/C++のスキルがないと 一切の開発を行う事ができません。 そこで、C/C++(特にC++)を使用して行ったものや開発したものがあればそれについても説明してください。 GitHub等に自作のコードがあれば、そのリンクも共有してください。 もし経験がない場合は、ゼミ本番までのC++の習得に関する計画を述べてください。経験の有無自体が採点に影響する事はありません。 ## Q2. Intel SGXにおいては、それがいかに重要な機能であっても、比較的唐突かつ十分な猶予無しに廃止を宣告される事があります。 例えば、種々の信頼可能な機能を提供していた、Intel製の特別なEnclaveであるPSE(Platform Service Enclave)がこれに該当します。 また、リモートに存在するEnclaveやそのSGXマシンの正当性(信頼可能か)と完全性(コードが改竄されていないか)を検証するために、 Remote Attestation(RA)という手続きが必要ですが、今まで主流であったEPID-RAという方式のRAが、突如サービス終了を宣告され、 2025年4月にはもう完全に使えない代物となってしまいます。 さらに言えば、クライアント向けCPUであるCoreシリーズでも第6~10世代でSGXに対応していましたが、第11世代以降突如SGXが削除され、 現行のCPUとしてはXeonプロセッサでのみSGXを使用可能です。 あなたは、これらの機能やSGX自体をヘビーに使用している状態で、もしこのような唐突な廃止を宣告された場合どのように思いますか。 また、上記のIntelによる運用は褒められたものでは無いと考えられますが、それでもIntelがそうせざるを得なかった理由と、 本来取るべきであった理想的な運用についても考察(あるいは調査)して回答してください。 ## Q3. TEEには、通常のOSすら信頼不可能と見なして特定のコードのみを信頼可能とする「部分隔離型」と、 VMを丸ごと隔離保護する(つまりはOSも丸ごと内包し信頼する)「VM型」の2種類が存在します。 部分隔離型には、本ゼミでメインとして扱うIntel SGXに加え、ARM TrustZoneやRISC-V Keystoneが存在します。 一方、VM型としては、Intel TDX、AMD SEV、ARM CCAが主なものとして存在します。 ここで、SGXのような部分隔離型では対処できるものの、TDXのようなVM型では対策できない攻撃シナリオを考察し説明してください。 攻撃シナリオについての説明は、具体的なあるサービスにTEEを使用する想定での説明でも、より一般化した議論としての説明でも どちらでも構いません。 ## Q4. この大問Q4は、属する小問Q4-1~Q4-3から自由に選択し解答する選択問題の形を取っています。各大問での指示に従い、 問題を選択して解答してください。 余力があれば指定された選択数よりも多くの問題に解答しても構いません。 ### Q4-1. (C/C++経験者向け) C++において、16バイト以上の適当な初期化済みunsigned char型バッファ全体に対する、単一のECDSA電子署名を作成してください。 その後、生成した署名を検証し、バッファと比較して署名が正当であるかを標準出力する機能を実装してください。 署名及び検証のためのキーペアは(OpenSSLのAPIを用いるなどして)適当に生成したものを使用してください。このキーペアについては、 こだわりが無ければNISTのP-256コンテキストの256bit ECDSAキーペアを使用してください。 署名と検証のコードは同一ソースコード上に実装し、地続きで実行するような形で構いません。 ソースコードには必要最低限のコメントを入れてください。 OpenSSLで実装するのが比較的楽であると思いますが、その場合はOpenSSL公式GitHubリポジトリのサンプルコードも参考になります。 https://github.com/openssl/openssl/tree/openssl-3.2.1/demos/signature ただし、システムコール(例:system, fork+exec)によりopensslコマンド等を呼び出すような実装は不可とし、 C/C++コードから直接OpenSSL等の暗号ライブラリを用いて実装するものとします。 実装の上で必要な前提知識については、例えば以下の文献を参考にしてください。 * ECDSA署名:https://www.jipdec.or.jp/project/research/why-e-signature/public-key-cryptography.html * ECDSA署名及びNIST P-256について:https://www.jnsa.org/seminar/pki-day/2011/data/02_kanaoka.pdf * NIST P-256コンテキストを指定するために使用可能なOpenSSL APIのドキュメント:https://www.openssl.org/docs/man3.2/man3/EVP_PKEY_CTX_set_ec_paramgen_curve_nid.html NIST P-256を指定するには`NID_X9_62_prime256v1`マクロが使用可能。 ### Q4-2.(任意のプログラミング言語経験者向け) 以下のようなプログラムについて考えます。 ``` C++ //グローバル変数 int g_a[4096] = {0}; int g_b[4096] = {0}; int g_c[4096] = {0}; void func(...) { g_c[0] = 100; //target //コードを挿入 } int main() { //コードを挿入 func(...); //コードを挿入 func(...); return 0; } ``` 上記のプログラムの2回目の`func`関数の呼び出しにおける`g_c[0] = 100`の実行に対して、セグメンテーション違反を誘発する事で妨害(DoS)する攻撃コードを実装してください。 ただし、実装の上で以下の条件を満たす必要があるものとします。 * 妨害(セグメンテーション違反の誘発)の方法としてはページテーブルエントリ(PTE)の改竄のみが使用可能。 * PTEの改竄を比較的簡単に行える方法としては、`mprotect`関数の使用が挙げられるが、PTEを改竄できればこれに限らない。 * 上記コードにおける`func`関数の引数の仕様は、自身で必要に応じて設定する。 * `g_c`へのポインタを上記のコード内で取得する場合、`func`関数内で実装で取得し、`func`関数の引数経由でのみで`main`関数が取得できるものとする。 つまり、`main`関数で直接`g_c`のポインタを得る実装は不可である。 * 上記コード中の`//コードを挿入`というコメントは、`mprotect`関数を用いた場合に、攻撃のための追加実装を行うのに適した場所の1つである事を示している。 あくまで目安であるため、これらの部分にコードを挿入する事は必須ではない。 * `mprotect`を用いる場合、セグメンテーション違反が`func`内の`g_c`へのアクセス以外で発生してはいけない。 例えば、`mprotect`関数自体でセグメンテーション違反が発生するのも不可とする。 * 基本的にroot権限を必要とせずに攻撃を成功させる事はできるが、root権限を必要とする攻撃方法も可能とする。 上記コードはC/C++で記述していますが、同等の実装であれば使用する言語は問いません。 ### Q4-3.(任意の方々向け) 以下のような関数について考えます。 ``` C++ void sample_func(uint8_t *buf, uint8_t *ptr_in) { uint8_t v = *ptr_in; v = v * 0x1000; uint64_t val = buf[v]; } ``` この関数の3行目、つまり`uint8_t v = *ptr_in;`の実行において、何らかのフォールトや例外が発生したとします(例:ページフォールト)。 ここで、`ptr_in`の指すアドレスのデータが、この関数の実行者が本来アクセスしてはならないデータである場合 (例:非rootユーザによるカーネルメモリへのアクセス、SGX Enclave内のデータへのEnclave外からの直接アクセス)、   潜在的に発生し得る攻撃やセキュリティ上の危険性について考察してください。 参考までに、以下の状態を適宜前提条件として構いません。 * `ptr_in`の指すアドレスの値がL1Dキャッシュにキャッシュされている。 * 3行目でフォールトや例外が発生した際、CPUは投機的実行を行う事ができる。この投機的実行では、キャッシュから投機的にフェッチしたデータを用いて、 上記関数の5行目までの処理を投機的に行えるものとする。 * 攻撃の一環としてキャッシュサイドチャネル攻撃を使用できるものとする。 * この潜在的な危険性に対する、CPUやOS等へのパッチが存在する場合、それらは適用されていない前提としてよい。