未验证 提交 174504be 编写于 作者: W wangxiaozhe 提交者: GitHub

rune/libenclave: Refresh skeleton example

This new implementation inspires the design of https://github.com/jsakkine-intel/linux-sgx/tree/next/tools/testing/selftests/x86/sgx, which is a real enclave runtime.
Signed-off-by: Njack.wxz <wangxiaozhe@linux.alibaba.com>
上级 15f17876
......@@ -44,7 +44,7 @@ recvtty:
skeleton: libenclave/internal/runtime/pal/skeleton/liberpal-skeleton.so
libenclave/internal/runtime/pal/skeleton/liberpal-skeleton.so:
gcc -fPIC -shared -Wall -Wno-unused-const-variable -Ilibenclave/pal -o $@ libenclave/internal/runtime/pal/skeleton/liberpal-skeleton.c
make -C libenclave/internal/runtime/pal/skeleton
static:
$(GO_BUILD_STATIC) -o rune .
......@@ -125,7 +125,7 @@ clean:
rm -rf release
rm -rf man/man8
rm -f libenclave/proto/*.pb.go
rm -f libenclave/internal/runtime/pal/skeleton/liberpal-skeleton.so
make -C libenclave/internal/runtime/pal/skeleton clean
validate:
script/validate-gofmt
......
ifndef OBJCOPY
OBJCOPY := $(CROSS_COMPILE)objcopy
endif
OUTPUT ?= ./
HOST_CFLAGS := -Wall -Werror -g -fPIC -z noexecstack \
-Wno-unused-const-variable
ENCL_CFLAGS := -Wall -Werror -static -nostdlib -nostartfiles -fPIC \
-fno-stack-protector -mrdrnd
HOST_LDFLAGS := -fPIC -shared
TEST_CUSTOM_PROGS := $(OUTPUT)/encl.bin $(OUTPUT)/encl.ss $(OUTPUT)/liberpal-skeleton.so $(OUTPUT)/signing_key.pem $(OUTPUT)/encl.token
all: $(TEST_CUSTOM_PROGS)
$(OUTPUT)/liberpal-skeleton.so: $(OUTPUT)/sgx_call.o $(OUTPUT)/liberpal-skeleton.o
$(CC) $(HOST_LDFLAGS) -o $@ $^
$(OUTPUT)/liberpal-skeleton.o: liberpal-skeleton.c
$(CC) $(HOST_CFLAGS) -c $< -o $@
$(OUTPUT)/sgx_call.o: sgx_call.S
$(CC) $(HOST_CFLAGS) -c $< -o $@
$(OUTPUT)/encl.bin: $(OUTPUT)/encl.elf $(OUTPUT)/sgxsign
$(OBJCOPY) -O binary $< $@
$(OUTPUT)/encl.elf: encl.lds encl.c encl_bootstrap.S
$(CC) $(ENCL_CFLAGS) -T $^ -o $@
$(OUTPUT)/signing_key.pem:
openssl genrsa -3 -out $@ 3072
$(OUTPUT)/encl.ss: $(OUTPUT)/encl.bin $(OUTPUT)/signing_key.pem
$(OUTPUT)/sgxsign signing_key.pem $(OUTPUT)/encl.bin $(OUTPUT)/encl.ss
$(OUTPUT)/encl.token: $(OUTPUT)/encl.ss
runectl gen-token --signature encl.ss --token $@
$(OUTPUT)/sgxsign: sgxsign.c
$(CC) -I../include -o $@ $< -lcrypto
EXTRA_CLEAN := \
$(OUTPUT)/encl.bin \
$(OUTPUT)/encl.elf \
$(OUTPUT)/encl.ss \
$(OUTPUT)/sgx_call.o \
$(OUTPUT)/sgxsign \
$(OUTPUT)/liberpal-skeleton.o \
$(OUTPUT)/liberpal-skeleton.so \
$(OUTPUT)/signing_key.pem \
$(OUTPUT)/encl.token
clean:
rm -f ${EXTRA_CLEAN}
.PHONY: clean all
The files in this directory are used to implement a skeleton enclave runtime,
in order to help to write your own enclave runtime.
# Install runectl
Refer to this document:[runectl](https://github.com/alibaba/inclavare-containers/tree/master/runectl)
# Build liberpal-skeleton.so
```shell
cd "$GOPATH/src/github.com/alibaba/inclavare-containers/rune"
......
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/**
* Copyright(c) 2016-18 Intel Corporation.
*
* Contains data structures defined by the SGX architecture. Data structures
* defined by the Linux software stack should not be placed here.
*
* Inspired by https://github.com/jsakkine-intel/linux-sgx/tree/next/tools/testing/selftests/x86/sgx
*/
#ifndef _ASM_X86_SGX_ARCH_H
#define _ASM_X86_SGX_ARCH_H
#include <linux/types.h>
#define SGX_CPUID 0x12
#define SGX_CPUID_FIRST_VARIABLE_SUB_LEAF 2
#ifndef BIT
#define BIT(nr) (1UL << (nr))
#endif
/**
* enum sgx_return_code - The return code type for ENCLS, ENCLU and ENCLV
* %SGX_NOT_TRACKED: Previous ETRACK's shootdown sequence has not
* been completed yet.
* %SGX_INVALID_EINITTOKEN: EINITTOKEN is invalid and enclave signer's
* public key does not match IA32_SGXLEPUBKEYHASH.
* %SGX_UNMASKED_EVENT: An unmasked event, e.g. INTR, was received
*/
enum sgx_return_code {
SGX_NOT_TRACKED = 11,
SGX_INVALID_EINITTOKEN = 16,
SGX_UNMASKED_EVENT = 128,
};
/**
* enum sgx_sub_leaf_types - SGX CPUID variable sub-leaf types
* %SGX_CPUID_SUB_LEAF_INVALID: Indicates this sub-leaf is invalid.
* %SGX_CPUID_SUB_LEAF_EPC_SECTION: Sub-leaf enumerates an EPC section.
*/
enum sgx_sub_leaf_types {
SGX_CPUID_SUB_LEAF_INVALID = 0x0,
SGX_CPUID_SUB_LEAF_EPC_SECTION = 0x1,
};
#define SGX_CPUID_SUB_LEAF_TYPE_MASK GENMASK(3, 0)
#define SGX_MODULUS_SIZE 384
/**
* enum sgx_miscselect - additional information to an SSA frame
* %SGX_MISC_EXINFO: Report #PF or #GP to the SSA frame.
*
* Save State Area (SSA) is a stack inside the enclave used to store processor
* state when an exception or interrupt occurs. This enum defines additional
* information stored to an SSA frame.
*/
enum sgx_miscselect {
SGX_MISC_EXINFO = BIT(0),
};
#define SGX_MISC_RESERVED_MASK GENMASK_ULL(63, 1)
#define SGX_SSA_GPRS_SIZE 184
#define SGX_SSA_MISC_EXINFO_SIZE 16
/**
* enum sgx_attributes - the attributes field in &struct sgx_secs
* %SGX_ATTR_INIT: Enclave can be entered (is initialized).
* %SGX_ATTR_DEBUG: Allow ENCLS(EDBGRD) and ENCLS(EDBGWR).
* %SGX_ATTR_MODE64BIT: Tell that this a 64-bit enclave.
* %SGX_ATTR_PROVISIONKEY: Allow to use provisioning keys for remote
* attestation.
* %SGX_ATTR_KSS: Allow to use key separation and sharing (KSS).
* %SGX_ATTR_EINITTOKENKEY: Allow to use token signing key that is used to
* sign cryptographic tokens that can be passed to
* EINIT as an authorization to run an enclave.
*/
enum sgx_attribute {
SGX_ATTR_INIT = BIT(0),
SGX_ATTR_DEBUG = BIT(1),
SGX_ATTR_MODE64BIT = BIT(2),
SGX_ATTR_PROVISIONKEY = BIT(4),
SGX_ATTR_EINITTOKENKEY = BIT(5),
SGX_ATTR_KSS = BIT(7),
};
#define SGX_ATTR_RESERVED_MASK (BIT_ULL(3) | BIT_ULL(6) | GENMASK_ULL(63, 8))
#define SGX_ATTR_ALLOWED_MASK (SGX_ATTR_DEBUG | SGX_ATTR_MODE64BIT | \
SGX_ATTR_KSS)
/**
* struct sgx_secs - SGX Enclave Control Structure (SECS)
* @size: size of the address space
* @base: base address of the address space
* @ssa_frame_size: size of an SSA frame
* @miscselect: additional information stored to an SSA frame
* @attributes: attributes for enclave
* @xfrm: XSave-Feature Request Mask (subset of XCR0)
* @mrenclave: SHA256-hash of the enclave contents
* @mrsigner: SHA256-hash of the public key used to sign the SIGSTRUCT
* @config_id: a user-defined value that is used in key derivation
* @isv_prod_id: a user-defined value that is used in key derivation
* @isv_svn: a user-defined value that is used in key derivation
* @config_svn: a user-defined value that is used in key derivation
*
* SGX Enclave Control Structure (SECS) is a special enclave page that is not
* visible in the address space. In fact, this structure defines the address
* range and other global attributes for the enclave and it is the first EPC
* page created for any enclave. It is moved from a temporary buffer to an EPC
* by the means of ENCLS(ECREATE) leaf.
*/
struct sgx_secs {
uint64_t size;
uint64_t base;
uint32_t ssa_frame_size;
uint32_t miscselect;
uint8_t reserved1[24];
uint64_t attributes;
uint64_t xfrm;
uint32_t mrenclave[8];
uint8_t reserved2[32];
uint32_t mrsigner[8];
uint8_t reserved3[32];
uint32_t config_id[16];
uint16_t isv_prod_id;
uint16_t isv_svn;
uint16_t config_svn;
uint8_t reserved4[3834];
} __packed;
/**
* enum sgx_tcs_flags - execution flags for TCS
* %SGX_TCS_DBGOPTIN: If enabled allows single-stepping and breakpoints
* inside an enclave. It is cleared by EADD but can
* be set later with EDBGWR.
*/
enum sgx_tcs_flags {
SGX_TCS_DBGOPTIN = 0x01,
};
#define SGX_TCS_RESERVED_MASK GENMASK_ULL(63, 1)
#define SGX_TCS_RESERVED_SIZE 4024
/**
* struct sgx_tcs - Thread Control Structure (TCS)
* @state: used to mark an entered TCS
* @flags: execution flags (cleared by EADD)
* @ssa_offset: SSA stack offset relative to the enclave base
* @ssa_index: the current SSA frame index (cleard by EADD)
* @nr_ssa_frames: the number of frame in the SSA stack
* @entry_offset: entry point offset relative to the enclave base
* @exit_addr: address outside the enclave to exit on an exception or
* interrupt
* @fs_offset: offset relative to the enclave base to become FS
* segment inside the enclave
* @gs_offset: offset relative to the enclave base to become GS
* segment inside the enclave
* @fs_limit: size to become a new FS-limit (only 32-bit enclaves)
* @gs_limit: size to become a new GS-limit (only 32-bit enclaves)
*
* Thread Control Structure (TCS) is an enclave page visible in its address
* space that defines an entry point inside the enclave. A thread enters inside
* an enclave by supplying address of TCS to ENCLU(EENTER). A TCS can be entered
* by only one thread at a time.
*/
struct sgx_tcs {
uint64_t state;
uint64_t flags;
uint64_t ssa_offset;
uint32_t ssa_index;
uint32_t nr_ssa_frames;
uint64_t entry_offset;
uint64_t exit_addr;
uint64_t fs_offset;
uint64_t gs_offset;
uint32_t fs_limit;
uint32_t gs_limit;
uint8_t reserved[SGX_TCS_RESERVED_SIZE];
} __packed;
/**
* struct sgx_pageinfo - an enclave page descriptor
* @addr: address of the enclave page
* @contents: pointer to the page contents
* @metadata: pointer either to a SECINFO or PCMD instance
* @secs: address of the SECS page
*/
struct sgx_pageinfo {
uint64_t addr;
uint64_t contents;
uint64_t metadata;
uint64_t secs;
} __packed __aligned(32);
/**
* enum sgx_page_type - bits in the SECINFO flags defining the page type
* %SGX_PAGE_TYPE_SECS: a SECS page
* %SGX_PAGE_TYPE_TCS: a TCS page
* %SGX_PAGE_TYPE_REG: a regular page
* %SGX_PAGE_TYPE_VA: a VA page
* %SGX_PAGE_TYPE_TRIM: a page in trimmed state
*/
enum sgx_page_type {
SGX_PAGE_TYPE_SECS,
SGX_PAGE_TYPE_TCS,
SGX_PAGE_TYPE_REG,
SGX_PAGE_TYPE_VA,
SGX_PAGE_TYPE_TRIM,
};
#define SGX_NR_PAGE_TYPES 5
#define SGX_PAGE_TYPE_MASK GENMASK(7, 0)
/**
* enum sgx_secinfo_flags - the flags field in &struct sgx_secinfo
* %SGX_SECINFO_R: allow read
* %SGX_SECINFO_W: allow write
* %SGX_SECINFO_X: allow execution
* %SGX_SECINFO_SECS: a SECS page
* %SGX_SECINFO_TCS: a TCS page
* %SGX_SECINFO_REG: a regular page
* %SGX_SECINFO_VA: a VA page
* %SGX_SECINFO_TRIM: a page in trimmed state
*/
enum sgx_secinfo_flags {
SGX_SECINFO_R = BIT(0),
SGX_SECINFO_W = BIT(1),
SGX_SECINFO_X = BIT(2),
SGX_SECINFO_SECS = (SGX_PAGE_TYPE_SECS << 8),
SGX_SECINFO_TCS = (SGX_PAGE_TYPE_TCS << 8),
SGX_SECINFO_REG = (SGX_PAGE_TYPE_REG << 8),
SGX_SECINFO_VA = (SGX_PAGE_TYPE_VA << 8),
SGX_SECINFO_TRIM = (SGX_PAGE_TYPE_TRIM << 8),
};
#define SGX_SECINFO_PERMISSION_MASK GENMASK_ULL(2, 0)
#define SGX_SECINFO_PAGE_TYPE_MASK (SGX_PAGE_TYPE_MASK << 8)
#define SGX_SECINFO_RESERVED_MASK ~(SGX_SECINFO_PERMISSION_MASK | \
SGX_SECINFO_PAGE_TYPE_MASK)
/**
* struct sgx_secinfo - describes attributes of an EPC page
* @flags: permissions and type
*
* Used together with ENCLS leaves that add or modify an EPC page to an
* enclave to define page permissions and type.
*/
struct sgx_secinfo {
uint64_t flags;
uint8_t reserved[56];
} __packed __aligned(64);
#define SGX_PCMD_RESERVED_SIZE 40
/**
* struct sgx_pcmd - Paging Crypto Metadata (PCMD)
* @enclave_id: enclave identifier
* @mac: MAC over PCMD, page contents and isvsvn
*
* PCMD is stored for every swapped page to the regular memory. When ELDU loads
* the page back it recalculates the MAC by using a isvsvn number stored in a
* VA page. Together these two structures bring integrity and rollback
* protection.
*/
struct sgx_pcmd {
struct sgx_secinfo secinfo;
uint64_t enclave_id;
uint8_t reserved[SGX_PCMD_RESERVED_SIZE];
uint8_t mac[16];
} __packed __aligned(128);
#define SGX_SIGSTRUCT_RESERVED1_SIZE 84
#define SGX_SIGSTRUCT_RESERVED2_SIZE 20
#define SGX_SIGSTRUCT_RESERVED3_SIZE 32
#define SGX_SIGSTRUCT_RESERVED4_SIZE 12
/**
* struct sgx_sigstruct_header - defines author of the enclave
* @header1: constant byte string
* @vendor: must be either 0x0000 or 0x8086
* @date: YYYYMMDD in BCD
* @header2: costant byte string
* @swdefined: software defined value
*/
struct sgx_sigstruct_header {
uint64_t header1[2];
uint32_t vendor;
uint32_t date;
uint64_t header2[2];
uint32_t swdefined;
uint8_t reserved1[84];
} __packed;
/**
* struct sgx_sigstruct_body - defines contents of the enclave
* @miscselect: additional information stored to an SSA frame
* @misc_mask: required miscselect in SECS
* @attributes: attributes for enclave
* @xfrm: XSave-Feature Request Mask (subset of XCR0)
* @attributes_mask: required attributes in SECS
* @xfrm_mask: required XFRM in SECS
* @mrenclave: SHA256-hash of the enclave contents
* @isvprodid: a user-defined value that is used in key derivation
* @isvsvn: a user-defined value that is used in key derivation
*/
struct sgx_sigstruct_body {
uint32_t miscselect;
uint32_t misc_mask;
uint8_t reserved2[20];
uint64_t attributes;
uint64_t xfrm;
uint64_t attributes_mask;
uint64_t xfrm_mask;
uint8_t mrenclave[32];
uint8_t reserved3[32];
uint16_t isvprodid;
uint16_t isvsvn;
} __packed;
/**
* struct sgx_sigstruct - an enclave signature
* @header: defines author of the enclave
* @modulus: the modulus of the public key
* @exponent: the exponent of the public key
* @signature: the signature calculated over the fields except modulus,
* @body: defines contents of the enclave
* @q1: a value used in RSA signature verification
* @q2: a value used in RSA signature verification
*
* Header and body are the parts that are actual signed. The remaining fields
* define the signature of the enclave.
*/
struct sgx_sigstruct {
struct sgx_sigstruct_header header;
uint8_t modulus[SGX_MODULUS_SIZE];
uint32_t exponent;
uint8_t signature[SGX_MODULUS_SIZE];
struct sgx_sigstruct_body body;
uint8_t reserved4[12];
uint8_t q1[SGX_MODULUS_SIZE];
uint8_t q2[SGX_MODULUS_SIZE];
} __packed;
struct sgx_einittoken_payload {
uint32_t valid;
uint32_t reserved1[11];
uint64_t attributes;
uint64_t xfrm;
uint8_t mrenclave[32];
uint8_t reserved2[32];
uint8_t mrsigner[32];
uint8_t reserved3[32];
};
struct sgx_einittoken {
struct sgx_einittoken_payload payload;
uint8_t cpusvnle[16];
uint16_t isvprodidle;
uint16_t isvsvnle;
uint8_t reserved2[24];
uint32_t maskedmiscselectle;
uint64_t maskedattributesle;
uint64_t maskedxfrmle;
uint8_t keyid[32];
uint8_t mac[16];
};
#define SGX_LAUNCH_TOKEN_SIZE 304
#endif /* _ASM_X86_SGX_ARCH_H */
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright(c) 2016-19 Intel Corporation.
*/
#ifndef DEFINES_H
#define DEFINES_H
#include <stdint.h>
#define __aligned(x) __attribute__((__aligned__(x)))
#define __packed __attribute__((packed))
#include "arch.h"
#include "sgx.h"
#endif /* DEFINES_H */
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
// Copyright(c) 2016-18 Intel Corporation.
#include <stddef.h>
#include "defines.h"
static void *memcpy(void *dest, const void *src, size_t n)
{
size_t i;
for (i = 0; i < n; i++)
((char *)dest)[i] = ((char *)src)[i];
return dest;
}
void encl_body(void *rdi, void *rsi)
{
memcpy(rsi, rdi, 8);
}
OUTPUT_FORMAT(elf64-x86-64)
SECTIONS
{
. = 0;
.tcs : {
*(.tcs*)
}
. = ALIGN(4096);
.text : {
*(.text*)
*(.rodata*)
}
. = ALIGN(4096);
.data : {
*(.data*)
}
/DISCARD/ : {
*(.data*)
*(.comment*)
*(.note*)
*(.debug*)
*(.eh_frame*)
}
}
ASSERT(!DEFINED(.altinstructions), "ALTERNATIVES are not supported in enclaves")
ASSERT(!DEFINED(.altinstr_replacement), "ALTERNATIVES are not supported in enclaves")
ASSERT(!DEFINED(.discard.retpoline_safe), "RETPOLINE ALTERNATIVES are not supported in enclaves")
ASSERT(!DEFINED(.discard.nospec), "RETPOLINE ALTERNATIVES are not supported in enclaves")
ASSERT(!DEFINED(.got.plt), "Libcalls are not supported in enclaves")
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* Copyright(c) 2016-18 Intel Corporation.
*/
.macro ENCLU
.byte 0x0f, 0x01, 0xd7
.endm
.section ".tcs", "a"
.balign 4096
.fill 1, 8, 0 # STATE (set by CPU)
.fill 1, 8, 0 # FLAGS
.quad encl_ssa # OSSA
.fill 1, 4, 0 # CSSA (set by CPU)
.fill 1, 4, 1 # NSSA
.quad encl_entry # OENTRY
.fill 1, 8, 0 # AEP (set by EENTER and ERESUME)
.fill 1, 8, 0 # OFSBASE
.fill 1, 8, 0 # OGSBASE
.fill 1, 4, 0xFFFFFFFF # FSLIMIT
.fill 1, 4, 0xFFFFFFFF # GSLIMIT
.fill 4024, 1, 0 # Reserved
.text
encl_entry:
# RBX contains the base address for TCS, which is also the first address
# inside the enclave. By adding the value of le_stack_end to it, we get
# the absolute address for the stack.
lea (encl_stack)(%rbx), %rax
xchg %rsp, %rax
push %rax
push %rcx # push the address after EENTER
push %rbx # push the enclave base address
call encl_body
pop %rbx # pop the enclave base address
# Restore XSAVE registers to a synthetic state.
mov $0xFFFFFFFF, %rax
mov $0xFFFFFFFF, %rdx
lea (xsave_area)(%rbx), %rdi
fxrstor (%rdi)
# Clear GPRs.
xor %rcx, %rcx
xor %rdx, %rdx
xor %rdi, %rdi
xor %rsi, %rsi
xor %r8, %r8
xor %r9, %r9
xor %r10, %r10
xor %r11, %r11
xor %r12, %r12
xor %r13, %r13
xor %r14, %r14
xor %r15, %r15
# Reset status flags.
add %rdx, %rdx # OF = SF = AF = CF = 0; ZF = PF = 1
# Prepare EEXIT target by popping the address of the instruction after
# EENTER to RBX.
pop %rbx
# Restore the caller stack.
pop %rax
mov %rax, %rsp
# EEXIT
mov $4, %rax
enclu
.section ".data", "aw"
encl_ssa:
.space 4096
xsave_area:
.fill 1, 4, 0x037F # FCW
.fill 5, 4, 0
.fill 1, 4, 0x1F80 # MXCSR
.fill 1, 4, 0xFFFF # MXCSR_MASK
.fill 123, 4, 0
.fill 1, 4, 0x80000000 # XCOMP_BV[63] = 1, compaction mode
.fill 12, 4, 0
.balign 4096
.space 8192
encl_stack:
#include <stdio.h>
#include <unistd.h>
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
// Copyright(c) 2016-18 Intel Corporation.
#include <elf.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include "defines.h"
#include "sgx_call.h"
#define BUFF_LEN 1024
#define DEBUG_ARGS "debug"
#define PAGE_SIZE 4096
static const unsigned int skeleton_pal_version = 1;
#define SGX_REG_PAGE_FLAGS \
(SGX_SECINFO_REG | SGX_SECINFO_R | SGX_SECINFO_W | SGX_SECINFO_X)
static bool initialized = false;
static bool debug = false;
#define IMAGE "encl.bin"
#define SIGSTRUCT "encl.ss"
#define TOKEN "encl.token"
struct pal_attr_t {
const char *args;
......@@ -21,82 +36,252 @@ struct pal_stdio_fds {
int stdin, stdout, stderr;
};
int skeleton_pal_init(struct pal_attr_t *attr)
static const unsigned int skeleton_pal_version = 1;
static const uint64_t MAGIC = 0x1122334455667788ULL;
static struct sgx_secs secs;
static bool initialized = false;
static bool encl_create(int dev_fd, unsigned long bin_size,
struct sgx_secs *secs)
{
if (!attr->args)
return -ENOENT;
struct sgx_enclave_create ioc;
void *area;
int rc;
char *args = (char *)attr->args;
while ((args = strtok(args, " "))) {
if (!strcmp(args, DEBUG_ARGS))
debug = true;
args = NULL;
memset(secs, 0, sizeof(*secs));
secs->ssa_frame_size = 1;
secs->attributes = SGX_ATTR_MODE64BIT | SGX_ATTR_DEBUG;
secs->xfrm = 7;
for (secs->size = PAGE_SIZE; secs->size < bin_size; )
secs->size <<= 1;
area = mmap(NULL, secs->size * 2, PROT_NONE, MAP_SHARED, dev_fd, 0);
if (area == MAP_FAILED) {
perror("mmap");
return false;
}
initialized = true;
secs->base = ((uint64_t)area + secs->size - 1) & ~(secs->size - 1);
munmap(area, secs->base - (uint64_t)area);
munmap((void *)(secs->base + secs->size),
(uint64_t)area + secs->size - secs->base);
return 0;
if (mprotect((void *)secs->base, secs->size, PROT_READ | PROT_WRITE | PROT_EXEC)) {
perror("mprotect");
return false;
}
ioc.src = (unsigned long)secs;
rc = ioctl(dev_fd, SGX_IOC_ENCLAVE_CREATE, &ioc);
if (rc) {
fprintf(stderr, "ECREATE failed rc=%d, err=%d.\n", rc, errno);
munmap((void *)secs->base, secs->size);
return false;
}
return true;
}
int skeleton_pal_exec(char *path, char *argv[], struct pal_stdio_fds *stdio,
int *exit_code)
static bool encl_add_pages(int dev_fd, unsigned long addr, void *data,
unsigned long length, uint64_t flags)
{
if (!path || access(path, F_OK) != 0)
return -ENOENT;
struct sgx_enclave_add_page ioc;
struct sgx_secinfo secinfo;
int rc;
if (access(path, R_OK) != 0)
return -EACCES;
memset(&secinfo, 0, sizeof(secinfo));
secinfo.flags = flags;
if (!stdio)
return -EINVAL;
ioc.src = (uint64_t)data;
ioc.addr = addr;
ioc.secinfo = (unsigned long)&secinfo;
ioc.mrmask = (__u16)-1;
if (!exit_code)
return -EINVAL;
uint64_t added_size = 0;
while (added_size < length) {
rc = ioctl(dev_fd, SGX_IOC_ENCLAVE_ADD_PAGE, &ioc);
if (rc) {
fprintf(stderr, "EADD failed rc=%d.\n", rc);
return false;
}
if (!initialized) {
fprintf(stderr, "enclave runtime skeleton uninitialized yet!\n");
return -EINVAL;
ioc.addr += PAGE_SIZE;
ioc.src += PAGE_SIZE;
added_size += PAGE_SIZE;
}
int i;
return true;
}
if (debug) {
for (i = 0; argv[i]; ++i)
printf("argv[%d] = %s\n", i, argv[i]);
static bool encl_build(struct sgx_secs *secs, void *bin, unsigned long bin_size,
struct sgx_sigstruct *sigstruct,struct sgx_einittoken *token)
{
struct sgx_enclave_init ioc;
int dev_fd;
int rc;
dev_fd = open("/dev/isgx", O_RDWR);
if (dev_fd < 0) {
fprintf(stderr, "Unable to open /dev/sgx\n");
return false;
}
for (i = 0; i < 60; ++i) {
sleep(1);
if (stdio->stdout < 0 && debug) {
printf("pal_exec running %d seconds\n", i + 1);
} else {
char buf[BUFF_LEN];
if (!encl_create(dev_fd, bin_size, secs))
goto out_dev_fd;
ssize_t len;
if (debug)
len = snprintf(buf, BUFF_LEN, "pal_exec running %d seconds, "
"outputting to fd %d\n", i + 1, stdio->stdout);
else
len = snprintf(buf, BUFF_LEN, "%d", i + 1);
if (!encl_add_pages(dev_fd, secs->base + 0, bin, PAGE_SIZE, SGX_SECINFO_TCS))
goto out_dev_fd;
ssize_t bytes = 0;
while (bytes < len) {
ssize_t n = write(stdio->stdout, &buf[bytes], len - bytes);
if (n < 0) {
if (errno == EAGAIN || errno == EINTR)
continue;
if (!encl_add_pages(dev_fd, secs->base + PAGE_SIZE, bin + PAGE_SIZE,
bin_size - PAGE_SIZE, SGX_REG_PAGE_FLAGS))
goto out_dev_fd;
fprintf(stderr, "write failed\n");
return -1;
} else if (n == 0) {
fprintf(stderr, "stdout is EOF\n");
return -1;
} else
bytes += n;
ioc.addr = secs->base;
ioc.sigstruct = (uint64_t)sigstruct;
ioc.einittoken = (uint64_t)token;
rc = ioctl(dev_fd, SGX_IOC_ENCLAVE_INIT, &ioc);
if (rc) {
printf("EINIT failed rc=%d\n", rc);
goto out_map;
}
close(dev_fd);
return true;
out_map:
munmap((void *)secs->base, secs->size);
out_dev_fd:
close(dev_fd);
return false;
}
bool get_file_size(const char *path, off_t *bin_size)
{
struct stat sb;
int ret;
ret = stat(path, &sb);
if (ret) {
perror("stat");
return false;
}
if (!sb.st_size || sb.st_size & 0xfff) {
fprintf(stderr, "Invalid blob size %lu\n", sb.st_size);
return false;
}
*bin_size = sb.st_size;
return true;
}
bool encl_data_map(const char *path, void **bin, off_t *bin_size)
{
int fd;
fd = open(path, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "open() %s failed, errno=%d.\n", path, errno);
return false;
}
if (!get_file_size(path, bin_size))
goto err_out;
*bin = mmap(NULL, *bin_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (*bin == MAP_FAILED) {
fprintf(stderr, "mmap() %s failed, errno=%d.\n", path, errno);
goto err_out;
}
close(fd);
return true;
err_out:
close(fd);
return false;
}
bool load_sigstruct(const char *path, void *sigstruct)
{
int fd;
fd = open(path, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "open() %s failed, errno=%d.\n", path, errno);
return false;
}
if (read(fd, sigstruct, sizeof(struct sgx_sigstruct)) !=
sizeof(struct sgx_sigstruct)) {
fprintf(stderr, "read() %s failed, errno=%d.\n", path, errno);
close(fd);
return false;
}
close(fd);
return true;
}
bool load_token(const char *path, void *token)
{
int fd;
fd = open(path, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "open() %s failed, errno=%d.\n", path, errno);
return false;
}
if (read(fd, token, sizeof(struct sgx_einittoken)) !=
sizeof(struct sgx_einittoken)) {
fprintf(stderr, "read() %s failed, errno=%d.\n", path, errno);
close(fd);
return false;
}
close(fd);
return true;
}
int skeleton_pal_init(struct pal_attr_t *attr)
{
struct sgx_sigstruct sigstruct;
struct sgx_einittoken token;
off_t bin_size;
void *bin;
if (!encl_data_map(IMAGE, &bin, &bin_size))
return ENOENT;
if (!load_sigstruct(SIGSTRUCT, &sigstruct))
return ENOENT;
if (!load_token(TOKEN, &token))
return ENOENT;
if (!encl_build(&secs, bin, bin_size, &sigstruct, &token))
return EINVAL;
initialized = true;
return 0;
}
int skeleton_pal_exec(char *path, char *argv[], struct pal_stdio_fds *stdio,
int *exit_code)
{
uint64_t result = 0;
sgx_call_eenter((void *)&MAGIC, &result, (void *)secs.base);
if (result != MAGIC) {
fprintf(stderr, "0x%lx != 0x%lx\n", result, MAGIC);
return -1;
}
fprintf(stderr, "copy MAGIC with enclave sucess.\n");
*exit_code = 0;
return 0;
}
......@@ -106,7 +291,5 @@ int skeleton_pal_destroy(void)
fprintf(stderr, "enclave runtime skeleton uninitialized yet!\n");
return -1;
}
printf("enclave runtime skeleton exits\n");
return 0;
}
int pal_skeleton_init(char *instance_path);
int pal_skeleton_exec(char *path, char *argv[], int *exit_value,
int stdin_fd, int stdout_fd, int stderr_fd);
int pal_skeleton_kill(int sig, int pid);
int pal_skeleton_destroy();
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) WITH Linux-syscall-note */
/*
* Copyright(c) 2016-19 Intel Corporation.
*/
#ifndef _UAPI_ASM_X86_SGX_H
#define _UAPI_ASM_X86_SGX_H
#include <linux/types.h>
#include <linux/ioctl.h>
/**
* enum sgx_epage_flags - page control flags
* %SGX_PAGE_MEASURE: Measure the page contents with a sequence of
* ENCLS[EEXTEND] operations.
*/
enum sgx_page_flags {
SGX_PAGE_MEASURE = 0x01,
};
#define SGX_MAGIC 0xA4
#define SGX_IOC_ENCLAVE_CREATE \
_IOW(SGX_MAGIC, 0x00, struct sgx_enclave_create)
#define SGX_IOC_ENCLAVE_ADD_PAGES \
_IOWR(SGX_MAGIC, 0x01, struct sgx_enclave_add_pages)
#define SGX_IOC_ENCLAVE_INIT \
_IOW(SGX_MAGIC, 0x02, struct sgx_enclave_init)
#define SGX_IOC_ENCLAVE_SET_ATTRIBUTE \
_IOW(SGX_MAGIC, 0x03, struct sgx_enclave_set_attribute)
#define SGX_IOC_ENCLAVE_ADD_PAGE \
_IOW(SGX_MAGIC, 0x01, struct sgx_enclave_add_page)
/**
* struct sgx_enclave_create - parameter structure for the
* %SGX_IOC_ENCLAVE_CREATE ioctl
* @src: address for the SECS page data
*/
struct sgx_enclave_create {
__u64 src;
};
/**
* struct sgx_enclave_add_pages - parameter structure for the
* %SGX_IOC_ENCLAVE_ADD_PAGE ioctl
* @src: start address for the page data
* @offset: starting page offset
* @length: length of the data (multiple of the page size)
* @secinfo: address for the SECINFO data
* @flags: page control flags
* @count: number of bytes added (multiple of the page size)
*/
struct sgx_enclave_add_pages {
__u64 src;
__u64 offset;
__u64 length;
__u64 secinfo;
__u64 flags;
__u64 count;
};
struct sgx_enclave_add_page {
__u64 addr;
__u64 src;
__u64 secinfo;
__u16 mrmask;
} __attribute__((__packed__));
/**
* struct sgx_enclave_init - parameter structure for the
* %SGX_IOC_ENCLAVE_INIT ioctl
* @sigstruct: address for the SIGSTRUCT data
*/
struct sgx_enclave_init {
__u64 addr;
__u64 sigstruct;
__u64 einittoken;
} __attribute__((__packed__));
/**
* struct sgx_enclave_set_attribute - parameter structure for the
* %SGX_IOC_ENCLAVE_SET_ATTRIBUTE ioctl
* @attribute_fd: file handle of the attribute file in the securityfs
*/
struct sgx_enclave_set_attribute {
__u64 attribute_fd;
};
/**
* struct sgx_enclave_exception - structure to report exceptions encountered in
* __vdso_sgx_enter_enclave()
*
* @leaf: ENCLU leaf from \%eax at time of exception
* @trapnr: exception trap number, a.k.a. fault vector
* @error_code: exception error code
* @address: exception address, e.g. CR2 on a #PF
* @reserved: reserved for future use
*/
struct sgx_enclave_exception {
__u32 leaf;
__u16 trapnr;
__u16 error_code;
__u64 address;
__u64 reserved[2];
};
/**
* typedef sgx_enclave_exit_handler_t - Exit handler function accepted by
* __vdso_sgx_enter_enclave()
*
* @rdi: RDI at the time of enclave exit
* @rsi: RSI at the time of enclave exit
* @rdx: RDX at the time of enclave exit
* @ursp: RSP at the time of enclave exit (untrusted stack)
* @r8: R8 at the time of enclave exit
* @r9: R9 at the time of enclave exit
* @tcs: Thread Control Structure used to enter enclave
* @ret: 0 on success (EEXIT), -EFAULT on an exception
* @e: Pointer to struct sgx_enclave_exception (as provided by caller)
*/
typedef int (*sgx_enclave_exit_handler_t)(long rdi, long rsi, long rdx,
long ursp, long r8, long r9,
void *tcs, int ret,
struct sgx_enclave_exception *e);
#endif /* _UAPI_ASM_X86_SGX_H */
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/**
* Copyright(c) 2016-18 Intel Corporation.
*/
.text
.macro ENCLU
.byte 0x0f, 0x01, 0xd7
.endm
.text
.global sgx_call_eenter
sgx_call_eenter:
push %rbx
push %rdi
push %rsi
push %r12
push %r13
push %r14
push %r15
mov $0x02, %rax
mov %rdx, %rbx
lea sgx_async_exit(%rip), %rcx
sgx_async_exit:
ENCLU
pop %r15
pop %r14
pop %r13
pop %r12
pop %rsi
pop %rdi
pop %rbx
ret
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright(c) 2016-19 Intel Corporation.
*/
#ifndef SGX_CALL_H
#define SGX_CALL_H
void sgx_call_eenter(void *rdi, void *rsi, void *entry);
#endif /* SGX_CALL_H */
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
// Copyright(c) 2016-18 Intel Corporation.
#define _GNU_SOURCE
#include <getopt.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include "defines.h"
struct sgx_sigstruct_payload {
struct sgx_sigstruct_header header;
struct sgx_sigstruct_body body;
};
static bool check_crypto_errors(void)
{
int err;
bool had_errors = false;
const char *filename;
int line;
char str[256];
for ( ; ; ) {
if (ERR_peek_error() == 0)
break;
had_errors = true;
err = ERR_get_error_line(&filename, &line);
ERR_error_string_n(err, str, sizeof(str));
fprintf(stderr, "crypto: %s: %s:%d\n", str, filename, line);
}
return had_errors;
}
static void exit_usage(const char *program)
{
fprintf(stderr,
"Usage: %s/sign-le <key> <enclave> <sigstruct>\n", program);
exit(1);
}
static inline const BIGNUM *get_modulus(RSA *key)
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
return key->n;
#else
const BIGNUM *n;
RSA_get0_key(key, &n, NULL, NULL);
return n;
#endif
}
static RSA *load_sign_key(const char *path)
{
FILE *f;
RSA *key;
f = fopen(path, "rb");
if (!f) {
fprintf(stderr, "Unable to open %s\n", path);
return NULL;
}
key = RSA_new();
if (!PEM_read_RSAPrivateKey(f, &key, NULL, NULL))
return NULL;
fclose(f);
if (BN_num_bytes(get_modulus(key)) != SGX_MODULUS_SIZE) {
fprintf(stderr, "Invalid key size %d\n",
BN_num_bytes(get_modulus(key)));
RSA_free(key);
return NULL;
}
return key;
}
static void reverse_bytes(void *data, int length)
{
int i = 0;
int j = length - 1;
uint8_t temp;
uint8_t *ptr = data;
while (i < j) {
temp = ptr[i];
ptr[i] = ptr[j];
ptr[j] = temp;
i++;
j--;
}
}
enum mrtags {
MRECREATE = 0x0045544145524345,
MREADD = 0x0000000044444145,
MREEXTEND = 0x00444E4554584545,
};
static bool mrenclave_update(EVP_MD_CTX *ctx, const void *data)
{
if (!EVP_DigestUpdate(ctx, data, 64)) {
fprintf(stderr, "digest update failed\n");
return false;
}
return true;
}
static bool mrenclave_commit(EVP_MD_CTX *ctx, uint8_t *mrenclave)
{
unsigned int size;
if (!EVP_DigestFinal_ex(ctx, (unsigned char *)mrenclave, &size)) {
fprintf(stderr, "digest commit failed\n");
return false;
}
if (size != 32) {
fprintf(stderr, "invalid digest size = %u\n", size);
return false;
}
return true;
}
struct mrecreate {
uint64_t tag;
uint32_t ssaframesize;
uint64_t size;
uint8_t reserved[44];
} __attribute__((__packed__));
static bool mrenclave_ecreate(EVP_MD_CTX *ctx, uint64_t blob_size)
{
struct mrecreate mrecreate;
uint64_t encl_size;
for (encl_size = 0x1000; encl_size < blob_size; )
encl_size <<= 1;
memset(&mrecreate, 0, sizeof(mrecreate));
mrecreate.tag = MRECREATE;
mrecreate.ssaframesize = 1;
mrecreate.size = encl_size;
if (!EVP_DigestInit_ex(ctx, EVP_sha256(), NULL))
return false;
return mrenclave_update(ctx, &mrecreate);
}
struct mreadd {
uint64_t tag;
uint64_t offset;
uint64_t flags; /* SECINFO flags */
uint8_t reserved[40];
} __attribute__((__packed__));
static bool mrenclave_eadd(EVP_MD_CTX *ctx, uint64_t offset, uint64_t flags)
{
struct mreadd mreadd;
memset(&mreadd, 0, sizeof(mreadd));
mreadd.tag = MREADD;
mreadd.offset = offset;
mreadd.flags = flags;
return mrenclave_update(ctx, &mreadd);
}
struct mreextend {
uint64_t tag;
uint64_t offset;
uint8_t reserved[48];
} __attribute__((__packed__));
static bool mrenclave_eextend(EVP_MD_CTX *ctx, uint64_t offset, uint8_t *data)
{
struct mreextend mreextend;
int i;
for (i = 0; i < 0x1000; i += 0x100) {
memset(&mreextend, 0, sizeof(mreextend));
mreextend.tag = MREEXTEND;
mreextend.offset = offset + i;
if (!mrenclave_update(ctx, &mreextend))
return false;
if (!mrenclave_update(ctx, &data[i + 0x00]))
return false;
if (!mrenclave_update(ctx, &data[i + 0x40]))
return false;
if (!mrenclave_update(ctx, &data[i + 0x80]))
return false;
if (!mrenclave_update(ctx, &data[i + 0xC0]))
return false;
}
return true;
}
/**
* measure_encl - measure enclave
* @path: path to the enclave
* @mrenclave: measurement
*
* Calculates MRENCLAVE. Assumes that the very first page is a TCS page and
* following pages are regular pages. Does not measure the contents of the
* enclave as the signing tool is used at the moment only for the launch
* enclave, which is pass-through (everything gets a token).
*/
static bool measure_encl(const char *path, uint8_t *mrenclave)
{
FILE *file;
struct stat sb;
EVP_MD_CTX *ctx;
uint64_t flags;
uint64_t offset;
uint8_t data[0x1000];
int rc;
ctx = EVP_MD_CTX_create();
if (!ctx)
return false;
file = fopen(path, "rb");
if (!file) {
perror("fopen");
EVP_MD_CTX_destroy(ctx);
return false;
}
rc = stat(path, &sb);
if (rc) {
perror("stat");
goto out;
}
if (!sb.st_size || sb.st_size & 0xfff) {
fprintf(stderr, "Invalid blob size %lu\n", sb.st_size);
goto out;
}
if (!mrenclave_ecreate(ctx, sb.st_size))
goto out;
for (offset = 0; offset < sb.st_size; offset += 0x1000) {
if (!offset)
flags = SGX_SECINFO_TCS;
else
flags = SGX_SECINFO_REG | SGX_SECINFO_R |
SGX_SECINFO_W | SGX_SECINFO_X;
if (!mrenclave_eadd(ctx, offset, flags))
goto out;
rc = fread(data, 1, 0x1000, file);
if (!rc)
break;
if (rc < 0x1000)
goto out;
if (!mrenclave_eextend(ctx, offset, data))
goto out;
}
if (!mrenclave_commit(ctx, mrenclave))
goto out;
fclose(file);
EVP_MD_CTX_destroy(ctx);
return true;
out:
fclose(file);
EVP_MD_CTX_destroy(ctx);
return false;
}
/**
* sign_encl - sign enclave
* @sigstruct: pointer to SIGSTRUCT
* @key: 3072-bit RSA key
* @signature: byte array for the signature
*
* Calculates EMSA-PKCSv1.5 signature for the given SIGSTRUCT. The result is
* stored in big-endian format so that it can be further passed to OpenSSL
* libcrypto functions.
*/
static bool sign_encl(const struct sgx_sigstruct *sigstruct, RSA *key,
uint8_t *signature)
{
struct sgx_sigstruct_payload payload;
unsigned int siglen;
uint8_t digest[SHA256_DIGEST_LENGTH];
bool ret;
memcpy(&payload.header, &sigstruct->header, sizeof(sigstruct->header));
memcpy(&payload.body, &sigstruct->body, sizeof(sigstruct->body));
SHA256((unsigned char *)&payload, sizeof(payload), digest);
ret = RSA_sign(NID_sha256, digest, SHA256_DIGEST_LENGTH, signature,
&siglen, key);
return ret;
}
struct q1q2_ctx {
BN_CTX *bn_ctx;
BIGNUM *m;
BIGNUM *s;
BIGNUM *q1;
BIGNUM *qr;
BIGNUM *q2;
};
static void free_q1q2_ctx(struct q1q2_ctx *ctx)
{
BN_CTX_free(ctx->bn_ctx);
BN_free(ctx->m);
BN_free(ctx->s);
BN_free(ctx->q1);
BN_free(ctx->qr);
BN_free(ctx->q2);
}
static bool alloc_q1q2_ctx(const uint8_t *s, const uint8_t *m,
struct q1q2_ctx *ctx)
{
ctx->bn_ctx = BN_CTX_new();
ctx->s = BN_bin2bn(s, SGX_MODULUS_SIZE, NULL);
ctx->m = BN_bin2bn(m, SGX_MODULUS_SIZE, NULL);
ctx->q1 = BN_new();
ctx->qr = BN_new();
ctx->q2 = BN_new();
if (!ctx->bn_ctx || !ctx->s || !ctx->m || !ctx->q1 || !ctx->qr ||
!ctx->q2) {
free_q1q2_ctx(ctx);
return false;
}
return true;
}
static bool calc_q1q2(const uint8_t *s, const uint8_t *m, uint8_t *q1,
uint8_t *q2)
{
struct q1q2_ctx ctx;
if (!alloc_q1q2_ctx(s, m, &ctx)) {
fprintf(stderr, "Not enough memory for Q1Q2 calculation\n");
return false;
}
if (!BN_mul(ctx.q1, ctx.s, ctx.s, ctx.bn_ctx))
goto out;
if (!BN_div(ctx.q1, ctx.qr, ctx.q1, ctx.m, ctx.bn_ctx))
goto out;
if (BN_num_bytes(ctx.q1) > SGX_MODULUS_SIZE) {
fprintf(stderr, "Too large Q1 %d bytes\n",
BN_num_bytes(ctx.q1));
goto out;
}
if (!BN_mul(ctx.q2, ctx.s, ctx.qr, ctx.bn_ctx))
goto out;
if (!BN_div(ctx.q2, NULL, ctx.q2, ctx.m, ctx.bn_ctx))
goto out;
if (BN_num_bytes(ctx.q2) > SGX_MODULUS_SIZE) {
fprintf(stderr, "Too large Q2 %d bytes\n",
BN_num_bytes(ctx.q2));
goto out;
}
BN_bn2bin(ctx.q1, q1);
BN_bn2bin(ctx.q2, q2);
free_q1q2_ctx(&ctx);
return true;
out:
free_q1q2_ctx(&ctx);
return false;
}
static bool save_sigstruct(const struct sgx_sigstruct *sigstruct,
const char *path)
{
FILE *f = fopen(path, "wb");
if (!f) {
fprintf(stderr, "Unable to open %s\n", path);
return false;
}
fwrite(sigstruct, sizeof(*sigstruct), 1, f);
fclose(f);
return true;
}
int main(int argc, char **argv)
{
uint64_t header1[2] = {0x000000E100000006, 0x0000000000010000};
uint64_t header2[2] = {0x0000006000000101, 0x0000000100000060};
struct sgx_sigstruct ss;
const char *program;
int opt;
RSA *sign_key;
memset(&ss, 0, sizeof(ss));
ss.header.header1[0] = header1[0];
ss.header.header1[1] = header1[1];
ss.header.header2[0] = header2[0];
ss.header.header2[1] = header2[1];
ss.exponent = 3;
#ifndef CONFIG_EINITTOKENKEY
ss.body.attributes = SGX_ATTR_MODE64BIT;
#else
ss.body.attributes = SGX_ATTR_MODE64BIT | SGX_ATTR_EINITTOKENKEY;
#endif
ss.body.attributes |= SGX_ATTR_DEBUG;
ss.body.xfrm = 7;
ss.body.attributes_mask = ss.body.attributes;
program = argv[0];
do {
opt = getopt(argc, argv, "");
switch (opt) {
case -1:
break;
default:
exit_usage(program);
}
} while (opt != -1);
argc -= optind;
argv += optind;
if (argc < 3)
exit_usage(program);
/* sanity check only */
if (check_crypto_errors())
exit(1);
sign_key = load_sign_key(argv[0]);
if (!sign_key)
goto out;
BN_bn2bin(get_modulus(sign_key), ss.modulus);
if (!measure_encl(argv[1], ss.body.mrenclave))
goto out;
if (!sign_encl(&ss, sign_key, ss.signature))
goto out;
if (!calc_q1q2(ss.signature, ss.modulus, ss.q1, ss.q2))
goto out;
/* convert to little endian */
reverse_bytes(ss.signature, SGX_MODULUS_SIZE);
reverse_bytes(ss.modulus, SGX_MODULUS_SIZE);
reverse_bytes(ss.q1, SGX_MODULUS_SIZE);
reverse_bytes(ss.q2, SGX_MODULUS_SIZE);
if (!save_sigstruct(&ss, argv[2]))
goto out;
exit(0);
out:
check_crypto_errors();
exit(1);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册