-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
app/baresgx: minimal bare-metal test enclave
This directory contains a minimal test enclave hand written in assembly using the `bare-sgx` runtime. This setup allows you to load the enclave on a bare-metal Linux platform without needing any bloated SDK installation. The test enclave consists of a single code page with _exactly_ 100 instructions, which can be precisely single-stepped by SGX-Step, making it an ideal resource for testing and debugging. See also: <https://github.com/jovanbulck/bare-sgx>
- Loading branch information
1 parent
f527d53
commit 1483dc8
Showing
9 changed files
with
249 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,3 +16,4 @@ | |
*.mk | ||
*.mod | ||
*.swn | ||
*.elf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
LIBSGXSTEP_DIR = ../.. | ||
LIBSGXSTEP = $(LIBSGXSTEP_DIR)/libsgxstep | ||
-include $(LIBSGXSTEP)/Makefile.config | ||
LIBSGXSTEP_SILENT = 1 | ||
|
||
BARESGX = ../../sdk/bare-sgx/urts | ||
ENCLAVE = enclave | ||
|
||
|
||
SUBDIRS = $(ENCLAVE) $(BARESGX) $(LIBSGXSTEP) | ||
|
||
CC := gcc | ||
LD := gcc | ||
INCLUDE := -I$(BARESGX)/include/ -I$(LIBSGXSTEP_DIR) | ||
CFLAGS := -Wall -g -fPIC | ||
LDFLAGS := -z noexecstack -pthread -lbaresgx-urts -lsgx-step -L$(BARESGX) -L$(LIBSGXSTEP) -lcrypto -lelf | ||
|
||
SOURCES = $(shell ls *.c) | ||
OBJECTS = $(SOURCES:.c=.o) | ||
OUTPUT = app | ||
|
||
BUILDDIRS = $(SUBDIRS:%=build-%) | ||
CLEANDIRS = $(SUBDIRS:%=clean-%) | ||
|
||
MAKEFLAGS = --silent | ||
|
||
all: $(OUTPUT) | ||
|
||
$(OUTPUT): $(BUILDDIRS) $(OBJECTS) | ||
$(LD) $(OBJECTS) $(LDFLAGS) -o $(OUTPUT) | ||
|
||
%.o : %.c | ||
$(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDE) -c $< -o $@ | ||
|
||
$(BUILDDIRS): | ||
$(MAKE) -C $(@:build-%=%) | ||
|
||
$(CLEANDIRS): | ||
$(MAKE) clean -C $(@:clean-%=%) | ||
|
||
clean: $(CLEANDIRS) | ||
rm -f $(OBJECTS) $(OUTPUT) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Minimal baresgx test enclave | ||
|
||
This directory contains a minimal test enclave hand written in assembly using | ||
the [`bare-sgx`](https://github.com/jovanbulck/bare-sgx) runtime. This setup | ||
allows you to load the enclave on a bare-metal Linux platform without needing | ||
any bloated SDK installation. | ||
|
||
The test enclave consists of a single code page with _exactly_ 100 instructions, | ||
which can be precisely single-stepped by SGX-Step, making it an ideal resource | ||
for testing and debugging. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
.PHONY: all clean | ||
|
||
CFLAGS += -Wall -Werror -static-pie -nostdlib -ffreestanding -fPIE \ | ||
-fno-stack-protector -mrdrnd $(INCLUDES) | ||
LDFLAGS := -Wl,-T,encl.lds,--build-id=none | ||
|
||
encl.elf: encl.S | ||
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) | ||
|
||
clean: | ||
rm -f *.elf *.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
.section ".tcs", "aw" | ||
.balign 4096 | ||
|
||
.fill 1, 8, 0 # STATE (set by CPU) | ||
.fill 1, 8, 0 # FLAGS | ||
.quad encl_ssa_tcs1 # 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 | ||
|
||
/* | ||
* Minimal test enclave with a single code page with exactly 100 | ||
* instructions. | ||
*/ | ||
.text | ||
.align 0x1000 | ||
encl_entry: | ||
mov encl_secret(%rip), %rsi | ||
|
||
.rept 96 | ||
nop | ||
.endr | ||
|
||
# EEXIT | ||
mov %rcx, %rbx | ||
mov $4, %rax | ||
enclu | ||
|
||
.data | ||
encl_ssa_tcs1: | ||
.space 4096 | ||
|
||
encl_secret: | ||
.quad 0xdeadbeefcafebabe | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
OUTPUT_FORMAT(elf64-x86-64) | ||
|
||
PHDRS | ||
{ | ||
tcs PT_LOAD; | ||
text PT_LOAD; | ||
data PT_LOAD; | ||
} | ||
|
||
SECTIONS | ||
{ | ||
. = 0; | ||
__encl_base = .; | ||
.tcs : { | ||
*(.tcs*) | ||
} : tcs | ||
|
||
. = ALIGN(4096); | ||
.text : { | ||
*(.text*) | ||
*(.rodata*) | ||
} : text | ||
|
||
. = ALIGN(4096); | ||
.data : { | ||
*(.data.encl_buffer) | ||
*(.data*) | ||
} : data | ||
|
||
/DISCARD/ : { | ||
*(.comment*) | ||
*(.note*) | ||
*(.debug*) | ||
*(.eh_frame*) | ||
*(.dyn*) | ||
*(.gnu.hash) | ||
} | ||
} | ||
|
||
ASSERT(!DEFINED(_GLOBAL_OFFSET_TABLE_), "Libcalls through GOT are not supported in enclaves") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#include <stdio.h> | ||
#include <signal.h> | ||
#include "baresgx/urts.h" | ||
#include "libsgxstep/debug.h" | ||
#include "libsgxstep/enclave.h" | ||
#include "libsgxstep/pt.h" | ||
#include "libsgxstep/apic.h" | ||
#include "libsgxstep/idt.h" | ||
#include "libsgxstep/cache.h" | ||
#include "libsgxstep/elf_parser.h" | ||
|
||
#define ENCLAVE_PATH "enclave/encl.elf" | ||
#define ENCLAVE_DBG 1 | ||
#define SINGLE_STEP_ENABLE 1 | ||
|
||
void *encl_page = NULL; | ||
uint64_t *pte_encl = 0; | ||
int do_step = 0, step_cnt = 0, zero_cnt = 0; | ||
|
||
void aep_cb_func(void) | ||
{ | ||
uint64_t erip = edbgrd_erip() - (uint64_t)get_enclave_base(); | ||
info("^^ enclave RIP=%#lx; ACCESSED=%lu", erip, ACCESSED(*pte_encl)); | ||
|
||
if (do_step && ACCESSED(*pte_encl)) step_cnt++; | ||
else if (do_step) zero_cnt++; | ||
|
||
/* | ||
* NOTE: We explicitly clear the "accessed" bit of the _unprotected_ PTE | ||
* referencing the enclave code page about to be executed, so as to be able | ||
* to filter out "zero-step" results that won't set the accessed bit. | ||
* | ||
* Clearing the PTE "accessed" bit forces the CPU to take a ucode-assisted | ||
* page-table walk for the first instruction following ERESUME, which | ||
* causes that instruction to be much longer. We additionally flush this | ||
* PTE from the cache to further delay the page-table walk and increase the | ||
* landing space for the timer interrupt. | ||
*/ | ||
*pte_encl = MARK_NOT_ACCESSED(*pte_encl); | ||
flush(pte_encl); | ||
|
||
if (do_step) | ||
{ | ||
apic_timer_irq(SGX_STEP_TIMER_INTERVAL); | ||
} | ||
} | ||
|
||
void handle_fault(int sig) | ||
{ | ||
info("caught signal %d; restoring trigger page access rights", sig); | ||
*pte_encl = MARK_EXECUTABLE(*pte_encl); | ||
do_step = 1; | ||
} | ||
|
||
int main(void) | ||
{ | ||
void *tcs; | ||
uint64_t rv; | ||
idt_t idt = {0}; | ||
|
||
/************************************************************************/ | ||
info_event("loading baresgx enclave"); | ||
tcs = baresgx_load_elf_enclave(ENCLAVE_PATH, ENCLAVE_DBG); | ||
print_enclave_info(); | ||
register_symbols(ENCLAVE_PATH); | ||
|
||
info("dry run"); | ||
rv = baresgx_enter_enclave(tcs, /*arg=*/0); | ||
printf("\tL enclave returned %lx\n", rv); | ||
|
||
/************************************************************************/ | ||
info_event("configuring attacker runtime"); | ||
register_aep_cb(aep_cb_func); | ||
ASSERT( signal(SIGSEGV, handle_fault) != SIG_ERR); | ||
|
||
encl_page = get_symbol_offset("encl_entry") + get_enclave_base(); | ||
info("entry page at %p", encl_page); | ||
ASSERT(pte_encl = remap_page_table_level(encl_page, PTE)); | ||
ASSERT(PRESENT(*pte_encl)); | ||
print_pte(pte_encl); | ||
#if SINGLE_STEP_ENABLE | ||
*pte_encl = MARK_EXECUTE_DISABLE(*pte_encl); | ||
|
||
map_idt(&idt); | ||
install_kernel_irq_handler(&idt, __ss_irq_handler, IRQ_VECTOR); | ||
apic_timer_oneshot(IRQ_VECTOR); | ||
|
||
__ss_irq_fired = 0; | ||
apic_timer_irq( SGX_STEP_TIMER_INTERVAL ); | ||
while (!__ss_irq_fired); | ||
info("APIC timer IRQ handler seems to be working"); | ||
#endif | ||
|
||
/************************************************************************/ | ||
info_event("single-stepping baresgx enclave"); | ||
rv = baresgx_enter_enclave(tcs, /*arg=*/0); | ||
info("enclave returned %lx; step_cnt=%d; zero_cnt=%d\n", rv, step_cnt, zero_cnt); | ||
|
||
return 0; | ||
} |