このトピックでは、信頼できる実行環境 (TEE) SDKを使用して、Intel Software Guard Extensions (SGX) 2.0アプリケーションを開発、ビルド、およびデプロイする方法について説明します。 このトピックでは、helloworld
という名前のアプリケーションを例として使用します。 このアプリケーションは、エンクレーブで定期的にメッセージを生成し、信頼できないバッファにメッセージを送信します。 その後、メッセージは端末に送信される。
インテルSGXのしくみ
Intel SGX 2.0アプリケーションは、信頼できないコンポーネントと信頼できるコンポーネントの2つのコンポーネントで構成されています。
信頼できないコンポーネント: 信頼できないコンポーネントは、メモリの暗号化されていない部分です。 この部分にアプリケーションのコードとデータを格納する場合、アプリケーションのmain()
入力関数も信頼できないコンポーネントに配置する必要があります。 上の図では、main()
関数とbar()
関数が信頼できないコンポーネントに配置されています。
信頼できるコンポーネント: 信頼できるコンポーネントまたはエンクレーブは、メモリの暗号化された部分です。 このコンポーネントはCPUによって作成され、このコンポーネントのデータとコードはCPUによってのみアクセスできます。 上の図では、helloworld()
関数とfoo()
関数がエンクレーブに配置されています。
信頼できないコンポーネントからエンクレーブ内の関数を呼び出すには、アプリケーションはエンクレーブ呼び出し (ECALL) を実行する必要があります。 エンクレーブから信頼されていないコンポーネントの関数を呼び出すには、アプリケーションは外部呼び出し (OCALL) を実行する必要があります。 ECALLおよびOCALLは、エンクレーブ定義言語 (EDL) ファイルで宣言される。
サンプルコードとディレクトリツリー
この例では、helloworld
という名前のIntel SGX 2.0アプリケーションがデプロイされています。 ソースコードの詳細については、『GitHub』をご参照ください。 ソースコードには、アプリケーションのコンパイル、イメージの構築、およびアプリケーションの展開のためのコードが含まれます。 次のサンプルコードは、ディレクトリツリーを示しています。
App.hsgx-device-plugin/samples/hello_world/
├── Dockerfile
├── Makefile
├── README.md
└── src
├── App
│ ├── App.cpp
│ └── App.h
├── Enclave
│ ├── Enclave.config.xml
│ ├── Enclave.cpp
│ ├── Enclave.edl
│ ├── Enclave.h
│ ├── Enclave.lds
│ └── Enclave_private.pem
└── Makefile
次の表に、src
ディレクトリと関連ファイルを示します。
ディレクトリ | 説明 | ファイル | 説明 |
アプリ | Appディレクトリには、main() 関数 (エントリ関数) やOCALL関数のコードなど、信頼できないコードが含まれています。 | App.cpp | 信頼できないコンポーネントのコード。The code in the untrusted component. |
アプリ. h | ヘッダーファイル。 |
エンクレーブ | ECALL関数のコードを含む、信頼済みコンポーネント内のコード。 | Enclave.edl | EDLファイル。 |
Enclave.lds | enclaveリンカスクリプト。 |
Enclave_private.pem | enclave.soファイルに署名するために使用される秘密鍵。 |
Enclave.config.xml | スタックサイズやデバッグを有効にするかどうかなどのパラメーターを指定するエンクレーブ構成ファイル。 |
Enclave.hとEnclave.cpp。 | 信頼できるコンポーネントを実装するコード。 |
ステップ1: hello_worldをコンパイルする
次のコマンドを実行してGitをインストールします。
sudo yum install git
次のコマンドを実行して、hello_worldアプリケーションをコンパイルします。
git clone https://github.com/AliyunContainerService/sgx-device-plugin
cd sgx-device-plugin/samples/hello_world
SGX_SDK=/opt/alibaba/teesdk/intel/sgxsdk make build
hello_worldというバイナリファイルがプロジェクトのルートディレクトリに生成されます。
バイナリファイルの内容を表示
GEN => App/Enclave_u.h
CC <= App/Enclave_u.c
CXX <= App/App.cpp
LINK => app
GEN => Enclave/Enclave_t.h
CC <= Enclave/Enclave_t.c
CXX <= Enclave/Enclave.cpp
LINK => enclave.so
<EnclaveConfiguration>
<ProdID>0</ProdID>
<ISVSVN>0</ISVSVN>
<StackMaxSize>0x40000</StackMaxSize>
<HeapMaxSize>0x100000</HeapMaxSize>
<TCSNum>10</TCSNum>
<TCSPolicy>1</TCSPolicy>
<!-- Recommend changing 'DisableDebug' to 1 to make the enclave undebuggable for enclave release -->
<DisableDebug>0</DisableDebug>
<MiscSelect>0</MiscSelect>
<MiscMask>0xFFFFFFFF</MiscMask>
</EnclaveConfiguration>
tcs_num 10, tcs_max_num 10, tcs_min_pool 1
The required memory is 3960832B.
The required memory is 0x3c7000, 3868 KB.
Succeed.
SIGN => enclave.signed.so
The project has been built in debug hardware mode
を実行します。Run the. /hello_world
SGXをサポートするインスタンスで、hello_worldアプリケーションを実行するコマンドを実行します。
cd src/
./hello_world
期待される出力:
Wed May 6 06:53:33 2020
Hello world From SGX Enclave!
Wed May 6 06:53:34 2020
Hello world From SGX Enclave!
...
次の内容は、アプリケーションをコンパイルする方法と、コンパイルされたコードのディレクトリツリーを示しています。
コンパイル手順の表示
sgx_edger8rツールとsgx_ecall
ecall関数を使用して、信頼できないコード (Enclave_u.c
およびEnclave_u.h
) をAppディレクトリに生成します。
Appディレクトリで信頼できないバイナリファイルをコンパイルします。
sgx_edger8rツールを使用して、信頼できるコード (Enclave_t.c
およびEnclave_t.h
) をEnclave_tディレクトリに生成します。
enclave.soファイルをコンパイルします。 信頼できるダイナミックリンクライブラリです。
sgx_signツールを使用して、信頼できるダイナミックリンクライブラリに署名します。 信頼できるダイナミックリンクライブラリの名前がenclave.signed.soに変わります。
アプリケーションはコンパイルされます。
コンパイルされたコードのディレクトリツリーの表示
sgx-device-plugin/samples/hello_world/src/
├── hello_world #[generated]
├── App
│ ├── App.cpp
│ ├── App.h
│ ├── App.o #[generated]
│ ├── Enclave_u.c #[generated]
│ ├── Enclave_u.h #[generated]
│ └── Enclave_u.o #[generated]
├── Enclave
│ ├── Enclave.config.xml
│ ├── Enclave.cpp
│ ├── Enclave.edl
│ ├── Enclave.h
│ ├── Enclave.lds
│ ├── Enclave.o #[generated]
│ ├── Enclave_private.pem
│ ├── Enclave_t.c #[generated]
│ ├── Enclave_t.h #[generated]
│ └── Enclave_t.o #[generated]
├── enclave.signed.so #[generated]
├── enclave.so #[generated]
└── Makefile
ファイルパス | 説明 | サンプルコード |
Encalve/Enclave.edl | パブリックECALL関数を宣言するEDLファイル。 SGXアプリケーションのEDLファイルでは、次の関数の少なくとも1つを宣言する必要があります。 この例では、アプリケーションはOCALL関数を呼び出す必要はありません。 したがって、ECALL関数 (ecall_hello_from_enclave) は1つだけ宣言されます。 このECALL関数は、エンクレーブにバッファを作成し、helloworldアプリケーション をデプロイするために使用されます。 次に、バッファ内の情報が、信頼できないコンポーネント内の信頼できないバッファにコピーされる。 アプリケーションは、信頼できないコンポーネント内のprintf を呼び出して情報を印刷します。 | enclave {
trusted {
public void ecall_hello_from_enclave([out, size=len] char* buf, size_t len);
};
};
|
Enclave/Enclave.lds | 非該当 | enclave.so
{
global:
g_global_data_sim;
g_global_data;
enclave_entry;
g_peak_heap_used;
local:
*;
};
|
Enclave/Enclave.config.xml | 非該当 | <EnclaveConfiguration>
<ProdID>0</ProdID>
<ISVSVN>0</ISVSVN>
<StackMaxSize>0x40000</StackMaxSize>
<HeapMaxSize>0x100000</HeapMaxSize>
<TCSNum>10</TCSNum>
<TCSPolicy>1</TCSPolicy>
<!-- Recommend changing 'DisableDebug' to 1 to make the enclave undebuggable for enclave release -->
<DisableDebug>0</DisableDebug>
<MiscSelect>0</MiscSelect>
<MiscMask>0xFFFFFFFF</MiscMask>
</EnclaveConfiguration>
|
Enclave/Enclave.h | ほとんどの場合、このヘッダーファイルは空です。 | #ifndef _ENCLAVE_H_
#define _ENCLAVE_H_
#endif
|
Enclave/Enclave.cpp | 非該当 | #include "Enclave.h"
#include "Enclave_t.h" /* print_string */
#include <string.h>
void ecall_hello_from_enclave(char *buf, size_t len)
{
const char *hello = "Hello world";
size_t size = len;
if(strlen(hello) < len)
{
size = strlen(hello) + 1;
}
memcpy(buf, hello, size - 1);
buf[size-1] = '\0';
}
|
エンクレーブ /Enclave_private.pem | enclave.soファイルの署名に使用される秘密鍵 | openssl genrsa -out Enclave/Enclave_private.pem -3 3072
|
アプリ /App.h | 非該当 | #ifndef _APP_H_
#define _APP_H_
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "sgx_error.h" /* sgx_status_t */
#include "sgx_eid.h" /* sgx_enclave_id_t */
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
# define TOKEN_FILENAME "enclave.token"
# define ENCLAVE_FILENAME "enclave.signed.so"
extern sgx_enclave_id_t global_eid; /* global enclave id */
#if defined(__cplusplus)
extern "C" {
#endif
#if defined(__cplusplus)
}
#endif
#endif /* !_APP_H_ */
|
App/App.cpp | 非該当 | #include <stdio.h>
#include <string.h>
#include <assert.h>
#include <time.h>
#include <ctime>
# include <unistd.h>
# include <pwd.h>
# define MAX_PATH FILENAME_MAX
#include "sgx_urts.h"
#include "App.h"
#include "Enclave_u.h"
/* Global EID shared by multiple threads */
sgx_enclave_id_t global_eid = 0;
int initialize_enclave(void)
{
sgx_status_t ret = SGX_ERROR_UNEXPECTED;
char enclavefile[256];
getcwd(enclavefile, sizeof(enclavefile));
strcat(enclavefile, "/enclave.signed.so");
/* Call sgx_create_enclave to initialize an enclave instance */
/* Debug Support: set 2nd parameter to 1 */
ret = sgx_create_enclave(enclavefile, SGX_DEBUG_FLAG, NULL, NULL, &global_eid, NULL);
if (ret != SGX_SUCCESS) {
printf("Failed to create enclave, ret code: %d, enclave file: %s\n", ret, enclavefile);
return -1;
}
return 0;
}
tm* get_time() {
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
return timeinfo;
}
/* Application entry */
int SGX_CDECL main(int argc, char *argv[])
{
(void)(argc);
(void)(argv);
const size_t max_buf_len = 100;
char buffer[max_buf_len] = {0};
/* Initialize the enclave */
if(initialize_enclave() < 0){
printf("Enter a character before exit ...\n");
getchar();
return -1;
}
/* Enclave calls */
while(1) {
ecall_hello_from_enclave(global_eid, buffer, max_buf_len);
printf("%s%s\n", asctime(get_time()), buffer);
fflush(stdout);
sleep(1);
}
/* Destroy the enclave */
sgx_destroy_enclave(global_eid);
printf("Info: SampleEnclave successfully returned.\n");
printf("Enter a character before exit ...\n");
getchar();
return 0;
}
|
ステップ2: helloworldアプリケーションのビルドとデプロイ
潜在的なリスクを軽減するために、Alibaba Cloud Linuxイメージを構築し、最新のSGX SDKバージョンをインストールし、SDKを定期的に更新することを推奨します。
サンプルDockerfile
次のサンプルDockerfileはAlibaba Cloud Linux 3を使用しています。
FROM registry.cn-hangzhou.aliyuncs.com/alinux/alinux3
ARG REGION_ID=cn-hangzhou
RUN yum install -y curl && \
repo_url=https://enclave-${REGION_ID}.oss-${REGION_ID}.aliyuncs.com/repo/alinux/enclave-expr.repo && \
yum install -y yum-utils && \
yum-config-manager --add-repo ${repo_url} && \
yum install -y libsgx-urts libsgx-uae-service # Add more SGX runtime dependencies on demand.
WORKDIR /src
COPY src/hello_world src/enclave.signed.so /src
ENTRYPOINT ["/src/hello_world"]
手順
Dockerをインストールします。
詳細については、「Dockerのインストール」をご参照ください。
次のコマンドを実行して、テストイメージをコンパイルしてビルドします。
${IMAGE_URL}
をテストイメージのアドレスに置き換えます。
cd sgx-device-plugin/samples/hello_world
TARGET_IMAGE=${IMAGE_URL} SGX_SDK=/opt/alibaba/teesdk/intel/sgxsdk make image
docker push ${IMAGE_URL}
次のコマンドを実行して、helloworld
アプリケーションをデプロイします。
${IMAGE_URL}
を、前の手順で構築したテストイメージのアドレスに置き換えます。
cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: helloworld
template:
metadata:
labels:
app: helloworld
spec:
containers:
- image: ${IMAGE_URL}
imagePullPolicy: Always
name: helloworld
resources:
limits:
cpu: 250m
memory: 512Mi
alibabacloud.com/sgx_epc_MiB: 2
EOF