Add SGX KSS support

Signed-off-by: Zheng, Qi <huaiqing.zq@antgroup.com>
This commit is contained in:
Zheng, Qi 2021-08-23 03:16:45 +00:00 committed by Zongmin.Gu
parent 8cb08aac29
commit 7db9d9b955
7 changed files with 225 additions and 5 deletions

@ -24,7 +24,16 @@
"metadata": { "metadata": {
"product_id": 0, "product_id": 0,
"version_number": 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": [ "mount": [
{ {

68
src/pal/src/base64.c Normal file

@ -0,0 +1,68 @@
/*
* Base64 encoding/decoding (RFC1341)
* Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}
}
}

14
src/pal/src/base64.h Normal file

@ -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__ */

@ -22,6 +22,7 @@
#include "pal_enclave.h" #include "pal_enclave.h"
#include "pal_error.h" #include "pal_error.h"
#include "pal_log.h" #include "pal_log.h"
#include "base64.h"
#define MAX_PATH FILENAME_MAX #define MAX_PATH FILENAME_MAX
#define TOKEN_FILENAME "enclave.token" #define TOKEN_FILENAME "enclave.token"
@ -43,6 +44,20 @@ static int get_enclave_debug_flag() {
return 1; 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 const char *get_enclave_absolute_path(const char *instance_dir) {
static char enclave_path[MAX_PATH + 1] = {0}; static char enclave_path[MAX_PATH + 1] = {0};
strncat(enclave_path, instance_dir, MAX_PATH); 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 */ /* Debug Support: set 2nd parameter to 1 */
const char *enclave_path = get_enclave_absolute_path(instance_dir); const char *enclave_path = get_enclave_absolute_path(instance_dir);
int sgx_debug_flag = get_enclave_debug_flag(); int sgx_debug_flag = get_enclave_debug_flag();
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, ret = sgx_create_enclave(enclave_path, sgx_debug_flag, &token, &updated, &global_eid,
NULL); NULL);
}
if (ret != SGX_SUCCESS) { if (ret != SGX_SUCCESS) {
const char *sgx_err_msg = pal_get_sgx_error_msg(ret); 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); PAL_ERROR("Failed to create enclave with error code 0x%x: %s", ret, sgx_err_msg);

@ -27,7 +27,16 @@
"metadata": { "metadata": {
"product_id": 0, "product_id": 0,
"version_number": 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": [ "mount": [
{ {

@ -155,6 +155,8 @@ fn main() {
return; return;
} }
let kss_tuple = parse_kss_conf(&occlum_config);
// Generate the enclave configuration // Generate the enclave configuration
let sgx_enclave_configuration = EnclaveConfiguration { let sgx_enclave_configuration = EnclaveConfiguration {
ProdID: occlum_config.metadata.product_id, ProdID: occlum_config.metadata.product_id,
@ -175,6 +177,11 @@ fn main() {
ReservedMemMinSize: user_space_size.unwrap() as u64, ReservedMemMinSize: user_space_size.unwrap() as u64,
ReservedMemInitSize: user_space_size.unwrap() as u64, ReservedMemInitSize: user_space_size.unwrap() as u64,
ReservedMemExecutable: 1, 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(); let enclave_config = serde_xml_rs::to_string(&sgx_enclave_configuration).unwrap();
debug!("The enclave config:{:?}", enclave_config); debug!("The enclave config:{:?}", enclave_config);
@ -286,6 +293,30 @@ fn parse_memory_size(mem_str: &str) -> Result<usize, &str> {
Ok(mem_val * unit_factor) 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( fn gen_user_mount_config(
mount_conf: Vec<OcclumMount>, mount_conf: Vec<OcclumMount>,
occlum_conf_user_fs_mac: String, occlum_conf_user_fs_mac: String,
@ -385,11 +416,20 @@ struct OcclumProcess {
default_mmap_size: String, default_mmap_size: String,
} }
#[derive(Debug, PartialEq, Deserialize)]
struct OcclumMetaID {
high: String,
low: String
}
#[derive(Debug, PartialEq, Deserialize)] #[derive(Debug, PartialEq, Deserialize)]
struct OcclumMetadata { struct OcclumMetadata {
product_id: u32, product_id: u32,
version_number: u32, version_number: u32,
debuggable: bool, debuggable: bool,
enable_kss: bool,
family_id: OcclumMetaID,
ext_prod_id: OcclumMetaID
} }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@ -443,6 +483,11 @@ struct EnclaveConfiguration {
ReservedMemMinSize: u64, ReservedMemMinSize: u64,
ReservedMemInitSize: u64, ReservedMemInitSize: u64,
ReservedMemExecutable: u32, ReservedMemExecutable: u32,
EnableKSS: u32,
ISVEXTPRODID_H: u64,
ISVEXTPRODID_L: u64,
ISVFAMILYID_H: u64,
ISVFAMILYID_L: u64,
} }
#[derive(Debug, PartialEq, Clone, Serialize)] #[derive(Debug, PartialEq, Clone, Serialize)]

@ -36,6 +36,10 @@ get_enclave_debuggable_flag() {
jq '.metadata.debuggable' $instance_dir/Occlum.json jq '.metadata.debuggable' $instance_dir/Occlum.json
} }
get_enclave_enable_kss_flag() {
jq '.metadata.enable_kss' $instance_dir/Occlum.json
}
exit_error() { exit_error() {
echo "Error: $@" >&2 echo "Error: $@" >&2
exit 1 exit 1
@ -312,11 +316,21 @@ cmd_build() {
echo "Built the Occlum image and enclave successfully" echo "Built the Occlum image and enclave successfully"
} }
cmd_run() { cmd_run() {
check_has_built check_has_built
check_has_run check_has_run
check_aesm_service 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) SGX_MODE=$(cat $instance_dir/.sgx_mode)
if [[ -n $SGX_MODE && "$SGX_MODE" != "HW" ]]; then if [[ -n $SGX_MODE && "$SGX_MODE" != "HW" ]]; then
export LD_LIBRARY_PATH="$instance_dir/build/lib:$SGX_SDK/sdk_libs/" 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 if [ "`get_enclave_debuggable_flag`" == "false" ]; then
export OCCLUM_RELEASE_ENCLAVE=1 export OCCLUM_RELEASE_ENCLAVE=1
fi fi
if [ "`get_enclave_enable_kss_flag`" == "true" ]; then
export OCCLUM_ENABLE_KSS=1
fi
RUST_BACKTRACE=1 "$instance_dir/build/bin/occlum-run" "$@" RUST_BACKTRACE=1 "$instance_dir/build/bin/occlum-run" "$@"
echo "built" > $status_file echo "built" > $status_file
@ -338,6 +357,15 @@ cmd_start() {
check_has_built check_has_built
check_aesm_service 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) SGX_MODE=$(cat $instance_dir/.sgx_mode)
if [[ -n $SGX_MODE && "$SGX_MODE" != "HW" ]]; then if [[ -n $SGX_MODE && "$SGX_MODE" != "HW" ]]; then
export LD_LIBRARY_PATH="$instance_dir/build/lib:$SGX_SDK/sdk_libs/" 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 if [ "`get_enclave_debuggable_flag`" == "false" ]; then
export OCCLUM_RELEASE_ENCLAVE=1 export OCCLUM_RELEASE_ENCLAVE=1
fi 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 RUST_BACKTRACE=1 "$instance_dir/build/bin/occlum_exec_client" start
echo "built" > $status_file echo "built" > $status_file
@ -565,7 +597,7 @@ case "$cmd" in
cmd_run "${@:2}" cmd_run "${@:2}"
;; ;;
start) start)
cmd_start cmd_start "${@:2}"
;; ;;
exec) exec)
cmd_exec "${@:2}" cmd_exec "${@:2}"