Skip to content

Commit

Permalink
Add draft of extended attestation with user data and example
Browse files Browse the repository at this point in the history
Signed-off-by: Christoph M. Wintersteiger <[email protected]>
  • Loading branch information
Christoph M. Wintersteiger committed Jan 23, 2020
1 parent d4aa3af commit 6af0e52
Show file tree
Hide file tree
Showing 9 changed files with 328 additions and 3 deletions.
27 changes: 27 additions & 0 deletions enclave/core/sgx/calls.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,30 @@ extern bool oe_disable_debug_malloc_check;
**==============================================================================
*/

static oe_result_t _oe_check_user_data()
{
oe_result_t result = OE_OK;

const uint8_t* user_data = __oe_get_user_data_base();
uint64_t user_data_size = __oe_get_user_data_size();

const uint8_t* old_signature = user_data + user_data_size;
const uint8_t* hash_ud_sig = old_signature + OE_KEY_SIZE;

oe_sha256_context_t hctx;
OE_SHA256 h;
oe_sha256_init(&hctx);
oe_sha256_update(&hctx, user_data, user_data_size);
oe_sha256_update(&hctx, old_signature, OE_KEY_SIZE);
oe_sha256_final(&hctx, &h);

if (memcmp(hash_ud_sig, h.buf, OE_SHA256_SIZE) != 0)
OE_RAISE(OE_VERIFY_FAILED);

done:
return result;
}

/*
**==============================================================================
**
Expand Down Expand Up @@ -171,6 +195,9 @@ static oe_result_t _handle_init_enclave(uint64_t arg_in)
* instructions like CPUID. */
oe_call_init_functions();

/* Check that the user data has not been tampered with */
OE_CHECK(_oe_check_user_data());

/* DCLP Release barrier. */
OE_ATOMIC_MEMORY_BARRIER_RELEASE();
_once = true;
Expand Down
28 changes: 28 additions & 0 deletions enclave/core/sgx/globals.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ extern volatile const oe_sgx_enclave_properties_t oe_enclave_properties_sgx;
static volatile uint64_t _enclave_rva;
static volatile uint64_t _reloc_rva;
static volatile uint64_t _reloc_size;
static volatile uint64_t _user_data_rva;
static volatile uint64_t _user_data_size;

#endif

Expand Down Expand Up @@ -196,6 +198,32 @@ size_t __oe_get_reloc_size()
#endif
}

const void* __oe_get_user_data_base()
{
const unsigned char* base = __oe_get_enclave_base();

#if defined(__linux__)
return base + _user_data_rva;
#else
#error "unsupported"
#endif
}

uint64_t __oe_get_user_data_size()
{
#if defined(__linux__)
return _user_data_size;
#else
#error "unsupported"
#endif
}

const void* __oe_get_user_data_end()
{
return (const uint8_t*)__oe_get_user_data_base() +
__oe_get_user_data_size();
}

/*
**==============================================================================
**
Expand Down
182 changes: 181 additions & 1 deletion host/sgx/create.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ static char* get_fullpath(const char* path)
#include <openenclave/internal/raise.h>
#include <openenclave/internal/result.h>
#include <openenclave/internal/sgxcreate.h>
#include <openenclave/internal/sgxsign.h>
#include <openenclave/internal/sgxtypes.h>
#include <openenclave/internal/switchless.h>
#include <openenclave/internal/trace.h>
#include <openenclave/internal/utils.h>
#include <string.h>
#include "../memalign.h"
#include "../signkey.h"
#include "cpuid.h"
#include "enclave.h"
#include "exception.h"
Expand Down Expand Up @@ -545,10 +547,145 @@ oe_result_t oe_sgx_validate_enclave_properties(
return result;
}

static oe_result_t _add_extra_data_pages(
oe_sgx_load_context_t* context,
uint64_t enclave_addr,
const oe_page_t* pages,
const size_t num_pages,
uint64_t* vaddr)
{
oe_result_t result = OE_UNEXPECTED;

if (!context || !vaddr)
OE_RAISE(OE_INVALID_PARAMETER);

/* Add any data pages as regular-read-only pages. */
if (pages && num_pages)
{
uint64_t size = num_pages * OE_PAGE_SIZE;
assert((size & (OE_PAGE_SIZE - 1)) == 0);

for (size_t i = 0; i < num_pages; i++)
{
uint64_t addr = enclave_addr + *vaddr;
uint64_t src = (uint64_t)&pages[i];
uint64_t flags = SGX_SECINFO_REG | SGX_SECINFO_R;
bool extend = true;

OE_CHECK(oe_sgx_load_enclave_data(
context, enclave_addr, addr, src, flags, extend));
(*vaddr) += sizeof(oe_page_t);
}
}

result = OE_OK;

done:
return result;
}

static uint64_t user_data_pages_size(uint64_t user_data_size)
{
return oe_round_up_to_page_size(
user_data_size + OE_KEY_SIZE + OE_SHA256_SIZE);
}

static oe_result_t _patch_user_data_symbols(
oe_enclave_image_t* oeimage,
uint64_t enclave_end,
const void* user_data,
const size_t user_data_size)
{
if (user_data && user_data_size)
{
elf64_sym_t sym_rva = {0}, sym_sz = {0};
if (elf64_find_symbol_by_name(
&oeimage->u.elf.elf, "_user_data_rva", &sym_rva) == 0 &&
elf64_find_symbol_by_name(
&oeimage->u.elf.elf, "_user_data_size", &sym_sz) == 0)
{
uint64_t sz = user_data_pages_size(user_data_size);
uint64_t *sym_rva_addr = NULL, *sym_sz_addr = NULL;
sym_rva_addr = (uint64_t*)(oeimage->image_base + sym_rva.st_value);
*sym_rva_addr = enclave_end - sz;
sym_sz_addr = (uint64_t*)(oeimage->image_base + sym_sz.st_value);
*sym_sz_addr = user_data_size;
}
}

return OE_OK;
}

static oe_result_t _add_user_data_pages(
oe_sgx_load_context_t* context,
oe_enclave_t* enclave,
uint64_t enclave_end,
oe_sgx_enclave_properties_t* properties,
uint64_t* vaddr,
uint8_t* user_data,
uint32_t user_data_size)
{
oe_result_t result = OE_OK;

if (user_data_size > 0 && user_data != NULL)
{
sgx_sigstruct_t* sigstruct = (sgx_sigstruct_t*)properties->sigstruct;
// cwinter: verify sigstruct->signature here?

uint64_t sz = user_data_pages_size(user_data_size);
assert(*vaddr == enclave_end - sz);

oe_sha256_context_t hctx;
OE_SHA256 hash_ud_sig;
oe_sha256_init(&hctx);
oe_sha256_update(&hctx, user_data, user_data_size);
oe_sha256_update(&hctx, sigstruct->signature, OE_KEY_SIZE);
oe_sha256_final(&hctx, &hash_ud_sig);

uint8_t data[sz];
memset(data, 0, sz);
memcpy(data, user_data, user_data_size); /* not necessary? */
memcpy(
data + user_data_size,
sigstruct->signature,
OE_KEY_SIZE); /* not necessary? */
memcpy(
data + user_data_size + OE_KEY_SIZE,
hash_ud_sig.buf,
OE_SHA256_SIZE);

OE_CHECK(_add_extra_data_pages(
context,
enclave->addr,
(const oe_page_t*)data,
sz / OE_PAGE_SIZE,
vaddr));

OE_SHA256 ext_mrenclave;
oe_sha256_final(&context->hash_context, &ext_mrenclave);

OE_CHECK(oe_sgx_sign_enclave(
&ext_mrenclave,
properties->config.attributes,
properties->config.product_id,
properties->config.security_version,
OE_DEBUG_SIGN_KEY, /* Use different key? */
OE_DEBUG_SIGN_KEY_SIZE,
sigstruct));

assert(*vaddr == enclave_end);
}

done:
return result;
}

oe_result_t oe_sgx_build_enclave(
oe_sgx_load_context_t* context,
const char* path,
const oe_sgx_enclave_properties_t* properties,
uint8_t* user_data,
uint32_t user_data_size,
oe_enclave_t* enclave)
{
oe_result_t result = OE_UNEXPECTED;
Expand Down Expand Up @@ -633,6 +770,9 @@ oe_result_t oe_sgx_build_enclave(
/* Calculate the size of image */
OE_CHECK(oeimage.calculate_size(&oeimage, &image_size));

/* Add (optional) user data pages size */
image_size += user_data_pages_size(user_data_size);

/* Calculate the size of this enclave in memory */
OE_CHECK(_calculate_enclave_size(
image_size, &props, &enclave_end, &enclave_size));
Expand All @@ -648,13 +788,27 @@ oe_result_t oe_sgx_build_enclave(
/* Patch image */
OE_CHECK(oeimage.patch(&oeimage, enclave_end));

/* Patch user data */
OE_CHECK(_patch_user_data_symbols(
&oeimage, enclave_end, user_data, user_data_size));

/* Add image to enclave */
OE_CHECK(oeimage.add_pages(&oeimage, context, enclave, &vaddr));

/* Add data pages */
OE_CHECK(
_add_data_pages(context, enclave, &props, oeimage.entry_rva, &vaddr));

/* Add user data for extended attestation */
OE_CHECK(_add_user_data_pages(
context,
enclave,
enclave_end,
&props,
&vaddr,
user_data,
user_data_size));

/* Ask the platform to initialize the enclave and finalize the hash */
OE_CHECK(oe_sgx_initialize_enclave(
context, enclave_addr, &props, &enclave->hash));
Expand Down Expand Up @@ -705,6 +859,31 @@ oe_result_t oe_create_enclave(
const oe_ocall_func_t* ocall_table,
uint32_t ocall_count,
oe_enclave_t** enclave_out)
{
return oe_create_enclave_wud(
enclave_path,
enclave_type,
flags,
settings,
setting_count,
ocall_table,
ocall_count,
NULL,
0,
enclave_out);
}

oe_result_t oe_create_enclave_wud(
const char* enclave_path,
oe_enclave_type_t enclave_type,
uint32_t flags,
const oe_enclave_setting_t* settings,
uint32_t setting_count,
const oe_ocall_func_t* ocall_table,
uint32_t ocall_count,
uint8_t* user_data,
uint32_t user_data_size,
oe_enclave_t** enclave_out)
{
oe_result_t result = OE_UNEXPECTED;
oe_enclave_t* enclave = NULL;
Expand Down Expand Up @@ -760,7 +939,8 @@ oe_result_t oe_create_enclave(
&context, OE_SGX_LOAD_TYPE_CREATE, flags));

/* Build the enclave */
OE_CHECK(oe_sgx_build_enclave(&context, enclave_path, NULL, enclave));
OE_CHECK(oe_sgx_build_enclave(
&context, enclave_path, NULL, user_data, user_data_size, enclave));

/* Push the new created enclave to the global list. */
if (oe_push_enclave_instance(enclave) != 0)
Expand Down
50 changes: 50 additions & 0 deletions include/openenclave/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,56 @@ oe_result_t oe_create_enclave(
uint32_t ocall_count,
oe_enclave_t** enclave);

/**
* Create an enclave from an enclave image file with optional user data.
*
* This function creates an enclave from an enclave image file. On successful
* return, the enclave is fully initialized and ready to use.
*
* @param path The path of an enclave image file in ELF-64 format. This
* file must have been linked with the **oecore** library and signed by the
* **oesign** tool.
*
* @param type The type of enclave supported by the enclave image file.
* - OE_ENCLAVE_TYPE_SGX - An SGX enclave
*
* @param flags These flags control how the enclave is run.
* It is the bitwise OR of zero or more of the following flags
* - OE_ENCLAVE_FLAG_SIMULATE - runs the enclave in simulation mode
* - OE_ENCLAVE_FLAG_DEBUG - runs the enclave in debug mode.
* DO NOT SHIP CODE with this flag
*
* @param settings Array of additional enclave creation settings for the
* specific enclave type.
*
* @param setting_count The number of settings in the **settings**.
*
* @param ocall_table Pointer to table of ocall functions generated by
* oeedger8r.
*
* @param ocall_count The number of functions in the **ocall_table**.
*
* @param user_data Optional user data for attestation.
*
* @param user_data_size Size of the user data.
*
* @param enclave This points to the enclave instance upon success.
*
* @returns Returns OE_OK on success.
*
*/
oe_result_t oe_create_enclave_wud(
const char* path,
oe_enclave_type_t type,
uint32_t flags,
const oe_enclave_setting_t* settings,
uint32_t setting_count,
const oe_ocall_func_t* ocall_table,
uint32_t ocall_count,
uint8_t* user_data,
uint32_t user_data_size,
oe_enclave_t** enclave);

/**
* Terminate an enclave and reclaims its resources.
*
Expand Down
5 changes: 5 additions & 0 deletions include/openenclave/internal/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ uint64_t oe_get_base_heap_page(void);
uint64_t oe_get_num_heap_pages(void);
uint64_t oe_get_num_pages(void);

/* User data */
const void* __oe_get_user_data_base(void);
const void* __oe_get_user_data_end(void);
uint64_t __oe_get_user_data_size(void);

OE_EXTERNC_END

#endif /* _OE_GLOBALS_H */
Loading

2 comments on commit 6af0e52

@jxyang
Copy link

@jxyang jxyang commented on 6af0e52 Jan 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have sample code to show how to use oe_create_enclave_wud?

@wintersteiger
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about that, forgot to check in the example! It's here: aec1baa#diff-587c9a25688f4e2d2c71356b63402e91R16 It's a copy of the remote attestation sample with only a few lines modified. Enclave creation is at samples/remote_attestation_wud/host/host.cpp:16.

Please sign in to comment.