Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support SGX extended product ID #903

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CI-Examples/kss-helloworld/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/kss-helloworld
/*.o
/OUTPUT
64 changes: 64 additions & 0 deletions CI-Examples/kss-helloworld/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
GRAMINEDIR ?= ../..
RA_TYPE ?= dcap

CFLAGS = -Wall -Wextra -I$(GRAMINEDIR)/pal/src/host/linux-sgx

ifeq ($(DEBUG),1)
GRAMINE_LOG_LEVEL = debug
CFLAGS += -g
else
GRAMINE_LOG_LEVEL = error
CFLAGS += -O3
endif

.PHONY: all
all: kss-helloworld.manifest.sgx kss-helloworld.sig kss-helloworld.token

kss-helloworld: kss-helloworld.o

kss-helloworld.o: kss-helloworld.c

kss-helloworld.manifest: kss-helloworld.manifest.template
gramine-manifest \
-Dlog_level=$(GRAMINE_LOG_LEVEL) \
-Dra_type=$(RA_TYPE) \
$< $@

# gramine-sgx-sign generates both a .sig file and a .manifest.sgx file. This is somewhat
# hard to express properly in Make. The simple solution would be to use
# "Rules with Grouped Targets" (`&:`), however make on Ubuntu <= 20.04 doesn't support it.
#
# Simply using a normal rule with "two targets" is equivalent to creating separate rules
# for each of the targets, and when using `make -j`, this might cause two instances
# of gramine-sgx-sign to get launched simultaneously, potentially breaking the build.
#
# As a workaround, we use a dummy intermediate target, and mark both files as depending on it, to
# get the dependency graph we want. We mark this dummy target as .INTERMEDIATE, which means
# that make will consider the source tree up-to-date even if the sgx_sign file doesn't exist,
# as long as the other dependencies check out. This is in contrast to .PHONY, which would
# be rebuilt on every invocation of make.
kss-helloworld.sig kss-helloworld.manifest.sgx: sgx_sign
@:

.INTERMEDIATE: sgx_sign
sgx_sign: kss-helloworld.manifest kss-helloworld
gramine-sgx-sign \
--manifest $< \
--output $<.sgx

kss-helloworld.token: kss-helloworld.sig
gramine-sgx-get-token \
--output $@ --sig $<

GRAMINE = gramine-sgx

.PHONY: check
check: all
$(GRAMINE) kss-helloworld

.PHONY: clean
clean:
$(RM) *.token *.sig *.manifest.sgx *.manifest kss-helloworld.o kss-helloworld OUTPUT

.PHONY: distclean
distclean: clean
24 changes: 24 additions & 0 deletions CI-Examples/kss-helloworld/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# KSS Hello World

This directory contains a Makefile and a manifest template for running a simple
"Hello World" program with KSS in Gramine. It is built with KSS support and non-zero
values for `isvextprodid` and `isvfamilyid`, which are printed by the enclave.
report.

This example is SGX-specific.

# Build

Run `make` (non-debug) or `make DEBUG=1` (debug) in the directory.

Remote attestation must be supported to run this test. Default attestation type is `dcap`.
It can be modified with the `RA_TYPE` flag in make. For example: `make RA_TYPE=epid`.

# Run

```sh
gramine-sgx ./kss-helloworld
```

Note that a platform with KSS support must be used, otherwise this example will not work.
Use `is-sgx-available` tool to determine if the platform supports KSS.
63 changes: 63 additions & 0 deletions CI-Examples/kss-helloworld/kss-helloworld.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "sgx_arch.h"

#define MAX_DIGITS (256ULL) // Should be more than enough to contain all buffers

static void blob2hex(const void* input, size_t len, char* output) {
static const char digits[] = "0123456789abcdef";
for(size_t i=0;i<len;i++) {
uint8_t byte = *((uint8_t *) input + i);
output[2*i] = digits[byte >> 4];
output[2*i+1] = digits[byte & 0xf];
}
output[2*len + 1] = 0;
}

int main(void) {
char print_buffer[MAX_DIGITS];
FILE* attestation_type_fd = NULL;
FILE* report_fd = NULL;
sgx_report_t report;

attestation_type_fd = fopen("/dev/attestation/attestation_type", "rb");
if(attestation_type_fd == NULL) {
fprintf(stderr, "Failed to open attestation type handle\n");
return 1;
}
if(fread(print_buffer, 1, sizeof(print_buffer), attestation_type_fd) <= 0) {
fprintf(stderr, "Failed to read attestation type\n");
return 2;
}
// Report handles are loaded only if remote attestation is enabled
if(strcmp(print_buffer, "none") == 0) {
fprintf(stderr, "Must be built with remote attestation\n");
return 3;
}
fclose(attestation_type_fd);

// We only care about this enclave's attributes, so we omit report data and target info
report_fd = fopen("/dev/attestation/report", "rb");
if(report_fd == NULL) {
fprintf(stderr, "Failed to open report handle\n");
return 4;
}
if(fread(&report, sizeof(report), 1, report_fd) <= 0) {
fprintf(stderr, "Failed to read report\n");
return 5;
}
fclose(report_fd);

printf("isvprodid = %04x\n", report.body.isv_prod_id);
printf("isvsvn = %d\n", report.body.isv_svn);
blob2hex(report.body.isv_ext_prod_id, sizeof(report.body.isv_ext_prod_id), print_buffer);
printf("isvextprodid = %s\n", print_buffer);
blob2hex(report.body.isv_family_id, sizeof(report.body.isv_family_id), print_buffer);
printf("isvfamilyid = %s\n", print_buffer);
blob2hex(report.body.config_id.data, sizeof(report.body.config_id.data), print_buffer);
printf("configid = %s\n", print_buffer);
printf("configsvn = %d\n", report.body.config_svn);
return 0;
}
29 changes: 29 additions & 0 deletions CI-Examples/kss-helloworld/kss-helloworld.manifest.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Hello World manifest file example

loader.entrypoint = "file:{{ gramine.libos }}"
libos.entrypoint = "/kss-helloworld"
loader.log_level = "{{ log_level }}"

loader.env.LD_LIBRARY_PATH = "/lib"

fs.mounts = [
{ path = "/lib", uri = "file:{{ gramine.runtimedir() }}" },
{ path = "/kss-helloworld", uri = "file:kss-helloworld" },
]

sgx.debug = true
sgx.nonpie_binary = true

sgx.remote_attestation = "{{ ra_type }}"

sgx.kss = true
sgx.isvprodid = 5
sgx.isvsvn = 2
sgx.isvfamilyid = "0x00112233445566778899aabbccddeeff"
sgx.isvextprodid = "0xcafef00dcafef00df00dcafef00dcafe"

sgx.trusted_files = [
"file:{{ gramine.libos }}",
"file:kss-helloworld",
"file:{{ gramine.runtimedir() }}/",
]
19 changes: 19 additions & 0 deletions CI-Examples/kss-helloworld/run_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash

set -e

# Default is SGX, because this test is SGX-specific
if test -n "$DIRECT"
then
GRAMINE=gramine-direct
else
GRAMINE=gramine-sgx
fi

echo Running kss-helloworld
$GRAMINE ./kss-helloworld > OUTPUT
grep -q 'isvprodid = 0005' OUTPUT && echo '[ Success 1/4 ]'
grep -q 'isvsvn = 2' OUTPUT && echo '[ Success 2/4 ]'
grep -q 'isvextprodid = cafef00dcafef00df00dcafef00dcafe' OUTPUT && echo '[ Success 3/4 ]'
grep -q 'isvfamilyid = 00112233445566778899aabbccddeeff' OUTPUT && echo '[ Success 4/4 ]'
rm OUTPUT
13 changes: 13 additions & 0 deletions Documentation/manifest-syntax.rst
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,19 @@ ISV Product ID and SVN
This syntax specifies the ISV Product ID and SVN to be added to the enclave
signature.

Extended ISV Product ID (KSS)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

::

sgx.kss = [true|false] (default: false)
sgx.isvextprodid = "[16-byte hex value]" (default: "0x00000000000000000000000000000000")
sgx.isvfamily = "[16-byte hex value]" (default: "0x00000000000000000000000000000000")

If ``sgx.kss = true``, this syntax specifies the extended ISV product ID and family ID to be added to the
enclave signature. The platform must support KSS to launch the enclave.
Otherwise, these two fields are ignored and remain zero.

Attribute masks for SGX sealing key derivation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
2 changes: 2 additions & 0 deletions pal/src/host/linux-sgx/enclave_framework.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ static void print_report(sgx_report_t* r) {
log_debug(" attr.xfrm: %016lx", r->body.attributes.xfrm);
log_debug(" isv_prod_id: %02x", r->body.isv_prod_id);
log_debug(" isv_svn: %02x", r->body.isv_svn);
log_debug(" isv_ext_prod_id: %s", BYTES2HEX(r->body.isv_ext_prod_id));
log_debug(" isv_family_id: %s", BYTES2HEX(r->body.isv_family_id));
log_debug(" report_data: %s", BYTES2HEX(r->body.report_data.d));
log_debug(" key_id: %s", BYTES2HEX(r->key_id.id));
log_debug(" mac: %s", BYTES2HEX(r->mac));
Expand Down
1 change: 1 addition & 0 deletions pal/src/host/linux-sgx/generated_offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const struct generated_offset generated_offsets[] = {
/* defines from sgx_arch.h */
DEFINE(SGX_FLAGS_DEBUG, SGX_FLAGS_DEBUG),
DEFINE(SGX_FLAGS_MODE64BIT, SGX_FLAGS_MODE64BIT),
DEFINE(SGX_FLAGS_KSS, SGX_FLAGS_KSS),
DEFINE(SGX_XFRM_LEGACY, SGX_XFRM_LEGACY),
DEFINE(SGX_XFRM_AVX, SGX_XFRM_AVX),
DEFINE(SGX_XFRM_MPX, SGX_XFRM_MPX),
Expand Down
1 change: 1 addition & 0 deletions pal/src/host/linux-sgx/sgx_arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ typedef uint8_t sgx_isvfamily_id_t[SGX_ISV_FAMILY_ID_SIZE];
#define SGX_FLAGS_MODE64BIT 0x04ULL
#define SGX_FLAGS_PROVISION_KEY 0x10ULL
#define SGX_FLAGS_LICENSE_KEY 0x20ULL
#define SGX_FLAGS_KSS 0x80ULL

/* EINIT must verify *all* SECS.ATTRIBUTES[63..0] bits (FLAGS bits) against
* SIGSTRUCT.ATTRIBUTES[63..0].
Expand Down
3 changes: 3 additions & 0 deletions python/graminelibos/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ def __init__(self, manifest_str):

sgx.setdefault('isvprodid', 0)
sgx.setdefault('isvsvn', 0)
sgx.setdefault('kss', False)
sgx.setdefault('isvextprodid', 0)
sgx.setdefault('isvfamilyid', 0)
sgx.setdefault('remote_attestation', "none")
sgx.setdefault('debug', False)
sgx.setdefault('require_avx', False)
Expand Down
4 changes: 4 additions & 0 deletions python/graminelibos/sgx_sign.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def collect_bits(manifest_sgx, options_dict):
def get_enclave_attributes(manifest_sgx):
flags_dict = {
'debug': offs.SGX_FLAGS_DEBUG,
'kss': offs.SGX_FLAGS_KSS,
}

xfrms_dict = {
Expand Down Expand Up @@ -539,6 +540,9 @@ def get_tbssigstruct(manifest_path, date, libpal=SGX_LIBPAL, verbose=False):
sig['attribute_flags'] = attribute_flags
sig['attribute_xfrms'] = attribute_xfrms
sig['misc_select'] = misc_select
if attribute_flags & offs.SGX_FLAGS_KSS:
sig['isv_ext_prod_id'] = int(manifest_sgx['isvextprodid'], 16).to_bytes(16, 'big')
sig['isv_family_id'] = int(manifest_sgx['isvfamilyid'], 16).to_bytes(16, 'big')

return sig

Expand Down
4 changes: 4 additions & 0 deletions python/graminelibos/sigstruct.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class Sigstruct:
'attribute_xfrm_mask': (offs.SGX_ARCH_SIGSTRUCT_ATTRIBUTE_MASK + 8, '<Q'),
'enclave_hash': (offs.SGX_ARCH_SIGSTRUCT_ENCLAVE_HASH, '32s'),
'isv_prod_id': (offs.SGX_ARCH_SIGSTRUCT_ISV_PROD_ID, '<H'),
'isv_ext_prod_id': (offs.SGX_ARCH_SIGSTRUCT_ISVEXT_PROD_ID, '<16s'),
'isv_family_id': (offs.SGX_ARCH_SIGSTRUCT_ISV_FAMILY_ID, '<16s'),
'isv_svn': (offs.SGX_ARCH_SIGSTRUCT_ISV_SVN, '<H'),
'q1': (offs.SGX_ARCH_SIGSTRUCT_Q1, '384s'),
'q2': (offs.SGX_ARCH_SIGSTRUCT_Q2, '384s'),
Expand All @@ -48,6 +50,8 @@ class Sigstruct:
'misc_mask': offs.SGX_MISCSELECT_MASK_CONST,
'attribute_flags_mask': offs.SGX_FLAGS_MASK_CONST,
'attribute_xfrm_mask': offs.SGX_XFRM_MASK_CONST,
'isv_ext_prod_id': b'\x00' * 16,
'isv_family_id': b'\x00' * 16,
}


Expand Down