[Intel SGX] Local Attestationやってみた

（追記）この方法でできた。ダブルポインタ出てくるので非常にややこしい。
（追記）この方法だめかもしれない。シリアライズしないとだめかも。要は配列を送信することができない。

## 本記事の目的
Intel SGX SDKをインストールするともれなくついてくるサンプルの中に、Local Attestationのサンプルがあるのでこれを動かしてみる。そして任意のメッセージ２つのEnclave間で送れるようにちょこっと改造してみる。

## 本記事の対象
- LocalAttestationについて理解していること
- LocalAttestationのサンプルをコンパイルして動くこと（環境が整っていれば何もしなくても動くはず）

## 本題
Enclave1がfizzを送ったら、Enclave2から0が返ってくるようなプログラムを作ってみます。サンプルのままではint32型の数値しか送れないので次のような手順で魔改造してみます。

#### STEP1. Enclave1からEnclave2に値の送信ができているかの確認。
プログラムを改造しなくとも、Intel SGX Debugger使って、Enclave2.cppの311行目にブレイクポイントを設定してあげればOKです。inp_secret_data=305419896(=0x12345678)と表示されていればOKです。この数値はEnclave1のsecretで設定されている値です。

printfでデバッグしたい場合は、グローバル変数を宣言しとけばOKですね。（本当にいいのかは疑問）

#### STEP2. Enclave1から送れるデータを数値型から文字列に魔改造。
先にUtil_E1.hおよびUtil_E1.cppのmarshal_message_exchange_requestを改造します。これで文字列が送れるようになりました。secret_dataをintからcharに変更したので、引数に長さが追加されたり、memcpyに渡すポインタが変わってたりします。

```
uint32_t marshal_message_exchange_request(uint32_t target_fn_id, uint32_t msg_type, 
	char * secret_data, int secret_data_len, char** marshalled_buff, size_t* marshalled_buff_len)
{
    ms_in_msg_exchange_t *ms;
    size_t ms_len;
    if(!marshalled_buff_len)
        return INVALID_PARAMETER_ERROR;
    ms_len = sizeof(ms_in_msg_exchange_t) + secret_data_len;
    ms = (ms_in_msg_exchange_t *)malloc(ms_len);
    if(!ms)
        return MALLOC_ERROR;

    ms->msg_type = msg_type;
    ms->target_fn_id = target_fn_id;
    ms->inparam_buff_len = (uint32_t)secret_data_len;
    memcpy(&ms->inparam_buff, secret_data, secret_data_len);
    *marshalled_buff = (char*)ms;
    *marshalled_buff_len = ms_len;
     return SUCCESS;
}
```

すると、Enclave1.cppでエラー吐かれるはずなので、適宜修正していきます。secret_dataをchar型に変更するのと、長さにstrlen()を渡してあげればよいです。

```
uint32_t test_message_exchange(sgx_enclave_id_t src_enclave_id,
                               sgx_enclave_id_t dest_enclave_id)
{
　// 省略
  char secret_data[] = "fizz"; //Secret Data here is shown only for purpose of demonstration.

  //Marshals the secret data into a buffer
  ke_status = marshal_message_exchange_request(target_fn_id, msg_type, secret_data, strlen(secret_data), &marshalled_inp_buff, &marshalled_inp_buff_len);
  // 省略
}
```

#### STEP3. Enclave2で文字列を受け取ることができるようにします。
ここも、inp_secret_dataをchar**にして、size_tを追加してあげます。

```
uint32_t umarshal_message_exchange_request(char** inp_secret_data,  size_t *inp_secret_data_len,
	ms_in_msg_exchange_t* ms)
{
	char *buff;
	size_t len;
    if(!inp_secret_data || !ms)
        return INVALID_PARAMETER_ERROR;    
	buff = ms->inparam_buff;
	len = ms->inparam_buff_len;

    *inp_secret_data_len = ms->inparam_buff_len;
	*inp_secret_data = (char *) malloc(len*sizeof(char));
	if (!inp_secret_data)
		return MALLOC_ERROR;

	memcpy(*inp_secret_data, buff, len);

    return SUCCESS;
}
```

inp_secret_dataはchar型になりました。従ってここも書き換えます。ただし、このままだとget_message_exchange_responseでエラーが出るので、0を返すように設定します。

```
extern "C" uint32_t message_exchange_response_generator(char* decrypted_data,
                                              char** resp_buffer,
                                               size_t* resp_length)
{
    ms_in_msg_exchange_t *ms;
    char *inp_secret_data;
	size_t inp_secret_data_len;
    uint32_t out_secret_data;
    if(!decrypted_data || !resp_length)
    {
        return INVALID_PARAMETER_ERROR;
    }
    ms = (ms_in_msg_exchange_t *)decrypted_data;

	if (umarshal_message_exchange_request(&inp_secret_data, &inp_secret_data_len, ms) != SUCCESS) {
		SAFE_FREE(inp_secret_data);
		return ATTESTATION_ERROR;
	}

	//out_secret_data = get_message_exchange_response(inp_secret_data);
	out_secret_data = 0;

	if (marshal_message_exchange_response(resp_buffer, resp_length, out_secret_data) != SUCCESS) {
		SAFE_FREE(inp_secret_data);
		return MALLOC_ERROR;
	}

    return SUCCESS;

}
```

#### STEP4. Debuggerで確認
Enclave2のmessage_exchange_response_generatorで、適当なところでbreakpointを設定。ms->inparam_buff[0]からms->inparam_buff[3]で、fizzが表示されるか確認。