Intel SGX入門 - SGX基礎知識編

# Intel SGX入門 - 基礎知識編
本記事では、Intel SGXの仕組みを理解するための入門的な説明を行います。SGXプログラミングの基礎や実践に関するエントリは、このページの末尾にリンクを記載してあります。

## Intel SGXとは？
Intel SGXは、メモリ上に「**Enclave**」(エンクレーブ、直訳で「飛び地」の意)と呼ばれる暗号的に厳重に保護された領域を生成することで、センシティブデータを保護しつつプログラムを実行する為のCPUの拡張機能です。

最近のIntel製CPUには、CPUのコア(主要演算部分)の周辺回路である「アンコア(uncore)」と呼ばれる回路の中に、「MEE(メモリ暗号化エンジン)」と呼ばれるユニットが存在します。このMEEこそがEnclaveを形成する中核であり、以下のテクノロジの組み合わせにより非常に強固なRAM上の保護領域を実現します。

* 微調整を加えた128bit AES/CTR暗号
* 複雑な組み合わせのマークル木
* Carter-Wegman式メッセージ認証符号

すぐ下の図に概略図を載せますが、CPUパッケージ内は(Intel曰く)保護されており、データバス及びEnclave内ではデータは暗号化された状態で配置・通信されるため、総じてデータを保護しながら実行できる、というのがSGXのエッセンスです。

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349383/b94bbf4b-f1bc-2a13-a08d-87bd64391dbf.png)

また、Enclaveを操作できるのは、対応するIntel製CPUに搭載された専用の特殊な命令のみとなっています(後述)。

## Intel SGXが対策できる脅威モデル
SGXが対策できる脅威モデルとしては、図示すると以下の図のように表せます。
![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349383/e978f05f-ab7f-8ec5-4bb9-ba0a211d103e.png)

この図は、SGX界隈ではかの有名なGraphene-SGX[4]の論文中の図を和訳したものですが、大変端的に脅威モデルを表現してくれています。以下、それぞれについて説明をします。

### プロセス内攻撃
こちらはCTF等でもおなじみであるため、イメージが付きやすいのではないでしょうか。メモリ破壊を行いオペレーションを無力化する攻撃であったり、あるいはROP攻撃(Return Oriented Programming; 関数の戻りアドレスを改竄し不正な動作をさせる命令を格納したアドレスへ誘導するような攻撃)は、そもそもメモリ自体が厳重に保護されているため、容易く弾かれてしまいます。

### OS・ハイパーバイザ等による攻撃
こちらの攻撃への対策は、SGXの大きな売りの一つとなっています。厳格に定義づけられた、専用の手続きに従って生成されたEnclave用の静的ライブラリ、あるいは専用のソースコードによって初めて特殊な命令の発行が可能になるため、OSやハイパーバイザが悪性であろうとEnclaveには手も足も出ません。
OSからの攻撃の例としては、外部攻撃者が設置以降侵入を容易にするツールである「カーネルモードで駆動するルートキット」等がありますが、Enclaveはこちらに対してもしっかり防護してくれます。
この特徴は、必然的にSGXが「**OSを信頼していない**」事を意味します(これが後述する酷い制限に直結します)。

### CPU以外のハードウェアへの攻撃
少し視点を変えると、「CPU以外のハードウェア」(要するにRAM)への「物理的な」攻撃が存在します。有名所(?)ですと、「コールドブート攻撃」というものが存在します。これは、攻撃対象のPCの電源が落ちた後、すぐにメモリを取り外し急速に冷却することでメモリ内のデータの揮発を遅延させ、他のPCに取り付けて電源を通しメモリの中身を盗聴するような攻撃です。
しかし、Enclave内のデータは暗号的に保護されているので、この攻撃をしても支離滅裂な暗号文が得られるだけです。

## Intel SGXが対策できない攻撃と前提条件
### Intel SGXが対策できない攻撃
前述のような暗号的に防護できる攻撃に対しては無類の強さを発揮するSGXですが、反面サイドチャネル攻撃には至って脆弱です。簡単なものでは実行時間計測によるサイドチャネル攻撃から、キャッシュヒット率を計測してのサイドチャネル攻撃、そしてCPU自体の脆弱性(SGXpectre等)を利用しての攻撃等が該当します(SGXPectreに関してはすぐに修正が入る、あるいは既に修正済みであると思いますが[要検証])。


### Intel SGXにおける前提条件
まず、Intel SGXは第6世代、つまりSkylakeアーキテクチャ以降のCPUでなければ実装されていませんので、大前提としてこれに適合するCPUを利用する必要があります。

デスクトップPCである場合、更にマザーボードの対応にも留意する必要があり、対応マザーボードは[こちら](https://github.com/ayeks/SGX-hardware/blob/master/README.md)に掲載されています。

更にもっと根本的な前提条件として、以下の3つを**無条件に信頼する必要がある**という前提が存在します:

* Intel製CPUパッケージ内の全てが保護されているということ
* SGXにより形成されるArchitectural Enclaveという特殊なEnclave群(後述)
* Intelのサーバ

なので、仮にIntelの猛烈なアンチな方がいらっしゃるとすれば、到底SGXは信用に値しないという事になるでしょう。これはSGXを利用する以上は割り切る必要があります(これを理由にSGXを信用しない方には幾数名出会っています)。

## Enclave内で駆動するプログラムの実行権限
Enclave内で駆動するプログラムは、Ring-3権限、つまり**ユーザモード**の権限しか許容されていません。リングプロテクションの概念図を以下に示します[6]。
![450px-Priv_rings.svg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349383/12b37f79-4d79-9d2a-04b2-925e5daed4ae.png)

この図で言うRing-3でしかEnclave内のプログラムは動作できないため、カーネルモードやデバイスドライバ権限での動作は一切不可能であることを意味します。これは、Enclaveを搭載しているホストに対してSGXによるプログラムが破壊的なオペレーションを実行することを防ぐための措置です。

## SGXで利用される特殊な命令
SGXにおけるEnclaveの管理には、大元では現代のコンピュータアーキテクチャの主流であるページング方式が採用されています。SGXにおけるスーパバイザ(OSクラス)命令(ENCLS)には、このページング方式にまつわる命令に富んでいます。

### スーパバイザ命令[7]
| インストラクション名 | 機能 |
|--------------------|------|
| EADD | ページの追加 |
| EBLOCK | EPC(狭義の保護領域)をブロック |
| ECREATE | 保護領域を作成 |
| EDBGRD | デバッガでのデータ読み取り |
| EDBGWR | デバッガでのデータ書き出し |
| EEXTEND | EPCデータ評価値の拡張 |
| EINIT | 保護領域の初期化(Enclaveイメージを以降不可変にする) |
| ELDB | EPCページをブロック単位でロード |
| ELDU | EPCページを非ブロックとしてロード |
| EPA | バージョン配列を追加 |
| EREMOVE | EPCからページを削除 |
| ETRACK | EBLOCKチェックの有効化 |
| EWB | EPCページのライトバック/無効化 |

### ユーザ命令[7]
また、ユーザによるプログラムにより直接操作可能な命令(ENCLU)も存在します。

| インストラクション名 | 機能 |
|---|---  |
| EENTER | Enclaveへの進入 |
| EEXIT | Enclaveからの脱出 |
| EGETKEY | 暗号鍵の取得 |
| EREPORT | Enclaveのメタデータの一部であるREPORT構造体の取得 |
| ERESUME | Enclaveへの再進入。電源遷移等により一旦Enclaveを脱出した際に利用される |

## SGXを支えるデータ構造
一般的に保護領域の事を「Enclave」と呼びますが、より低位レベルで見た場合、実際に秘密データ等を保護しつつ格納するメモリ上の領域は「EPC(Enclave Page Cache)」と呼ばれます。SGXは、EPCはもちろん、EPC内に配置されたり、また特定の処理で使用される様々なデータ構造によって支えられています。

| 構造体名 | 機能 |
|------|------|
| EPC | 狭義の保護領域。ユーザが使用可能なサイズ上限は96MB |
| SECS | Enclaveのメタデータを保持 |
| TCS | Enclave内の実行スレッドを管理 |
| SSA | AEX(非同期イグジット)時にステートを保持 |
| PAGEINFO | EPCのアドレス情報やSECS等を保持 |
| SECINFO | ページタイプ等EPCのメタデータを保持 |
| PCMD | ページアウトしたEPCページの暗号的メタデータを保持 |
| VA | 退避したEPCページのバージョン配列 |
| EPCM | CPUがEPCコンテンツを追跡するための情報を保持 |
| SIGSTRUCT | Enclaveのハッシュ値やEnclave署名者に関する情報を保持 |
| EINITTOKEN | Enclaveの起動(EINIT)許可を確認するトークン |
| REPORT | Enclave検証用の公開情報。QUOTE構造体の一部として組み込まれ、アテステーション(後述)で用いられる |
| TARGETINFO | REPORTの暗号的検証が可能なEnclaveの識別に使用 |
| KEYREQUEST | 暗号鍵取得時に使用されるパラメータ |

この中でSGXプログラミングをする上でも特に目にする機会が多いのは、「SIGSTRUCT」「EINITTOKEN」「REPORT」、おまけで「KEYREQUEST」辺りでしょう。また、「データを保護しつつ保持しておく場所」役割を果たすのは狭義には「EPC」ですが、普通にその意味合いで「Enclave」という単語が使われることがほとんどです。
その他の構造体については、SGXの仕組みについての厳密な学習をしたい場合等で無い限りはほとんど目にしません。

## Architectural Enclave (AE)
SGXには、Architectural Enclaveと呼ばれる、ユーザが直接処理の命令やデータのやり取りを行えない特殊なEnclave群が存在します。
言うなればSGXの安全性の中核に携わるようなシステム用Enclaveのようなものです。前述の通り、SGXを利用する上ではこのAEに対して信用する事も前提となります。

以下、それぞれのAEについて説明を行います。

### Provisioning Enclave (PvE)
実は、SGX対応のIntel製CPUには、e-fuseと呼ばれる部分にProvisioning Secretと呼ばれるCPU固有のIDのようなものがストアされています。これはCPUの製造時に焼き付けられ、かつIntel Provisioning Service (ここでは以下IPSとします)のデータベースにストアされます[1]。

PvEは、このProvisioning Secretから生成されるPK (Provisioning Key)を始めとした値を取得後、IPSと通信し、EPID鍵と呼ばれる匿名グループ署名鍵のグループ鍵とメンバ秘密鍵を取得するために用いられるEnclaveです。EPIDの詳細を記述すると本筋から外れるのでここではしませんが、簡単に言えばマスターキーで生成した公開鍵に対し複数の秘密鍵を対応させられ、かつ秘密鍵を保持するユーザが匿名でいられるような仕組みです。

その後、PvEはCPUをEPID鍵の定めるグループに加入させるプロトコルを走らせ、最後にメンバ秘密鍵を再びe-fuseにストアします(シーリング)。シーリングについては後述します。

PvEによるEPID鍵の取得のイメージは、参考文献[8]中の以下の図が明快です。MemberをSGXマシン、VerifierをIPSとし、EPIDKey.GroupIDをProvisioning Secretとして眺めてみると今回のコンテキストに一致します。
![secuence-2-provision-flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349383/c8697b2b-affa-6ca4-83f2-998ac79b0ad1.png)

このメンバ秘密鍵は、主に「アテステーション」と呼ばれるプロトコルで重要な役割を果たします。アテステーションの中でも遠隔のSGXマシンを検証するプロトコルである「リモート・アテステーション」については、後ほど筆者の別の記事へのリンクを載せますので、興味がございましたら参照下さい。

ちなみに、PvEはIPSからEPID秘密鍵を取得する事が任務ですので、~~基本的にSGXの初回利用時が過ぎればその役目を終えます~~。

**追記（2022/5/22）**：**こちら大嘘でした**。Provisionningは初回起動時だけでなく、重要なシステムコンポネント（例：BIOS、マイクロコード）が更新された際にも実行されるため、その都度PvEは利用される事になります。


### Quoting Enclave (QE)
QEは、PvEがシーリングしたEPIDメンバ秘密鍵に対して唯一アクセス権を有するEnclaveです。リモート・アテステーションを行う際に、EGETKEY命令によりメンバ秘密鍵を取得し、前述のREPORT構造体にEPIDメンバ秘密鍵で署名をする事でQUOTE構造体を生成します。

### Launch Enclave (LE)
LEは、ユーザによりビルドされたEnclaveの起動時に、Enclaveの完全性を検証するAEです。具体的には、おなじみのEGETKEY命令により「起動キー」という鍵を取得し、それを用いてEnclaveの起動(EINIT)を行います。

もし起動に成功した(=EnclaveがLEにより承認された)場合、LEは前述のEINITTOKEN構造体を生成します。EINITTOKEN構造体は「起動トークン」とも呼ばれ、主にEnclaveについてのEnclave自体のメタデータ(MRENCLAVE)と署名者のメタデータ(MRSIGNER)を包含しています。

また、起動トークンは保存しておく事で次回のEnclave起動時に渡す事が出来ます。こうすることで、起動トークンが正当性を保てている間は、LEによる完全性検証をまるまるすっ飛ばすことが出来ます。よって、起動トークンの使い回しにより若干の高速化が見込めるでしょう（~~まず体感できるようなパフォーマンス向上とはなりませんが~~）。

ちなみに、筆者の場合ですと毎回0で埋め尽くした起動トークンを渡しています。仮に起動トークンがバージョン違い等で無効化しても、新たにLEにより正しい起動トークンが生成されるだけですし、使いまわした所でたかが知れています。Enclave自体に問題があれば起動トークンに関係なくLEがEINITを拒絶しますし、まあわざわざ使い回す必要性は低いでしょう。

なお、参考文献[1]に至っては、**そもそもLE自体がSGXから消えるべき**、という記述をしています(LEでやっている事はわざわざAEでやる必要もなく、システムソフトウェア等でも十分に上位互換の動きを実現できるという事らしいです)。

**追記（2020/5/29）**：最近のアップデートにより、ついに起動トークンがdeprecatedになった模様です（Developer Reference内のsgx_create_enclave等のAPIリファレンスで確認できます）。起動トークンがdeprecatedになったという事は、上記の論文で言及された通り、LEも廃止される可能性が高そうです（もしかしたら既にされているかも知れません）。なお、バージョン間の互換性を保つためか、元々起動トークンを渡していたAPIには、形骸化した起動トークン関連のデータを引き続き渡す仕様となっています。~~Intelなのでいつ無告知で非互換な仕様にされてもおかしくないですが……。~~

## シーリング
あるデータを不揮発性メモリ上に保存するという操作は、アプリケーションに求められる機能として、言うまでもなくごく当たり前の操作です。これはSGXを利用したアプリケーションにおいても例外ではありません。

Enclaveに関しては、プログラムの正常・異常終了や意図的なEnclaveのデストラクトだけでなく、安全上の観点から電源状態の遷移(例：スリープ、休止状態)が発生しただけでも内容物が消し飛ぶように設計されています。そうなると、普通のアプリケーションにも増して不揮発性メモリへの保存へのニーズが高まります。

しかし、わざわざEnclaveの中で扱っているような機密性の高いデータを、生の状態でEnclaveの外に吐き出していいわけがありません。

ここで考えられるのはEnclave内でデータを暗号化して外に吐き出して保存するという方法ですが、今度はその暗号鍵をどこに保存するのか？という話になります。SGXを使っている以上、Enclave外は危険であるというシナリオを想定しているわけですから、当然鍵もEnclave外に置いてはおけません。しかもEnclaveは揮発性ですから、Enclave内での保持も困難であり……と、堂々巡りとなります。

そこで、SGXには「**シーリング**」と呼ばれる機能があります。これは、先程も出てきたCPUパッケージ内のe-fuse内にストアされた鍵を用いて、Enclave内のデータを128bit AES/GCMにて暗号化する機能です。シーリングしたら、その暗号化したデータをEnclave外に吐き出し、`fprintf`や`ofstream`等でファイルに保存してやれば、無事この問題が解決できるわけです。

反対に、シーリングしたデータをEnclaveにロードし復号することを「アンシーリング」と呼びます。

このシーリングに用いられる鍵は、とある2つのポリシの内1つをプログラム中で指定し、そのポリシに従ってSGX側が生成します。その2つのポリシとは、「**MRENCLAVE**ポリシ」と「**MRSIGNER**ポリシ」です。MRENCLAVEとMRSIGNERはそれぞれ特殊なハッシュ値であり、それぞれ以下のような仕様となっています。

### MRENCLAVE
MRENCLAVEは、簡単に言えば「Enclave内で動作させるプログラムのオブジェクトファイルをビルドしたマシンと環境に対するハッシュ値」です。詳細は次回記述しますが、Enclaveで動作するコードを格納した署名済み共有オブジェクト内に存在する、SIGSTRUCT構造体内のENCLAVEHASHと呼ばれる値と同値で、いわば実際にRAMに展開された後のENCLAVEHASHの呼称です。

具体的には、

* コンフィグファイル (Enclaveのバージョンや最大ヒープサイズ等を設定)
* Enclaveイメージ (Enclave内で動作させるプログラムのオブジェクトファイルをリンクし生成した共有ライブラリ)
* Enclave署名ツール (`sgx_sign`) のバージョン

に依存します。Enclave署名ツールとは、上述のEnclaveイメージに対して署名しSIGSTRUCT (これにはMRENCLAVEと等価であるENCLAVEHASHだけでなく、MRSIGNERの元となるRSA署名のMODULUSも含まれています)の追加等を行い、署名済みEnclaveイメージを生成するツールなのですが、詳細は次回のSGXプログラミングの基礎にてお話します。

裏を返せば、コンフィグファイルを一切弄らず、全く同じ環境で全く同じソースコードによりビルドすれば、同一のMRENCLAVEが得られます。

MRENCLAVEポリシは、文字通りこのMRENCLAVEからシーリング鍵を生成する方式です。一般に、後述のMRSIGNERポリシよりも厳しいポリシであると言えます。

### MRSIGNER
MESIGNERは、簡単に言えば「署名者情報に対応するハッシュ値」です。もう少し具体的に言えば、RSA署名のモジュラスに対しSHA-256ハッシュをかけたハッシュ値となっています。

MRSIGNERは、署名鍵さえ同一であれば一致しますので、**ビルドに用いられたソースコードやコンフィグファイルが異なる**Enclaveであっても、署名済みイメージを生成した署名鍵さえ一致していればアンシーリング出来る事になります。

よって、MRSIGNERポリシはMRENCLAVEポリシよりも一般的に小回りが利くポリシであると言えます。
<br>

上記2つのポリシの両方に共通するのは、例えEnclaveイメージや署名鍵が全く同じでも、シーリングしたデータを別のマシンにコピーしてアンシーリングする事は出来ない、という事です。シーリング鍵は、そのCPU固有のコンテキストを交えながら生成されそのマシンのCPUパッケージ内の素子(e-fuse)にストアされていますので、マシンを変えると互換性が無くなるのは至極当然の話です。

ちなみに、前述のEPIDメンバ秘密鍵の安全なストアに関しては、シーリングが実行されるEnclaveがPvEであるという特殊な例のシーリングであると表現する事が出来ます。

## アテステーション
アテステーションとは、直訳で「認証」の意味となる、SGXにおいて非常に重要な機能の一つです。簡単に言えば、「相手としているEnclaveはちゃんとしているのか」を確かめる為のプロトコルです。

アテステーションには、同一マシン上のEnclave同士で行う「ローカル・アテステーション」と、リモートのクライアントとSGXサーバが行う「リモート・アテステーション」が存在します。

### ローカル・アテステーション
ローカル・アテステーションは、同一マシン上に存在するEnclave同士が、本当に同じマシン上で動作しているかを検証するためのプロトコルです。検証には、お互いに相手の**MRENCLAVE**を使用します。ローカル・アテステーションのより詳しい話を知りたい場合は、参考文献[9]を参照して下さい。

### リモート・アテステーション
リモート・アテステーションは、ローカル・アテステーションに比べより理解するのが厄介なプロトコルです。リモートのクライアントがSGXサーバを相手取り検証するわけですから、以下の要件を全て検証する必要があります：

* サーバが搭載しているCPUは、Intelから正式に認められているものなのか？
* 通信をしようとしている相手のEnclaveやマシンには、何らかの脆弱性等は無いか？
* 通信をしようとしている相手のEnclaveは、本当に自分が意図している動作をするのか？(=Enclaveが別の動作をするものに差し替えられていないか？)

この上で、認証後の暗号化通信で使用するセッション鍵の交換をする必要もあります。

リモート・アテステーションに関しては、筆者の[別の記事](https://qiita.com/Cliffford/items/095b1df450583b4803f2)に詳述してありますので、興味があれば参考にして下さい。

## Enclaveに関する様々な制限
さて、以上のような仕組みでデータの保護を行いながらの処理を実現するSGXですが、そう一筋縄には行かず、手放しで便利であるとは言えません。寧ろ、課される制限が非常に重く、SGXプログラマの頭を悩ませる要因となっています。

Enclaveには大きく分けて2つの制限が存在し、**サイズ制限**と**Enclave内プログラムの機能制限**があります。この他にも、SGX独特の境界管理や型・API等、プログラミング自体の煩雑さという問題(？)もありますが、それは次回のお話にします。

### Enclaveのサイズ制限
まず、Enclaveのサイズ制限ですが、基本的にEnclave（EPC）は最大で128MBまでしか確保することが出来ません。しかも、これは管理用のデータ構造（SECSやTCS等）を含めてのサイズ上限ですので、実際にはユーザは**96MB**までしか自由に確保し使用する事が出来ません。

この上限を超えた場合、ページアウトが可能な場合はページアウトが発生しますし、不可能な場合はセグメンテーションフォールトが発生します(経験上セグフォのケースの方が多い気がします)。

また、意図的に96MBを超過させたい場合は、コンフィグファイルの最大ヒープサイズを96MB以上に設定する必要がありますが、96MBを超えた途端にEnclaveの起動に物凄い時間が掛かります。これではSGXの売りである「高速さ」が半分台無しになってしまうようなものです(起動さえすればその後の演算は通常通り高速ですが)。

ちなみに、現在IntelからSGXのGitHubリポジトリで最新版として配布されている**SGX2**は、動的にこの上限を増やせるようになるという、言わば「実現計画」としての数年前に公開された情報があります。

ただ、実際にこれが実装されているのかの情報がイマイチ見当たらず(筆者の探し方が悪いだけで多分あります)、Intelによるこの情報に関するリリースノートについても見つけられていません(こちらも探せばあるかも知れません)。

一応、現在Intelが配布しているサンプルコードの中に、SGX2で追加されたAPIでこの機能に関与している可能性のあるコードはあるのですが、少なくとも手元のマシンでは動作しませんでした。

というのも、仮にこの動的なサイズ追加が実装されていたとしても、更にハードウェアが対応している必要があるからです。
この動的サイズ追加には、EAUGと呼ばれる新しい命令が必要になります。しかし、現在流通しているCPUでこのEAUGを実行できる製品が**無い**[10]ので、結局動作できないというわけです。

参考文献[10]の時点から環境が変わっていて対応しているマシンも出ているかも知れませんが、SGX1のみ対応しているマシンとの互換性を考えれば、まずこのサイズ制限を前提としておいた方が賢明でしょう。

**追記（2021/2/4）**：公式文書では一切記述されていない内容ではありますが、筆者独自の実験及び参考文献[12]のフォーラムにおける内容を鑑みる限り、LinuxにおいてはSGX2を入れるまでもなく動的ページング（EWB命令やELD系命令ページスワップ）によりEPCを128MB以上に擬似的に増やせる模様です[12]。これにより、一部の機種でBIOSにて設定できるEPCサイズ制限（=PRM；プロセッサ予約メモリ）も、ページスワップで対応可能な範囲で突破できます。

ただし、WindowsにおいてはこのEPCページング機能が存在しないため、SGX2無しでは依然サイズ制限に縛られる事になります。
参考文献[13]によれば、2020年2月時点でBIOSで設定できるEnclaveサイズ上限が256MBであるマシンも流通してきているようです（恐らくEPCはもう少し小さくなると考えられます）。

### Enclave内プログラムの機能制限
次に、Enclave内で動作するプログラムの機能制限についてです。復習となりますが、SGXは「OSを信頼しておらず」、かつ「ユーザモード(Ring-3権限)でのみ動作できる」という前提があります。つまり、結果として「**Enclave内のプログラムはシステムコールを一切使用できない**」事を意味します。

システムコールが使用できないのですから、例えば`fork`, `exec`は勿論、`printf`, `scanf`, `exit`, `fopen`, `rand`, `time`, `setlocale`等は一切使用できません。

また、メモリ破壊を起こしかねないような潜在的に危険な関数(`strcpy`等)も使用を禁止されています。

この制限は、SGXがC/C++のライブラリとして唯一使用を許可している、Intelが用意したtlibc及びtlibcxxという専用のライブラリにより実現されています。つまり、この制限は確実に守らねばならないので、SGXプログラマはこれらの制限を前提として実装をする必要があります。

この問題を回避するための手段として、Enclave内からEnclave外の関数を呼び出す**OCALL**と呼ばれる機能がSGXにはありますが、詳細は次回お話します。

少し前までは、使用できないマクロや関数のリストがIntelのサイトで掲載されていたのですが、どういうわけか現在削除されているため、どれが使えないかを探し当てるには実際にtlibc及びtlibcxxを覗くしか方法がありません。

しかし、個人的に使用不可リストのバックアップを取ってあるので、後日別の記事に掲載しようとは考えております。

追記: リストを列挙したエントリへのリンクを後述しました。

## まとめ
本記事では、SGXの基礎的な仕組みについて説明致しました。次回以降、SGXを用いたプログラミングやビルドを行う上での基礎知識から、簡単なSGXアプリケーションの実装までご紹介するつもりです。

最後に、本記事は出来る限り正確性に気をつけてはおりますが、何だかんだ言いまして参考文献[1]に勝る仕様書はございませんので、英語力(と時間)のある方は是非[1]に目を通してみて下さい。

また、実際に実装を行う上では、参考文献[11]の開発者向けリファレンスも参考になると思います。

## 追記
SGXアプリケーションの簡単な開発手法についてエントリを作成しましたので、興味がありましたら[こちら](https://qiita.com/Cliffford/items/c6c0c696d4cc6d60d515)をご参照下さい。
また、Enclave内での非対応C標準関数は[こちら](https://qiita.com/Cliffford/items/4679e91ac2a693b46bf0)、Enclave内でのC++標準関数の使用可否リストは[こちら](https://qiita.com/Cliffford/items/ad7696cfd102bd6accbb)を参照して下さい。



## 参考文献
[1] "Intel SGX Explained", by Costan and Devadas. Cryptology ePrint Archive: Report 2016/086, https://eprint.iacr.org/2016/086
[2] "A Memory Encryption Engine Suitable for General Purpose Processors", by Shay Gueron. Cryptology ePrint Archive: Report 2016/204, https://eprint.iacr.org/2016/204
[3] "Presentation for Intel SGX: ISCA 2015". https://software.intel.com/sites/default/files/332680-001.pdf
[4] "Graphene-SGX: A Practical Library OS for Unmodified Applications on SGX", by Chia-Che Tsai, Donald E. Porter, Mona Vij. USENIX: https://www.usenix.org/system/files/conference/atc17/atc17-tsai.pdf
[5] "SGX-hardware list", https://github.com/ayeks/SGX-hardware/blob/master/README.md
[6] "リングプロテクション - Wikipedia", https://ja.wikipedia.org/wiki/%E3%83%AA%E3%83%B3%E3%82%B0%E3%83%97%E3%83%AD%E3%83%86%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3
[7] "インテル®SGX命令とデータ構造の概要 - ISUS", https://www.isus.jp/security/overview-of-sgx-instructions-and-data-structures/
[8] "Intel® Enhanced Privacy ID (EPID) Security Technology", https://software.intel.com/en-us/articles/intel-enhanced-privacy-id-epid-security-technology
[9] "Local (Intra-Platform) Attestation", https://software.intel.com/en-us/node/702983
[10] "A detail about SGX loading", https://stackoverflow.com/questions/36168439/a-detail-about-sgx-loading
[11] "Intel® Software Guard Extensions (Intel® SGX) SDK for Linux* OS ", https://download.01.org/intel-sgx/linux-2.5/docs/Intel_SGX_Developer_Reference_Linux_2.5_Open_Source.pdf
[12] "Solved: SGX protected memory limit in SGX - Intel Community", https://community.intel.com/t5/Intel-Software-Guard-Extensions/SGX-protected-memory-limit-in-SGX/td-p/1068817
[13] "Monitoring Intel® SGX Enclaves", https://fortanix.com/blog/2020/02/monitoring-intel-sgx-enclaves/#:~:text=This%20Enclave%20Page%20Cache%20(EPC,we%20can%20overcommit%20the%20EPC.