├── app ├── sgx │ ├── 000-pin │ │ ├── .gitignore │ │ ├── Enclave │ │ │ ├── .gitignore │ │ │ ├── encl.config.xml │ │ │ ├── encl.c │ │ │ ├── encl.edl │ │ │ └── Makefile │ │ ├── Makefile │ │ ├── main.c │ │ └── README.md │ ├── 001-attestation │ │ ├── .gitignore │ │ ├── Enclave │ │ │ ├── .gitignore │ │ │ ├── encl.config.xml │ │ │ ├── encl.edl │ │ │ ├── encl.c │ │ │ └── Makefile │ │ ├── Makefile │ │ ├── main.c │ │ └── README.md │ ├── 002-auth-exec │ │ ├── .gitignore │ │ ├── Enclave │ │ │ ├── .gitignore │ │ │ ├── encl.config.xml │ │ │ ├── encl.edl │ │ │ ├── encl.c │ │ │ └── Makefile │ │ ├── Makefile │ │ ├── main.c │ │ └── README.md │ ├── 001-attestation-unprotected │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── README.md │ │ └── main.c │ ├── common │ │ ├── debug.c │ │ ├── can.h │ │ ├── can.c │ │ └── debug.h │ └── README.md └── sancus │ ├── 002-auth-exec │ ├── foo.h │ ├── pmodbtn.h │ ├── pmodled.h │ ├── Makefile │ ├── pmodbtn.c │ ├── foo.c │ ├── pmodled.c │ ├── main.c │ └── README.md │ ├── 001-attestation │ ├── foo.h │ ├── foo.c │ ├── Makefile │ ├── main.c │ └── README.md │ ├── 000-blinking-led │ ├── pmodbtn.h │ ├── pmodled.h │ ├── Makefile │ ├── pmodled.c │ ├── pmodbtn.c │ ├── main.c │ └── README.md │ ├── Makefile.include │ └── README.md ├── slides.pdf ├── .gitignore ├── usbtin └── USBtinViewer_v1.3.jar ├── scripts ├── Makefile ├── README.md ├── checknflash.sh ├── manage_accounts.sh ├── manage_ifs.sh └── slcanconfig.sh ├── .gitmodules └── README.md /app/sgx/000-pin/.gitignore: -------------------------------------------------------------------------------- 1 | app 2 | -------------------------------------------------------------------------------- /app/sgx/001-attestation/.gitignore: -------------------------------------------------------------------------------- 1 | app 2 | -------------------------------------------------------------------------------- /app/sgx/002-auth-exec/.gitignore: -------------------------------------------------------------------------------- 1 | app 2 | -------------------------------------------------------------------------------- /app/sgx/001-attestation-unprotected/.gitignore: -------------------------------------------------------------------------------- 1 | app 2 | -------------------------------------------------------------------------------- /slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sancus-tee/tutorial-dsn18/HEAD/slides.pdf -------------------------------------------------------------------------------- /app/sgx/000-pin/Enclave/.gitignore: -------------------------------------------------------------------------------- 1 | encl 2 | *.pem 3 | *.a 4 | *.s 5 | *.so 6 | *_u.* 7 | *_t.* 8 | -------------------------------------------------------------------------------- /app/sgx/001-attestation/Enclave/.gitignore: -------------------------------------------------------------------------------- 1 | encl 2 | *.pem 3 | *.a 4 | *.s 5 | *.so 6 | *_u.* 7 | *_t.* 8 | -------------------------------------------------------------------------------- /app/sgx/002-auth-exec/Enclave/.gitignore: -------------------------------------------------------------------------------- 1 | encl 2 | *.pem 3 | *.a 4 | *.s 5 | *.so 6 | *_u.* 7 | *_t.* 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.o 3 | *.elf 4 | *.elf.* 5 | *.bin 6 | *.fst 7 | *.fst.* 8 | *.out 9 | *.swo 10 | -------------------------------------------------------------------------------- /usbtin/USBtinViewer_v1.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sancus-tee/tutorial-dsn18/HEAD/usbtin/USBtinViewer_v1.3.jar -------------------------------------------------------------------------------- /scripts/Makefile: -------------------------------------------------------------------------------- 1 | 2 | dsn: manage_accounts.sh manage_ifs.sh 3 | ./manage_accounts.sh -n10 -f0 4 | ./manage_ifs.sh -n10 -f0 5 | 6 | dsn-clean: 7 | ./manage_ifs.sh -n10 -f0 -D 8 | ./manage_accounts.sh -n10 -f0 -D 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/sgx/common/debug.c: -------------------------------------------------------------------------------- 1 | #include "debug.h" 2 | 3 | int enclave_rv = 0; 4 | 5 | void dump_hex(char *str, uint8_t *buf, int len) 6 | { 7 | printf("%s = ", str); 8 | for (int i=0; i < len; i++) 9 | printf("%02x ", *(buf + i)); 10 | printf("\n"); 11 | } 12 | -------------------------------------------------------------------------------- /app/sancus/002-auth-exec/foo.h: -------------------------------------------------------------------------------- 1 | #ifndef SM_FOO_H_INC 2 | #define SM_FOO_H_INC 3 | 4 | #include 5 | #include 6 | 7 | extern struct SancusModule foo; 8 | 9 | int SM_ENTRY(foo) calc_foo(int i); 10 | 11 | int SM_ENTRY(foo) attest_foo(uint8_t *buf, int len, uint16_t *btn, uint8_t *mac); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /app/sancus/002-auth-exec/pmodbtn.h: -------------------------------------------------------------------------------- 1 | #ifndef SM_MMIO_PMODBTN_H_INC 2 | #define SM_MMIO_PMODBTN_H_INC 3 | 4 | #include 5 | #include 6 | 7 | extern struct SancusModule pmodbtn; 8 | 9 | uint8_t SM_MMIO_ENTRY(pmodbtn) pmodbtn_poll(void); 10 | void SM_MMIO_ENTRY(pmodbtn) pmodbtn_init(void); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /app/sancus/002-auth-exec/pmodled.h: -------------------------------------------------------------------------------- 1 | #ifndef SM_MMIO_PMODLED_H_INC 2 | #define SM_MMIO_PMODLED_H_INC 3 | 4 | #include 5 | #include 6 | 7 | extern struct SancusModule pmodled; 8 | 9 | void SM_MMIO_ENTRY(pmodled) pmodled_actuate(uint8_t state); 10 | void SM_MMIO_ENTRY(pmodled) pmodled_init(void); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "usbtin/USBtinViewer"] 2 | path = usbtin/USBtinViewer 3 | url = https://github.com/EmbedME/USBtinViewer.git 4 | [submodule "app/sancus/vulcan"] 5 | path = app/sancus/vulcan 6 | url = https://github.com/sancus-pma/vulcan.git 7 | [submodule "app/sgx/libspongent"] 8 | path = app/sgx/libspongent 9 | url = https://github.com/sancus-pma/libspongent.git 10 | -------------------------------------------------------------------------------- /app/sgx/000-pin/Enclave/encl.config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 0 4 | 0 5 | 0x40000 6 | 0x100000 7 | 1 8 | 1 9 | 0 10 | 11 | -------------------------------------------------------------------------------- /app/sgx/001-attestation/Enclave/encl.config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 0 4 | 0 5 | 0x40000 6 | 0x100000 7 | 1 8 | 1 9 | 0 10 | 11 | -------------------------------------------------------------------------------- /app/sgx/002-auth-exec/Enclave/encl.config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 0 4 | 0 5 | 0x40000 6 | 0x100000 7 | 1 8 | 1 9 | 0 10 | 11 | -------------------------------------------------------------------------------- /app/sgx/001-attestation/Enclave/encl.edl: -------------------------------------------------------------------------------- 1 | #include "../../libspongent/libspongent/config.h" 2 | 3 | enclave { 4 | 5 | trusted { 6 | /* define ECALLs here. */ 7 | public uint64_t ecall_get_challenge(void); 8 | public int ecall_verify_response([in, size=SPONGENT_TAG_SIZE] uint8_t *mac); 9 | }; 10 | 11 | untrusted { 12 | /* define OCALLs here. */ 13 | }; 14 | }; 15 | -------------------------------------------------------------------------------- /app/sgx/common/can.h: -------------------------------------------------------------------------------- 1 | #ifndef CAN_H_INC 2 | #define CAN_H_INC 3 | 4 | #include 5 | #include 6 | 7 | #define CAN_PAYLOAD_SIZE 8 8 | #define CAN_SID_SIZE 2 9 | 10 | int can_open(char *ican); 11 | int can_send(int can_socket, uint16_t id, uint8_t *buf, size_t len); 12 | int can_recv(int can_socket, uint16_t *id, uint8_t *buf); 13 | int can_close(int can_socket); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /app/sancus/001-attestation/foo.h: -------------------------------------------------------------------------------- 1 | #ifndef SM_FOO_H_INC 2 | #define SM_FOO_H_INC 3 | 4 | #include 5 | #include 6 | 7 | extern struct SancusModule foo; 8 | 9 | int SM_ENTRY(foo) calc_foo(int i); 10 | 11 | /* =========================== START SOLUTION =========================== */ 12 | /* ============================ END SOLUTION ============================ */ 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /app/sancus/001-attestation/foo.c: -------------------------------------------------------------------------------- 1 | #include "foo.h" 2 | #include 3 | 4 | DECLARE_SM(foo, 0x1234); 5 | 6 | const SM_DATA(foo) int foo_magic_const = 12; 7 | 8 | int SM_ENTRY(foo) calc_foo(int i) 9 | { 10 | return i + foo_magic_const; 11 | } 12 | 13 | /* =========================== START SOLUTION =========================== */ 14 | 15 | /* ============================ END SOLUTION ============================ */ 16 | -------------------------------------------------------------------------------- /app/sancus/000-blinking-led/pmodbtn.h: -------------------------------------------------------------------------------- 1 | #ifndef PMOD_BTN_H_INC 2 | #define PMOD_BTN_H_INC 3 | 4 | #include 5 | 6 | /* Our setup: BTN0123 mapped to P3IN[4:7] */ 7 | typedef enum { 8 | PMOD_BTN_NONE = 0, 9 | PMOD_BTN3 = 4, 10 | PMOD_BTN2 = 5, 11 | PMOD_BTN1 = 6, 12 | PMOD_BTN0 = 7, 13 | } pmodbtn_t; 14 | 15 | #define PMOD_BTN_TO_NUM( btn ) (PMOD_BTN0 - btn) 16 | 17 | void pmodbtn_init(void); 18 | pmodbtn_t pmodbtn_poll(void); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /app/sgx/002-auth-exec/Enclave/encl.edl: -------------------------------------------------------------------------------- 1 | #include "../../libspongent/libspongent/config.h" 2 | 3 | enclave { 4 | 5 | trusted { 6 | /* define ECALLs here. */ 7 | public uint64_t ecall_get_challenge(void); 8 | public int ecall_verify_response([in, size=SPONGENT_TAG_SIZE] uint8_t *mac, uint16_t btn); 9 | }; 10 | 11 | untrusted { 12 | /* define OCALLs here. */ 13 | void ocall_dump_buf([in, string] char *str, [in, size=len] uint8_t *buf, int len); 14 | }; 15 | }; 16 | -------------------------------------------------------------------------------- /app/sancus/000-blinking-led/pmodled.h: -------------------------------------------------------------------------------- 1 | #ifndef PMOD_LED_H_INC 2 | #define PMOD_LED_H_INC 3 | 4 | #include 5 | 6 | /* Our setup: LD0 permanently grounded, LD123 mapped to P1OUT[5:7] */ 7 | typedef enum { 8 | PMOD_LED0 = 4, 9 | PMOD_LED1 = 5, 10 | PMOD_LED2 = 6, 11 | PMOD_LED3 = 7, 12 | } pmodled_t; 13 | 14 | #define PMOD_LED_TO_NUM( led ) (led - PMOD_LED0) 15 | #define PMOD_LED_TO_MASK( led ) (0x1 << led) 16 | 17 | void pmodled_init(void); 18 | void pmodled_toggle(pmodled_t led); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /app/sgx/000-pin/Enclave/encl.c: -------------------------------------------------------------------------------- 1 | #include "encl_t.h" 2 | 3 | /* 4 | * NOTE: for demonstration purposes, we hard-code secrets at compile time and 5 | * abstract away how they are securely provisioned at runtime. 6 | */ 7 | int super_secret_constant = 0xdeadbeef; 8 | int super_secret_pin = 1234; 9 | 10 | int ecall_dummy(int i) 11 | { 12 | ocall_print("hello world from ecall_dummy!"); 13 | return super_secret_constant + i; 14 | } 15 | 16 | /* =========================== START SOLUTION =========================== */ 17 | 18 | /* ============================ END SOLUTION ============================ */ 19 | -------------------------------------------------------------------------------- /app/sgx/000-pin/Enclave/encl.edl: -------------------------------------------------------------------------------- 1 | enclave { 2 | 3 | trusted { 4 | /* define ECALLs here. */ 5 | public int ecall_dummy(int i); 6 | 7 | /* =========================== START SOLUTION =========================== */ 8 | /* ============================ END SOLUTION ============================ */ 9 | }; 10 | 11 | untrusted { 12 | /* define OCALLs here. */ 13 | void ocall_print([in,string] const char *str); 14 | 15 | /* =========================== START SOLUTION =========================== */ 16 | /* ============================ END SOLUTION ============================ */ 17 | }; 18 | }; 19 | -------------------------------------------------------------------------------- /app/sancus/002-auth-exec/Makefile: -------------------------------------------------------------------------------- 1 | include ../Makefile.include 2 | 3 | VULCAN_DIR = .. 4 | 5 | CFLAGS += -I$(VULCAN_DIR) 6 | 7 | SOURCES = $(shell ls *.c) $(VULCAN_DIR)/vulcan/drivers/mcp2515.c 8 | OBJECTS = $(SOURCES:.c=.o) 9 | 10 | TARGET = main.elf 11 | TARGET_NO_MAC = no_mac_$(TARGET) 12 | 13 | all: $(TARGET) 14 | 15 | $(TARGET_NO_MAC): $(OBJECTS) 16 | $(LD) $(LDFLAGS) -o $@ $^ 17 | 18 | $(TARGET): $(TARGET_NO_MAC) 19 | $(SANCUS_CRYPTO) --fill-macs $(CRYPTOFLAGS) -o $@ $< 20 | 21 | load: $(TARGET) 22 | $(SANCUS_LOAD) $(LOADFLAGS) $< 23 | 24 | clean: 25 | $(RM) $(TARGET) $(TARGET_NO_MAC) $(OBJECTS) 26 | rm -f sim-input.bin sim-output.bin sim.out 27 | rm -f *.fst *.vcd 28 | -------------------------------------------------------------------------------- /app/sancus/000-blinking-led/Makefile: -------------------------------------------------------------------------------- 1 | include ../Makefile.include 2 | 3 | VULCAN_DIR = .. 4 | 5 | CFLAGS += -I$(VULCAN_DIR) 6 | 7 | SOURCES = $(shell ls *.c) $(VULCAN_DIR)/vulcan/drivers/mcp2515.c 8 | OBJECTS = $(SOURCES:.c=.o) 9 | 10 | TARGET = main.elf 11 | TARGET_NO_MAC = no_mac_$(TARGET) 12 | 13 | all: $(TARGET) 14 | 15 | $(TARGET_NO_MAC): $(OBJECTS) 16 | $(LD) $(LDFLAGS) -o $@ $^ 17 | 18 | $(TARGET): $(TARGET_NO_MAC) 19 | $(SANCUS_CRYPTO) --fill-macs $(CRYPTOFLAGS) -o $@ $< 20 | 21 | load: $(TARGET) 22 | $(SANCUS_LOAD) $(LOADFLAGS) $< 23 | 24 | clean: 25 | $(RM) $(TARGET) $(TARGET_NO_MAC) $(OBJECTS) 26 | rm -f sim-input.bin sim-output.bin sim.out 27 | rm -f *.fst *.vcd 28 | -------------------------------------------------------------------------------- /app/sancus/001-attestation/Makefile: -------------------------------------------------------------------------------- 1 | include ../Makefile.include 2 | 3 | VULCAN_DIR = .. 4 | 5 | CFLAGS += -I$(VULCAN_DIR) 6 | 7 | SOURCES = $(shell ls *.c) $(VULCAN_DIR)/vulcan/drivers/mcp2515.c 8 | OBJECTS = $(SOURCES:.c=.o) 9 | 10 | TARGET = main.elf 11 | TARGET_NO_MAC = no_mac_$(TARGET) 12 | 13 | all: $(TARGET) 14 | 15 | $(TARGET_NO_MAC): $(OBJECTS) 16 | $(LD) $(LDFLAGS) -o $@ $^ 17 | 18 | $(TARGET): $(TARGET_NO_MAC) 19 | $(SANCUS_CRYPTO) --fill-macs $(CRYPTOFLAGS) -o $@ $< 20 | 21 | load: $(TARGET) 22 | $(SANCUS_LOAD) $(LOADFLAGS) $< 23 | 24 | clean: 25 | $(RM) $(TARGET) $(TARGET_NO_MAC) $(OBJECTS) 26 | rm -f sim-input.bin sim-output.bin sim.out 27 | rm -f *.fst *.vcd 28 | -------------------------------------------------------------------------------- /app/sgx/001-attestation/Enclave/encl.c: -------------------------------------------------------------------------------- 1 | #include "libspongent/spongewrap.h" 2 | #include 3 | #include "encl_t.h" 4 | 5 | /* 6 | * XXX Fill in the correct Sancus-specific key computed from the final foo.c enclave source code: 7 | * 8 | * $ sancus-crypto --key 0b7bf3ae40880a8be430d0da34fb76f0 --gen-sm-key foo --c-array main.elf 9 | */ 10 | uint8_t key[] = { 0x39, 0x8f, 0x2b, 0x56, 0x31, 0x0d, 0x58, 0xaa, 0x8c, 0xf5, 0x09, 0x23, 0x89, 0x31, 0xcb, 0x7b}; 11 | 12 | uint64_t ecall_get_challenge(void) 13 | { 14 | /* =========================== START SOLUTION =========================== */ 15 | /* ============================ END SOLUTION ============================ */ 16 | } 17 | 18 | int ecall_verify_response(uint8_t *sm_mac) 19 | { 20 | /* =========================== START SOLUTION =========================== */ 21 | /* ============================ END SOLUTION ============================ */ 22 | } 23 | -------------------------------------------------------------------------------- /app/sancus/000-blinking-led/pmodled.c: -------------------------------------------------------------------------------- 1 | #include "pmodled.h" 2 | #include 3 | 4 | int pmodled_initialized = 0; 5 | 6 | void pmodled_init(void) 7 | { 8 | /* 9 | * Our setup: LD0 permanently grounded, LD123 mapped to P1OUT[5:7] 10 | * 11 | * https://store.digilentinc.com/pmod-led-four-high-brightness-leds/ 12 | * http://processors.wiki.ti.com/index.php/Digital_I/O_(MSP430) 13 | */ 14 | P1SEL = 0x00; 15 | P1DIR = 0xff; 16 | P1OUT = 0x00; 17 | 18 | pmodled_initialized = 1; 19 | } 20 | 21 | void pmodled_toggle(pmodled_t led) 22 | { 23 | if (led < PMOD_LED1 || led > PMOD_LED3) 24 | return; 25 | 26 | printf("[pmodled] toggling LED %d \n", PMOD_LED_TO_NUM(led)); 27 | 28 | if (!pmodled_initialized) 29 | pmodled_init(); 30 | 31 | int toggled = P1OUT & PMOD_LED_TO_MASK(led); 32 | 33 | if (!toggled) 34 | P1OUT |= PMOD_LED_TO_MASK(led); 35 | else 36 | P1OUT &= ~PMOD_LED_TO_MASK(led); 37 | } 38 | -------------------------------------------------------------------------------- /app/sancus/002-auth-exec/pmodbtn.c: -------------------------------------------------------------------------------- 1 | #include "pmodbtn.h" 2 | #include 3 | 4 | DECLARE_EXCLUSIVE_MMIO_SM(pmodbtn, 5 | /*[secret_start, end[=*/ P3IN_, P4IN_, 6 | /*caller_id=*/ 1, 7 | /*vendor_id=*/ 0x1234); 8 | 9 | uint8_t SM_MMIO_ENTRY(pmodbtn) pmodbtn_poll(void) 10 | { 11 | asm( 12 | "mov.b &%0, r15 \n\t" 13 | ::"m"(P3IN) 14 | ); 15 | } 16 | 17 | void SM_MMIO_ENTRY(pmodbtn) pmodbtn_init(void) 18 | { 19 | /* 20 | * Our setup: BTN0123 mapped to P3IN[4:7] 21 | * 22 | * https://store.digilentinc.com/pmodbtn-4-user-pushbuttons/ 23 | * http://processors.wiki.ti.com/index.php/Digital_I/O_(MSP430) 24 | */ 25 | asm( 26 | "mov.b #0x00, &%0 \n\t" 27 | "mov.b #0x00, &%1 \n\t" 28 | ::"m"(P3SEL), "m"(P3DIR): 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /app/sancus/002-auth-exec/foo.c: -------------------------------------------------------------------------------- 1 | #include "foo.h" 2 | #include "pmodbtn.h" 3 | #include "pmodled.h" 4 | #include 5 | 6 | DECLARE_SM(foo, 0x1234); 7 | 8 | const SM_DATA(foo) int foo_magic_const = 12; 9 | 10 | int SM_ENTRY(foo) calc_foo(int i) 11 | { 12 | return i + foo_magic_const; 13 | } 14 | 15 | /* 16 | * We create a MAC over: challenge (8B) | PMODBTN sensor reading (2B) 17 | * 18 | * NOTE: we use a 2B sensor reading size to ensure the total size of the buffer 19 | * is a multiple of 2 (to work around a known erratum in the Sancus crypto HW 20 | * instructions). 21 | */ 22 | #define ATTEST_MSG_SIZE (sizeof(uint64_t) + sizeof(uint16_t)) 23 | 24 | uint8_t SM_DATA(foo) msg[ATTEST_MSG_SIZE] = {0x0}; 25 | int SM_DATA(foo) foo_drv_init = 0; 26 | 27 | int SM_ENTRY(foo) attest_foo(uint8_t *challenge, int len, uint16_t *btn, uint8_t *mac) 28 | { 29 | /* =========================== START SOLUTION =========================== */ 30 | /* ============================ END SOLUTION ============================ */ 31 | } 32 | -------------------------------------------------------------------------------- /app/sancus/002-auth-exec/pmodled.c: -------------------------------------------------------------------------------- 1 | #include "pmodled.h" 2 | #include 3 | 4 | DECLARE_EXCLUSIVE_MMIO_SM(pmodled, 5 | /*[secret_start, end[=*/ P1IN_, P2IN_, 6 | /*caller_id=*/ 1, 7 | /*vendor_id=*/ 0x1234); 8 | 9 | void SM_MMIO_ENTRY(pmodled) pmodled_actuate(uint8_t state) 10 | { 11 | asm( 12 | "mov.b r15, &%0 \n\t" 13 | ::"m"(P1OUT) 14 | ); 15 | } 16 | 17 | void SM_MMIO_ENTRY(pmodled) pmodled_init(void) 18 | { 19 | /* 20 | * Our setup: LD0 permanently grounded, LD123 mapped to P1OUT[5:7] 21 | * 22 | * https://store.digilentinc.com/pmod-led-four-high-brightness-leds/ 23 | * http://processors.wiki.ti.com/index.php/Digital_I/O_(MSP430) 24 | */ 25 | asm( 26 | "mov.b #0x00, &%0 \n\t" 27 | "mov.b #0xff, &%1 \n\t" 28 | ::"m"(P1SEL), "m"(P1DIR): 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /app/sancus/000-blinking-led/pmodbtn.c: -------------------------------------------------------------------------------- 1 | #include "pmodbtn.h" 2 | #include 3 | 4 | int pmodbtn_initialized = 0; 5 | 6 | void pmodbtn_init(void) 7 | { 8 | /* 9 | * Our setup: BTN0123 mapped to P3IN[4:7] 10 | * 11 | * https://store.digilentinc.com/pmodbtn-4-user-pushbuttons/ 12 | * http://processors.wiki.ti.com/index.php/Digital_I/O_(MSP430) 13 | */ 14 | P3SEL = 0x00; 15 | P3DIR = 0x00; 16 | P3OUT = 0x00; 17 | 18 | pmodbtn_initialized = 1; 19 | } 20 | 21 | pmodbtn_t pmodbtn_poll(void) 22 | { 23 | int i, state; 24 | pmodbtn_t rv = PMOD_BTN_NONE; 25 | 26 | if (!pmodbtn_initialized) 27 | pmodbtn_init(); 28 | 29 | state = P3IN; 30 | 31 | /* 32 | * Return the highest numerical button which is pressed. 33 | * 34 | * NOTE: no early-out on first hit to avoid timing side-channels 35 | */ 36 | for (i = PMOD_BTN0; i >= PMOD_BTN3; i--) 37 | { 38 | if (state & (0x1 << i)) 39 | { 40 | printf("[pmodnbtn] BTN %d pressed!\n", PMOD_BTN_TO_NUM(i) ); 41 | rv = i; 42 | } 43 | } 44 | 45 | return rv; 46 | } 47 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | For tutorial participants, the teaching setup boxes should already be flashed 2 | and properly connected to the PC. If you are not configuring the box, you can 3 | safely ignore the instructions below. 4 | 5 | ## Check connected FPGA boards 6 | 7 | This assumes five connected boards (i.e. one teaching setup). Check the 8 | script for details on programming different numbers of boards or individual 9 | FPGA units. 10 | 11 | ```bash 12 | % sudo scripts/checknflash.sh 13 | ``` 14 | 15 | ## Flash connected FPGA boards 16 | 17 | ```bash 18 | $ sudo scripts/checknflash.sh -f1 19 | ``` 20 | 21 | ## Create `dsnXX` user accounts with default password `dsnXX` in `dialout` group 22 | 23 | ```bash 24 | $ sudo scripts/create-users.sh -n2 -f0 # Creates dsn00, dsn01 25 | $ sudo scripts/create-users.sh -n2 -f0 -D # Removes dsn00, dsn01 26 | ``` 27 | 28 | ## Setup CAN network interface 29 | 30 | ```bash 31 | $ sudo scripts/slcanconfig.sh -d0 -i0 # attaches slcan0 to /dev/ttyACM0 32 | $ sudo scripts/slcanconfig.sh -d0 -i0 -D # detaches slcan0 from /dev/ttyACM0 33 | ``` 34 | 35 | ## Configure user/group permissions for CAN and USB devices 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/sgx/002-auth-exec/Enclave/encl.c: -------------------------------------------------------------------------------- 1 | #include "libspongent/spongewrap.h" 2 | #include 3 | #include "encl_t.h" 4 | 5 | /* 6 | * XXX Fill in the correct Sancus-specific key computed from the final foo.c enclave source code: 7 | * 8 | * $ sancus-crypto --key 0b7bf3ae40880a8be430d0da34fb76f0 --gen-sm-key foo --c-array main.elf 9 | */ 10 | uint8_t key[] = { 0x39, 0x8f, 0x2b, 0x56, 0x31, 0x0d, 0x58, 0xaa, 0x8c, 0xf5, 0x09, 0x23, 0x89, 0x31, 0xcb, 0x7b}; 11 | 12 | uint64_t ecall_get_challenge(void) 13 | { 14 | /* =========================== START SOLUTION =========================== */ 15 | /* ============================ END SOLUTION ============================ */ 16 | } 17 | 18 | /* 19 | * We create a MAC over: challenge (8B) | PMODBTN sensor reading (2B) 20 | * 21 | * NOTE: we use a 2B sensor reading size to ensure the total size of the buffer 22 | * is a multiple of 2 (to work around a known erratum in the Sancus crypto HW 23 | * instructions). 24 | */ 25 | #define ATTEST_MSG_SIZE (sizeof(uint64_t) + sizeof(uint16_t)) 26 | 27 | int ecall_verify_response(uint8_t *sm_mac, uint16_t btn) 28 | { 29 | /* =========================== START SOLUTION =========================== */ 30 | /* ============================ END SOLUTION ============================ */ 31 | } 32 | -------------------------------------------------------------------------------- /scripts/checknflash.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | default_numfpgas=5 4 | default_flash=0 5 | default_image="app/sancus/sancus-core-128bit-pm1spi-pm2uart-pm3p3-hatp1.mcs" 6 | 7 | OPTIND=1 # for getopt 8 | 9 | numfpgas=$default_numfpgas 10 | fpgaid="-1" 11 | flash=$default_flash 12 | 13 | while getopts "hn:i:f:" opt; do 14 | case "$opt" in 15 | h) 16 | echo "Synopsis: $0 [-h] [-n numfpgas:int] [-i fpgaid:int] [-f flash:0|1]"; 17 | exit 0; 18 | ;; 19 | n) 20 | numfpgas=$OPTARG; 21 | if [ $numfpgas -lt 0 ]; then 22 | echo "Bad numfpgas."; exit 1; 23 | fi 24 | ;; 25 | i) 26 | fpgaid=$OPTARG; 27 | if [ $fpgaid -lt 0 ]; then 28 | echo "Bad fpgaid."; exit 1; 29 | fi 30 | ;; 31 | f) 32 | flash=$OPTARG; 33 | if [ $flash -lt 0 ]; then 34 | echo "Bad flash."; exit 1; 35 | fi 36 | ;; 37 | esac 38 | done 39 | 40 | 41 | firstfpga=0 42 | lastfpga=$(expr $numfpgas - 1) 43 | 44 | if [ $fpgaid -ge 0 ]; then 45 | numfpgas=$fpgaid; 46 | firstfpga=$fpgaid; 47 | lastfpga=$fpgaid; 48 | fi 49 | 50 | for (( fpga=$firstfpga; fpga<=$lastfpga; fpga++ )); do 51 | echo -n "FPGA $fpga: "; 52 | xstest -u $fpga; 53 | if [ $flash -gt 0 ]; then 54 | echo -n "Flashing: "; 55 | xsload --usb $fpga -b xula2-lx25 --flash "$default_image"; 56 | fi 57 | done 58 | 59 | 60 | -------------------------------------------------------------------------------- /app/sgx/001-attestation-unprotected/Makefile: -------------------------------------------------------------------------------- 1 | LIBSPONGENT_DIR = ../libspongent 2 | LIBSPONGENT = $(LIBSPONGENT_DIR)/libspongent 3 | 4 | CC = gcc 5 | AS = gcc 6 | LD = gcc 7 | 8 | ifndef CAN_INTERFACE 9 | CAN_INTERFACE = "slcan0" 10 | endif 11 | 12 | CFLAGS += -fPIC \ 13 | -fno-stack-protector -fno-builtin -fno-jump-tables \ 14 | -fno-common -Wno-attributes -g -D_GNU_SOURCE -O0 \ 15 | -DCAN_INTERFACE=$(CAN_INTERFACE) 16 | INCLUDE = -I../common/ -I$(LIBSPONGENT_DIR) 17 | LDFLAGS = -lspongent -L$(LIBSPONGENT) 18 | 19 | SOURCES = $(shell ls *.c ../common/*.c) 20 | OBJECTS = $(SOURCES:.c=.o) 21 | OUTPUT = app 22 | 23 | .SILENT: 24 | all: libspongent $(OUTPUT) 25 | 26 | libspongent: 27 | $(MAKE) -C $(LIBSPONGENT) 28 | 29 | run: clean all 30 | ./$(OUTPUT) 31 | 32 | $(OUTPUT): $(BUILDDIRS) $(OBJECTS) 33 | echo "$(INDENT)[LD]" $(OBJECTS) $(LIBS) -o $(OUTPUT) 34 | $(LD) $(OBJECTS) $(LDFLAGS) -o $(OUTPUT) 35 | 36 | %.o : %.c 37 | echo "$(INDENT)[CC] " $< 38 | $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ 39 | 40 | %.o : %.S 41 | echo "$(INDENT)[AS] " $< 42 | $(AS) $(INCLUDE) -c $< -o $@ 43 | 44 | clean: $(CLEANDIRS) 45 | echo "$(INDENT)[RM]" $(OBJECTS) $(OUTPUT) 46 | rm -f $(OBJECTS) $(OUTPUT) 47 | $(MAKE) -C $(LIBSPONGENT) clean 48 | -------------------------------------------------------------------------------- /app/sancus/Makefile.include: -------------------------------------------------------------------------------- 1 | ifndef SANCUS_DIR 2 | SANCUS_SUPPORT_DIR = "/usr/local/share/sancus-support" 3 | else 4 | SANCUS_SUPPORT_DIR = ${SANCUS_DIR}/share/sancus-support 5 | endif 6 | 7 | ifndef SANCUS_SECURITY 8 | SANCUS_SECURITY = 128 9 | endif 10 | ifeq ($(SANCUS_SECURITY), 64) 11 | SANCUS_KEY = deadbeefcafebabe 12 | else 13 | SANCUS_KEY = deadbeefcafebabec0defeeddefec8ed 14 | endif 15 | 16 | CC = sancus-cc 17 | LD = sancus-ld 18 | SANCUS_CRYPTO = sancus-crypto 19 | SANCUS_SIM = sancus-sim 20 | SANCUS_LOAD = sancus-loader 21 | RM = rm -f 22 | 23 | VENDOR_ID = 1234 24 | RAM_SIZE = 16K 25 | ROM_SIZE = 41K 26 | ifndef FPGA_DEV 27 | FPGA_DEV = /dev/ttyUSB0 28 | endif 29 | FPGA_RATE = 115200 30 | 31 | VENDOR_KEY = $(shell $(SANCUS_CRYPTO) --key $(SANCUS_KEY) --gen-vendor-key $(VENDOR_ID) | xxd -p) 32 | MEMFLAGS = --ram $(RAM_SIZE) --rom $(ROM_SIZE) 33 | 34 | CFLAGS = -I$(SANCUS_SUPPORT_DIR)/include/ -Wfatal-errors -fcolor-diagnostics -g -Os 35 | LDFLAGS = -L$(SANCUS_SUPPORT_DIR)/lib/ $(MEMFLAGS) -lsm-io -ldev --inline-arithmetic --standalone --verbose 36 | SIMFLAGS = $(MEMFLAGS) 37 | CRYPTOFLAGS = --key $(VENDOR_KEY) --verbose 38 | LOADFLAGS = -device $(FPGA_DEV) -baudrate $(FPGA_RATE) 39 | 40 | ifeq ($(QUIET),1) 41 | CFLAGS += -DQUIET 42 | endif 43 | -------------------------------------------------------------------------------- /scripts/manage_accounts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | USER_PREFIX="dsn" 4 | USER_EXPIRE="+10 days" 5 | 6 | 7 | num_users=1 8 | first_user=0 9 | delete=0 10 | 11 | while getopts "hDn:f:" opt; do 12 | case "$opt" in 13 | h) 14 | echo "Synopsis: $0 [-h] [-n num_users:int] [-f first_user:int] [-D]"; 15 | echo "Example 1: $0 -n2 -f1 # creates ${USER_PREFIX}01, ${USER_PREFIX}02"; 16 | exit 0; 17 | ;; 18 | n) 19 | num_users=$OPTARG; 20 | if [ $num_users -lt 0 ]; then 21 | echo "Bad num_users."; exit 1; 22 | fi 23 | ;; 24 | f) 25 | first_user=$OPTARG; 26 | if [ $first_user -lt 0 ]; then 27 | echo "Bad first_user."; exit 1; 28 | fi 29 | ;; 30 | D) 31 | delete=1; 32 | ;; 33 | esac 34 | done 35 | 36 | firstunum=$first_user 37 | lastunum=$(expr $first_user + $num_users - 1) 38 | 39 | for (( unum=$firstunum; unum<=$lastunum; unum++ )); do 40 | USR=$(printf "%b%02d" $USER_PREFIX $unum) 41 | EXP=$(date -d "$USER_EXPIRE" "+%Y-%m-%d") 42 | echo -n "User $USR expires on $EXP: " 43 | 44 | if [ $delete -eq 1 ]; then 45 | userdel -r $USR 46 | if [ $? -ne 0 ]; then 47 | echo "failed."; exit 1; 48 | fi 49 | echo "deleted." 50 | else 51 | useradd --groups dialout --expiredate $EXP -m -U $USR 52 | if [ $? -ne 0 ]; then 53 | echo "failed."; exit 1; 54 | fi 55 | echo "$USR:$USR" | chpasswd 56 | if [ $? -ne 0 ]; then 57 | echo "failed."; exit 1; 58 | fi 59 | echo "created." 60 | fi 61 | done 62 | 63 | -------------------------------------------------------------------------------- /app/sgx/000-pin/Makefile: -------------------------------------------------------------------------------- 1 | ENCLAVE = Enclave 2 | SUBDIRS = $(ENCLAVE) 3 | 4 | CC = gcc 5 | AS = gcc 6 | LD = gcc 7 | 8 | CFLAGS += -fPIC -fno-stack-protector -fno-builtin -fno-jump-tables \ 9 | -fno-common -Wno-attributes -g -D_GNU_SOURCE -O0 10 | INCLUDE = -I$(SGX_SDK)/include/ -I../common/ 11 | LDFLAGS += -lencl_proxy -lsgx_urts \ 12 | -lsgx_uae_service -pthread $(SUBDIRS:%=-L %) -L$(SGX_SDK)/lib64/ 13 | 14 | SOURCES = $(shell ls *.c ../common/*.c) 15 | OBJECTS = $(SOURCES:.c=.o) 16 | OUTPUT = app 17 | 18 | BUILDDIRS = $(SUBDIRS:%=build-%) 19 | CLEANDIRS = $(SUBDIRS:%=clean-%) 20 | 21 | 22 | .SILENT: 23 | all: $(OUTPUT) 24 | 25 | run: clean all 26 | ./$(OUTPUT) 27 | 28 | $(OUTPUT): $(BUILDDIRS) $(OBJECTS) 29 | echo "$(INDENT)[LD]" $(OBJECTS) $(LIBS) -o $(OUTPUT) 30 | $(LD) $(OBJECTS) $(LDFLAGS) -o $(OUTPUT) 31 | 32 | %.o : %.c 33 | echo "$(INDENT)[CC] " $< 34 | $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ 35 | 36 | %.o : %.S 37 | echo "$(INDENT)[AS] " $< 38 | $(AS) $(INCLUDE) -c $< -o $@ 39 | 40 | clean: $(CLEANDIRS) 41 | echo "$(INDENT)[RM]" $(OBJECTS) $(OUTPUT) 42 | rm -f $(OBJECTS) $(OUTPUT) 43 | 44 | $(BUILDDIRS): 45 | echo "$(INDENT)[===] $(@:build-%=%) [===]" 46 | $(MAKE) -C $(@:build-%=%) INDENT+="$(INDENT_STEP)" curr-dir=$(curr-dir)/$(@:build-%=%) 47 | 48 | $(CLEANDIRS): 49 | echo "$(INDENT)[===] $(@:clean-%=%) [===]" 50 | $(MAKE) clean -C $(@:clean-%=%) INDENT+="$(INDENT_STEP)" curr-dir=$(curr-dir)/$(@:build-%=%) 51 | -------------------------------------------------------------------------------- /app/sgx/000-pin/main.c: -------------------------------------------------------------------------------- 1 | /* utility headers */ 2 | #include "debug.h" 3 | 4 | /* SGX untrusted runtime */ 5 | #include 6 | #include "Enclave/encl_u.h" 7 | 8 | /* define untrusted OCALL functions here */ 9 | 10 | void ocall_print(const char *str) 11 | { 12 | info("ocall_print: enclave says: '%s'", str); 13 | } 14 | 15 | int ocall_get_pin(void) 16 | { 17 | int pin = 0; 18 | printf("enter PIN code > "); 19 | scanf("%d", &pin); 20 | return pin; 21 | } 22 | 23 | sgx_enclave_id_t create_enclave(void) 24 | { 25 | sgx_launch_token_t token = {0}; 26 | int updated = 0; 27 | sgx_enclave_id_t eid = -1; 28 | 29 | info_event("Creating enclave..."); 30 | SGX_ASSERT( sgx_create_enclave( "./Enclave/encl.so", /*debug=*/1, 31 | &token, &updated, &eid, NULL ) ); 32 | 33 | return eid; 34 | } 35 | 36 | int main( int argc, char **argv ) 37 | { 38 | sgx_enclave_id_t eid = create_enclave(); 39 | int rv = 1, secret = 0; 40 | 41 | /* ---------------------------------------------------------------------- */ 42 | info_event("calling enclave..."); 43 | 44 | SGX_ASSERT( ecall_dummy(eid, &rv, 1) ); 45 | info("ecall_dummy(1) enclave entry point returned %d", rv); 46 | 47 | /* =========================== START SOLUTION =========================== */ 48 | info("ecall_get_secret enclave entry point returned %d (secret 0x%x)", 49 | rv, secret); 50 | /* ============================ END SOLUTION ============================ */ 51 | 52 | /* ---------------------------------------------------------------------- */ 53 | info_event("destroying SGX enclave"); 54 | SGX_ASSERT( sgx_destroy_enclave( eid ) ); 55 | 56 | info("all is well; exiting.."); 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /app/sgx/common/can.c: -------------------------------------------------------------------------------- 1 | #include "can.h" 2 | #include "debug.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int can_open(char *ican) 10 | { 11 | int can_socket; 12 | struct sockaddr_can can_addr; 13 | 14 | info("Creating Linux CAN socket for interface '%s'...", ican); 15 | ASSERT( (can_socket = socket(PF_CAN, SOCK_RAW, CAN_RAW)) >= 0 ); 16 | 17 | memset(&can_addr, 0, sizeof(can_addr)); 18 | can_addr.can_family = AF_CAN; 19 | ASSERT( (can_addr.can_ifindex = if_nametoindex(ican)) ); 20 | ASSERT( bind(can_socket, (struct sockaddr *)&can_addr, sizeof(can_addr)) >= 0 ); 21 | 22 | return can_socket; 23 | } 24 | 25 | void can_dump_frame(char *msg, struct can_frame *frame) 26 | { 27 | info("%s: CAN frame with ID 0x%x (len=%d)", msg, frame->can_id, frame->can_dlc); 28 | dump_hex("MSG ", frame->data, frame->can_dlc); 29 | } 30 | 31 | int can_send(int can_socket, uint16_t id, uint8_t *buf, size_t len) 32 | { 33 | struct can_frame frame; 34 | int i; 35 | ASSERT(len <= CAN_PAYLOAD_SIZE); 36 | 37 | frame.can_id = id; 38 | frame.can_dlc = len; 39 | for (i=0; i < len; i++) 40 | frame.data[i] = buf[i]; 41 | 42 | can_dump_frame("send", &frame); 43 | 44 | return write(can_socket, &frame, CAN_MTU); 45 | } 46 | 47 | int can_recv(int can_socket, uint16_t *id, uint8_t *buf) 48 | { 49 | struct can_frame frame; 50 | int i; 51 | ASSERT( recv(can_socket, &frame, sizeof(frame), 0) == CAN_MTU ); 52 | 53 | *id = frame.can_id; 54 | for (i=0; i < frame.can_dlc; i++) 55 | buf[i] = frame.data[i]; 56 | 57 | can_dump_frame("recv", &frame); 58 | 59 | return frame.can_dlc; 60 | } 61 | 62 | int can_close(int can_socket) 63 | { 64 | return close(can_socket); 65 | } 66 | -------------------------------------------------------------------------------- /app/sgx/002-auth-exec/Makefile: -------------------------------------------------------------------------------- 1 | ENCLAVE = Enclave 2 | SUBDIRS = $(ENCLAVE) 3 | 4 | CC = gcc 5 | AS = gcc 6 | LD = gcc 7 | 8 | ifndef CAN_INTERFACE 9 | CAN_INTERFACE = "slcan0" 10 | endif 11 | 12 | CFLAGS += -fPIC \ 13 | -fno-stack-protector -fno-builtin -fno-jump-tables \ 14 | -fno-common -Wno-attributes -g -D_GNU_SOURCE -O0 \ 15 | -DCAN_INTERFACE=$(CAN_INTERFACE) 16 | INCLUDE = -I$(SGX_SDK)/include/ -I../common/ 17 | LDFLAGS += -lencl_proxy -lsgx_urts \ 18 | -lsgx_uae_service -pthread $(SUBDIRS:%=-L %) -L$(SGX_SDK)/lib64/ 19 | 20 | SOURCES = $(shell ls *.c ../common/*.c) 21 | OBJECTS = $(SOURCES:.c=.o) 22 | OUTPUT = app 23 | 24 | BUILDDIRS = $(SUBDIRS:%=build-%) 25 | CLEANDIRS = $(SUBDIRS:%=clean-%) 26 | 27 | 28 | .SILENT: 29 | all: $(OUTPUT) 30 | 31 | run: clean all 32 | ./$(OUTPUT) 33 | 34 | $(OUTPUT): $(BUILDDIRS) $(OBJECTS) 35 | echo "$(INDENT)[LD]" $(OBJECTS) $(LIBS) -o $(OUTPUT) 36 | $(LD) $(OBJECTS) $(LDFLAGS) -o $(OUTPUT) 37 | 38 | %.o : %.c 39 | echo "$(INDENT)[CC] " $< 40 | $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ 41 | 42 | %.o : %.S 43 | echo "$(INDENT)[AS] " $< 44 | $(AS) $(INCLUDE) -c $< -o $@ 45 | 46 | clean: $(CLEANDIRS) 47 | echo "$(INDENT)[RM]" $(OBJECTS) $(OUTPUT) 48 | rm -f $(OBJECTS) $(OUTPUT) 49 | 50 | $(BUILDDIRS): 51 | echo "$(INDENT)[===] $(@:build-%=%) [===]" 52 | $(MAKE) -C $(@:build-%=%) INDENT+="$(INDENT_STEP)" curr-dir=$(curr-dir)/$(@:build-%=%) 53 | 54 | $(CLEANDIRS): 55 | echo "$(INDENT)[===] $(@:clean-%=%) [===]" 56 | $(MAKE) clean -C $(@:clean-%=%) INDENT+="$(INDENT_STEP)" curr-dir=$(curr-dir)/$(@:build-%=%) 57 | -------------------------------------------------------------------------------- /app/sgx/001-attestation/Makefile: -------------------------------------------------------------------------------- 1 | ENCLAVE = Enclave 2 | SUBDIRS = $(ENCLAVE) 3 | 4 | CC = gcc 5 | AS = gcc 6 | LD = gcc 7 | 8 | ifndef CAN_INTERFACE 9 | CAN_INTERFACE = "slcan0" 10 | endif 11 | 12 | CFLAGS += -fPIC \ 13 | -fno-stack-protector -fno-builtin -fno-jump-tables \ 14 | -fno-common -Wno-attributes -g -D_GNU_SOURCE -O0 \ 15 | -DCAN_INTERFACE=$(CAN_INTERFACE) 16 | INCLUDE = -I$(SGX_SDK)/include/ -I../common/ 17 | LDFLAGS += -lencl_proxy -lsgx_urts \ 18 | -lsgx_uae_service -pthread $(SUBDIRS:%=-L %) -L$(SGX_SDK)/lib64/ 19 | 20 | SOURCES = $(shell ls *.c ../common/*.c) 21 | OBJECTS = $(SOURCES:.c=.o) 22 | OUTPUT = app 23 | 24 | BUILDDIRS = $(SUBDIRS:%=build-%) 25 | CLEANDIRS = $(SUBDIRS:%=clean-%) 26 | 27 | 28 | .SILENT: 29 | all: $(OUTPUT) 30 | 31 | run: clean all 32 | ./$(OUTPUT) 33 | 34 | $(OUTPUT): $(BUILDDIRS) $(OBJECTS) 35 | echo "$(INDENT)[LD]" $(OBJECTS) $(LIBS) -o $(OUTPUT) 36 | $(LD) $(OBJECTS) $(LDFLAGS) -o $(OUTPUT) 37 | 38 | %.o : %.c 39 | echo "$(INDENT)[CC] " $< 40 | $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ 41 | 42 | %.o : %.S 43 | echo "$(INDENT)[AS] " $< 44 | $(AS) $(INCLUDE) -c $< -o $@ 45 | 46 | clean: $(CLEANDIRS) 47 | echo "$(INDENT)[RM]" $(OBJECTS) $(OUTPUT) 48 | rm -f $(OBJECTS) $(OUTPUT) 49 | 50 | $(BUILDDIRS): 51 | echo "$(INDENT)[===] $(@:build-%=%) [===]" 52 | $(MAKE) -C $(@:build-%=%) INDENT+="$(INDENT_STEP)" curr-dir=$(curr-dir)/$(@:build-%=%) 53 | 54 | $(CLEANDIRS): 55 | echo "$(INDENT)[===] $(@:clean-%=%) [===]" 56 | $(MAKE) clean -C $(@:clean-%=%) INDENT+="$(INDENT_STEP)" curr-dir=$(curr-dir)/$(@:build-%=%) 57 | -------------------------------------------------------------------------------- /app/sgx/common/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG_H_INC 2 | #define DEBUG_H_INC 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define ASSERT(cond) \ 9 | do { \ 10 | if (!(cond)) \ 11 | { \ 12 | perror("[" __FILE__ "] assertion '" #cond "' failed"); \ 13 | abort(); \ 14 | } \ 15 | } while(0) 16 | 17 | #define SGX_ASSERT(f) { if ( SGX_SUCCESS != (enclave_rv = (f)) ) \ 18 | { \ 19 | printf( "Error calling enclave at %s:%d (rv=0x%x)\n", __FILE__, \ 20 | __LINE__, enclave_rv); \ 21 | abort(); \ 22 | } } 23 | 24 | #define info(msg, ...) \ 25 | do { \ 26 | printf("[" __FILE__ "] " msg "\n", ##__VA_ARGS__); \ 27 | fflush(stdout); \ 28 | } while(0) 29 | 30 | #define info_event(msg, ...) \ 31 | do { \ 32 | printf("\n--------------------------------------------------------------------------------\n"); \ 33 | info(msg,##__VA_ARGS__); \ 34 | printf("--------------------------------------------------------------------------------\n\n"); \ 35 | } while(0) 36 | 37 | extern int enclave_rv; 38 | 39 | void dump_hex(char *str, uint8_t *buf, int len); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /app/sancus/000-blinking-led/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "vulcan/drivers/mcp2515.h" 4 | #include "pmodled.h" 5 | #include "pmodbtn.h" 6 | 7 | #define BLINKING_DELAY 999999999 8 | #define CAN_ID 0x40 9 | #define MSG_LEN CAN_PAYLOAD_SIZE 10 | 11 | DECLARE_ICAN(msp_ican, /*spi_ss=*/1, CAN_500_KHZ); 12 | 13 | int main() 14 | { 15 | volatile long i; 16 | uint8_t led = 0; 17 | uint8_t msg[MSG_LEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; 18 | pmodbtn_t btn = PMOD_BTN_NONE; 19 | 20 | /* ---------------------------------------------------------------------- */ 21 | msp430_io_init(); 22 | pr_info("initializing hardware..."); 23 | pmodled_init(); 24 | pmodbtn_init(); 25 | ican_init(&msp_ican); 26 | 27 | /* ---------------------------------------------------------------------- */ 28 | pr_info("entering blinking led loop (press any button).."); 29 | 30 | while ((btn = pmodbtn_poll()) == PMOD_BTN_NONE) 31 | { 32 | pmodled_toggle(PMOD_LED1 + led); 33 | for (i=0; i < BLINKING_DELAY; i++); 34 | for (i=0; i < BLINKING_DELAY; i++); 35 | pmodled_toggle(PMOD_LED1 + led); 36 | 37 | led++; 38 | led = (led % 3); 39 | } 40 | 41 | /* ---------------------------------------------------------------------- */ 42 | pr_info("press btn number to toggle led.."); 43 | 44 | while (1) { 45 | pmodled_toggle(PMOD_LED0 + PMOD_BTN_TO_NUM(btn)); 46 | 47 | if ((btn = pmodbtn_poll()) != PMOD_BTN_NONE) 48 | { 49 | pr_info("waiting for button release..."); 50 | while (pmodbtn_poll() != PMOD_BTN_NONE); 51 | pr_info("button released!"); 52 | 53 | if (btn == PMOD_BTN0) 54 | { 55 | pr_info("sending dummy CAN message (block wait)..."); 56 | ican_send(&msp_ican, CAN_ID, msg, MSG_LEN, /*block=*/1); 57 | can_dump_regs(&msp_ican); 58 | } 59 | } 60 | } 61 | 62 | pr_info("all done!"); 63 | EXIT(); 64 | } 65 | -------------------------------------------------------------------------------- /app/sancus/001-attestation/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "vulcan/drivers/mcp2515.h" 4 | #include "foo.h" 5 | 6 | #if SANCUS_TAG_SIZE != (CAN_PAYLOAD_SIZE*2) 7 | #error expecting 128-bit Sancus core 8 | #endif 9 | 10 | #define CAN_ATTEST_ID 0x40 11 | #define CAN_SEND_DELAY 999999999 12 | 13 | DECLARE_ICAN(msp_ican, /*spi_ss=*/1, CAN_500_KHZ); 14 | 15 | int main() 16 | { 17 | volatile long i; 18 | uint16_t can_id = 0x0; 19 | int can_msg_len = 0x0; 20 | uint8_t mac[SANCUS_TAG_SIZE] = {0x0}; 21 | uint8_t msg[CAN_PAYLOAD_SIZE] = {0x0}; 22 | 23 | /* ---------------------------------------------------------------------- */ 24 | msp430_io_init(); 25 | pr_info("initializing hardware..."); 26 | ican_init(&msp_ican); 27 | 28 | pr_info("enabling foo SM..."); 29 | sancus_enable(&foo); 30 | pr_sm_info(&foo); 31 | pr_info1("calc_foo(1) is %d\n", calc_foo(1) ); 32 | 33 | /* ---------------------------------------------------------------------- */ 34 | pr_info("waiting for attestation challenge CAN message..."); 35 | can_msg_len = ican_recv(&msp_ican, &can_id, msg, /*block=*/1); 36 | dump_buf(msg, can_msg_len, "MSG"); 37 | ASSERT( (can_id == CAN_ATTEST_ID) && "unexpected CAN attestation challenge message format" ); 38 | 39 | /* ---------------------------------------------------------------------- */ 40 | pr_info("calling into foo SM for MAC over attestation nonce..."); 41 | /* =========================== START SOLUTION =========================== */ 42 | /* ============================ END SOLUTION ============================ */ 43 | dump_buf(mac, SANCUS_TAG_SIZE, "MAC"); 44 | 45 | /* ---------------------------------------------------------------------- */ 46 | pr_info("replying with MAC(nonce) attestation CAN message..."); 47 | can_msg_len = 48 | ican_send(&msp_ican, CAN_ATTEST_ID, &mac[0], CAN_PAYLOAD_SIZE, /*block=*/1); 49 | for (i=0; i < CAN_SEND_DELAY; i++); 50 | for (i=0; i < CAN_SEND_DELAY; i++); 51 | ican_send(&msp_ican, CAN_ATTEST_ID, &mac[SANCUS_TAG_SIZE/2], CAN_PAYLOAD_SIZE, /*block=*/1); 52 | 53 | pr_info("all done!"); 54 | EXIT(); 55 | } 56 | -------------------------------------------------------------------------------- /scripts/manage_ifs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | USER_PREFIX="dsn" 4 | 5 | 6 | num_users=1 7 | first_user=0 8 | delete=0 9 | user_prefix=${USER_PREFIX} 10 | dont=0 11 | 12 | while getopts "hdDn:f:u:" opt; do 13 | case "$opt" in 14 | h) 15 | echo "Synopsis: $0 [-h] [-n num_users:int] [-f first_user:int] \\" 16 | echo " [-u user_prefix:str] [-D] [-d]"; 17 | echo "Example 1: $0 -n2 -f1 # creates ${USER_PREFIX}01, ${USER_PREFIX}02"; 18 | exit 0; 19 | ;; 20 | n) 21 | num_users=$OPTARG; 22 | if [ $num_users -lt 0 ]; then 23 | echo "Bad num_users."; exit 1; 24 | fi 25 | ;; 26 | f) 27 | first_user=$OPTARG; 28 | if [ $first_user -lt 0 ]; then 29 | echo "Bad first_user."; exit 1; 30 | fi 31 | ;; 32 | u) user_prefix=$OPTARG; 33 | ;; 34 | d) dont=1; 35 | ;; 36 | D) 37 | delete=1; 38 | ;; 39 | esac 40 | done 41 | 42 | firstunum=$first_user 43 | lastunum=$(expr $first_user + $num_users - 1) 44 | 45 | acmnum=0 # /dev/ttyACM${acmnum} 46 | slcnum=0 # slcan${slcnum} 47 | ttyctr=0 # /dev/ttyUSB${ttyctr} -- program upload 48 | ttydbg=1 # /dev/ttyUSB${ttydbg} -- debug output 49 | 50 | for (( unum=$firstunum; unum<=$lastunum; unum++ )); do 51 | USR=$(printf "%b%02d" $user_prefix $unum) 52 | 53 | echo "User $USR: /dev/ttyACM${acmnum} -> slcan${slcnum}:" 54 | echo -n " " 55 | 56 | if [ $delete -eq 1 ]; then 57 | if [ $dont -eq 0 ]; then 58 | ./slcanconfig.sh -d${acmnum} -i${slcnum} -D; 59 | fi 60 | if [ $? -ne 0 ]; then 61 | echo "failed."; exit 1; 62 | fi 63 | echo "deleted." 64 | else 65 | if [ $dont -eq 0 ]; then 66 | chown ${USR}:${USR} \ 67 | /dev/ttyACM${acmnum} \ 68 | /dev/ttyUSB${ttyctr} /dev/ttyUSB${ttydbg}; 69 | fi 70 | if [ $? -ne 0 ]; then 71 | echo "failed."; exit 1; 72 | fi 73 | if [ $dont -eq 0 ]; then 74 | ./slcanconfig.sh -d${acmnum} -i${slcnum}; 75 | fi 76 | if [ $? -ne 0 ]; then 77 | echo "failed."; exit 1; 78 | fi 79 | echo "created." 80 | fi 81 | 82 | acmnum=$(( $acmnum + 1 )) 83 | slcnum=$(( $slcnum + 1 )) 84 | ttyctr=$(( $ttyctr + 2 )) 85 | ttydbg=$(( $ttydbg + 2 )) 86 | done 87 | 88 | -------------------------------------------------------------------------------- /app/sgx/001-attestation-unprotected/README.md: -------------------------------------------------------------------------------- 1 | # Attestation: unprotected remote verifier application 2 | 3 | ## Application overview 4 | 5 | The purpose of this application is to allow you to get started quickly with 6 | implementing the attestation response code on the Sancus MSP430 side. The 7 | program in this directory therefore completely takes care of the remote 8 | verifier part of the remote attestation protocol (depicted below). 9 | Specifically, the program performs the following steps: 10 | 11 | 1. Query the verifier (you) for a unique 64-bit attestation challenge *n*. 12 | 2. Construct a CAN message in the expected format destined for the MSP430 13 | untrusted runtime. 14 | 3. Wait for the two CAN messages with the 128-bit attestation response. 15 | 4. Compute the expected attestation response *MAC(K_N_SP_SM, n)*. 16 | 5. Compare the received and expected responses and print whether remote 17 | attestation succeeded or not. 18 | 19 | ![attestation-overview](https://distrinet.cs.kuleuven.be/software/sancus/images/dsn18-attestation.png) 20 | 21 | **Note.** To get started, we focus on implementing the Sancus MSP430 side 22 | first, and for now we completely trust the PC side. The program in this 23 | directory therefore runs completely unprotected. 24 | In the following exercises (`../001-attesation-enclave`), we will relax this 25 | TCB requirement by implementing the remote stakeholder's critical attestation 26 | verification code in an SGX enclave. 27 | 28 | ## Your task 29 | 30 | Simply running the program suffices to send and receive CAN messages and get 31 | started on implementing the Sancus MSP430 side of the attestation protocol. 32 | After this is done, however, in order to successfully complete the remote 33 | attestation protocol, you will still need to generate and fill in the Sancus 34 | module-specific key in `main.c`. We refer to 35 | `../../sancus/001-attestation/README.md` for detailed instructions on how to 36 | do this. 37 | 38 | ## Building and running 39 | 40 | First upload the `../../sancus/001-attestation` Sancus program to the MSP430 41 | FPGA, then run the verifier program as follows: 42 | 43 | ```bash 44 | $ make run CAN_INTERFACE=slcanN 45 | ``` 46 | 47 | **Note.** Here, slcanN refers to the CAN network interface you are using to 48 | communicate with the MSP430 FPGA. slcan0 is the default if you ommit this 49 | parameter. 50 | -------------------------------------------------------------------------------- /scripts/slcanconfig.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | OPTIND=1 # for getopt 4 | 5 | acmnum="-1" 6 | slcnum="-1" 7 | detach="-1" 8 | 9 | while getopts "hDd:i:" opt; do 10 | case "$opt" in 11 | h) 12 | echo "Synopsis: $0 [-h] [-d ttyACMX:int] [-i slcanY:int] [-D]"; 13 | echo "Example 1: $0 -d3 -i0 # attaches slcan0 to /dev/ttyACM3"; 14 | echo "Example 2: $0 -d3 -i0 -D # detaches slcan0 from /dev/ttyACM3"; 15 | exit 0; 16 | ;; 17 | d) 18 | acmnum=$OPTARG; 19 | if [ $acmnum -lt 0 ]; then 20 | echo "Bad acmnum."; exit 1; 21 | fi 22 | ;; 23 | i) 24 | slcnum=$OPTARG; 25 | if [ $slcnum -lt 0 ]; then 26 | echo "Bad slnum."; exit 1; 27 | fi 28 | ;; 29 | D) 30 | detach=1; 31 | ;; 32 | esac 33 | done 34 | 35 | if [ $acmnum -eq -1 -o $slcnum -eq -1 ]; then 36 | echo "We cannot. Provide -dX and -iY."; 37 | exit 1; 38 | fi 39 | 40 | SPEED=6 # baudrate 500k 41 | DEV="/dev/ttyACM$acmnum" # serial device 42 | ICAN="slcan$slcnum" # network interface 43 | 44 | if [ $detach -eq 1 ]; then 45 | echo "Detaching $ICAN and $DEV..." 46 | psline=`ps ax | grep slcand | grep $DEV | grep $ICAN` 47 | if [ $? -ne 0 ]; then 48 | echo "- We cannot. Device not configured."; exit 1; 49 | fi 50 | pid=`echo $psline | awk -F" " '{if ($1) print $1}'` 51 | numpids=`echo $pid | wc -w` 52 | if [ $numpids -ne 1 ]; then 53 | echo "- We cannot. Multiple slcand for this configuration."; exit 1; 54 | fi 55 | ifconfig $ICAN down 56 | if [ $? -ne 0 ]; then 57 | echo "- We cannot."; exit 1; 58 | fi 59 | kill $pid 60 | ifconfig $ICAN down 61 | if [ $? -ne 0 ]; then 62 | echo "- We cannot."; exit 1; 63 | fi 64 | slcan_attach -c -d $DEV 65 | if [ $? -ne 0 ]; then 66 | echo "- We cannot."; exit 1; 67 | fi 68 | echo "+ Success." 69 | else 70 | echo "Attaching $ICAN and $DEV..." 71 | 72 | # https://www.fischl.de/usbtin/linux_can_socketcan/ 73 | slcan_attach -f -s$SPEED -o $DEV 74 | if [ $? -ne 0 ]; then 75 | echo "- We cannot."; exit 1; 76 | fi 77 | slcand $DEV $ICAN 78 | if [ $? -ne 0 ]; then 79 | echo "- We cannot."; exit 1; 80 | fi 81 | ifconfig $ICAN up 82 | if [ $? -ne 0 ]; then 83 | echo "- We cannot."; exit 1; 84 | fi 85 | echo "+ Success." 86 | fi 87 | 88 | -------------------------------------------------------------------------------- /app/sancus/README.md: -------------------------------------------------------------------------------- 1 | # Sancus enclave applications 2 | 3 | This directory collects the tutorial code to be ran on 4 | [Sancus](https://distrinet.cs.kuleuven.be/software/sancus/)-enabled MSP430 5 | MCUs. 6 | 7 | ## Exercises overview 8 | 9 | Exercises are organized in increasing complexity as follows: 10 | 11 | - **000-blinking-led:** basic _unprotected_ application to test tutorial hardware setup. 12 | - **001-attestation:** cryptographically prove untampered protected execution 13 | to remote stakeholders. 14 | - **002-auth-exec:** TODO 15 | 16 | ## 000: Blinking LEDs 17 | 18 | The classic hardware-level "hello world" counterpart. The purpose of this 19 | application is to test the basic hardware setup for an _unprotected_ 20 | example program (i.e., without leveraging the secure Sancus CPU extensions yet). 21 | 22 | **Your task.** Build and run the unmodified example program, play around with 23 | the buttons, and inspect associated debug and CAN output. 24 | 25 | **Goals.** After this exercise, you should be able to: 26 | 27 | * Build and upload C applications to the MSP430 FPGA. 28 | * Inspect debug output from the FPGA via the serial `/dev/ttyUSB1` UART 29 | connection. 30 | * Inspect CAN messages from the FPGA with the `candump` utility. 31 | 32 | ## 001: Remote attestation 33 | 34 | The purpose of this application is to cryptographically prove to a remote 35 | stakeholder that her Sancus enclave has been loaded untampered with protection 36 | enabled on a genuine Sancus-enabled MSP430 CPU. 37 | 38 | **Your task.** Implement remote attestation for the `foo.c` Sancus enclave, and 39 | extend the untrusted `main.c` runtime to properly forward attestation 40 | challenges and responses over the local CAN network. 41 | 42 | **Goals.** After this exercise, you should be able to: 43 | 44 | * Understand remote attestation concepts. 45 | * Create minimalistic Sancus enclaves with ecalls (`SM_ENTRY`), private 46 | data (`SM_DATA`), and function calls (`SM_FUNC`). 47 | * Thwart basic protocol-level replay attacks via the proper use of nonces. 48 | * Understand the dangers of untrusted pointer dereferences in enclave programs. 49 | 50 | ## 002: Authentic execution 51 | 52 | The purpose of this application is to extend the remote attestation protocol of 53 | the previous exercise to include proof of an authentic local PmodBTN sensor 54 | reading (plus corresponding PmodLED actuation event). 55 | 56 | **Goals.** After this exercise, you should be able to: 57 | 58 | * Understand local attestation concepts and transitive trust relations. 59 | * Securely link to Sancus secure I/O driver enclaves. 60 | -------------------------------------------------------------------------------- /app/sancus/000-blinking-led/README.md: -------------------------------------------------------------------------------- 1 | # Blinking-led: unprotected hardware setup test program 2 | 3 | ## Application overview 4 | 5 | The purpose of this application is to test the basic hardware setup for an 6 | _unprotected_ example program (i.e., without leveraging the secure Sancus CPU 7 | extensions yet). The application should fist cycle through LEDs1-3, while 8 | waiting for user input from the BTNs module. Pressing BTNs1-3 will toggle the 9 | corresponding LEDs, whereas BTN0 will send out a CAN message (this may block 10 | when no other device is listening on the CAN bus). 11 | 12 | ![fpga-board](https://distrinet.cs.kuleuven.be/software/sancus/images/dsn18-fpga.jpg) 13 | 14 | ## Your task 15 | 16 | Build and run the unmodified example program, play around with 17 | the buttons, and inspect associated debug and CAN output. 18 | 19 | ![tutorial-hardware](https://distrinet.cs.kuleuven.be/software/sancus/images/dsn18-hardware.png) 20 | 21 | ## Building and running 22 | 23 | The FPGA is connected to the PC via two UART USB serial lines (`/dev/ttyUSB*`) and 24 | one CAN network interface (`slcan*`). 25 | Before uploading and running the MSP430 application, you should prepare the PC 26 | side to receive CAN messages and debug output in separate terminals. 27 | 28 | ### Monitoring application debug output via downlink 29 | 30 | We rely on the GNU `screen` utility to read the stdio UART serial device at a baudrate of 115200. 31 | Simply execute (in a separate terminal): 32 | 33 | ```bash 34 | $ screen /dev/ttyUSB1 115200 # in case of permission errors, replace `USB1` with the 35 | # downlink UART USB device that was assigned to your FPGA 36 | ``` 37 | 38 | ### Monitoring application CAN network interface 39 | 40 | To dump all incoming CAN frames at the PC side, simply execute (in a separate 41 | terminal): 42 | 43 | ```bash 44 | $ candump slcan0 # in case of permission errors, replace `slcan0` with the CAN 45 | # network interface that was assigned to your FPGA 46 | ``` 47 | 48 | ### Uploading application via uplink 49 | 50 | Finally, use `make load` to build and upload the application binary to the FPGA 51 | over the downlink UART USB connection `/dev/ttyUSB0`. 52 | 53 | ```bash 54 | $ FPGA_DEV=/dev/ttyUSB0 make load # in case of permission errors, replace `USB0` with the 55 | # uplink UART USB device that was assigned to your FPGA 56 | ``` 57 | 58 | ## Expected behavior 59 | 60 | Pressing BTNs1-3 should light up the corresponding LEDs and result in debug 61 | output on the downlink. Pressing BTN0 should result in the following CAN 62 | message being printed by `candump`: 63 | 64 | ``` 65 | slcan0 040 [8] 00 11 22 33 44 55 66 77 66 | ``` 67 | -------------------------------------------------------------------------------- /app/sancus/002-auth-exec/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "vulcan/drivers/mcp2515.h" 4 | #include "foo.h" 5 | #include "pmodbtn.h" 6 | #include "pmodled.h" 7 | 8 | #if SANCUS_TAG_SIZE != (CAN_PAYLOAD_SIZE*2) 9 | #error expecting 128-bit Sancus core 10 | #endif 11 | 12 | #define CAN_ATTEST_ID 0x40 13 | #define CAN_SEND_DELAY 999999999 14 | 15 | DECLARE_ICAN(msp_ican, /*spi_ss=*/1, CAN_500_KHZ); 16 | 17 | int main() 18 | { 19 | volatile long i; 20 | uint16_t can_id = 0x0; 21 | int can_msg_len = 0x0; 22 | uint8_t msg[CAN_PAYLOAD_SIZE] = {0x0}; 23 | uint8_t mac[SANCUS_TAG_SIZE] = {0x0}; 24 | uint16_t btn = 0x0; 25 | 26 | /* ---------------------------------------------------------------------- */ 27 | msp430_io_init(); 28 | pr_info("initializing hardware..."); 29 | ican_init(&msp_ican); 30 | 31 | pr_info("enabling foo SM..."); 32 | sancus_enable(&foo); 33 | pr_sm_info(&foo); 34 | pr_info1("calc_foo(1) is %d\n", calc_foo(1) ); 35 | 36 | pr_info("enabling PMODBTN SM..."); 37 | sancus_enable(&pmodbtn); 38 | pr_sm_info(&pmodbtn); 39 | 40 | pr_info("enabling PMODLED SM..."); 41 | sancus_enable(&pmodled); 42 | pr_sm_info(&pmodled); 43 | 44 | while (1) 45 | { 46 | /* ---------------------------------------------------------------------- */ 47 | pr_info("waiting for attestation challenge CAN message..."); 48 | can_msg_len = ican_recv(&msp_ican, &can_id, msg, /*block=*/1); 49 | dump_buf(msg, can_msg_len, "MSG"); 50 | if ( (can_id != CAN_ATTEST_ID) ) 51 | pr_info( "WARNING: unexpected CAN button request message format" ); 52 | 53 | /* ---------------------------------------------------------------------- */ 54 | pr_info("calling into foo SM for MAC over attestation nonce..."); 55 | ASSERT( !attest_foo(msg, can_msg_len, &btn, mac) ); 56 | dump_buf(mac, SANCUS_TAG_SIZE, "MAC"); 57 | 58 | /* ---------------------------------------------------------------------- */ 59 | pr_info("replying with MAC(nonce) attestation CAN message..."); 60 | can_msg_len = 61 | ican_send(&msp_ican, CAN_ATTEST_ID, (uint8_t*) &btn, sizeof(uint16_t), /*block=*/1); 62 | for (i=0; i < CAN_SEND_DELAY; i++); 63 | for (i=0; i < CAN_SEND_DELAY; i++); 64 | ican_send(&msp_ican, CAN_ATTEST_ID, &mac[0], CAN_PAYLOAD_SIZE, /*block=*/1); 65 | for (i=0; i < CAN_SEND_DELAY; i++); 66 | for (i=0; i < CAN_SEND_DELAY; i++); 67 | ican_send(&msp_ican, CAN_ATTEST_ID, &mac[SANCUS_TAG_SIZE/2], CAN_PAYLOAD_SIZE, /*block=*/1); 68 | } 69 | 70 | pr_info("all done!"); 71 | EXIT(); 72 | } 73 | -------------------------------------------------------------------------------- /app/sgx/001-attestation/main.c: -------------------------------------------------------------------------------- 1 | /* utility headers */ 2 | #include 3 | #include "debug.h" 4 | #include "can.h" 5 | 6 | /* SGX untrusted runtime */ 7 | #include 8 | #include "Enclave/encl_u.h" 9 | 10 | /* for configurable SPONGENT_KEY_SIZE */ 11 | #include "../libspongent/libspongent/spongewrap.h" 12 | #include "../libspongent/libspongent/config.h" 13 | 14 | #if SPONGENT_TAG_SIZE != (CAN_PAYLOAD_SIZE*2) 15 | #error expecting 128-bit Sancus core 16 | #endif 17 | 18 | #ifndef CAN_INTERFACE 19 | #define CAN_INTERFACE "slcan0" 20 | #endif 21 | #define CAN_ATTEST_ID 0x40 22 | 23 | int can_socket = -1; 24 | 25 | sgx_enclave_id_t create_enclave(void) 26 | { 27 | sgx_launch_token_t token = {0}; 28 | int updated = 0; 29 | sgx_enclave_id_t eid = -1; 30 | 31 | info_event("Creating enclave..."); 32 | SGX_ASSERT( sgx_create_enclave( "./Enclave/encl.so", /*debug=*/1, 33 | &token, &updated, &eid, NULL ) ); 34 | 35 | return eid; 36 | } 37 | 38 | int main( int argc, char **argv ) 39 | { 40 | uint64_t challenge = 0x0; 41 | uint8_t sm_mac[SPONGENT_TAG_SIZE] = {0x0}; 42 | uint16_t id = 0x0; 43 | int i, len, rv; 44 | sgx_enclave_id_t eid = create_enclave(); 45 | 46 | info("setup"); 47 | ASSERT( (can_socket = can_open(CAN_INTERFACE)) >= 0 ); 48 | 49 | /* ---------------------------------------------------------------------- */ 50 | info_event("remote attestation challenge"); 51 | SGX_ASSERT( ecall_get_challenge(eid, &challenge) ); 52 | info("enclave returned challenge 0x%llx", challenge); 53 | ASSERT( can_send(can_socket, CAN_ATTEST_ID, (uint8_t*) &challenge, sizeof(uint64_t)) > 0 ); 54 | 55 | /* ---------------------------------------------------------------------- */ 56 | info_event("remote attestation response"); 57 | 58 | info("waiting for CAN response messages..."); 59 | len = can_recv(can_socket, &id, &sm_mac[0]); 60 | ASSERT( (id == CAN_ATTEST_ID) && (len == CAN_PAYLOAD_SIZE) && 61 | "unexpected CAN attestation challenge message format" ); 62 | 63 | len = can_recv(can_socket, &id, &sm_mac[CAN_PAYLOAD_SIZE]); 64 | ASSERT( (id == CAN_ATTEST_ID) && (len == CAN_PAYLOAD_SIZE) && 65 | "unexpected CAN attestation challenge message format" ); 66 | dump_hex("SM_MAC", sm_mac, SPONGENT_TAG_SIZE); 67 | 68 | /* ---------------------------------------------------------------------- */ 69 | info_event("comparing expected and received MACs..."); 70 | SGX_ASSERT( ecall_verify_response(eid, &rv, sm_mac) ); 71 | 72 | if (rv) 73 | info("OK : remote attestation succeeded!"); 74 | else 75 | info("FAIL : remote attestation failed!"); 76 | 77 | /* ---------------------------------------------------------------------- */ 78 | can_close(can_socket); 79 | 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /app/sgx/001-attestation-unprotected/main.c: -------------------------------------------------------------------------------- 1 | /* utility headers */ 2 | #include "debug.h" 3 | #include "can.h" 4 | 5 | /* for configurable SPONGENT_KEY_SIZE */ 6 | #include "../libspongent/libspongent/spongewrap.h" 7 | #include "../libspongent/libspongent/config.h" 8 | 9 | #if SPONGENT_TAG_SIZE != (CAN_PAYLOAD_SIZE*2) 10 | #error expecting 128-bit Sancus core 11 | #endif 12 | 13 | #ifndef CAN_INTERFACE 14 | #define CAN_INTERFACE "slcan0" 15 | #endif 16 | #define CAN_ATTEST_ID 0x40 17 | 18 | int can_socket = -1; 19 | 20 | /* 21 | * XXX Fill in the correct Sancus-specific key computed from the final foo.c enclave source code: 22 | * 23 | * $ sancus-crypto --key 0b7bf3ae40880a8be430d0da34fb76f0 --gen-sm-key foo --c-array main.elf 24 | */ 25 | const uint8_t key[SPONGENT_KEY_SIZE] = {0x05, 0x41, 0x87, 0x10, 0xff, 0xa4, 0x83, 0xc1, 26 | 0x2e, 0xe2, 0xda, 0x82, 0x81, 0x36, 0xb7, 0x6b}; 27 | 28 | int main( int argc, char **argv ) 29 | { 30 | uint64_t challenge = 0x0; 31 | uint8_t my_mac[SPONGENT_TAG_SIZE] = {0x0}; 32 | uint8_t sm_mac[SPONGENT_TAG_SIZE] = {0x0}; 33 | uint16_t id = 0x0; 34 | int i, len; 35 | 36 | info("setup"); 37 | ASSERT( (can_socket = can_open(CAN_INTERFACE)) >= 0 ); 38 | 39 | /* ---------------------------------------------------------------------- */ 40 | info_event("remote attestation challenge"); 41 | printf("enter attesation challenge (64-bit number) > "); 42 | scanf("%llu", &challenge); 43 | ASSERT( can_send(can_socket, CAN_ATTEST_ID, (uint8_t*) &challenge, sizeof(uint64_t)) > 0 ); 44 | 45 | /* ---------------------------------------------------------------------- */ 46 | info_event("remote attestation response"); 47 | 48 | info("waiting for CAN response messages..."); 49 | len = can_recv(can_socket, &id, &sm_mac[0]); 50 | ASSERT( (id == CAN_ATTEST_ID) && (len == CAN_PAYLOAD_SIZE) && 51 | "unexpected CAN attestation challenge message format" ); 52 | 53 | len = can_recv(can_socket, &id, &sm_mac[CAN_PAYLOAD_SIZE]); 54 | ASSERT( (id == CAN_ATTEST_ID) && (len == CAN_PAYLOAD_SIZE) && 55 | "unexpected CAN attestation challenge message format" ); 56 | dump_hex("SM_MAC", sm_mac, SPONGENT_TAG_SIZE); 57 | 58 | /* ---------------------------------------------------------------------- */ 59 | info_event("comparing expected and received MACs..."); 60 | 61 | info("calculating expected MAC..."); 62 | ASSERT( !spongent_mac((void*) key, (uint8_t*) &challenge, sizeof(uint64_t), my_mac) ); 63 | dump_hex("MY_MAC", my_mac, SPONGENT_TAG_SIZE); 64 | 65 | for (i = 0; (i < SPONGENT_TAG_SIZE) && (my_mac[i] == sm_mac[i]); i++); 66 | 67 | if (i >= SPONGENT_TAG_SIZE) 68 | info("OK : remote attestation succeeded!"); 69 | else 70 | info("FAIL : remote attestation failed!"); 71 | 72 | /* ---------------------------------------------------------------------- */ 73 | can_close(can_socket); 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Application overview and objectives 2 | 3 | Participants of this tutorial will develop a distributed trusted computing 4 | application that features secure, authenticated communication between an embedded 5 | MSP430 [Sancus](https://distrinet.cs.kuleuven.be/software/sancus) enclave and 6 | an off-the-shelf x86 [Intel SGX](https://software.intel.com/en-us/sgx) enclave. 7 | Particularly, as depicted below, the application's goal is to cryptographically 8 | prove to a trusted SGX enclave that an expected Sancus enclave is executing 9 | untampered on a genuine Sancus-enabled CPU (i.e., _remote attestation_ 10 | guarantee). The Sancus enclave itself will furthermore establish local trust 11 | relations with dedicated Sancus driver enclaves for secure I/O (i.e., _local 12 | attestation_ guarantee). All communication between the SGX and Sancus sides 13 | proceeds over an _untrusted_ automotive industry-standard 14 | [CAN](https://en.wikipedia.org/wiki/CAN_bus) bus. 15 | 16 | ![tutorial-overview](https://distrinet.cs.kuleuven.be/software/sancus/images/dsn18-overview.png) 17 | 18 | # Tutorial organization 19 | 20 | This tutorial is aimed at a target audience of C programmers with an interest 21 | in security. The tutorial takes about three hours, with an equal split between 22 | lectures and practical exercises (further details are provided on the 23 | [webpage](https://distrinet.cs.kuleuven.be/software/sancus/tutorial.php)). 24 | 25 | To get started, simply clone this repository: 26 | 27 | ```bash 28 | $ git clone https://github.com/sancus-pma/tutorial-dsn18.git 29 | $ cd tutorial-dsn18 30 | $ git submodule init 31 | $ git submodule update 32 | ``` 33 | 34 | The source code in this repository is organized as follows: 35 | 36 | - **app/sancus:** instructions and source code exercises for the Sancus-enabled 37 | MSP430 FPGA side of the distributed enclave application. 38 | - **app/sgx:** instructions and source code exercises for the SGX-capable PC 39 | side of the distributed enclave application. 40 | - **scrips:** collection of utility scrips for configuring the teaching setup 41 | boxes (not needed for participants). 42 | - **usbtin:** utilities for configuring the CAN2USB interface (not needed for 43 | participants). 44 | 45 | # Teaching setup overview 46 | 47 | One teaching setup box features five Sancus-enabled Xess 48 | [XuLA2-LX25](http://www.xess.com/shop/product/xula2-lx25/) Spartan-6 FPGAs, 49 | each synthesized with a Sancus-enabled OpenMSP430 50 | [core](https://github.com/sancus-pma/sancus-core) and mounted on a 51 | [Stickit!-2 board](http://www.xess.com/shop/product/stickit-mb-4_0/). 52 | All Sancus nodes are interfaced with a [Pmod 53 | LED](https://store.digilentinc.com/pmod-led-four-high-brightness-leds/), a 54 | [Pmod BTN](https://store.digilentinc.com/pmodbtn-4-user-pushbuttons/), and a 55 | [NiRen](http://henrysbench.capnfatz.com/henrys-bench/arduino-projects-tips-and-more/arduino-can-bus-module-pin-outs-and-schematics/) 56 | SPI CAN transceiver peripheral module. Each FPGA connects to the PC side 57 | via a dedicated [USBtin](https://www.fischl.de/usbtin/) connector. 58 | 59 | ![fpga-box](https://distrinet.cs.kuleuven.be/software/sancus/images/dsn18-box.jpeg) 60 | -------------------------------------------------------------------------------- /app/sgx/002-auth-exec/main.c: -------------------------------------------------------------------------------- 1 | /* utility headers */ 2 | #include 3 | #include "debug.h" 4 | #include "can.h" 5 | 6 | /* SGX untrusted runtime */ 7 | #include 8 | #include "Enclave/encl_u.h" 9 | 10 | /* for configurable SPONGENT_KEY_SIZE */ 11 | #include "../libspongent/libspongent/spongewrap.h" 12 | #include "../libspongent/libspongent/config.h" 13 | 14 | #if SPONGENT_TAG_SIZE != (CAN_PAYLOAD_SIZE*2) 15 | #error expecting 128-bit Sancus core 16 | #endif 17 | 18 | #ifndef CAN_INTERFACE 19 | #define CAN_INTERFACE "slcan0" 20 | #endif 21 | #define CAN_ATTEST_ID 0x40 22 | 23 | int can_socket = -1; 24 | 25 | /* define OCALLs here. */ 26 | 27 | void ocall_dump_buf(char *str, uint8_t *buf, int len) 28 | { 29 | dump_hex(str, buf, len); 30 | } 31 | 32 | sgx_enclave_id_t create_enclave(void) 33 | { 34 | sgx_launch_token_t token = {0}; 35 | int updated = 0; 36 | sgx_enclave_id_t eid = -1; 37 | 38 | info_event("Creating enclave..."); 39 | SGX_ASSERT( sgx_create_enclave( "./Enclave/encl.so", /*debug=*/1, 40 | &token, &updated, &eid, NULL ) ); 41 | 42 | return eid; 43 | } 44 | 45 | int main( int argc, char **argv ) 46 | { 47 | uint64_t challenge = 0x0; 48 | uint16_t sm_btn = 0x00; 49 | uint8_t sm_mac[SPONGENT_TAG_SIZE] = {0x0}; 50 | uint16_t id = 0x0; 51 | int i, len, rv; 52 | sgx_enclave_id_t eid = create_enclave(); 53 | 54 | info("setup"); 55 | ASSERT( (can_socket = can_open(CAN_INTERFACE)) >= 0 ); 56 | 57 | while(1) 58 | { 59 | /* ---------------------------------------------------------------------- */ 60 | info_event("remote attestation challenge"); 61 | SGX_ASSERT( ecall_get_challenge(eid, &challenge) ); 62 | info("enclave returned challenge 0x%llx", challenge); 63 | ASSERT( can_send(can_socket, CAN_ATTEST_ID, (uint8_t*) &challenge, sizeof(uint64_t)) > 0 ); 64 | 65 | /* ---------------------------------------------------------------------- */ 66 | info_event("remote attestation response"); 67 | 68 | info("waiting for CAN response messages..."); 69 | len = can_recv(can_socket, &id, &sm_mac[0]); 70 | ASSERT( (id == CAN_ATTEST_ID) && (len == sizeof(uint16_t)) && 71 | "unexpected CAN attestation challenge message format" ); 72 | sm_btn = sm_mac[0]; 73 | 74 | len = can_recv(can_socket, &id, &sm_mac[0]); 75 | ASSERT( (id == CAN_ATTEST_ID) && (len == CAN_PAYLOAD_SIZE) && 76 | "unexpected CAN attestation challenge message format" ); 77 | 78 | len = can_recv(can_socket, &id, &sm_mac[CAN_PAYLOAD_SIZE]); 79 | ASSERT( (id == CAN_ATTEST_ID) && (len == CAN_PAYLOAD_SIZE) && 80 | "unexpected CAN attestation challenge message format" ); 81 | dump_hex("SM_MAC", sm_mac, SPONGENT_TAG_SIZE); 82 | 83 | /* ---------------------------------------------------------------------- */ 84 | info_event("comparing expected and received MACs..."); 85 | SGX_ASSERT( ecall_verify_response(eid, &rv, sm_mac, sm_btn) ); 86 | 87 | if (rv) 88 | info("OK : remote attestation succeeded (sensor reading 0x%x is authentic)!", sm_btn); 89 | else 90 | info("FAIL : remote attestation failed (sensor reading 0x%x is spoofed)!", sm_btn); 91 | sleep(1); 92 | } 93 | 94 | /* ---------------------------------------------------------------------- */ 95 | can_close(can_socket); 96 | 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /app/sgx/000-pin/Enclave/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | AR = ar 3 | LD = gcc 4 | EDGER = sgx_edger8r 5 | SIGNER = sgx_sign 6 | INCLUDE = -I$(SGX_SDK)/include/ -I$(SGX_SDK)/include/tlibc 7 | T_CFLAGS = $(CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector -g -Os 8 | U_CFLAGS = $(CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector -g 9 | AR_FLAGS = rcs 10 | OBJECTS = encl.o 11 | LIB_SGX_TRTS = -lsgx_trts 12 | LIB_SGX_TSERVICE = -lsgx_tservice 13 | 14 | ENCLAVE_LIBS = $(LIB_SGX_TRTS) 15 | ENCLAVE_LIB_PARTS = -lsgx_tstdc -lsgx_tcrypto $(LIB_SGX_TSERVICE) 16 | ENCLAVE = encl 17 | PRIVATE_KEY = private_key.pem 18 | PUBLIC_KEY = public_key.pem 19 | KEY_SIZE = 3072 20 | ENCLAVE_EDL = $(ENCLAVE).edl 21 | ENCLAVE_CONFIG = $(ENCLAVE).config.xml 22 | OUTPUT_T = $(ENCLAVE).so 23 | OUTPUT_T_UNSIG = $(ENCLAVE).unsigned.so 24 | OUTPUT_U = lib$(ENCLAVE)_proxy.a 25 | LIB_DIRS = -L $(SGX_SDK)/lib64 26 | LD_FLAGS = -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles \ 27 | -Wl,--whole-archive -Wl,--start-group $(ENCLAVE_LIBS) -Wl,--end-group \ 28 | -Wl,--no-whole-archive -Wl,--start-group $(ENCLAVE_LIB_PARTS) -Wl,--end-group \ 29 | -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ 30 | -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ 31 | -Wl,--defsym,__ImageBase=0 32 | TRUSTED_OBJECTS = $(ENCLAVE)_t.o 33 | UNTRUSTED_OBJECTS = $(ENCLAVE)_u.o 34 | TRUSTED_CODE = $(ENCLAVE)_t.h $(ENCLAVE)_t.c 35 | UNTRUSTED_CODE = $(ENCLAVE)_u.h $(ENCLAVE)_u.c 36 | 37 | #.SILENT: 38 | all: $(OUTPUT_T) $(OUTPUT_U) 39 | 40 | $(OUTPUT_T) : $(TRUSTED_OBJECTS) $(OBJECTS) $(PRIVATE_KEY) 41 | echo "$(INDENT)[LD] " $(OBJECTS) $(TRUSTED_OBJECTS) $(ENCLAVE_LIBS) $(ENCLAVE_LIBS_PARTS) $(OUTPUT_T_UNSIG) 42 | $(LD) $(OBJECTS) $(TRUSTED_OBJECTS) $(LD_FLAGS) $(LIB_DIRS) -o $(OUTPUT_T_UNSIG) 43 | 44 | echo "$(INDENT)[SGN]" $(OUTPUT_T_UNSIG) 45 | $(SIGNER) sign -key $(PRIVATE_KEY) -enclave $(OUTPUT_T_UNSIG) -out $(OUTPUT_T) -config $(ENCLAVE_CONFIG) > /dev/null 2> /dev/null 46 | 47 | $(OUTPUT_U) : $(UNTRUSTED_OBJECTS) 48 | echo "$(INDENT)[AR] " $(OUTPUT_U) 49 | $(AR) $(AR_FLAGS) $(OUTPUT_U) $(UNTRUSTED_OBJECTS) 50 | 51 | %_t.o : $(subst .o,.c,$@) edger 52 | echo "$(INDENT)[CC] " $(subst .o,.c,$@) "(trusted edge)" 53 | touch $(subst .o,.c,$@) 54 | $(CC) -c $(INCLUDE) $(T_CFLAGS) $(subst .o,.c,$@) 55 | 56 | %_u.o : $(subst .o,.c,$@) edger 57 | echo "$(INDENT)[CC] " $(subst .o,.c,$@) "(untrusted edge)" 58 | touch $(subst .o,.c,$@) 59 | $(CC) -c $(INCLUDE) $(U_CFLAGS) $(subst .o,.c,$@) 60 | 61 | %.o : %.c edger 62 | echo "$(INDENT)[CC] " $< "(core)" 63 | $(CC) $(INCLUDE) $(T_CFLAGS) -c $< 64 | 65 | %.o : %.S 66 | echo "$(INDENT)[AS] " $< "(core)" 67 | $(CC) $(INCLUDE) $(T_CFLAGS) -c $< -o $@ 68 | 69 | edger: $(ENCLAVE).edl 70 | echo "$(INDENT)[GEN]" $(EDGER) $(ENCLAVE_EDL) 71 | $(EDGER) $(ENCLAVE_EDL) 72 | 73 | .PHONY: force_check 74 | force_check: 75 | true 76 | 77 | .PHONY: scrub 78 | scrub: clean 79 | echo "$(INDENT)[RM] " $(PRIVATE_KEY) $(PUBLIC_KEY) 80 | $(RM) $(PRIVATE_KEY) $(PUBLIC_KEY) 81 | 82 | $(PRIVATE_KEY): 83 | echo "$(INDENT)[GEN] $(PRIVATE_KEY) ($(KEY_SIZE) bits)" 84 | 85 | # generate 3072 bit private RSA key 86 | openssl genrsa -out $(PRIVATE_KEY) -3 $(KEY_SIZE) 87 | 88 | echo "$(INDENT)[EXT] $(PUBLIC_KEY)" 89 | # extract public key 90 | openssl rsa -in $(PRIVATE_KEY) -pubout -out $(PUBLIC_KEY) 91 | 92 | # sign enclave 93 | #sgx_sign sign -key private_key.pem -enclave Enclave/encl.so -out encl.signed.so 94 | 95 | .PHONY: clean 96 | clean: 97 | echo "$(INDENT)[RM]" $(OBJECTS) $(OUTPUT_T_UNSIG) $(OUTPUT_T) $(OUTPUT_U) 98 | $(RM) $(OBJECTS) $(OUTPUT_T_UNSIG) $(OUTPUT_T) $(OUTPUT_U) 99 | echo "$(INDENT)[RM]" $(TRUSTED_OBJECTS) $(UNTRUSTED_OBJECTS) $(TRUSTED_CODE) $(UNTRUSTED_CODE) 100 | $(RM) $(TRUSTED_OBJECTS) $(UNTRUSTED_OBJECTS) $(TRUSTED_CODE) $(UNTRUSTED_CODE) 101 | -------------------------------------------------------------------------------- /app/sgx/002-auth-exec/README.md: -------------------------------------------------------------------------------- 1 | # Authentic execution: secure remote sensor-actuator distributed enclave application 2 | 3 | ## Application overview 4 | 5 | After completing the `../001-attestation` exercise, remote verifiers can attest 6 | the untampered execution of a Sancus enclave with a minimal trusted computing 7 | base. For remote attestation to be _useful_, however, the Sancus enclave should 8 | also report on the results of some local computation. We will therefore extend 9 | the remote attestation protocol from the previous exercises to include proof of 10 | a genuine sensor reading (button press) on the MSP430 side. 11 | 12 | ## Your task 13 | 14 | The `../sancus/002-auth-exec` application should now produce a MAC over both 15 | the attestation challenge plus a sensor reading, obtained from a locally 16 | attested PmodBTN Sancus driver enclave. Particularly, the expected 128-bit MAC 17 | is computed as follows: 18 | 19 | ``` 20 | sm_msg = ( challenge | btn ) # concatenation of 64-bit challenge and 16-bit sensor reading 21 | sm_mac = MAC( msg ) # authenticate 10-byte msg 22 | ``` 23 | 24 | We already extended the untrusted runtime `main.c` to process the additional 25 | CAN messages. The only change in the trusted enclave interface is an additional 26 | 16-bit `btn` parameter in the verification ECALL: 27 | 28 | ```C 29 | int ecall_verify_response(uint8_t *sm_mac, uint16_t btn) 30 | ``` 31 | 32 | **Do it yourself.** Based on you `../001-attestation` enclave implementation, 33 | extend the `ecall_verify_response()` ECALL that returns whether or not remote 34 | attestation succeeded. Particularly, your implementation should perform the 35 | following steps: 36 | 37 | 1. Allocate a local buffer of `ATTEST_MSG_SIZE` to hold the 38 | reconstructed attestation message `sm_msg`. 39 | 2. Copy inside this buffer: the 64-bit challenge, generated by the last 40 | `ecall_get_challenge` call, plus the 16-bit sensor reading `btn`. 41 | 3. Compute the expected attestation MAC. 42 | 4. Compare expected and received attestation MACs. 43 | 44 | ## Building and running 45 | 46 | First upload the `../../sancus/002-auth-exec` Sancus program to the MSP430 47 | FPGA, then run the verifier program as follows: 48 | 49 | ```bash 50 | $ make run CAN_INTERFACE=slcanN 51 | 52 | -------------------------------------------------------------------------------- 53 | [main.c] remote attestation challenge 54 | -------------------------------------------------------------------------------- 55 | 56 | [main.c] enclave returned challenge 0xf9c85275ff9ed337 57 | [../common/can.c] send: CAN frame with ID 0x40 (len=8) 58 | MSG = 37 d3 9e ff 75 52 c8 f9 59 | 60 | -------------------------------------------------------------------------------- 61 | [main.c] remote attestation response 62 | -------------------------------------------------------------------------------- 63 | 64 | [main.c] waiting for CAN response messages... 65 | [../common/can.c] recv: CAN frame with ID 0x40 (len=2) 66 | MSG = 00 00 67 | [../common/can.c] recv: CAN frame with ID 0x40 (len=8) 68 | MSG = f8 e0 25 b9 26 fd 58 20 69 | [../common/can.c] recv: CAN frame with ID 0x40 (len=8) 70 | MSG = 5f af 65 63 9e eb 9c b4 71 | SM_MAC = f8 e0 25 b9 26 fd 58 20 5f af 65 63 9e eb 9c b4 72 | 73 | -------------------------------------------------------------------------------- 74 | [main.c] comparing expected and received MACs... 75 | -------------------------------------------------------------------------------- 76 | 77 | ATTEST_MSG = 37 d3 9e ff 75 52 c8 f9 00 00 78 | MY_MAC = f8 e0 25 b9 26 fd 58 20 5f af 65 63 9e eb 9c b4 79 | [main.c] OK : remote attestation succeeded (sensor reading 0x20 is authentic)! 80 | 81 | ``` 82 | 83 | **Note.** Here, slcanN refers to the CAN network interface you are using to 84 | communicate with the MSP430 FPGA. slcan0 is the default if you ommit this 85 | parameter. 86 | 87 | **Note.** Since this exercise changes the source code of the `foo.c` enclave, 88 | in order to successfully complete the remote attestation protocol in the end, 89 | you will have to fill in the correct Sancus module-specific key in the SGX 90 | enclave again. We refer to `../../sancus/001-attestation` for details 91 | instructions on how to do this. 92 | -------------------------------------------------------------------------------- /app/sgx/001-attestation/Enclave/Makefile: -------------------------------------------------------------------------------- 1 | LIBSPONGENT_DIR = ../../libspongent 2 | LIBSPONGENT = $(LIBSPONGENT_DIR)/libspongent 3 | 4 | CC = gcc 5 | AR = ar 6 | LD = gcc 7 | EDGER = sgx_edger8r 8 | SIGNER = sgx_sign 9 | INCLUDE = -I$(SGX_SDK)/include/ -I$(SGX_SDK)/include/tlibc \ 10 | -I$(LIBSPONGENT_DIR) 11 | T_CFLAGS = $(CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector -g -Os 12 | U_CFLAGS = $(CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector -g 13 | AR_FLAGS = rcs 14 | OBJECTS = encl.o 15 | LIB_SGX_TRTS = -lsgx_trts 16 | LIB_SGX_TSERVICE = -lsgx_tservice 17 | 18 | ENCLAVE_LIBS = $(LIB_SGX_TRTS) 19 | ENCLAVE_LIB_PARTS = -lsgx_tstdc -lsgx_tcrypto $(LIB_SGX_TSERVICE) 20 | ENCLAVE = encl 21 | PRIVATE_KEY = private_key.pem 22 | PUBLIC_KEY = public_key.pem 23 | KEY_SIZE = 3072 24 | ENCLAVE_EDL = $(ENCLAVE).edl 25 | ENCLAVE_CONFIG = $(ENCLAVE).config.xml 26 | OUTPUT_T = $(ENCLAVE).so 27 | OUTPUT_T_UNSIG = $(ENCLAVE).unsigned.so 28 | OUTPUT_U = lib$(ENCLAVE)_proxy.a 29 | LIB_DIRS = -L $(SGX_SDK)/lib64 30 | LD_FLAGS = -lspongent -L$(LIBSPONGENT) \ 31 | -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles \ 32 | -Wl,--whole-archive -Wl,--start-group $(ENCLAVE_LIBS) -Wl,--end-group \ 33 | -Wl,--no-whole-archive -Wl,--start-group $(ENCLAVE_LIB_PARTS) -Wl,--end-group \ 34 | -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ 35 | -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ 36 | -Wl,--defsym,__ImageBase=0 37 | TRUSTED_OBJECTS = $(ENCLAVE)_t.o 38 | UNTRUSTED_OBJECTS = $(ENCLAVE)_u.o 39 | TRUSTED_CODE = $(ENCLAVE)_t.h $(ENCLAVE)_t.c 40 | UNTRUSTED_CODE = $(ENCLAVE)_u.h $(ENCLAVE)_u.c 41 | 42 | #.SILENT: 43 | all: libspongent $(OUTPUT_T) $(OUTPUT_U) 44 | 45 | libspongent: 46 | $(MAKE) -C $(LIBSPONGENT) 47 | 48 | $(OUTPUT_T) : $(TRUSTED_OBJECTS) $(OBJECTS) $(PRIVATE_KEY) 49 | echo "$(INDENT)[LD] " $(OBJECTS) $(TRUSTED_OBJECTS) $(ENCLAVE_LIBS) $(ENCLAVE_LIBS_PARTS) $(OUTPUT_T_UNSIG) 50 | $(LD) $(OBJECTS) $(TRUSTED_OBJECTS) $(LD_FLAGS) $(LIB_DIRS) -o $(OUTPUT_T_UNSIG) 51 | 52 | echo "$(INDENT)[SGN]" $(OUTPUT_T_UNSIG) 53 | $(SIGNER) sign -key $(PRIVATE_KEY) -enclave $(OUTPUT_T_UNSIG) -out $(OUTPUT_T) -config $(ENCLAVE_CONFIG) > /dev/null 2> /dev/null 54 | 55 | $(OUTPUT_U) : $(UNTRUSTED_OBJECTS) 56 | echo "$(INDENT)[AR] " $(OUTPUT_U) 57 | $(AR) $(AR_FLAGS) $(OUTPUT_U) $(UNTRUSTED_OBJECTS) 58 | 59 | %_t.o : $(subst .o,.c,$@) edger 60 | echo "$(INDENT)[CC] " $(subst .o,.c,$@) "(trusted edge)" 61 | touch $(subst .o,.c,$@) 62 | $(CC) -c $(INCLUDE) $(T_CFLAGS) $(subst .o,.c,$@) 63 | 64 | %_u.o : $(subst .o,.c,$@) edger 65 | echo "$(INDENT)[CC] " $(subst .o,.c,$@) "(untrusted edge)" 66 | touch $(subst .o,.c,$@) 67 | $(CC) -c $(INCLUDE) $(U_CFLAGS) $(subst .o,.c,$@) 68 | 69 | %.o : %.c edger 70 | echo "$(INDENT)[CC] " $< "(core)" 71 | $(CC) $(INCLUDE) $(T_CFLAGS) -c $< 72 | 73 | %.o : %.S 74 | echo "$(INDENT)[AS] " $< "(core)" 75 | $(CC) $(INCLUDE) $(T_CFLAGS) -c $< -o $@ 76 | 77 | edger: $(ENCLAVE).edl 78 | echo "$(INDENT)[GEN]" $(EDGER) $(ENCLAVE_EDL) 79 | $(EDGER) $(ENCLAVE_EDL) 80 | 81 | .PHONY: force_check 82 | force_check: 83 | true 84 | 85 | .PHONY: scrub 86 | scrub: clean 87 | echo "$(INDENT)[RM] " $(PRIVATE_KEY) $(PUBLIC_KEY) 88 | $(RM) $(PRIVATE_KEY) $(PUBLIC_KEY) 89 | 90 | $(PRIVATE_KEY): 91 | echo "$(INDENT)[GEN] $(PRIVATE_KEY) ($(KEY_SIZE) bits)" 92 | 93 | # generate 3072 bit private RSA key 94 | openssl genrsa -out $(PRIVATE_KEY) -3 $(KEY_SIZE) 95 | 96 | echo "$(INDENT)[EXT] $(PUBLIC_KEY)" 97 | # extract public key 98 | openssl rsa -in $(PRIVATE_KEY) -pubout -out $(PUBLIC_KEY) 99 | 100 | # sign enclave 101 | #sgx_sign sign -key private_key.pem -enclave Enclave/encl.so -out encl.signed.so 102 | 103 | .PHONY: clean 104 | clean: 105 | echo "$(INDENT)[RM]" $(OBJECTS) $(OUTPUT_T_UNSIG) $(OUTPUT_T) $(OUTPUT_U) 106 | $(RM) $(OBJECTS) $(OUTPUT_T_UNSIG) $(OUTPUT_T) $(OUTPUT_U) 107 | echo "$(INDENT)[RM]" $(TRUSTED_OBJECTS) $(UNTRUSTED_OBJECTS) $(TRUSTED_CODE) $(UNTRUSTED_CODE) 108 | $(RM) $(TRUSTED_OBJECTS) $(UNTRUSTED_OBJECTS) $(TRUSTED_CODE) $(UNTRUSTED_CODE) 109 | $(MAKE) -C $(LIBSPONGENT) clean 110 | -------------------------------------------------------------------------------- /app/sgx/002-auth-exec/Enclave/Makefile: -------------------------------------------------------------------------------- 1 | LIBSPONGENT_DIR = ../../libspongent 2 | LIBSPONGENT = $(LIBSPONGENT_DIR)/libspongent 3 | 4 | CC = gcc 5 | AR = ar 6 | LD = gcc 7 | EDGER = sgx_edger8r 8 | SIGNER = sgx_sign 9 | INCLUDE = -I$(SGX_SDK)/include/ -I$(SGX_SDK)/include/tlibc \ 10 | -I$(LIBSPONGENT_DIR) 11 | T_CFLAGS = $(CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector -g -Os 12 | U_CFLAGS = $(CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector -g 13 | AR_FLAGS = rcs 14 | OBJECTS = encl.o 15 | LIB_SGX_TRTS = -lsgx_trts 16 | LIB_SGX_TSERVICE = -lsgx_tservice 17 | 18 | ENCLAVE_LIBS = $(LIB_SGX_TRTS) 19 | ENCLAVE_LIB_PARTS = -lsgx_tstdc -lsgx_tcrypto $(LIB_SGX_TSERVICE) 20 | ENCLAVE = encl 21 | PRIVATE_KEY = private_key.pem 22 | PUBLIC_KEY = public_key.pem 23 | KEY_SIZE = 3072 24 | ENCLAVE_EDL = $(ENCLAVE).edl 25 | ENCLAVE_CONFIG = $(ENCLAVE).config.xml 26 | OUTPUT_T = $(ENCLAVE).so 27 | OUTPUT_T_UNSIG = $(ENCLAVE).unsigned.so 28 | OUTPUT_U = lib$(ENCLAVE)_proxy.a 29 | LIB_DIRS = -L $(SGX_SDK)/lib64 30 | LD_FLAGS = -lspongent -L$(LIBSPONGENT) \ 31 | -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles \ 32 | -Wl,--whole-archive -Wl,--start-group $(ENCLAVE_LIBS) -Wl,--end-group \ 33 | -Wl,--no-whole-archive -Wl,--start-group $(ENCLAVE_LIB_PARTS) -Wl,--end-group \ 34 | -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ 35 | -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ 36 | -Wl,--defsym,__ImageBase=0 37 | TRUSTED_OBJECTS = $(ENCLAVE)_t.o 38 | UNTRUSTED_OBJECTS = $(ENCLAVE)_u.o 39 | TRUSTED_CODE = $(ENCLAVE)_t.h $(ENCLAVE)_t.c 40 | UNTRUSTED_CODE = $(ENCLAVE)_u.h $(ENCLAVE)_u.c 41 | 42 | #.SILENT: 43 | all: libspongent $(OUTPUT_T) $(OUTPUT_U) 44 | 45 | libspongent: 46 | $(MAKE) -C $(LIBSPONGENT) 47 | 48 | $(OUTPUT_T) : $(TRUSTED_OBJECTS) $(OBJECTS) $(PRIVATE_KEY) 49 | echo "$(INDENT)[LD] " $(OBJECTS) $(TRUSTED_OBJECTS) $(ENCLAVE_LIBS) $(ENCLAVE_LIBS_PARTS) $(OUTPUT_T_UNSIG) 50 | $(LD) $(OBJECTS) $(TRUSTED_OBJECTS) $(LD_FLAGS) $(LIB_DIRS) -o $(OUTPUT_T_UNSIG) 51 | 52 | echo "$(INDENT)[SGN]" $(OUTPUT_T_UNSIG) 53 | $(SIGNER) sign -key $(PRIVATE_KEY) -enclave $(OUTPUT_T_UNSIG) -out $(OUTPUT_T) -config $(ENCLAVE_CONFIG) > /dev/null 2> /dev/null 54 | 55 | $(OUTPUT_U) : $(UNTRUSTED_OBJECTS) 56 | echo "$(INDENT)[AR] " $(OUTPUT_U) 57 | $(AR) $(AR_FLAGS) $(OUTPUT_U) $(UNTRUSTED_OBJECTS) 58 | 59 | %_t.o : $(subst .o,.c,$@) edger 60 | echo "$(INDENT)[CC] " $(subst .o,.c,$@) "(trusted edge)" 61 | touch $(subst .o,.c,$@) 62 | $(CC) -c $(INCLUDE) $(T_CFLAGS) $(subst .o,.c,$@) 63 | 64 | %_u.o : $(subst .o,.c,$@) edger 65 | echo "$(INDENT)[CC] " $(subst .o,.c,$@) "(untrusted edge)" 66 | touch $(subst .o,.c,$@) 67 | $(CC) -c $(INCLUDE) $(U_CFLAGS) $(subst .o,.c,$@) 68 | 69 | %.o : %.c edger 70 | echo "$(INDENT)[CC] " $< "(core)" 71 | $(CC) $(INCLUDE) $(T_CFLAGS) -c $< 72 | 73 | %.o : %.S 74 | echo "$(INDENT)[AS] " $< "(core)" 75 | $(CC) $(INCLUDE) $(T_CFLAGS) -c $< -o $@ 76 | 77 | edger: $(ENCLAVE).edl 78 | echo "$(INDENT)[GEN]" $(EDGER) $(ENCLAVE_EDL) 79 | $(EDGER) $(ENCLAVE_EDL) 80 | 81 | .PHONY: force_check 82 | force_check: 83 | true 84 | 85 | .PHONY: scrub 86 | scrub: clean 87 | echo "$(INDENT)[RM] " $(PRIVATE_KEY) $(PUBLIC_KEY) 88 | $(RM) $(PRIVATE_KEY) $(PUBLIC_KEY) 89 | 90 | $(PRIVATE_KEY): 91 | echo "$(INDENT)[GEN] $(PRIVATE_KEY) ($(KEY_SIZE) bits)" 92 | 93 | # generate 3072 bit private RSA key 94 | openssl genrsa -out $(PRIVATE_KEY) -3 $(KEY_SIZE) 95 | 96 | echo "$(INDENT)[EXT] $(PUBLIC_KEY)" 97 | # extract public key 98 | openssl rsa -in $(PRIVATE_KEY) -pubout -out $(PUBLIC_KEY) 99 | 100 | # sign enclave 101 | #sgx_sign sign -key private_key.pem -enclave Enclave/encl.so -out encl.signed.so 102 | 103 | .PHONY: clean 104 | clean: 105 | echo "$(INDENT)[RM]" $(OBJECTS) $(OUTPUT_T_UNSIG) $(OUTPUT_T) $(OUTPUT_U) 106 | $(RM) $(OBJECTS) $(OUTPUT_T_UNSIG) $(OUTPUT_T) $(OUTPUT_U) 107 | echo "$(INDENT)[RM]" $(TRUSTED_OBJECTS) $(UNTRUSTED_OBJECTS) $(TRUSTED_CODE) $(UNTRUSTED_CODE) 108 | $(RM) $(TRUSTED_OBJECTS) $(UNTRUSTED_OBJECTS) $(TRUSTED_CODE) $(UNTRUSTED_CODE) 109 | $(MAKE) -C $(LIBSPONGENT) clean 110 | -------------------------------------------------------------------------------- /app/sancus/002-auth-exec/README.md: -------------------------------------------------------------------------------- 1 | # Authentic execution: secure remote sensor-actuator distributed enclave application 2 | 3 | ## Application overview 4 | 5 | Low-end embedded microcontrollers are commonly interfaced with peripheral I/O 6 | devices via memory-mapped I/O. Since Sancus features a generic memory isolation 7 | primitive, small dedicated Sancus driver assembly enclaves can be provided with 8 | exclusive access to peripheral I/O devices. In this exercise, we will leverage 9 | Sancus's local attestation primitives to extend the remote attestation protocol 10 | of the 'foo' enclave with evidence of an authentic PmodBTN driver sensor 11 | reading (and PmodLED driver actuation). 12 | 13 | ## Your task 14 | 15 | We provide you with a fully implemented `main.c` untrusted runtime to take care 16 | of the CAN network communication, plus two trusted `pmodbtn.c` and `pmodled.c` 17 | Sancus driver enclaves to securely sense/actuate the PmodBTN/LED peripherals. 18 | 19 | **Do it yourself.** Based on your `../001-attestation` implementation, extend 20 | the `attest_foo` entry point to compute a MAC over both the provided 21 | attestation challenge, plus a local sensor reading from the 'pmodbtn' Sancus 22 | driver enclave. The signature of the extended foo entry point looks as follows: 23 | 24 | ```C 25 | int SM_ENTRY(foo) attest_foo(uint8_t *challenge, int len, uint16_t *btn, uint8_t *mac) 26 | ``` 27 | 28 | This function takes an _untrusted_ pointer to a `challenge` buffer with length 29 | `len`, and returns 0 iff the _untrusted_ `mac` buffer contains the 128-bit MAC 30 | and the _untrusted_ `btn` buffer contains the 16-bit PmodBTN output. 31 | Particularly, your implementation should perform the following steps: 32 | 33 | 1. If called for the first time, initialize the drive enclaves by calling the 34 | `pmodbtn_init()` and `pmodled_init()` entry points. 35 | 2. Fetch a PmodBTN sensor reading by calling the `pmodbtn_poll()` entry point 36 | of the 'PmodBTN' driver enclave. 37 | 3. (optional) Actuate the corresponding LED by calling the `pmodled_actuate` 38 | entry point of the 'PmodLED' driver enclave. 39 | 4. Convert the 8-bit sensor reading into a 16-bit driver state (for padding 40 | when calculating the MAC later) and store it in the untrusted `btn` output 41 | buffer. 42 | 5. Initialize an internal 10-byte `msg` buffer with the concatenation of the 43 | 64-bit attestation challenge, and the 16-bit driver state. 44 | 6. Compute the MAC over `msg` and store it in the untrusted `mac` output 45 | buffer. 46 | 47 | **Note.** The Sancus compiler transparently takes care of local attestation 48 | whenever encountering cross-enclave function calls. Merely calling the driver 49 | enclaves from the foo enclave thus suffices to establish their integrity. 50 | 51 | ### Authentic sensor readings via Sancus PmodBTN driver enclave 52 | 53 | We provide you with a fully working PmodBTN driver enclave that 54 | offers two entry points: 55 | 56 | 1. `pmodbtn_init`: should be called to initialize the driver enclave before 57 | requesting sensor readings. 58 | 2. `pmodbtn_poll`: returns an 8-bit bitmap indicating which buttons were down. 59 | 60 | ### Authentic actuation via Sancus PmodLED driver enclave 61 | 62 | We provide you with a fully working PmodLED driver enclave that 63 | offers two entry points: 64 | 65 | 1. `pmodled_init`: should be called to initialize the driver enclave before 66 | issuing sensor actuation calls. 67 | 2. `pmodled_actuate`: lights up the LEDs according to the 8-bit bitmap argument. 68 | 69 | ## Building and running 70 | 71 | ### Sancus side (foo/PmodBTN/PmodLED enclaves and untrusted runtime) 72 | 73 | Again, use `make load` to build and upload the application binary to the FPGA. 74 | 75 | ```bash 76 | $ FPGA_DEV=/dev/ttyUSB0 make load # in case of permission errors, replace `USB0` with the 77 | # uplink UART USB device that was assigned to your FPGA 78 | ``` 79 | 80 | ### PC side (remote stakeholder application) 81 | 82 | ```bash 83 | $ cd ../../sgx/002-auth-exec/ 84 | $ make run 85 | ``` 86 | 87 | **Note.** Since this exercise changes the source code of the `foo.c` enclave, 88 | in order to successfully complete the remote attestation protocol in the end, 89 | you will have to fill in the correct Sancus module-specific key in the SGX 90 | enclave again. We refer to `../001-attestation` for details instructions on how 91 | to do this. 92 | -------------------------------------------------------------------------------- /app/sgx/README.md: -------------------------------------------------------------------------------- 1 | # SGX enclave applications 2 | 3 | This directory collects the tutorial code to be ran on an SGX-capable Intel x86 CPU. 4 | 5 | ## Exercises overview 6 | 7 | Exercises are organized in increasing complexity as follows: 8 | 9 | - **000-pin:** basic example enclave program demonstrating ECALL/OCALL concepts. 10 | - **001-attestation-unprotected:** basic _unprotected_ remote verifier 11 | application to quickly start implementing Sancus MSP430 side of the remote 12 | attestation protocol. 13 | - **001-attestation:** enclaved version of the remote verifier application. 14 | - **002-auth-exec:** secure remote sensor-actuator distributed enclave application. 15 | 16 | ## 000: PIN code verifier 17 | 18 | The purpose of this application is to develop a first elementary SGX enclave 19 | program that compares a secret in-enclave PIN code against user input obtained 20 | from the untrusted world. 21 | 22 | **Your task.** Extend the trusted `Enclave/encl.edl` public interface, 23 | implement the required ECALL `Enclave/encl.c` functionality, and extend the 24 | untrusted `main.c` runtime to call into the enclave. 25 | 26 | **Goals.** After this exercise, you should be able to: 27 | 28 | * Build and run elementary SGX x86 applications. 29 | * Understand ECALL and OCALL concepts to securely transfer control flow 30 | to/from enclave mode. 31 | * Understand limitations of SGX's enclaved execution and the need for secure I/O. 32 | 33 | ## 001: Remote attestation (unprotected) 34 | 35 | The purpose of this application is to provide you with a fully working 36 | _unprotected_ implementation of the remote verifier part of the remote 37 | attestation protocol. This allows you on the one hand to get started quickly 38 | with implementing the attestation response code (`../sancus/001-attestation`) 39 | on the Sancus MSP430 side. On the other hand, in the next exercise, we will 40 | use the unprotected code as a starting point to develop a hardened enclaved 41 | version of the remote verifier's implementation. 42 | 43 | **Your task.** Simply run the program to send and receive CAN messages, and get 44 | started on implementing the Sancus MSP430 side of the attestation protocol. 45 | Thereafter, in order to successfully complete the remote attestation protocol, 46 | you will still need to generate and fill in the Sancus module-specific key in 47 | `main.c`. 48 | 49 | **Goals.** After this exercise, you should be able to: 50 | 51 | * Understand remote attestation concepts. 52 | * Thwart basic protocol-level replay attacks via the proper use of nonces. 53 | * Understand trusted computing base concerns and why it is undesirable to 54 | trust the entire remote verifier's PC software stack. 55 | 56 | ## 001: Remote attestation (enclaved) 57 | 58 | The purpose of this application is to minimize the trusted computing base for 59 | Sancus's remote attestation protocol by encapsulating the security-sensitive 60 | remote verifier's code in an SGX enclave, such that the secret Sancus 61 | module-specific `foo.c` attestation key never leaks to the untrusted world. 62 | 63 | **Your task.** Modify the `001-attestation-unprotected` application to identify 64 | and protect the security-relevant application parts. 65 | 66 | **Goals.** After this exercise, you should be able to: 67 | 68 | * Identify and encapsulate security-sensitive application logic in an SGX 69 | enclave, and reason about the resulting trusted computing base. 70 | * Securely generate random numbers in an SGX enclave. 71 | * Understand the dangers of untrusted pointer dereferences in enclave programs. 72 | * Understand "transitive trust" limitations of attesting the Sancus MSP430 73 | side within an SGX enclave (i.e., who guarantees the untampered execution of 74 | the SGX enclave in its turn?). 75 | 76 | ## 002: Authentic execution 77 | 78 | The purpose of this application is to show how remote attestation can be 79 | leveraged in practice to authenticate the results of remote computations 80 | (sensor readings) in a hostile environment. 81 | 82 | **Your task.** Modify the `001-attestation` application to verify an extended 83 | MAC over both the attestation challenge and a remote sensor reading. 84 | 85 | **Goals.** After this exercise, you should be able to: 86 | 87 | * Understand authentic execution concepts. 88 | * Understand how trust in a remote platform and its sensor readings can be 89 | established by combining remote attestation of an application enclave 90 | with local attestation of driver enclaves residing on the same device. 91 | -------------------------------------------------------------------------------- /app/sgx/001-attestation/README.md: -------------------------------------------------------------------------------- 1 | # Attestation: enclaved remote verifier application 2 | 3 | ## Application overview 4 | 5 | After completing the `../001-attestation-unprotected` exercise, remote 6 | verifiers can establish trust in a Sancus enclave deployed by untrusted code 7 | over a hostile network. For this guarantee to hold, however, one should still 8 | implicitly trust _all_ of the code running on the remote verifier's machine. 9 | The purpose of this application is to minimize the trusted computing base 10 | for Sancus's remote attestation protocol by encapsulating the security-sensitive 11 | verification code in an SGX enclave. 12 | 13 | Importantly, from the perspective of the Sancus enclave, nothing changes: you 14 | should still be able to run the exact same `../../sancus/0001-attestation` 15 | code, whether talking to an unprotected or enclaved remote verifier. 16 | 17 | ![attestation-overview](https://distrinet.cs.kuleuven.be/software/sancus/images/dsn18-attestation.png) 18 | 19 | **Note.** You should always strive to minimize the amount of application logic 20 | you encapsulate in an enclave. As a general rule of thumb, application logic 21 | that does _not_ operate on plaintext secrets (e.g., network stack) should run 22 | outside of the enclave in order to mimimize the trusted computing base of the 23 | application. 24 | 25 | ## Your task 26 | 27 | Developing an enclaved version of an existing application involves some 28 | security requirement analysis. 29 | For the purpose of this application, we set as an explict goals that the 30 | secret Sancus-module specific key for the `foo.c` enclave should never leak 31 | to the untrusted world. 32 | 33 | Based on the `../001-attestation-unprotected` source code, we provide a 34 | complete `main.c` untrusted runtime implementation, plus the trusted 35 | `Enclave/encl.edl` interface definitions. Your job is to implement the 36 | required `Enclave/encl.c` ECALL functionality. 37 | 38 | ### Providing attestation challenges 39 | 40 | Note that, in contrast to the `../001-attestation-unprotected` application, we 41 | cannot simply query the end user (you) for a trustworthy attestation challenge, 42 | since all I/O operations pass via the untrusted world. We will therefore rely 43 | on the secure hardware-level random number generation features found in modern 44 | Intel processors. 45 | 46 | **Do it yourself.** Implement the `ecall_get_challenge()` ECALL that returns a 47 | 64-bit random number, and securely stores it inside the enclave for use by the 48 | next verification ECALL. 49 | 50 | The Intel SGX SDK provides a convenient interface to access the CPU's random 51 | number generator via the 52 | [`sgx_read_rand`](https://software.intel.com/en-us/sgx-sdk-dev-reference-sgx-read-rand) 53 | C function. We repeat the documentation below for convenience: 54 | 55 | #### Syntax 56 | 57 | ```C 58 | sgx_status_t sgx_read_rand(unsigned char *rand, size_t length_in_bytes); 59 | ``` 60 | 61 | #### Parameters 62 | 63 | - `rand` [out] A pointer to the buffer that receives the random number. The 64 | pointer cannot be NULL. The rand buffer can be either within or outside the 65 | enclave, but it is not allowed to be across the enclave boundary or wrapped 66 | around. 67 | 68 | - `length_in_bytes` [in] The length of the buffer (in bytes). 69 | 70 | #### Return value 71 | 72 | `SGX_SUCCESS` Indicates success. 73 | 74 | ### Verifying attestation responses 75 | 76 | Verifying attestation responses comes down to (i) calculating a 128-bit MAC 77 | over the previously provided 64-bit challenge, and thereafter (ii) comparing 78 | the expected and received MACs. In order to complete step (i), we provide a 79 | convenient trusted [libspongent](https://github.com/sancus-pma/libspongent) 80 | in-enclave C library to create MACs. 81 | 82 | **Do it yourself.** Implement the `ecall_verify_response()` ECALL that 83 | returns whether or not remote attestation succeeded. 84 | 85 | We repeat the documentation for the relevant `libspongent` function below: 86 | 87 | #### Syntax 88 | 89 | ```C 90 | int spongent_mac(void* key, void* msg, unsigned int msg_len, void* mac); 91 | ``` 92 | 93 | #### Parameters 94 | 95 | - `key` [in] Pointer to input key buffer of `SPONGENT_KEY_SIZE` bytes. 96 | - `msg` [in] Pointer to start of associated data input buffer. 97 | - `msg_len` [in] Length of associated data input buffer. 98 | - `tag` [out] Pointer to output buffer of `SPONGENT_TAG_SIZE` bytes for MAC 99 | over associated data. 100 | 101 | #### Return value 102 | 103 | Returns 0 (zero) iff the wrapping succeeded. 104 | 105 | ## Building and running 106 | 107 | First upload the `../../sancus/001-attestation` Sancus program to the MSP430 108 | FPGA, then run the verifier program as follows: 109 | 110 | ```bash 111 | $ make run CAN_INTERFACE=slcanN 112 | ``` 113 | 114 | **Note.** Here, slcanN refers to the CAN network interface you are using to 115 | communicate with the MSP430 FPGA. slcan0 is the default if you ommit this 116 | parameter. 117 | 118 | **Note.** Since this exercise changes the source code of the `foo.c` enclave, 119 | in order to successfully complete the remote attestation protocol in the end, 120 | you will have to fill in the correct Sancus module-specific key in the SGX 121 | enclave again. We refer to `../../sancus/001-attestation` for details 122 | instructions on how to do this. 123 | -------------------------------------------------------------------------------- /app/sgx/000-pin/README.md: -------------------------------------------------------------------------------- 1 | # PIN code verifier: your first enclave program 2 | 3 | ## Application overview 4 | 5 | The purpose of this application is to develop a first elementary SGX enclave 6 | program that verifies untrusted user input. Particularly, we assume that the 7 | enclave has previously already been securely provisioned with a 4-digit PIN 8 | code and an application-level secret. The enclave's sole job is to enforce 9 | access control on the application secret by querying the untrusted world for 10 | the PIN code, destroying the secret after three successive failed comparison 11 | attempts, or returning it on success. 12 | 13 | **Note.** This application only serves demonstration purposes and does not aim 14 | to be a fully tamper-proof security solution. Notable enclave concepts that are 15 | missing include _secure I/O_, _secret provisioning_, _sealing_ for persistent 16 | storage, and _state continuity_ to protect against roll-back attacks. 17 | 18 | ## Your task 19 | 20 | Developing an SGX enclave application roughly falls down in three phases, 21 | outlined below. 22 | 23 | ### Extending enclave public interface (`Enclave/encl.edl`) 24 | 25 | In the enclaved execution paradigm, the programmer splits off a small trusted 26 | application part (the "enclave") that is shielded by the CPU from the remainder 27 | of the application. Since enclaves are designed to operate in an untrusted, 28 | potentially hostile, environment, they should enforce a strict public software 29 | interface. Generally, enclaves can interact with their untrusted environment in 30 | two distinct ways: 31 | 32 | - **ECALL:** Function call performed by the untrusted world to enter an 33 | enclave, passing some arguments and/or expecting a return value. 34 | - **OCALL:** Function call performed by the enclave to call back to the 35 | untrusted world, passing some arguments and/or expecting a return value. 36 | 37 | The Intel SGX SDK features a small domain-specific [Enclave Definition Language 38 | (EDL)](https://software.intel.com/en-us/sgx-sdk-dev-reference-enclave-definition-language-file-syntax) 39 | to unambiguously define the enclave's ECALL/OCALL interaction with the 40 | untrusted world. Pointer arguments should be explicitly marked with `[in]` and 41 | `[out]` attributes to indicate whether they represent input and/or output for 42 | the enclave (in case of an ECALL), or untrusted world (in case of an OCALL). 43 | Based on this description, the SDK automatically generates trusted and 44 | untrusted bridge code that securely transfers control to/from the untrusted 45 | environment. 46 | 47 | **Do it yourself.** The PIN code verifier application will feature an ECALL entry 48 | point to try and request the application secret, plus an OCALL callback function 49 | to query an untrusted PIN code from the end user. You will thus have to: 50 | 51 | - Extend `Enclave/encl.edl` with a trusted `ecall_get_secret` ECALL entry point 52 | that takes an `int*` pointer argument and returns an `int`, indicating whether 53 | or not PIN code verification succeeded and the application secret was written 54 | to the pointer argument. 55 | - Extend `Enclave/encl.edl` with an untrusted `ocall_get_pin` OCALL callback 56 | that takes no arguments and returns an untrusted `int` containing the PIN code. 57 | 58 | ### Extending enclave implementation (`Enclave/encl.c`) 59 | 60 | After defining the enclave's interface, you will have to implement the required 61 | ECALL functionality. Implement the `int ecall_get_secret(int *secret_pt)` 62 | function by making use of the `int ocall_get_pin(void)` untrusted helper 63 | function. Take care to ensure that: 64 | 65 | - The enclave only writes `super_secret_constant` to `secret_pt` when one of 66 | maximum three successive untrusted user-provided PIN code attempts matches 67 | `super_secret_pin`. 68 | - The enclave zeroes out all secrets upon three successive failed PIN code 69 | verification attempts (to prevent brute-force attacks by the untrusted 70 | world). 71 | 72 | ### Extending untrusted runtime (`main.c`) 73 | 74 | Finally, after finishing the trusted enclave's implementation, you have to 75 | extend the untrusted runtime support system. We already provided the enclave 76 | creation code, `ocall_get_pin()` function, and an example `ecall_dummy()` enclave 77 | function call. Now, add the `ecall_get_secret()` enclave function call, and 78 | print out the return value and secret returned by the trusted enclave. 79 | 80 | ## Building and running 81 | 82 | Simply execute: 83 | 84 | ```bash 85 | $ make run 86 | 87 | 88 | -------------------------------------------------------------------------------- 89 | [main.c] Creating enclave... 90 | -------------------------------------------------------------------------------- 91 | 92 | 93 | -------------------------------------------------------------------------------- 94 | [main.c] calling enclave... 95 | -------------------------------------------------------------------------------- 96 | 97 | [main.c] ocall_print: enclave says: 'hello world from ecall_dummy!' 98 | [main.c] ecall_dummy(1) enclave entry point returned -559038736 99 | [main.c] ocall_print: enclave says: 'hello world from ecall_get_secret!' 100 | enter PIN code > 1222 101 | enter PIN code > 1234 102 | [main.c] ecall_get_secret enclave entry point returned 1 (secret 0xdeadbeef) 103 | 104 | -------------------------------------------------------------------------------- 105 | [main.c] destroying SGX enclave 106 | -------------------------------------------------------------------------------- 107 | 108 | [main.c] all is well; exiting.. 109 | ``` 110 | -------------------------------------------------------------------------------- /app/sancus/001-attestation/README.md: -------------------------------------------------------------------------------- 1 | # Attestation: challenge-response protocol to prove untampered protected execution 2 | 3 | ## Application overview 4 | 5 | The purpose of this application is to cryptographically prove to a remote 6 | stakeholder that a Sancus enclave has been loaded untampered with protection 7 | enabled on a genuine Sancus-enabled MSP430 CPU. 8 | 9 | ![attestation-overview](https://distrinet.cs.kuleuven.be/software/sancus/images/dsn18-attestation.png) 10 | 11 | **Note.** For now, we focus exclusively on implementing the required 12 | functionality at the Sancus MSP430 side, and we assume the remote stakeholder's 13 | PC development side is completely trusted. In the following exercises, we will 14 | relax this TCB requirement by leveraging off-the-shelf Intel SGX isolation 15 | at the PC side to run the remote stakeholder's critical attestation verification 16 | code in SGX enclaves. 17 | 18 | ## Your task 19 | 20 | Your job is to implement remote attestation for the 'foo.c' Sancus enclave. 21 | This requires multiple steps, outlined below. 22 | 23 | ### Implementing attestation entry point for foo enclave 24 | 25 | In contrast to the Intel SGX SDK, the secure Sancus compiler does not require 26 | EDL definitions, but instead requires the enclave developer to annotate C 27 | source code with intuitive `SM_ENTRY(enclave_name)`, `SM_FUNC(enclave_name)`, 28 | `SM_DATA(enclave_name)` macros. Only code and data explicitly marked with these 29 | macros will be compiled into the enclave; all other code remains explicitly 30 | untrusted. 31 | 32 | **Do it yourself.** Add an `SM_ENTRY` enclave entry point in `foo.h` and 33 | `foo.c`: 34 | 35 | ```C 36 | int SM_ENTRY(foo) attest_foo(uint8_t *challenge, int len, uint8_t *mac); 37 | ``` 38 | 39 | This function takes an _untrusted_ pointer to a `challenge` buffer with length 40 | `len`, and returns 0 iff the _untrusted_ `mac` buffer contains the 128-bit MAC 41 | over the challenge computed with the Sancus module-specific key *K_N_SP_SM* of 42 | the 'foo' enclave. 43 | 44 | Note that to conveniently access the Sancus secure crypto hardware 45 | instructions, the Sancus compiler provides a small trusted in-enclave 46 | [`sm_support`](https://github.com/sancus-pma/sancus-compiler/blob/master/src/sancus_support/sm_support.h) 47 | library. We repeat the documentation for the relevant function below: 48 | 49 | #### Syntax 50 | 51 | ```C 52 | int sancus_tag(const void* body, size_t body_len, void* tag); 53 | ``` 54 | 55 | #### Parameters 56 | 57 | - `body` [in] Pointer to start of associated data input buffer. 58 | - `body_len` [in] Length of associated data input buffer. 59 | - `tag` [out] Pointer to output buffer of `SPONGENT_TAG_SIZE` bytes for MAC 60 | over associated data. 61 | 62 | #### Return value 63 | 64 | Returns true iff the wrapping succeeded. 65 | 66 | ### Extending untrusted runtime 67 | 68 | We already provide a complete `main.c` untrusted runtime to enable protection 69 | for the 'foo' enclave, and to properly forward 64-bit attestation challenges 70 | and 128-bit responses over the local CAN network. After implementing the 'foo' 71 | remote attestation entry point, however, it should still be called from the 72 | untrusted runtime. From the point of view of the programmer, Sancus ECALLs 73 | resemble ordinary function calls. 74 | 75 | **Do it yourself.** Simply insert the required `attest_foo()` function call 76 | after receiving the attestation challenge, and before sending the response in 77 | `main.c`. 78 | 79 | ## Building and running 80 | 81 | As with the `000-blinking-led` example, the application's debug output can be 82 | monitored over the tty USB serial line via the `screen` utility. At the PC 83 | side, we provide an elementary test application to provide attestation 84 | challenges and verify responses over the CAN bus. 85 | 86 | ### Sancus side (foo enclave and untrusted runtime) 87 | 88 | Again, use `make load` to build and upload the application binary to the FPGA. 89 | 90 | ```bash 91 | $ FPGA_DEV=/dev/ttyUSB0 make load # in case of permission errors, replace `USB0` with the 92 | # uplink UART USB device that was assigned to your FPGA 93 | ``` 94 | 95 | ### PC side (remote stakeholder application) 96 | 97 | We provide a minimalistic test application that can be ran at the PC side to 98 | construct attestation challenge CAN messages and verify responses. Run as 99 | follows: 100 | 101 | ```bash 102 | $ cd ../../sgx/001-attestation-unprotected/ 103 | $ make run 104 | 105 | -------------------------------------------------------------------------------- 106 | [main.c] remote attestation challenge 107 | -------------------------------------------------------------------------------- 108 | 109 | enter attesation challenge (64-bit number) > 1234 110 | [../common/can.c] send: CAN frame with ID 0x40 (len=8) 111 | MSG = d2 04 00 00 00 00 00 00 112 | 113 | -------------------------------------------------------------------------------- 114 | [main.c] remote attestation response 115 | -------------------------------------------------------------------------------- 116 | 117 | [main.c] waiting for CAN response messages... 118 | [../common/can.c] recv: CAN frame with ID 0x40 (len=8) 119 | MSG = df 4f 9e 35 15 9d c1 37 120 | [../common/can.c] recv: CAN frame with ID 0x40 (len=8) 121 | MSG = 73 b9 05 9f 1e 28 25 22 122 | SM_MAC = df 4f 9e 35 15 9d c1 37 73 b9 05 9f 1e 28 25 22 123 | 124 | -------------------------------------------------------------------------------- 125 | [main.c] comparing expected and received MACs... 126 | -------------------------------------------------------------------------------- 127 | 128 | [main.c] calculating expected MAC... 129 | MY_MAC = df 4f 9e 35 15 9d c1 37 73 b9 05 9f 1e 28 25 22 130 | [main.c] OK : remote attestation succeeded! 131 | 132 | ``` 133 | 134 | ### Providing attestation challenges 135 | 136 | The above application simply queries you for a 64-bit number. This number is 137 | subsequently included as the payload for an attestation challenge CAN frame 138 | destined for the remote Sancus enclave. Only a properly loaded foo enclave 139 | will have access to the correct Sancus module-specific key that is required 140 | to construct the 128-bit response MAC over the challenge. 141 | 142 | **Note.** Be aware that attackers with full control over the network can easily 143 | record and replay plaintext challenges and their corresponding MAC responses. To 144 | thwart such replay attacks, you will have to establish a _fresh_ attestation 145 | guarantee every time you run the application (i.e., the challenge you enter 146 | serves as a nonce and in real-world deployment, you should make sure to never 147 | re-use the same attestation challenge). 148 | 149 | ### Verifying attestation responses 150 | 151 | If all goes well and you implemented the required functionality at the Sancus 152 | side, the above program should still terminate with a failed attestation 153 | response verification. This is expected behavior, for we should still provide 154 | the PC application with the correct 128-bit Sancus module-specific key. 155 | 156 | We rely on the `sancus-crypto` utility to compute the Sancus module-specific 157 | key for the 'foo' module, deployed with software provider identity `0x1234` on 158 | the FPGA with 128-bit node master key `0xdeadbeefcafebabec0defeeddefec8ed`. 159 | 160 | ```bash 161 | # First, we derive the vendor key from the node master key 162 | $ sancus-crypto --key deadbeefcafebabec0defeeddefec8ed --gen-vendor-key 1234 163 | 0b7bf3ae40880a8be430d0da34fb76f0 164 | 165 | # Now, we derive the module-specific key for the foo module 166 | $ sancus-crypto --key 0b7bf3ae40880a8be430d0da34fb76f0 --gen-sm-key foo --c-array main.elf 167 | uint8_t key[] = { 0x05, 0x41, 0x87, 0x10, 0xff, 0xa4, 0x83, 0xc1, 0x2e, 0xe2, 0xda, 0x82, 0x81, 0x36, 0xb7, 0x6b}; 168 | ``` 169 | 170 | To successfully complete the remote attestation process, fill in this key in 171 | `../../sgx/001-attestation/main.c`, and run the Sancus and PC applications again. 172 | 173 | **Note.** The above Sancus module-specific key includes foo's compiled code 174 | section, such that you will have to repeat the above process each time when you 175 | change foo's source code. Any changes in foo's code will lead to a different 176 | key and will thus be detected by the remote stakeholder at the PC side; this is 177 | exactly what attestation is all about. 178 | --------------------------------------------------------------------------------