Skip to content

Commit

Permalink
[LibOS] Expose SGX sealing keys under /dev/attestation/keys/
Browse files Browse the repository at this point in the history
Gramine has two SGX sealing keys, named `_sgx_mrenclave` and
`_sgx_mrsigner`. Previously, these keys could be used in the manifest
file's `fs.mounts = [ key_name = "..." ]` syntax, but these keys were
not exposed as `/dev/attestation/keys/{_sgx_mrenclave,_sgx_mrsigner}`.

Signed-off-by: Dmitrii Kuvaiskii <dmitrii.kuvaiskii@intel.com>
  • Loading branch information
dimakuv committed Apr 5, 2023
1 parent 7865077 commit cd6a9cc
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 11 deletions.
9 changes: 9 additions & 0 deletions Documentation/manifest-syntax.rst
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,15 @@ Gramine:
identity of the enclave. This is useful to allow all enclaves signed with the
same key (and on the same platform) to unseal files.

.. warning::
The same key must not be used for the encrypted-files mount and for the
application's own crypto operations. Such "double" use of the same key may
lead to compromise of the key. For example, specifying an FS mount via
``{type = "encrypted", ..., key_name = "_sgx_mrenclave"}`` in the manifest
and using the same key obtained via ``/dev/attestation/keys/_sgx_mrenclave``
in the application is insecure. If you need to derive encryption keys from
such a "doubly-used" key, you must apply a KDF.

File check policy
^^^^^^^^^^^^^^^^^

Expand Down
24 changes: 18 additions & 6 deletions libos/src/fs/dev/attestation.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "api.h"
#include "libos_fs_encrypted.h"
#include "libos_fs_pseudo.h"
#include "pal.h"
#include "toml_utils.h"

/* user_report_data, target_info and quote are opaque blobs of predefined maximum sizes. Currently
Expand Down Expand Up @@ -322,7 +323,7 @@ static int key_save(struct libos_dentry* dent, const char* data, size_t size) {
return 0;
}

static int init_sgx_attestation(struct pseudo_node* attestation) {
static int init_sgx_attestation(struct pseudo_node* attestation, struct pseudo_node* keys) {
if (strcmp(g_pal_public_state->host_type, "Linux-SGX"))
return 0;

Expand All @@ -344,6 +345,21 @@ static int init_sgx_attestation(struct pseudo_node* attestation) {
target_info->perm = PSEUDO_PERM_FILE_RW;
target_info->str.save = &target_info_save;

/* dummy retrieval of SGX sealing keys, so that they appear under /dev/attestation/keys/ */
const char* sealing_keys_names[] = { PAL_KEY_NAME_SGX_MRENCLAVE, PAL_KEY_NAME_SGX_MRSIGNER };
for (size_t i = 0; i < ARRAY_SIZE(sealing_keys_names); i++) {
struct libos_encrypted_files_key* key;
int ret = get_or_create_encrypted_files_key(sealing_keys_names[i], &key);
if (ret < 0) {
log_error("Cannot initialize SGX sealing key `%s`", sealing_keys_names[i]);
return ret;
}
}

/* SGX sealing keys must be read-only, so we mount them over other /dev/attestation/keys/ */
pseudo_add_str(keys, PAL_KEY_NAME_SGX_MRENCLAVE, &key_load);
pseudo_add_str(keys, PAL_KEY_NAME_SGX_MRSIGNER, &key_load);

if (!strcmp(g_pal_public_state->attestation_type, "none")) {
log_debug("host is Linux-SGX and remote attestation type is 'none', skipping "
"/dev/attestation/quote file");
Expand All @@ -359,16 +375,12 @@ static int init_sgx_attestation(struct pseudo_node* attestation) {
int init_attestation(struct pseudo_node* dev) {
struct pseudo_node* attestation = pseudo_add_dir(dev, "attestation");

int ret = init_sgx_attestation(attestation);
if (ret < 0)
return ret;

struct pseudo_node* keys = pseudo_add_dir(attestation, "keys");
struct pseudo_node* key = pseudo_add_str(keys, /*name=*/NULL, &key_load);
key->name_exists = &key_name_exists;
key->list_names = &key_list_names;
key->perm = PSEUDO_PERM_FILE_RW;
key->str.save = &key_save;

return 0;
return init_sgx_attestation(attestation, keys);
}
32 changes: 31 additions & 1 deletion libos/test/regression/keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ typedef uint8_t pf_key_t[KEY_SIZE];
#define DEFAULT_KEY_PATH "/dev/attestation/keys/default"
#define CUSTOM_KEY_PATH "/dev/attestation/keys/my_custom_key"

/* Special keys (SGX sealing keys), always existing under SGX and read-only */
#define MRENCLAVE_KEY_PATH "/dev/attestation/keys/_sgx_mrenclave"
#define MRSIGNER_KEY_PATH "/dev/attestation/keys/_sgx_mrsigner"

static const pf_key_t default_key = {
0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00};

Expand All @@ -47,6 +51,15 @@ static void format_key(char buf[static KEY_STR_SIZE], const pf_key_t* key) {
buf[KEY_SIZE * 2] = '\0';
}

static void verify_key_exists(const char* desc, const char* path) {
pf_key_t key;
ssize_t n = posix_file_read(path, (char*)&key, sizeof(key));
if (n < 0)
err(1, "%s: error reading %s", desc, path);
if ((size_t)n != sizeof(key))
errx(1, "%s: file %s has wrong size: expected %zd, got %zd", desc, path, sizeof(key), n);
}

static void expect_key(const char* desc, const char* path, const pf_key_t* expected_key) {
pf_key_t key;

Expand Down Expand Up @@ -75,7 +88,24 @@ static void write_key(const char* desc, const char* path, const pf_key_t* key) {
errx(1, "%s: not enough bytes written to %s: %zd", desc, path, n);
}

int main(void) {
static void fail_write_key(const char* desc, const char* path) {
pf_key_t dummy_key = {0};
ssize_t n = posix_file_write(path, (char*)&dummy_key, sizeof(dummy_key));
if (n >= 0)
errx(1, "%s: writing to %s unexpectedly succeeded", desc, path);
}

int main(int argc, char** argv) {
if (argc > 2 || (argc == 2 && strcmp(argv[1], "sgx") != 0))
errx(1, "test expects either no arguments, or one argument `sgx`");

if (argc == 2) {
verify_key_exists("SGX sealing keys", MRENCLAVE_KEY_PATH);
verify_key_exists("SGX sealing keys", MRSIGNER_KEY_PATH);
fail_write_key("SGX sealing keys", MRENCLAVE_KEY_PATH);
fail_write_key("SGX sealing keys", MRSIGNER_KEY_PATH);
}

expect_key("before writing key", DEFAULT_KEY_PATH, &default_key);
expect_key("before writing key", CUSTOM_KEY_PATH, &custom_key);

Expand Down
5 changes: 4 additions & 1 deletion libos/test/regression/test_libos.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,10 @@ def _test_send_handle(self, path, delete=False):
self.assertIn('TEST OK', stdout, 'test failed: {}'.format(cmd))

def test_230_keys(self):
stdout, _ = self.run_binary(['keys'])
if HAS_SGX:
stdout, _ = self.run_binary(['keys', 'sgx'])
else:
stdout, _ = self.run_binary(['keys'])
self.assertIn('TEST OK', stdout)

def test_300_shared_object(self):
Expand Down
5 changes: 4 additions & 1 deletion pal/include/pal/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -949,13 +949,16 @@ int PalAttestationQuote(const void* user_report_data, size_t user_report_data_si
* size.
*
* Retrieve the value of a special key. Currently implemented for Linux-SGX PAL, which supports two
* such keys: `_sgx_mrenclave` and `_sgx_mrsigner`.
* such keys: `_sgx_mrenclave` and `_sgx_mrsigner` (see macros below).
*
* If a given key is not supported by the current PAL host, the function will return
* -PAL_ERROR_NOTIMPLEMENTED.
*/
int PalGetSpecialKey(const char* name, void* key, size_t* key_size);

#define PAL_KEY_NAME_SGX_MRENCLAVE "_sgx_mrenclave"
#define PAL_KEY_NAME_SGX_MRSIGNER "_sgx_mrsigner"

#ifdef __GNUC__
#define symbol_version_default(real, name, version) \
__asm__(".symver " #real "," #name "@@" #version "\n")
Expand Down
4 changes: 2 additions & 2 deletions pal/src/host/linux-sgx/pal_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -627,9 +627,9 @@ int _PalGetSpecialKey(const char* name, void* key, size_t* key_size) {
return -PAL_ERROR_INVAL;

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

0 comments on commit cd6a9cc

Please sign in to comment.