[demos] Add MAA demo

This commit is contained in:
Zheng, Qi 2022-03-29 17:25:32 +08:00 committed by volcano
parent 2cd20d315e
commit eba7e08453
9 changed files with 545 additions and 0 deletions

@ -0,0 +1,39 @@
## Sample code for Occlum Remote Attestation to generate Microsoft Azure Attestation json file
### References
* Part of the sample code, specifically the part to generate MAA format json file, is derived from the [Sample code for Intel® SGX Attestation using Microsoft Azure Attestation service and Intel® SGX SDK for Linux OS](https://github.com/Azure-Samples/microsoft-azure-attestation/tree/master/intel.sdk.attest.sample)
## Prerequisites
- Platform: Intel SGX enabled platform with DCAP installed. Follow [DCAP
Quick Install
Guide](https://software.intel.com/content/www/us/en/develop/articles/intel-software-guard-extensions-data-center-attestation-primitives-quick-install-guide.html)
for the detailed installation procedure.
- Container: Start the Occlum latest docker container image for the demo. Follow
the [guide](https://github.com/occlum/occlum#how-to-use).
Remember to configure `/etc/sgx_default_qcnl.conf`
in the container according to your PCCS setting after running the docker image.
### Overview
The full Microsoft Azure Attestation flow includes generating a quote in an SGX enclave and then get it validated by the Microsoft [`Azure Attestation (MAA) service`](https://github.com/Azure-Samples/microsoft-azure-attestation).
There are five steps for a full flow MAA.
1. Build an SGX enclave
2. Launch an SGX enclave and get SGX quote
3. Persist SGX quote and Enclave Held Data (EHD) to JSON file
4. Call Azure Attestation for validation
5. Output validation results
This demo only covers the first three steps.
* Build and Run
```
# ./run.sh
```
Once successful, four different MAA format json files are saved in `out` dir.
With the generated MAA format json files, users could continue on step 4 and 5 with general MAA service APIs to do validation.

@ -0,0 +1,74 @@
{
"resource_limits": {
"kernel_space_heap_size": "32MB",
"kernel_space_stack_size": "1MB",
"user_space_size": "300MB",
"max_num_of_threads": 32
},
"process": {
"default_stack_size": "4MB",
"default_heap_size": "32MB",
"default_mmap_size": "100MB"
},
"entry_points": [
"/bin"
],
"env": {
"default": [
"OCCLUM=yes"
],
"untrusted": [
"EXAMPLE"
]
},
"metadata": {
"product_id": 0,
"version_number": 0,
"debuggable": true,
"enable_kss": false,
"family_id": {
"high": "0x0",
"low": "0x0"
},
"ext_prod_id": {
"high": "0x0",
"low": "0x0"
}
},
"mount": [
{
"target": "/",
"type": "unionfs",
"options": {
"layers": [
{
"target": "/",
"type": "sefs",
"source": "./build/mount/__ROOT",
"options": {
"MAC": ""
}
},
{
"target": "/",
"type": "sefs",
"source": "./run/mount/__ROOT"
}
]
}
},
{
"target": "/host",
"type": "hostfs",
"source": "."
},
{
"target": "/proc",
"type": "procfs"
},
{
"target": "/dev",
"type": "devfs"
}
]
}

@ -0,0 +1,74 @@
{
"resource_limits": {
"kernel_space_heap_size": "32MB",
"kernel_space_stack_size": "1MB",
"user_space_size": "300MB",
"max_num_of_threads": 32
},
"process": {
"default_stack_size": "4MB",
"default_heap_size": "32MB",
"default_mmap_size": "100MB"
},
"entry_points": [
"/bin"
],
"env": {
"default": [
"OCCLUM=yes"
],
"untrusted": [
"EXAMPLE"
]
},
"metadata": {
"product_id": 9999,
"version_number": 0,
"debuggable": false,
"enable_kss": false,
"family_id": {
"high": "0x0",
"low": "0x0"
},
"ext_prod_id": {
"high": "0x0",
"low": "0x0"
}
},
"mount": [
{
"target": "/",
"type": "unionfs",
"options": {
"layers": [
{
"target": "/",
"type": "sefs",
"source": "./build/mount/__ROOT",
"options": {
"MAC": ""
}
},
{
"target": "/",
"type": "sefs",
"source": "./run/mount/__ROOT"
}
]
}
},
{
"target": "/host",
"type": "hostfs",
"source": "."
},
{
"target": "/proc",
"type": "procfs"
},
{
"target": "/dev",
"type": "devfs"
}
]
}

@ -0,0 +1,74 @@
{
"resource_limits": {
"kernel_space_heap_size": "32MB",
"kernel_space_stack_size": "1MB",
"user_space_size": "300MB",
"max_num_of_threads": 32
},
"process": {
"default_stack_size": "4MB",
"default_heap_size": "32MB",
"default_mmap_size": "100MB"
},
"entry_points": [
"/bin"
],
"env": {
"default": [
"OCCLUM=yes"
],
"untrusted": [
"EXAMPLE"
]
},
"metadata": {
"product_id": 0,
"version_number": 0,
"debuggable": false,
"enable_kss": false,
"family_id": {
"high": "0x0",
"low": "0x0"
},
"ext_prod_id": {
"high": "0x0",
"low": "0x0"
}
},
"mount": [
{
"target": "/",
"type": "unionfs",
"options": {
"layers": [
{
"target": "/",
"type": "sefs",
"source": "./build/mount/__ROOT",
"options": {
"MAC": ""
}
},
{
"target": "/",
"type": "sefs",
"source": "./run/mount/__ROOT"
}
]
}
},
{
"target": "/host",
"type": "hostfs",
"source": "."
},
{
"target": "/proc",
"type": "procfs"
},
{
"target": "/dev",
"type": "devfs"
}
]
}

@ -0,0 +1,74 @@
{
"resource_limits": {
"kernel_space_heap_size": "32MB",
"kernel_space_stack_size": "1MB",
"user_space_size": "300MB",
"max_num_of_threads": 32
},
"process": {
"default_stack_size": "4MB",
"default_heap_size": "32MB",
"default_mmap_size": "100MB"
},
"entry_points": [
"/bin"
],
"env": {
"default": [
"OCCLUM=yes"
],
"untrusted": [
"EXAMPLE"
]
},
"metadata": {
"product_id": 0,
"version_number": 8888,
"debuggable": false,
"enable_kss": false,
"family_id": {
"high": "0x0",
"low": "0x0"
},
"ext_prod_id": {
"high": "0x0",
"low": "0x0"
}
},
"mount": [
{
"target": "/",
"type": "unionfs",
"options": {
"layers": [
{
"target": "/",
"type": "sefs",
"source": "./build/mount/__ROOT",
"options": {
"MAC": ""
}
},
{
"target": "/",
"type": "sefs",
"source": "./run/mount/__ROOT"
}
]
}
},
{
"target": "/host",
"type": "hostfs",
"source": "."
},
{
"target": "/proc",
"type": "procfs"
},
{
"target": "/dev",
"type": "devfs"
}
]
}

@ -0,0 +1,16 @@
CC ?= gcc
LDFLAGS += -L/opt/occlum/toolchains/dcap_lib/glibc \
-locclum_dcap -lssl -lcrypto
CFLAGS += -fPIE -pie -I /opt/intel/sgxsdk/include \
-I /opt/occlum/toolchains/dcap_lib/inc
.PHONY: all clean
all: gen_maa_json
gen_maa_json: gen_maa_json.c
$(CC) $^ $(CFLAGS) $(LDFLAGS) -o $@
clean:
rm -rf gen_maa_json

@ -0,0 +1,130 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <openssl/sha.h>
#include "sgx_quote_3.h"
#include "occlum_dcap.h"
#define MAA_JSON "/host/maa.json"
void sha256sum(const uint8_t *data, uint32_t data_size, uint8_t *hash)
{
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, data, data_size);
SHA256_Final(hash, &sha256);
}
const char *uint16_to_buffer (char *buffer, unsigned int maxSize, uint16_t n, size_t size)
{
if (size * 2 >= maxSize || size < 2)
return "DEADBEEF";
sprintf(&buffer[0], "%02X", (uint8_t)(n));
sprintf(&buffer[2], "%02X", (uint8_t)(n >> 8));
for (int i=2; i < size; i++)
{
sprintf(&buffer[i*2], "%02X", 0);
}
buffer[size*2+1] = '\0';
return buffer;
}
const char *format_hex_buffer (char *buffer, unsigned int maxSize, uint8_t *data, size_t size)
{
if (size * 2 >= maxSize)
return "DEADBEEF";
for (int i=0; i < size; i++)
{
sprintf(&buffer[i*2], "%02X", data[i]);
}
buffer[size*2+1] = '\0';
return buffer;
}
void main() {
void *handle;
uint32_t quote_size;
uint8_t *p_quote_buffer;
sgx_quote3_t *p_quote;
sgx_report_body_t *p_report_body;
sgx_report_data_t *p_report_data;
int32_t ret;
const int hex_buffer_size = 1024*64;
char hex_buffer[hex_buffer_size];
handle = dcap_quote_open();
quote_size = dcap_get_quote_size(handle);
printf("quote size = %d\n", quote_size);
p_quote_buffer = (uint8_t*)malloc(quote_size);
if (NULL == p_quote_buffer) {
printf("Couldn't allocate quote_buffer\n");
goto CLEANUP;
}
memset(p_quote_buffer, 0, quote_size);
uint8_t enclave_held_data[6] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
sgx_report_data_t hash = {0};
sha256sum(enclave_held_data, 6, hash.d);
// printf("report data hash:\n");
// for (int i = 0; i < sizeof(hash.d); i++) {
// if (!(i % 16))
// printf("\n\t");
// printf("%02x ", hash.d[i]);
// }
// printf("\n");
// Get the Quote
ret = dcap_generate_quote(handle, p_quote_buffer, &hash);
if (0 != ret) {
printf( "Error in dcap_generate_quote.\n");
goto CLEANUP;
}
printf("DCAP generate quote successfully\n");
p_quote = (sgx_quote3_t *)p_quote_buffer;
p_report_body = (sgx_report_body_t *)(&p_quote->report_body);
p_report_data = (sgx_report_data_t *)(&p_report_body->report_data);
// check report data
if (memcmp((void *)&hash, (void *)p_report_data, sizeof(sgx_report_data_t)) != 0) {
printf("mismathced report data\n");
goto CLEANUP;
}
// Create json file
FILE *fp = fopen(MAA_JSON, "w");
if ( NULL == fp ) {
printf("fopen %s failed return %d\n", MAA_JSON, errno);
goto CLEANUP;
}
// Generate Azure attestion json file
// Refer to https://github.com/Azure-Samples/microsoft-azure-attestation
fprintf(fp, "%s\n", "{");
// Use 3 as type for now
fprintf(fp, " \"Type\": %d,\n", 3);
fprintf(fp, " \"MrEnclaveHex\": \"%s\",\n", format_hex_buffer(hex_buffer, hex_buffer_size, p_report_body->mr_enclave.m, SGX_HASH_SIZE));
fprintf(fp, " \"MrSignerHex\": \"%s\",\n", format_hex_buffer(hex_buffer, hex_buffer_size, p_report_body->mr_signer.m, SGX_HASH_SIZE));
fprintf(fp, " \"ProductIdHex\": \"%s\",\n", uint16_to_buffer(hex_buffer, hex_buffer_size, (uint16_t)p_report_body->isv_prod_id, 16));
fprintf(fp, " \"SecurityVersion\": %u,\n", (int)p_report_body->isv_svn);
fprintf(fp, " \"Attributes\": %lu,\n", (uint64_t)p_report_body->attributes.flags);
fprintf(fp, " \"QuoteHex\": \"%s\",\n", format_hex_buffer(hex_buffer, hex_buffer_size, (uint8_t *)p_quote, quote_size));
fprintf(fp, " \"EnclaveHeldDataHex\": \"%s\"\n", format_hex_buffer(hex_buffer, hex_buffer_size, enclave_held_data, sizeof( enclave_held_data)));
fprintf(fp, "%s\n", "}");
fclose(fp);
CLEANUP:
if (NULL != p_quote_buffer) {
free(p_quote_buffer);
}
dcap_quote_close(handle);
}

@ -0,0 +1,16 @@
includes:
- base.yaml
# dcap
targets:
# copy bins
- target: /bin
copy:
- files:
- ../gen_quote/gen_maa_json
# copy lib
- target: /opt/occlum/glibc/lib
copy:
- files:
- /opt/occlum/toolchains/dcap_lib/glibc/libocclum_dcap.so.0.1.0
- /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1

@ -0,0 +1,48 @@
#!/bin/bash
set -e
BLUE='\033[1;34m'
NC='\033[0m'
INSTANCE_DIR="occlum_instance"
bomfile="../maa.yaml"
json_dir=$PWD/out
# parameter 1 defines the predefined Occlum json
# parameter 2 defines the generated maa json
function gen_maa_json() {
config=$1
maa=${2:-"maa.json"}
if [ ! -f $config ]; then
echo "Please provide valid Occlum json file"
exit -1
fi
rm -rf ${INSTANCE_DIR} && occlum new ${INSTANCE_DIR}
pushd ${INSTANCE_DIR}
rm -rf image
copy_bom -f $bomfile --root image --include-dir /opt/occlum/etc/template
cp ../$config Occlum.json
occlum build
echo -e "${BLUE}occlum run to generate quote in maa json format${NC}"
occlum run /bin/gen_maa_json
echo -e "${BLUE}Generated maa json file ${json_dir}/$maa${NC}"
mv maa.json ${json_dir}/$maa
popd
}
echo "*** Build glibc maa demo ***"
make -C gen_quote clean
make -C gen_quote
rm -rf ${json_dir} && mkdir -p ${json_dir}
gen_maa_json ./config/Occlum.json maa_debug.json
gen_maa_json ./config/Occlum_prodid.json maa_prodid.json
gen_maa_json ./config/Occlum_release.json maa_release.json
gen_maa_json ./config/Occlum_securityversion.json maa_securityversion.json