Skip to content

Commit

Permalink
[LibOS] Support special keys (MRENCLAVE, MRSIGNER) in encrypted fs
Browse files Browse the repository at this point in the history
Key names beginning with `_` are considered special, and PAL is queried
for these keys. This is used for SGX MRENCLAVE and MRSIGNER keys.

If a key is not supported by the current PAL, mounting will still
succeed (but files will not be readable). This way, manifests using
these PAL-host-specific keys can still be loaded when using other PAL
hosts.

Signed-off-by: Paweł Marczewski <[email protected]>
  • Loading branch information
pwmarcz authored and Dmitrii Kuvaiskii committed Apr 26, 2022
1 parent 9774ce1 commit 52576fb
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 34 deletions.
1 change: 0 additions & 1 deletion LibOS/shim/src/fs/chroot/encrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
*
* TODO (most items are needed for feature parity with PAL protected files):
*
* - mounting with special keys (SGX MRENCLAVE and MRSIGNER)
* - mmap
* - truncate (the current `truncate` operation works only for extending the file, support for
* truncation needs to be added to the `protected_files` module)
Expand Down
35 changes: 31 additions & 4 deletions LibOS/shim/src/fs/shim_fs_encrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,12 +311,14 @@ static struct shim_encrypted_files_key* get_key(const char* name) {
return NULL;
}

static struct shim_encrypted_files_key* get_or_create_key(const char* name) {
static struct shim_encrypted_files_key* get_or_create_key(const char* name, bool* out_created) {
assert(locked(&g_keys_lock));

struct shim_encrypted_files_key* key = get_key(name);
if (key)
if (key) {
*out_created = false;
return key;
}

key = calloc(1, sizeof(*key));
if (!key)
Expand All @@ -328,6 +330,7 @@ static struct shim_encrypted_files_key* get_or_create_key(const char* name) {
}
key->is_set = false;
LISTP_ADD_TAIL(key, &g_keys, list);
*out_created = true;
return key;
}

Expand Down Expand Up @@ -361,13 +364,37 @@ int get_or_create_encrypted_files_key(const char* name, struct shim_encrypted_fi

int ret;

struct shim_encrypted_files_key* key = get_or_create_key(name);
bool created;
struct shim_encrypted_files_key* key = get_or_create_key(name, &created);
if (!key) {
ret = -ENOMEM;
goto out;
}

/* TODO: load special keys (MRENCLAVE, MRSIGNER) here */
if (created && name[0] == '_') {
pf_key_t pf_key;
size_t size = sizeof(pf_key);
ret = DkGetSpecialKey(name, &pf_key, &size);

if (ret == 0) {
if (size != sizeof(pf_key)) {
log_debug("DkGetSpecialKey(\"%s\") returned wrong size: %zu", name, size);
ret = -EINVAL;
goto out;
}
log_debug("Successfully retrieved special key \"%s\"", name);
memcpy(&key->pf_key, &pf_key, sizeof(pf_key));
key->is_set = true;
} else if (ret == -PAL_ERROR_NOTIMPLEMENTED) {
log_debug("Special key \"%s\" is not supported by current PAL. Mounts using this key "
"will not work.", name);
/* proceed without setting value */
} else {
log_debug("DkGetSpecialKey(\"%s\") failed: %d", name, ret);
ret = pal_to_unix_errno(ret);
goto out;
}
}

*out_key = key;
ret = 0;
Expand Down
2 changes: 2 additions & 0 deletions LibOS/shim/test/regression/manifest.template
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ fs.mounts = [

{ type = "tmpfs", path = "/mnt/tmpfs" },
{ type = "encrypted", path = "/tmp_enc", uri = "file:tmp_enc", key_name = "my_custom_key" },
{ type = "encrypted", path = "/encrypted_file_mrenclave.dat", uri = "file:encrypted_file_mrenclave.dat", key_name = "_sgx_mrenclave" },
{ type = "encrypted", path = "/encrypted_file_mrsigner.dat", uri = "file:encrypted_file_mrsigner.dat", key_name = "_sgx_mrsigner" },
]

sgx.thread_num = 16
Expand Down
61 changes: 32 additions & 29 deletions LibOS/shim/test/regression/test_libos.py
Original file line number Diff line number Diff line change
Expand Up @@ -985,45 +985,48 @@ def test_040_sysfs(self):

@unittest.skipUnless(HAS_SGX, 'Sealed (protected) files are only available with SGX')
def test_050_sealed_file_mrenclave(self):
pf_path = 'sealed_file_mrenclave.dat'
if os.path.exists(pf_path):
os.remove(pf_path)
# Test both old and new implementation
for pf_path in ['sealed_file_mrenclave.dat', 'encrypted_file_mrenclave.dat']:
if os.path.exists(pf_path):
os.remove(pf_path)

stdout, _ = self.run_binary(['sealed_file', pf_path])
self.assertIn('CREATION OK', stdout)
stdout, _ = self.run_binary(['sealed_file', pf_path])
self.assertIn('READING OK', stdout)
stdout, _ = self.run_binary(['sealed_file', pf_path])
self.assertIn('CREATION OK', stdout)
stdout, _ = self.run_binary(['sealed_file', pf_path])
self.assertIn('READING OK', stdout)

@unittest.skipUnless(HAS_SGX, 'Sealed (protected) files are only available with SGX')
def test_051_sealed_file_mrsigner(self):
pf_path = 'sealed_file_mrsigner.dat'
if os.path.exists(pf_path):
os.remove(pf_path)
# Test both old and new implementation
for pf_path in ['sealed_file_mrsigner.dat', 'encrypted_file_mrsigner.dat']:
if os.path.exists(pf_path):
os.remove(pf_path)

stdout, _ = self.run_binary(['sealed_file', pf_path])
self.assertIn('CREATION OK', stdout)
stdout, _ = self.run_binary(['sealed_file_mod', pf_path])
self.assertIn('READING FROM MODIFIED ENCLAVE OK', stdout)
stdout, _ = self.run_binary(['sealed_file', pf_path])
self.assertIn('CREATION OK', stdout)
stdout, _ = self.run_binary(['sealed_file_mod', pf_path])
self.assertIn('READING FROM MODIFIED ENCLAVE OK', stdout)

@unittest.skipUnless(HAS_SGX, 'Sealed (protected) files are only available with SGX')
def test_052_sealed_file_mrenclave_bad(self):
# Negative test: Seal MRENCLAVE-bound file in one enclave -> opening this file in another
# enclave (with different MRENCLAVE) should fail
pf_path = 'sealed_file_mrenclave.dat'
if os.path.exists(pf_path):
os.remove(pf_path)
# Test both old and new implementation
for pf_path in ['sealed_file_mrenclave.dat', 'encrypted_file_mrenclave.dat']:
# Negative test: Seal MRENCLAVE-bound file in one enclave -> opening this file in
# another enclave (with different MRENCLAVE) should fail
if os.path.exists(pf_path):
os.remove(pf_path)

stdout, _ = self.run_binary(['sealed_file', pf_path])
self.assertIn('CREATION OK', stdout)
stdout, _ = self.run_binary(['sealed_file', pf_path])
self.assertIn('CREATION OK', stdout)

try:
self.run_binary(['sealed_file_mod', pf_path])
self.fail('expected to return nonzero')
except subprocess.CalledProcessError as e:
self.assertEqual(e.returncode, 1)
stdout = e.stdout.decode()
self.assertNotIn('READING FROM MODIFIED ENCLAVE OK', stdout)
self.assertIn('Permission denied', stdout)
try:
self.run_binary(['sealed_file_mod', pf_path])
self.fail('expected to return nonzero')
except subprocess.CalledProcessError as e:
self.assertEqual(e.returncode, 1)
stdout = e.stdout.decode()
self.assertNotIn('READING FROM MODIFIED ENCLAVE OK', stdout)
self.assertIn('Permission denied', stdout)

def test_060_synthetic(self):
stdout, _ = self.run_binary(['synthetic'])
Expand Down
16 changes: 16 additions & 0 deletions Pal/include/pal/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,22 @@ int DkAttestationQuote(const void* user_report_data, PAL_NUM user_report_data_si
*/
int DkSetProtectedFilesKey(const char* pf_key_hex);

/*!
* \brief Get special key (specific to PAL host).
*
* \param[in] name Key name.
* \param[out] key On success, will be set to retrieved key.
* \param[in,out] key_size Caller specifies maximum size for `key`. On success, will contain actual
* size.
*
* Retrieve the value of a special key. Currently implemented for Linux-SGX PAL, which supports two
* such keys: `_sgx_mrenclave` and `_sgx_mrsigner`.
*
* If a given key is not supported by the current PAL host, the function will return
* -PAL_ERROR_NOTIMPLEMENTED.
*/
int DkGetSpecialKey(const char* name, void* key, size_t* key_size);

#ifdef __GNUC__
#define symbol_version_default(real, name, version) \
__asm__(".symver " #real "," #name "@@" #version "\n")
Expand Down
1 change: 1 addition & 0 deletions Pal/include/pal_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ int _DkAttestationReport(const void* user_report_data, PAL_NUM* user_report_data
int _DkAttestationQuote(const void* user_report_data, PAL_NUM user_report_data_size, void* quote,
PAL_NUM* quote_size);
int _DkSetProtectedFilesKey(const char* pf_key_hex);
int _DkGetSpecialKey(const char* name, void* key, size_t* key_size);

#define INIT_FAIL(exitcode, reason) \
do { \
Expand Down
4 changes: 4 additions & 0 deletions Pal/src/db_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,7 @@ int DkAttestationQuote(const void* user_report_data, PAL_NUM user_report_data_si
int DkSetProtectedFilesKey(const char* pf_key_hex) {
return _DkSetProtectedFilesKey(pf_key_hex);
}

int DkGetSpecialKey(const char* name, void* key, size_t* key_size) {
return _DkGetSpecialKey(name, key, key_size);
}
22 changes: 22 additions & 0 deletions Pal/src/host/Linux-SGX/db_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,28 @@ int _DkSetProtectedFilesKey(const char* pf_key_hex) {
return set_protected_files_key(pf_key_hex);
}

int _DkGetSpecialKey(const char* name, void* key, size_t* key_size) {
sgx_key_128bit_t sgx_key;

if (*key_size < sizeof(sgx_key))
return -PAL_ERROR_INVAL;

int ret;
if (!strcmp(name, "_sgx_mrenclave")) {
ret = sgx_get_seal_key(SGX_KEYPOLICY_MRENCLAVE, &sgx_key);
} else if (!strcmp(name, "_sgx_mrsigner")) {
ret = sgx_get_seal_key(SGX_KEYPOLICY_MRSIGNER, &sgx_key);
} else {
return -PAL_ERROR_NOTIMPLEMENTED;
}
if (ret < 0)
return ret;

memcpy(key, &sgx_key, sizeof(sgx_key));
*key_size = sizeof(sgx_key);
return 0;
}

/* Rest is moved from old `db_main-x86_64.c`. */

#define CPUID_LEAF_INVARIANT_TSC 0x80000007
Expand Down
7 changes: 7 additions & 0 deletions Pal/src/host/Linux/db_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,10 @@ int _DkSetProtectedFilesKey(const char* pf_key_hex) {
__UNUSED(pf_key_hex);
return -PAL_ERROR_NOTIMPLEMENTED;
}

int _DkGetSpecialKey(const char* name, void* key, size_t* key_size) {
__UNUSED(name);
__UNUSED(key);
__UNUSED(key_size);
return -PAL_ERROR_NOTIMPLEMENTED;
}
7 changes: 7 additions & 0 deletions Pal/src/host/Skeleton/db_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ int _DkSetProtectedFilesKey(const char* pf_key_hex) {
return -PAL_ERROR_NOTIMPLEMENTED;
}

int _DkGetSpecialKey(const char* name, void* key, size_t* key_size) {
__UNUSED(name);
__UNUSED(key);
__UNUSED(key_size);
return -PAL_ERROR_NOTIMPLEMENTED;
}

double _DkGetBogomips(void) {
/* this has to be implemented */
return 0.0;
Expand Down
1 change: 1 addition & 0 deletions Pal/src/pal-symbols
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,6 @@ DkDebugDescribeLocation
DkAttestationReport
DkAttestationQuote
DkSetProtectedFilesKey
DkGetSpecialKey
DkDebugLog
DkGetPalPublicState

0 comments on commit 52576fb

Please sign in to comment.