Skip to content

Commit

Permalink
[Pal/Linux-SGX] Remove SGX token dependency for DCAP enclaves
Browse files Browse the repository at this point in the history
The SGX Launch Token (aka EINITTOKEN) file is required for EPID-based
(more specifically, for non-FLC-based) SGX platforms. On these
platforms, the token file is generated by the Quoting Enclave (QE)
right-before the startup of the application in Gramine (Gramine sends a
request for generation of the token to QE via the AESM service, using
the `gramine-sgx-get-token` Python tool). Later, during enclave
initialization at Gramine startup, this token file is read and its
contents are provided as an arg to `SGX_IOC_ENCLAVE_INIT` ioctl.

However, this token file is not required for DCAP-based (more
specifically, for FLC-based) SGX platforms. Previously, Gramine still
required to use the `gramine-sgx-get-token` Python tool even on these
platforms, which generated a dummy token file. Generating this dummy
token file may be problematic: (a) this cannot work on read-only FS
mounts, and (b) it requires Python installed on the system. So this
commit removes this dummy token file completely on DCAP machines.

Co-authored-by: Dmitrii Kuvaiskii <[email protected]>
Signed-off-by: Frieder Paape, Integritee AG <[email protected]>
Signed-off-by: Dmitrii Kuvaiskii <[email protected]>
  • Loading branch information
Frieder Paape, Integritee AG and dimakuv committed Jun 1, 2022
1 parent d42e0cc commit e6fe602
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 31 deletions.
6 changes: 3 additions & 3 deletions Pal/src/host/Linux-SGX/sgx_framework.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,13 @@ bool is_wrfsbase_supported(void) {
return true;
}

int create_enclave(sgx_arch_secs_t* secs, sgx_arch_token_t* token) {
int create_enclave(sgx_arch_secs_t* secs, sgx_arch_enclave_css_t* sigstruct) {
assert(secs->size && IS_POWER_OF_2(secs->size));
assert(IS_ALIGNED(secs->base, secs->size));

secs->ssa_frame_size = SSA_FRAME_SIZE / g_page_size; /* SECS expects SSA frame size in pages */
secs->misc_select = token->masked_misc_select_le;
memcpy(&secs->attributes, &token->body.attributes, sizeof(sgx_attributes_t));
secs->misc_select = sigstruct->body.misc_select;
memcpy(&secs->attributes, &sigstruct->body.attributes, sizeof(sgx_attributes_t));

/* Do not initialize secs->mr_signer and secs->mr_enclave here as they are
* not used by ECREATE to populate the internal SECS. SECS's mr_enclave is
Expand Down
2 changes: 1 addition & 1 deletion Pal/src/host/Linux-SGX/sgx_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ bool is_wrfsbase_supported(void);
int read_enclave_token(int token_file, sgx_arch_token_t* token);
int read_enclave_sigstruct(int sigfile, sgx_arch_enclave_css_t* sig);

int create_enclave(sgx_arch_secs_t* secs, sgx_arch_token_t* token);
int create_enclave(sgx_arch_secs_t* secs, sgx_arch_enclave_css_t* sigstruct);

enum sgx_page_type { SGX_PAGE_SECS, SGX_PAGE_TCS, SGX_PAGE_REG };
int add_pages_to_enclave(sgx_arch_secs_t* secs, void* addr, void* user_addr, unsigned long size,
Expand Down
32 changes: 20 additions & 12 deletions Pal/src/host/Linux-SGX/sgx_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "asan.h"
#include "debug_map.h"
#include "gdb_integration/sgx_gdb.h"
#include "gsgx.h"
#include "linux_utils.h"
#include "pal_internal-arch.h"
#include "pal_linux_defs.h"
Expand Down Expand Up @@ -200,15 +201,20 @@ static int load_enclave_binary(sgx_arch_secs_t* secs, int fd, unsigned long base
static int initialize_enclave(struct pal_enclave* enclave, const char* manifest_to_measure) {
int ret = 0;
int enclave_image = -1;
sgx_arch_token_t enclave_token;
sgx_arch_enclave_css_t enclave_sigstruct;
int enclave_mem = -1;
sgx_arch_secs_t enclave_secs;
unsigned long enclave_entry_addr;
unsigned long enclave_heap_min;

sgx_arch_enclave_css_t enclave_sigstruct;
char* sig_path = NULL;
int sigfile_fd = -1;

/* Launch Token (aka EINITTOKEN) is used only on EPID (non-FLC-based) platforms and completely
* ignored on DCAP (FLC-based) platforms */
sgx_arch_token_t enclave_token;
char* token_path = NULL;
int sigfile_fd = -1, token_fd = -1;
int enclave_mem = -1;
int token_fd = -1;

/* this array may overflow the stack, so we allocate it in BSS */
static void* tcs_addrs[MAX_DBG_THREADS];
Expand Down Expand Up @@ -246,6 +252,13 @@ static int initialize_enclave(struct pal_enclave* enclave, const char* manifest_
goto out;
}

ret = read_enclave_sigstruct(sigfile_fd, &enclave_sigstruct);
if (ret < 0) {
log_error("Reading enclave sigstruct failed: %d", ret);
goto out;
}

#ifndef SGX_DCAP
token_path = alloc_concat(g_pal_enclave.application_path, -1, ".token", -1);
if (!token_path) {
ret = -ENOMEM;
Expand All @@ -266,10 +279,11 @@ static int initialize_enclave(struct pal_enclave* enclave, const char* manifest_
log_error("Reading enclave token failed: %d", ret);
goto out;
}
#endif

#ifdef DEBUG
if (enclave->profile_enable) {
if (!(enclave_token.body.attributes.flags & SGX_FLAGS_DEBUG)) {
if (!(enclave_sigstruct.body.attributes.flags & SGX_FLAGS_DEBUG)) {
log_error("Cannot use 'sgx.profile' with a production enclave");
ret = -EINVAL;
goto out;
Expand All @@ -288,16 +302,10 @@ static int initialize_enclave(struct pal_enclave* enclave, const char* manifest_
}
#endif

ret = read_enclave_sigstruct(sigfile_fd, &enclave_sigstruct);
if (ret < 0) {
log_error("Reading enclave sigstruct failed: %d", ret);
goto out;
}

memset(&enclave_secs, 0, sizeof(enclave_secs));
enclave_secs.base = enclave->baseaddr;
enclave_secs.size = enclave->size;
ret = create_enclave(&enclave_secs, &enclave_token);
ret = create_enclave(&enclave_secs, &enclave_sigstruct);
if (ret < 0) {
log_error("Creating enclave failed: %d", ret);
goto out;
Expand Down
20 changes: 5 additions & 15 deletions python/graminelibos/sgx_get_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,6 @@ def connect_aesmd(mrenclave, modulus, flags, xfrms):

return ret_msg.ret.token

def create_dummy_token(flags, xfrms, misc_select):
'''
Create dummy token with a few fields initialized with real values and others
with a placeholder ('\\0')
'''
token = bytearray(304)

# fields read by create_enclave() in sgx_framework.c
struct.pack_into('<Q', token, 48, flags)
struct.pack_into('<Q', token, 56, xfrms)
struct.pack_into('<L', token, 236, misc_select)

return token

def get_token(sig, verbose=False):
"""Get SGX token (aka EINITTOKEN).
Expand All @@ -128,6 +114,10 @@ def get_token(sig, verbose=False):
mrsigner = mrsigner.hexdigest()

if verbose:
if is_dcap():
print('INFO: DCAP platform was detected. SGX launch tokens (EINITTOKEN) are not '
'required on DCAP platforms. This tool will output an empty dummy token which '
'can be - but not required to - supplied during Gramine launch.')
print('Attributes:')
print(f' mr_enclave: {sig["enclave_hash"].hex()}')
print(f' mr_signer: {mrsigner}')
Expand All @@ -146,7 +136,7 @@ def get_token(sig, verbose=False):
f'{sig["date_day"]:02d}')

if is_dcap():
token = create_dummy_token(sig['attribute_flags'], xfrms, sig['misc_select'])
token = bytearray(0)
else:
token = connect_aesmd(sig['enclave_hash'], sig['modulus'], sig['attribute_flags'], xfrms)

Expand Down

0 comments on commit e6fe602

Please sign in to comment.