Skip to content

Commit

Permalink
Merge pull request sancus-tee#36 from gianlu33/rearrange-commits
Browse files Browse the repository at this point in the history
Changes in stubs and linker.py for Authentic Execution
  • Loading branch information
gianlu33 committed Nov 5, 2021
1 parent 193df1a commit 7982c96
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 92 deletions.
100 changes: 66 additions & 34 deletions src/drivers/linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

MAC_SIZE = int(sancus.config.SECURITY / 8)
KEY_SIZE = MAC_SIZE
CONNECTION_STRUCT_SIZE = 6 + KEY_SIZE


class SmEntry:
Expand Down Expand Up @@ -61,7 +62,7 @@ def add_sym(file, sym_map):

args += [file, file]
call_prog('msp430-elf-objcopy', args)
return file
return file


def parse_size(val):
Expand Down Expand Up @@ -90,18 +91,23 @@ def get_symbol(elf_file, name):

def get_io_sym_map(sm_name):
sym_map = {
'__sm_handle_input': '__sm_{}_handle_input'.format(sm_name),
'__sm_num_inputs': '__sm_{}_num_inputs'.format(sm_name),
'__sm_num_connections': '__sm_{}_num_connections'.format(sm_name),
'__sm_io_keys': '__sm_{}_io_keys'.format(sm_name),
'__sm_input_callbacks': '__sm_{}_input_callbacks'.format(sm_name),
'__sm_output_nonce': '__sm_{}_output_nonce'.format(sm_name),
'__sm_send_output': '__sm_{}_send_output'.format(sm_name),
'__sm_set_key': '__sm_{}_set_key'.format(sm_name),
'__sm_X_exit': '__sm_{}_exit'.format(sm_name),
'__sm_X_stub_malloc': '__sm_{}_stub_malloc'.format(sm_name),
'__sm_handle_input': '__sm_{}_handle_input'.format(sm_name),
'__sm_num_inputs': '__sm_{}_num_inputs'.format(sm_name),
'__sm_num_connections': '__sm_{}_num_connections'.format(sm_name),
'__sm_max_connections': '__sm_{}_max_connections'.format(sm_name),
'__sm_io_connections': '__sm_{}_io_connections'.format(sm_name),
'__sm_input_callbacks': '__sm_{}_input_callbacks'.format(sm_name),
'__sm_send_output': '__sm_{}_send_output'.format(sm_name),
'__sm_set_key': '__sm_{}_set_key'.format(sm_name),
'__sm_attest': '__sm_{}_attest'.format(sm_name),
'__sm_X_exit': '__sm_{}_exit'.format(sm_name),
'__sm_X_stub_malloc': '__sm_{}_stub_malloc'.format(sm_name),
'__sm_X_stub_reactive_handle_output':
'__sm_{}_stub_reactive_handle_output'.format(sm_name)
'__sm_{}_stub_reactive_handle_output'.format(sm_name),
'__sm_X_public_start': '__sm_{}_public_start'.format(sm_name),
'__sm_X_public_end': '__sm_{}_public_end'.format(sm_name),
'__sm_X_secret_start': '__sm_{}_secret_start'.format(sm_name),
'__sm_X_secret_end': '__sm_{}_secret_end'.format(sm_name)
}

return sym_map
Expand All @@ -113,7 +119,7 @@ def get_io_sect_map(sm_name):
'.rela.sm.X.text': '.rela.sm.{}.text'.format(sm_name),
}

for entry in ('__sm{}_set_key', '__sm{}_handle_input'):
for entry in ('__sm{}_set_key', '__sm{}_attest', '__sm{}_handle_input'):
map['.sm.X.{}.table'.format(entry.format(''))] = \
'.sm.{}.{}.table'.format(sm_name, entry.format('_' + sm_name))
map['.rela.sm.X.{}.table'.format(entry.format(''))] = \
Expand All @@ -134,15 +140,19 @@ def create_io_stub(sm, stub):


def sort_entries(entries):
# If the set_key entry exists, it should have index 0 and if the
# handle_input entry exists, it should have index 1. This is accomplished by
# mapping those entries to __ and ___ respectively since those come
# If the set_key entry exists, it should have index 0, if the
# attest entry exists, it should have index 1 and if
# handle_input entry exists, it should have index 2. This is accomplished by
# mapping those entries to __, ___ and ___ respectively since those come
# alphabetically before any valid entry name.
def sort_key(entry):
if re.match(r'__sm_\w+_set_key', entry.name):
return '__'
if re.match(r'__sm_\w+_handle_input', entry.name):
if re.match(r'__sm_\w+_attest', entry.name):
return '___'
if re.match(r'__sm_\w+_handle_input', entry.name):
return '____'

return entry.name

entries.sort(key=sort_key)
Expand Down Expand Up @@ -199,7 +209,7 @@ def sort_key(entry):
for a in archive_files:
debug("Unpacking archive for Sancus SM inspection: " + a)
file_name = a
if ':' in a:
if ':' in a:
# support calls such as -lib:/full/path
file_name = file_name.split(':')[1]

Expand Down Expand Up @@ -256,6 +266,7 @@ def sort_key(entry):
elf_relocations = defaultdict(list)

added_set_key_stub = False
added_attest_stub = False
added_input_stub = False
added_output_stub = False

Expand Down Expand Up @@ -396,6 +407,14 @@ def sort_key(entry):
input_files_to_scan.append(generated_file)
added_set_key_stub = True

if not added_attest_stub:
# Generate the attest stub file
generated_file = create_io_stub(sm, 'sm_attest.o')
generated_object_files.append(generated_file)
# And register it to also be scanned by this loop later
input_files_to_scan.append(generated_file)
added_attest_stub = True

if which == 'input':
dest = sms_inputs

Expand Down Expand Up @@ -740,32 +759,45 @@ def sort_key(entry):

call_prog('msp430-gcc', ['-c', '-o', o_file, c_file])

input_callbacks += ' {}(.sm.{}.callbacks)\n'.format(o_file, sm)
input_callbacks += ' KEEP({}(.sm.{}.callbacks))\n'.format(o_file, sm)
input_callbacks += ' . = ALIGN(2);'

# Table of connection keys
io_keys = ''
"""
Table of connections: in a reactive application, a connection links the
output of a SM (defined using the macro `SM_OUTPUT`) to the input of another
(defined using the macro `SM_INPUT`).
These connections are stored in a `Connection` array on each SM (see
`reactive_stubs_support.h`). The array is allocated here with a fixed size,
according to the `num_connections` parameter in the SM config (default 0).
"""

if len(ios) > 0:
io_keys += '__sm_{}_io_keys = .;\n'.format(sm)
io_keys += ' . += {};\n'.format(len(ios) * KEY_SIZE)
io_keys += ' . = ALIGN(2);'
num_connections = ''
io_connections = ''

if hasattr(sm_config[sm], "num_connections"):
sm_num_connections = sm_config[sm].num_connections
else:
sm_num_connections = 0

# Nonce used by outputs
outputs_nonce = ''
if len(ios) > 0:
# make sure we allocate space even if num_connections is zero
io_connections_size = max(sm_num_connections * CONNECTION_STRUCT_SIZE, 2)

if len(outputs) > 0:
outputs_nonce += '__sm_{}_output_nonce = .;\n'.format(sm)
outputs_nonce += ' . += 2;\n'
outputs_nonce += ' . = ALIGN(2);'
num_connections += '__sm_{}_num_connections = .;\n'.format(sm)
num_connections += ' . += 2;\n'
num_connections += ' . = ALIGN(2);'
io_connections += '__sm_{}_io_connections = .;\n'.format(sm)
io_connections += ' . += {};\n'.format(io_connections_size)
io_connections += ' . = ALIGN(2);'

text_sections.append(text_section.format(sm, entry_file, isr_file,
exit_file, '\n '.join(tables),
input_callbacks,
'\n '.join(extra_labels)))

data_sections.append(data_section.format(sm, '\n '.join(id_syms),
args.sm_stack_size, io_keys,
outputs_nonce))
args.sm_stack_size, num_connections,
io_connections))

if sm in sms_entries:
num_entries = len(sms_entries[sm])
Expand All @@ -782,7 +814,7 @@ def sort_key(entry):
symbols.append('__sm_{}_io_{}_idx = {};'.format(sm, io, index))

# Add symbols for the number of connections/inputs
symbols.append('__sm_{}_num_connections = {};'.format(sm, len(ios)))
symbols.append('__sm_{}_max_connections = {};'.format(sm, sm_num_connections))
symbols.append('__sm_{}_num_inputs = {};'.format(sm, len(inputs)))

if args.prepare_for_sm_text_section_wrapping:
Expand Down
19 changes: 10 additions & 9 deletions src/sancus_support/reactive.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@
#include <stdint.h>

typedef uint16_t io_index;
typedef uint16_t conn_index;
typedef uint8_t io_data __attribute__((aligned(2)));

// The ASM symbols are used for the linker to be able to detect inputs/outputs

#define SM_OUTPUT_AUX(sm, name) \
asm("__sm_" #sm "_output_tag_" #name " = 0\n"); \
SM_FUNC(sm) void name(const io_data* data, size_t len) \
{ \
extern char __sm_##sm##_io_##name##_idx; \
SM_FUNC(sm) void __sm_##sm##_send_output(unsigned int, \
const void*, size_t); \
__sm_##sm##_send_output((io_index)&__sm_##sm##_io_##name##_idx, \
data, len); \
#define SM_OUTPUT_AUX(sm, name) \
asm("__sm_" #sm "_output_tag_" #name " = 0\n"); \
SM_FUNC(sm) uint16_t name(const io_data* data, size_t len) \
{ \
extern char __sm_##sm##_io_##name##_idx; \
SM_FUNC(sm) uint16_t __sm_##sm##_send_output(unsigned int, \
const void*, size_t); \
return __sm_##sm##_send_output((io_index)&__sm_##sm##_io_##name##_idx, \
data, len); \
}

#define SM_OUTPUT(sm, name) SM_OUTPUT_AUX(sm, name)
Expand Down
41 changes: 35 additions & 6 deletions src/sancus_support/sm_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "config.h"

#include <stddef.h>
#include <stdint.h>

#if __GNUC__ >= 5 || __clang_major__ >= 5

Expand Down Expand Up @@ -199,15 +200,12 @@ extern char __unprotected_sp;

#endif

#define __OUTSIDE_SM( p, sm ) \
( ((void*) p < (void*) &__PS(sm)) || ((void*) p >= (void*) &__PE(sm)) ) && \
( ((void*) p < (void*) &__SS(sm)) || ((void*) p >= (void*) &__SE(sm)) )

/*
* Returns true iff whole buffer [p,p+len-1] is outside of the sm SancusModule
*/
#define sancus_is_outside_sm( sm, p, len) \
( __OUTSIDE_SM(p, sm) && __OUTSIDE_SM((p+len-1), sm) )
#define sancus_is_outside_sm(sm, p, len) \
( is_buffer_outside_region(&__PS(sm), &__PE(sm), p, len) && \
is_buffer_outside_region(&__SS(sm), &__SE(sm), p, len) )

/**
* Interrupt vector for the Sancus violation ISR.
Expand Down Expand Up @@ -311,6 +309,37 @@ sm_id sancus_enable_wrapped(struct SancusModule* sm, unsigned nonce, void* tag);
#undef always_inline
#define always_inline static inline __attribute__((always_inline))

/*
* Returns true if buf is outside the memory region [start, end)
* if start >= end, immediately return false
*/
always_inline int is_buffer_outside_region(void *start_p, void *end_p,
void *buf_p, size_t len) {
uintptr_t start = (uintptr_t) start_p;
uintptr_t end = (uintptr_t) end_p;
uintptr_t buf = (uintptr_t) buf_p;
uintptr_t buf_end;

// make sure start < end, otherwise return false
if (start >= end) {
return 0;
}

if(len > 0) {
buf_end = buf + len - 1;
}
else {
buf_end = buf;
}

/* check for int overflow and finally validate `buf` falls outside */
if( (buf <= buf_end) && ((end <= buf) || (start > buf_end))) {
return 1;
}

return 0;
}

/**
* Disable the protection of the calling module.
*/
Expand Down
2 changes: 2 additions & 0 deletions src/stubs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ set(EXTRA_FLAGS -I${CMAKE_SOURCE_DIR}/src/sancus_support)
add_object(sm_output.o sm_output.c ${EXTRA_FLAGS})
add_object(sm_input.o sm_input.c ${EXTRA_FLAGS})
add_object(sm_set_key.o sm_set_key.c ${EXTRA_FLAGS})
add_object(sm_attest.o sm_attest.c ${EXTRA_FLAGS})

set(STUBS
${CMAKE_CURRENT_BINARY_DIR}/sm_entry.o
Expand All @@ -32,6 +33,7 @@ set(STUBS
${CMAKE_CURRENT_BINARY_DIR}/sm_output.o
${CMAKE_CURRENT_BINARY_DIR}/sm_input.o
${CMAKE_CURRENT_BINARY_DIR}/sm_set_key.o
${CMAKE_CURRENT_BINARY_DIR}/sm_attest.o
${CMAKE_CURRENT_BINARY_DIR}/sm_mmio_entry.o
${CMAKE_CURRENT_BINARY_DIR}/sm_mmio_exclusive.o

Expand Down
41 changes: 33 additions & 8 deletions src/stubs/reactive_stubs_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,54 @@

#include "reactive.h"

void reactive_handle_output(io_index output_id, void* data, size_t len);
void reactive_handle_output(conn_index conn_id, void* data, size_t len);

typedef uint8_t IoKey[SANCUS_KEY_SIZE];
typedef void (*InputCallback)(const void*, size_t);

typedef enum
{
Ok = 0x0,
IllegalConnection = 0x1,
MalformedPayload = 0x2
Ok = 0x0,
IllegalConnection = 0x1,
MalformedPayload = 0x2,
IllegalParameters = 0x3,
BufferInsideSM = 0x4,
CryptoError = 0x5,
InternalError = 0x6
} ResultCode;

typedef struct Connection {
io_index io_id;
conn_index conn_id;
uint16_t nonce;
IoKey key;
} Connection;

// The size of the Connection struct is also hardcoded in linker.py. Hence,
// we need to make sure that it does not change at compile time (e.g. due to
// optimizations).
// Besides, if the struct changes, we need to adjust this value here and in
// linker.py (check the CONNECTION_STRUCT_SIZE global variable) as well.
_Static_assert (sizeof(Connection) == 6 + SANCUS_KEY_SIZE,
"Size of Connection struct differs from the expected value");

// These will be allocated by the linker
extern IoKey __sm_io_keys[];
extern Connection __sm_io_connections[];
extern InputCallback __sm_input_callbacks[];
extern uint16_t __sm_output_nonce;

extern char __sm_num_connections;
#define SM_NUM_CONNECTIONS (size_t)&__sm_num_connections
extern char __sm_max_connections;
#define SM_MAX_CONNECTIONS (size_t)&__sm_max_connections

extern uint16_t __sm_num_connections;

extern char __sm_num_inputs;
#define SM_NUM_INPUTS (size_t)&__sm_num_inputs

#define SM_NAME X

// declare symbols for the public/secret regions
#define __SECTION(sect, name) sect(name)
extern char __SECTION(__PS, SM_NAME), __SECTION(__PE, SM_NAME),
__SECTION(__SS, SM_NAME), __SECTION(__SE, SM_NAME);

#endif
16 changes: 16 additions & 0 deletions src/stubs/sm_attest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "reactive_stubs_support.h"

uint16_t SM_ENTRY(SM_NAME) __sm_attest(const uint8_t* challenge, size_t len,
uint8_t *result)
{
if( !sancus_is_outside_sm(SM_NAME, (void *) challenge, len) ||
!sancus_is_outside_sm(SM_NAME, (void *) result, SANCUS_TAG_SIZE) ) {
return BufferInsideSM;
}

if( !sancus_tag(challenge, len, result) ) {
return CryptoError;
}

return Ok;
}
Loading

0 comments on commit 7982c96

Please sign in to comment.