From 7db9d9b955d67f0e8e55105ec3b1d7a4e8932d7d Mon Sep 17 00:00:00 2001 From: "Zheng, Qi" Date: Mon, 23 Aug 2021 03:16:45 +0000 Subject: [PATCH] Add SGX KSS support Signed-off-by: Zheng, Qi --- etc/template/Occlum.json | 11 ++++- src/pal/src/base64.c | 68 +++++++++++++++++++++++++++++ src/pal/src/base64.h | 14 ++++++ src/pal/src/pal_enclave.c | 47 +++++++++++++++++++- test/Occlum.json | 11 ++++- tools/gen_internal_conf/src/main.rs | 45 +++++++++++++++++++ tools/occlum | 34 ++++++++++++++- 7 files changed, 225 insertions(+), 5 deletions(-) create mode 100644 src/pal/src/base64.c create mode 100644 src/pal/src/base64.h diff --git a/etc/template/Occlum.json b/etc/template/Occlum.json index 7fed012e..c5a45d24 100644 --- a/etc/template/Occlum.json +++ b/etc/template/Occlum.json @@ -24,7 +24,16 @@ "metadata": { "product_id": 0, "version_number": 0, - "debuggable": true + "debuggable": true, + "enable_kss": false, + "family_id": { + "high": "0x0", + "low": "0x0" + }, + "ext_prod_id": { + "high": "0x0", + "low": "0x0" + } }, "mount": [ { diff --git a/src/pal/src/base64.c b/src/pal/src/base64.c new file mode 100644 index 00000000..9898f7a3 --- /dev/null +++ b/src/pal/src/base64.c @@ -0,0 +1,68 @@ +/* + * Base64 encoding/decoding (RFC1341) + * Copyright (c) 2005-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include +#include +#include + +#include "pal_log.h" +#include "base64.h" + + +static const unsigned char base64_table[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static size_t base64_decode_len(const char *b64input) { + size_t len = strlen(b64input), padding = 0; + + if (b64input[len - 1] == '=' && b64input[len - 2] == '=') { //last two chars are = + padding = 2; + } else if (b64input[len - 1] == '=') { //last char is = + padding = 1; + } + + return (len * 3) / 4 - padding; +} + +/** + * base64_decode - Base64 decode + */ +void base64_decode(const char *b64input, unsigned char *dest, size_t dest_len) { + unsigned char dtable[256], *pos, block[4], tmp; + size_t i, count, olen; + size_t len = strlen(b64input); + + memset(dtable, 0x80, 256); + for (i = 0; i < sizeof(base64_table) - 1; i++) { + dtable[base64_table[i]] = (unsigned char) i; + } + dtable['='] = 0; + + olen = base64_decode_len(b64input); + if (olen > dest_len) { + PAL_WARN("Base64 encoded length %ld is biggeer than %ld\n", olen, dest_len); + return; + } + + pos = dest; + count = 0; + for (i = 0; i < len; i++) { + tmp = dtable[(unsigned char)b64input[i]]; + if (tmp == 0x80) { + continue; + } + block[count] = tmp; + count++; + if (count == 4) { + *pos++ = (block[0] << 2) | (block[1] >> 4); + *pos++ = (block[1] << 4) | (block[2] >> 2); + *pos++ = (block[2] << 6) | block[3]; + count = 0; + } + } +} \ No newline at end of file diff --git a/src/pal/src/base64.h b/src/pal/src/base64.h new file mode 100644 index 00000000..9de91ef1 --- /dev/null +++ b/src/pal/src/base64.h @@ -0,0 +1,14 @@ +#ifndef __BASE64_H__ +#define __BASE64_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void base64_decode(const char *b64input, unsigned char *dest, size_t dest_len); + +#ifdef __cplusplus +} +#endif + +#endif /* __BASE64_H__ */ \ No newline at end of file diff --git a/src/pal/src/pal_enclave.c b/src/pal/src/pal_enclave.c index c4c97fc3..115264b3 100644 --- a/src/pal/src/pal_enclave.c +++ b/src/pal/src/pal_enclave.c @@ -22,6 +22,7 @@ #include "pal_enclave.h" #include "pal_error.h" #include "pal_log.h" +#include "base64.h" #define MAX_PATH FILENAME_MAX #define TOKEN_FILENAME "enclave.token" @@ -43,6 +44,20 @@ static int get_enclave_debug_flag() { return 1; } +/* Get enable kss flag according to env "OCCLUM_ENABLE_KSS" */ +static int get_enable_kss_flag() { + const char *enable_kss_val = getenv("OCCLUM_ENABLE_KSS"); + if (enable_kss_val) { + if (!strcmp(enable_kss_val, "1") || + !strcasecmp(enable_kss_val, "y") || + !strcasecmp(enable_kss_val, "yes") || + !strcasecmp(enable_kss_val, "true")) { + return 1; + } + } + return 0; +} + static const char *get_enclave_absolute_path(const char *instance_dir) { static char enclave_path[MAX_PATH + 1] = {0}; strncat(enclave_path, instance_dir, MAX_PATH); @@ -102,8 +117,36 @@ int pal_init_enclave(const char *instance_dir) { /* Debug Support: set 2nd parameter to 1 */ const char *enclave_path = get_enclave_absolute_path(instance_dir); int sgx_debug_flag = get_enclave_debug_flag(); - ret = sgx_create_enclave(enclave_path, sgx_debug_flag, &token, &updated, &global_eid, - NULL); + int sgx_enable_kss = get_enable_kss_flag(); + + /* If enable kss, use sgx_create_enclave_ex to create enclave */ + if (sgx_enable_kss) { + sgx_kss_config_t kss_config = { 0 }; + const void *enclave_ex_p[32] = { 0 }; + const char *sgx_conf_id = getenv("OCCLUM_CONF_ID_BASE64"); + const char *sgx_conf_svn = getenv("OCCLUM_CONF_SVN"); + + if (sgx_conf_id) { + base64_decode(sgx_conf_id, kss_config.config_id, SGX_CONFIGID_SIZE); + } + + if (sgx_conf_svn) { + unsigned long svn_val = strtoul(sgx_conf_svn, NULL, 0); + /* CONFIG SVN is 16 bits long */ + if (svn_val > 0xFFFF) { + PAL_WARN("Invalid CONFIG SVN value: 0x%lx\n", svn_val); + } else { + kss_config.config_svn = svn_val; + } + } + + enclave_ex_p[SGX_CREATE_ENCLAVE_EX_KSS_BIT_IDX] = (const void *)&kss_config; + ret = sgx_create_enclave_ex(enclave_path, sgx_debug_flag, &token, &updated, &global_eid, + NULL, SGX_CREATE_ENCLAVE_EX_KSS, enclave_ex_p); + } else { + ret = sgx_create_enclave(enclave_path, sgx_debug_flag, &token, &updated, &global_eid, + NULL); + } if (ret != SGX_SUCCESS) { const char *sgx_err_msg = pal_get_sgx_error_msg(ret); PAL_ERROR("Failed to create enclave with error code 0x%x: %s", ret, sgx_err_msg); diff --git a/test/Occlum.json b/test/Occlum.json index fedb712f..a2811e04 100644 --- a/test/Occlum.json +++ b/test/Occlum.json @@ -27,7 +27,16 @@ "metadata": { "product_id": 0, "version_number": 0, - "debuggable": true + "debuggable": true, + "enable_kss": false, + "family_id": { + "high": "0x0", + "low": "0x0" + }, + "ext_prod_id": { + "high": "0x0", + "low": "0x0" + } }, "mount": [ { diff --git a/tools/gen_internal_conf/src/main.rs b/tools/gen_internal_conf/src/main.rs index 3353edff..f89eeb4b 100644 --- a/tools/gen_internal_conf/src/main.rs +++ b/tools/gen_internal_conf/src/main.rs @@ -155,6 +155,8 @@ fn main() { return; } + let kss_tuple = parse_kss_conf(&occlum_config); + // Generate the enclave configuration let sgx_enclave_configuration = EnclaveConfiguration { ProdID: occlum_config.metadata.product_id, @@ -175,6 +177,11 @@ fn main() { ReservedMemMinSize: user_space_size.unwrap() as u64, ReservedMemInitSize: user_space_size.unwrap() as u64, ReservedMemExecutable: 1, + EnableKSS: kss_tuple.0, + ISVEXTPRODID_H: kss_tuple.1, + ISVEXTPRODID_L: kss_tuple.2, + ISVFAMILYID_H: kss_tuple.3, + ISVFAMILYID_L: kss_tuple.4, }; let enclave_config = serde_xml_rs::to_string(&sgx_enclave_configuration).unwrap(); debug!("The enclave config:{:?}", enclave_config); @@ -286,6 +293,30 @@ fn parse_memory_size(mem_str: &str) -> Result { Ok(mem_val * unit_factor) } +fn get_u64_id_high_and_low(id: &OcclumMetaID) -> (u64, u64) { + let id_high = u64::from_str_radix(id.high.trim_start_matches("0x"), 16) + .expect("64 bit hex string ID required, such as 0x1234567812345678"); + let id_low = u64::from_str_radix(id.low.trim_start_matches("0x"), 16) + .expect("64 bit hex string ID required, such as 0x1234567812345678"); + + (id_high, id_low) +} + +// Return a tuple (EnableKSS, ISVEXTPRODID_H, ISVEXTPRODID_L, ISVFAMILYID_H, ISVFAMILYID_L) +fn parse_kss_conf(occlum_config: &OcclumConfiguration +) -> (u32, u64, u64, u64, u64) +{ + match occlum_config.metadata.enable_kss { + true => { + let ext_prod_id = get_u64_id_high_and_low(&occlum_config.metadata.ext_prod_id); + let family_id = get_u64_id_high_and_low(&occlum_config.metadata.family_id); + + (1, ext_prod_id.0, ext_prod_id.1, family_id.0, family_id.1) + }, + false => (0, 0, 0, 0, 0) + } +} + fn gen_user_mount_config( mount_conf: Vec, occlum_conf_user_fs_mac: String, @@ -385,11 +416,20 @@ struct OcclumProcess { default_mmap_size: String, } +#[derive(Debug, PartialEq, Deserialize)] +struct OcclumMetaID { + high: String, + low: String +} + #[derive(Debug, PartialEq, Deserialize)] struct OcclumMetadata { product_id: u32, version_number: u32, debuggable: bool, + enable_kss: bool, + family_id: OcclumMetaID, + ext_prod_id: OcclumMetaID } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -443,6 +483,11 @@ struct EnclaveConfiguration { ReservedMemMinSize: u64, ReservedMemInitSize: u64, ReservedMemExecutable: u32, + EnableKSS: u32, + ISVEXTPRODID_H: u64, + ISVEXTPRODID_L: u64, + ISVFAMILYID_H: u64, + ISVFAMILYID_L: u64, } #[derive(Debug, PartialEq, Clone, Serialize)] diff --git a/tools/occlum b/tools/occlum index e60e9052..dae52dbe 100755 --- a/tools/occlum +++ b/tools/occlum @@ -36,6 +36,10 @@ get_enclave_debuggable_flag() { jq '.metadata.debuggable' $instance_dir/Occlum.json } +get_enclave_enable_kss_flag() { + jq '.metadata.enable_kss' $instance_dir/Occlum.json +} + exit_error() { echo "Error: $@" >&2 exit 1 @@ -312,11 +316,21 @@ cmd_build() { echo "Built the Occlum image and enclave successfully" } + cmd_run() { check_has_built check_has_run check_aesm_service + loop=true + while [ -n "$1" ] && [ "$loop" = "true" ]; do + case "$1" in + --config-id) [ -n "$2" ] && export OCCLUM_CONF_ID_BASE64=$2 ; shift 2 || exit_error "Empty Base64 Encoded Occlum Config ID provided" ;; + --config-svn) [ -n "$2" ] && export OCCLUM_CONF_SVN=$2 ; shift 2 || exit_error "Empty Occlum Config SVN provided" ;; + *) loop=false ;; + esac + done + SGX_MODE=$(cat $instance_dir/.sgx_mode) if [[ -n $SGX_MODE && "$SGX_MODE" != "HW" ]]; then export LD_LIBRARY_PATH="$instance_dir/build/lib:$SGX_SDK/sdk_libs/" @@ -329,6 +343,11 @@ cmd_run() { if [ "`get_enclave_debuggable_flag`" == "false" ]; then export OCCLUM_RELEASE_ENCLAVE=1 fi + + if [ "`get_enclave_enable_kss_flag`" == "true" ]; then + export OCCLUM_ENABLE_KSS=1 + fi + RUST_BACKTRACE=1 "$instance_dir/build/bin/occlum-run" "$@" echo "built" > $status_file @@ -338,6 +357,15 @@ cmd_start() { check_has_built check_aesm_service + loop=true + while [ -n "$1" ] && [ "$loop" = "true" ]; do + case "$1" in + --config-id) [ -n "$2" ] && export OCCLUM_CONF_ID_BASE64=$2 ; shift 2 || exit_error "Empty Base64 Encoded Occlum Config ID provided" ;; + --config-svn) [ -n "$2" ] && export OCCLUM_CONF_SVN=$2 ; shift 2 || exit_error "Empty Occlum Config SVN provided" ;; + *) loop=false ;; + esac + done + SGX_MODE=$(cat $instance_dir/.sgx_mode) if [[ -n $SGX_MODE && "$SGX_MODE" != "HW" ]]; then export LD_LIBRARY_PATH="$instance_dir/build/lib:$SGX_SDK/sdk_libs/" @@ -350,6 +378,10 @@ cmd_start() { if [ "`get_enclave_debuggable_flag`" == "false" ]; then export OCCLUM_RELEASE_ENCLAVE=1 fi + + if [ "`get_enclave_enable_kss_flag`" == "true" ]; then + export OCCLUM_ENABLE_KSS=1 + fi RUST_BACKTRACE=1 "$instance_dir/build/bin/occlum_exec_client" start echo "built" > $status_file @@ -565,7 +597,7 @@ case "$cmd" in cmd_run "${@:2}" ;; start) - cmd_start + cmd_start "${@:2}" ;; exec) cmd_exec "${@:2}"