Intel SGX - Provisioning解説

# Intel SGX - Provisioning解説
本記事では、Remote Attestation（以下、RA）を行うための前座として実行される手続きである「Provisioning」についての解説を行います。  
大体は参考文献のリンク先で説明されてはいるのですが、一部分かりづらい部分もありますので、その辺りも補いつつ説明を進めます。


## 用語集
本記事で使用する、比較的一般的でない語彙の解説を以下の表に記載します。
| 用語 | 説明 |
|----|----|
| EPID | Issuer（発行者；SGXではIPSというIntelのサービス）が持つ公開鍵（グループ公開鍵）に対し複数の秘密鍵（**EPIDメンバ秘密鍵**）を対応させられ、かつ秘密鍵を保持するユーザが匿名でいられるような仕組み。<br>公開鍵に対応する「グループ」に、ユーザを加入させてEPIDメンバ秘密鍵を持たせるような運用になる。 |
| Attestationキー | 主にRemote Attestationにおいて非常に​重要な役割を果たす鍵で、Provisioning​により生成。その実はEPIDメンバ秘密鍵。 |
| Provisioning Enclave（PvE） | Architectural Enclave（以下、AE）の一つ。その名の通り、Provisioning処理において中核的な役割を果たす。 |
| Quoting Enclave（QE） | AEの一つ。RA中、PvEが生成しストアしたAttestationキーをロードし、その鍵でREPORT構造体に署名する事で、QUOTE構造体を作成する。 |
| Intel Provisioning Service（IPS） | Provisioning処理において、PvEとやり取りを行うIntel側のサービス。 |
| Intel Key Generation Facility（iKGF） | RPK（後述）やEPID関連鍵等、様々な鍵を​作成しストアする、Intelの鍵作成管理施設。​<br>インターネットからは接続できない場所（Intelのイントラネット上）に​隔離され、強固に保護されている。 |


## Provisioningの概要
Provisioningとは、SGXマシンが正当なCPUやSGX関連のソフトウェア（殊に、AEを司ったり、EGETKEYなどのEnclave命令を発行したりする中核の部分であると思われます）を搭載しているかを検証した後、EPIDというプロトコルに則ったグループのメンバとして加入させ、RAで使用する**Attestationキー**をSGXマシンに獲得させるための処理です。

Provisioning処理は、用語集においても記載した通り、SGX側ではAEの1つであるPvEが、Intel側ではIPSが中心となって進行していきます。

Provisioning処理が実行されるタイミングとしては、そのマシンの初使用時（これがマシン初回起動時なのか、SGX初利用時なのか、RA初実行時直前なのかは不明です）の他、ファームウェア、BIOS、マイクロコードといった重要なシステムコンポネントが更新された際にも実行されます（TCB Recovery）。


## Provisioningに使用される鍵一覧
Provisioningのフローを説明する上で、~~Intelらしく~~非常に紛らわしい名前をしたいくつかの鍵について説明する必要がありますので、以下の表に記載します。

| 鍵名 | 概要 |
|----|----|
| Root Provisioning Key（RPK） | CPU製造時に各CPUのe-fuseに焼き付け​られる秘密情報。この値はIntel側も​iKGFで管理・保持している。<br>SGXの有名なWhitepaperである参考文献[5]​においては、「Provisioning Secret」と呼ばれている。 |
| Root Seal Key（RSK） | CPU製造時に各CPU内で乱数的に生成され、e-fuseに格納される秘密情報。この値は​Intel側も保持・把握していない。<br>参考文献[5]において「Seal Secret」と呼ばれているものと同一。​ |
| Provisioning Key（PK） | RPKから導出されるプロビジョニング鍵。​Provisioningの手続きで使用される。​ |
| Provisioning Seal Key（PSK） | RSKから導出される、Provisioning手続き​上で必要なシーリングを行う為の​シーリング鍵。​ |

ちなみに、Provisioningと直接関係ないものとして、「Seal Key」という鍵も存在します。これは、その名の通り通常のシーリング処理で使用される鍵（シーリング鍵）です。このSeal KeyもRSKからポリシ（MRENCLAVE、MRSIGNER）に応じて生成されますが、PSKとは違いOWNEREPOCH（所有者を一意に特定するような情報）という値を有する等といった違いがあります。

これらの鍵の関係を図示すると以下のようになります。

![keyRel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349383/113152a8-fb58-9a42-e979-fe9c93af28a8.png)


## Provisioning処理解説
説明の準備も整いましたので、本題であるProvisioningの処理についての説明を行います。
最初に、Provisioningのフローの概要を以下の図に示します（ただし、再Provisioning時のサーバーチャレンジに含まれる、暗号化済みの以前のAttestationキーはこの図には入れていません）。

![provisioning.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349383/cfe36e50-bfbf-52b7-a105-dcdaf844b9d5.png)

以下、このフローに従って説明を進めます。

### ①PKの作成
Provisioningを行うにはPKを導出しておく必要があるため、前準備としてRPKにHW・SWそれぞれの特定のコンテキストを付与する事によってPKを導出します。  
HW・SWそれぞれについての処理がありますので、以下の2つの処理を行います。

#### RPKのHW-TCBとのバインド
HW-TCBは、言ってしまえばそのSGXマシンが搭載しているIntel製CPUのパッケージ境界内部です。以下の図（参考文献[1]より引用）の示す通り、Initial Key（=RPK）をSVN（Security Version Number）回だけPRF（擬似乱数関数）に通す事によって、**TCB鍵**と呼ばれる中間生成物を作成します。

![TCBKey.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349383/0e66fd93-72a5-3d75-858a-c6c6cfc557b5.png)

#### SW情報の付与
EGETKEY命令を発行する事で、上記TCB鍵をベースとして各種SW情報を付与します。  

参考文献[5]では、各種情報としてMRSIGNER、ISVPRODID、ISVSVN、CPUSVNを付与すると記述していますが、ISVSVNとCPUSVNのどちらかは、上記HW-TCBとのバインドで使用する値という意味で列挙している可能性もあります。  

これにより、Provisioningで使用するPKの作成が完了します。


### ②Enclave Hello
PKを作成したら、PvEはIPSにProvisioning手続きの開始をお願いするために、Enclave Helloと呼ばれるリクエストをIPSに向けて送信します。

まず、PvE内で以下の2つの値を作成します。
* **PPID** : PKのハッシュ値（具体的なハッシュの形式は不明）
* **Claimed TCB Version** : TCBのSVNから導出される値

その後、これら2つの値を**IPSの公開鍵**で双方ともに暗号化し、これをEnclave HelloとしてIPSに送信します。

ここで、ではその「IPSの公開鍵」というのは一体何なのか、という話になるのですが、**RAにおいてSPの検証用公開鍵をEnclaveコードにハードコーディングする**、という実装上の通例から類推し、PvEのコードをひたすら辿った所、最終的に以下のヘッダにハードコーディングされている事が判明しました：
[IPSの公開鍵のハードコーディング（GitHub）](https://github.com/intel/linux-sgx/blob/1efe23c20e37f868498f8287921eedfbcecdc216/psw/ae/data/constants/linux/peksk_pub.hh)


### ③サーバーチャレンジ
IPSはPvEからEnclave Helloを受け取ったら、相手のマシンが正当なHW・SWを搭載しているかの検証を行うためのサーバーチャレンジを作成します。

まず、IPSはPvEから受信したPPIDで（恐らくiKGFから）検索を実行し、そのPvEのSGXマシンが以前にProvisioningされた事があるかを確認します。

次に、確認の結果次第でそれぞれ以下のようにしてサーバーチャレンジを作成します。

#### Provisioningが初であった場合
対象PvEのSGXマシンを加入させるEPIDグループを決定した後（この時点ではまだ加入自体はさせません）、以下の3つの情報を用意し、これをサーバーチャレンジとします。
* EPIDグループパラメータ（EPID公開鍵）
* Liveness Challenge（詳細は後述）
* iKGFで予め作成済みのTCBチャレンジ

#### Provisioning履歴があった場合
初Provisioningの場合の3つの値に加え、以前生成したAttestationキーを暗号化したもの（原文：Encrypted version of attestation key。「Attestationキーのバージョンを暗号化したもの」とも解釈できますが、後述の手続きを鑑みると、「Attestationキーの（PSKによる）暗号化版」という解釈が適切そうです）を用意し、これら合計4つの値をサーバーチャレンジとします。

上記手順で作成後、IPSはサーバーチャレンジをPvEに返信します。


### ④Enclave応答
IPSからサーバーチャレンジを受信した後、PvEは自身のプラットフォームの正当性を証明するために、以下4つの値を準備します。
* TCB proof
* 「数学的に隠蔽」されたEPIDメンバ秘密鍵
* PSKによって暗号化されたEPIDメンバ秘密鍵
* 非失効（non-revoked）証明

これらについても、それぞれ作成手順を説明します。

#### TCB proof
TCB proofとは、その名の通りPvEのプラットフォームのTCBが正当である事を証明するための値です。  

はじめに、PvEはサーバーチャレンジに含まれているTCBチャレンジ（iKGFにてPKで暗号化されたnonce）を、自身の持つPKで復号します。その後、復号したTCBチャレンジをキーとして、同様にサーバーチャレンジに含まれているLiveness Challenge（TCBチャレンジとは別の平文のnonce）のCMACを取ります。このCMACをTCB proofとします。

前述の通り、PKを作成する過程においては、RPKをTCBのSVN回だけ擬似乱数関数（PRF）に通しています。
このPRFですが、[RPKのHW-TCBとのバインド](#rpkのhw-tcbとのバインド)の項の図でも示した通り、Derivation String（シード値）は固定となります。
よって、もしRPKをPRFに通す回数、即ちTCBのSVNが同一であれば、全く同じTCB鍵、ひいてはPKが生成される事になります。

この裏を返しますと、TCB proofには、PvEのプラットフォームのTCBのSVNがIntel側が要求・想定しているレベルと同一であるかを検証する意図も含まれています。

ちなみに、iKGFは全てのRPKを管理しているため、IPSは各PKを容易に再現して生成可能であるらしいですが、その具体的な手法は不明です。

余談ですが、参考文献[1]にはPvEとiKGFがそれぞれECDSAの鍵導出用のシード値としてPKを使用し、ECDSAのキーペアを作成して公開鍵が一致するかを試す方法も記載されていますが、こちらはサーバーチャレンジ内の値を一切使用していないのもあり、あまりメジャーでは無いようです。

#### EPIDメンバ秘密鍵
次に、PvEはEPIDメンバ秘密鍵を作成します。用語集でも記述した通り、このEPIDメンバ秘密鍵こそがAttestationキーそのものになります。

EPIDメンバ秘密鍵を作成したら、PvEはEPIDの定めたプロトコルに従って「数学的に隠蔽」（"hides it mathematically"の直訳）します。
この「EPIDのプロトコルに従った数学的隠蔽処理」ついては専門外であるため割愛しますが（というよりも筆者が[ヒントになりそうな論文](https://eprint.iacr.org/2009/095.pdf)を読めていないのですが）、これまた他の研究者の方と会話した結果、例えば数学の群上の何らかの操作や、楕円暗号上の加算などといった、文字通りEPIDメンバ秘密鍵をキーとし何らかのベースに数学的手続きを行い、逆算不能な出力を得るような処理なのではないかと考えられます。

更に、上記の「数学的に隠蔽」したEPIDメンバ秘密鍵とは別に、EPIDメンバ秘密鍵をPSKによって暗号化（シーリング）します。

留意点として、これら2つの数学的に隠蔽したEPIDメンバ秘密鍵、及び暗号化されたEPIDメンバ秘密鍵についてはIPSに送信しますが、EPIDメンバ秘密鍵の生の値についてはPvEを出る事はありません。暗号化されたEPIDメンバ秘密鍵についても、Intelが把握できない鍵であるPSKを用いて暗号化されているため、Intel側がこれを復号する事は出来ません。結果的に、EPIDメンバ秘密鍵はIntel側は一切知ることの出来ない値となっています。

参考文献[5]に記載されている図では、あたかもIPSがAttestationキーを作成しPvEに送信しているような描かれ方をしていますが、以上の事実からそれは誤った表現となっています。

#### 非失効証明
過去にProvisioningを行った事がある場合（即ち再Provisioningである場合）、そのPvEのプラットフォームが過去に一度もRevokeされていない事を証明する必要があります。

その証明の手段として、PvEはサーバーチャレンジに含まれているPSKで暗号化済みのAttestationキーをPSKで復号し、その復号済みAttestationキーでIntelが用意したメッセージ（詳細は不明ですが恐らくTCBチャレンジかLiveness Challengeだと思われます）に署名を行います。

この処理を行う事で、PvEのプラットフォームが本当に意図している検証相手であるかを確認（PSKは各マシンのみが知り得る値ですので、復号成功がそのまま確認成功を意味します）し、その上で署名により非失効を確認する事が出来ます。


### ⑤完了処理
IPSはEnclave応答を受信後、Enclave応答中のTCB proofを、iKGFから取得した値を用いて検証します。同時に、再Provisioningである場合は、恐らく非失効証明の検証もここで行います。

検証の結果、PvEがサーバーチャレンジに対して成功できた事が確認された場合、続いてPvEのプラットフォームを、前の手順で予め決定したEPIDグループに加入させます。

その後、IPSはEnclave応答中の「数学的に隠蔽」されたEPIDメンバ秘密鍵と、IPSの持つEPIDグループ発行者鍵（恐らく発行者であるIPS（あるいはiKGF）の持つEPIDグループ秘密鍵）を用いて署名済証明書を作成します。

最後に、このIPSはこの署名済証明書を同梱したメッセージをPvEに返送し、Provisioningを完了させます。


### ⑥最終処理
IPSがEnclave応答という形で受け取った、「数学的に隠蔽」されたEPIDメンバ秘密鍵とPSK暗号化済みEPIDメンバ秘密鍵は、今後の再Provisioningに備えてIPS側に保存されます。

再Provisioningの際、サーバーチャレンジにPSK暗号化済みAttestationキーが同梱され、非失効証明作成時にプラットフォーム同一性の検証に使用される、と前述しましたが、その暗号化済みAttestationキーは以前にここでIPSが保存したものであるという事になります。

一方で、PvE側はAttestationキーをPSKでシーリングし、プラットフォーム上に保存します。こうする事で、RA時にQEがAttestationキーをロードし、QUOTE構造体の作成に利用する事が出来るようになります。

余談ですが、PSKによるシーリングはMRSIGNERポリシである（参考文献[1]のTable3を読み込むと導き出せます）ため、いずれも同じ署名情報を使っていると考えられるPvEとQEは、いずれでシーリングしたものであっても互いにアンシーリング出来る事になります（でないとRA時にQEはAttestationキーを読み込めません）。おまけに、PSKはOWNEREPOCH値すら持たないため、所有者云々周りでいらぬ阻害を受けることも起こり得ません。


## まとめ
Provisioningについては通常のSGXプログラム実装の上であまり意識するものではありませんが、それだけに参考になる情報ソースがとっ散らかりがちなので、是非本記事がお役に立てればと思います。



## 参考文献
[1] "Intel® Software Guard Extensions:​ EPID Provisioning and Attestation Services",  https://cdrdv2.intel.com/v1/dl/getContent/671370
[2] "Attestation – SGX 101", https://sgx101.gitbook.io/sgx101/sgx-bootstrap/attestation
[3] "Intel® Enhanced Privacy ID (EPID) Security Technology", https://www.intel.com/content/www/us/en/developer/articles/technical/intel-enhanced-privacy-id-epid-security-technology.html
[4] "Intel® Software Guard Extensions Trusted Computing Base Recovery", https://community.intel.com/legacyfs/online/drupal_files/managed/01/7b/Intel-SGX-Trusted-Computing-Base-Recovery.pdf
[5] "Intel SGX Explained", by Costan and Devadas. Cryptology ePrint Archive: Report 2016/086, https://eprint.iacr.org/2016/086