From 14e17e6efd19622fbec6be8270be2c30a6b07920 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Thu, 15 Feb 2018 16:37:24 -0500 Subject: Cleanup: warn of signed/unsigned mismatches in libhal. This is from October's cleanup binge, but I forgot to commit it at the time. --- libraries/libhal/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/libhal/Makefile b/libraries/libhal/Makefile index 72225e1..d71956f 100644 --- a/libraries/libhal/Makefile +++ b/libraries/libhal/Makefile @@ -1,6 +1,6 @@ vpath %.c ${LIBHAL_SRC} vpath %.h ${LIBHAL_SRC} -CFLAGS += -Wno-missing-field-initializers -Wno-unused-parameter -Wno-sign-compare +CFLAGS += -Wno-missing-field-initializers -Wno-unused-parameter include ${LIBHAL_SRC}/Makefile -- cgit v1.2.3 From 1ceb5752a309397799e9ef4a99ff1b327fc42a8d Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Mon, 26 Feb 2018 16:06:42 -0500 Subject: Implement hash-based signatures, per draft-mcgrew-hash-sigs-08.txt --- projects/hsm/hsm.c | 9 +-------- projects/hsm/mgmt-keystore.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/projects/hsm/hsm.c b/projects/hsm/hsm.c index 7fc7410..3f7a6fd 100644 --- a/projects/hsm/hsm.c +++ b/projects/hsm/hsm.c @@ -90,18 +90,11 @@ static uint8_t busy_stack[BUSY_STACK_SIZE]; #endif static uint8_t cli_stack[CLI_STACK_SIZE]; -#ifndef MAX_PKT_SIZE -/* An arbitrary number, more or less driven by the 4096-bit RSA - * keygen test. - */ -#define MAX_PKT_SIZE 4096 -#endif - /* RPC buffers. For each active request, there will be two - input and output. */ typedef struct rpc_buffer_s { size_t len; - uint8_t buf[MAX_PKT_SIZE]; + uint8_t buf[HAL_RPC_MAX_PKT_SIZE]; struct rpc_buffer_s *next; /* for ibuf queue linking */ } rpc_buffer_t; diff --git a/projects/hsm/mgmt-keystore.c b/projects/hsm/mgmt-keystore.c index b79a5fe..a7fdffe 100644 --- a/projects/hsm/mgmt-keystore.c +++ b/projects/hsm/mgmt-keystore.c @@ -180,6 +180,8 @@ static int cmd_keystore_delete_key(struct cli_def *cli, const char *command, cha return CLI_OK; } +#include "ks.h" + static int show_keys(struct cli_def *cli, const char *title) { const hal_client_handle_t client = { -1 }; @@ -198,6 +200,16 @@ static int show_keys(struct cli_def *cli, const char *title) cli_print(cli, title); + size_t avail; + if ((status = hal_ks_available(hal_ks_token, &avail)) == HAL_OK) + cli_print(cli, "Token keystore: %d available", avail); + else + cli_print(cli, "Error reading token keystore: %s", hal_error_string(status)); + if ((status = hal_ks_available(hal_ks_volatile, &avail)) == HAL_OK) + cli_print(cli, "Volatile keystore: %d available", avail); + else + cli_print(cli, "Error reading volatile keystore: %s", hal_error_string(status)); + while (!done) { if ((status = hal_rpc_pkey_match(client, session, HAL_KEY_TYPE_NONE, HAL_CURVE_NONE, @@ -248,6 +260,10 @@ static int show_keys(struct cli_def *cli, const char *title) case HAL_KEY_TYPE_RSA_PUBLIC: type_name = "RSA public"; break; case HAL_KEY_TYPE_EC_PRIVATE: type_name = "EC private"; break; case HAL_KEY_TYPE_EC_PUBLIC: type_name = "EC public"; break; + case HAL_KEY_TYPE_HASHSIG_PRIVATE: type_name = "hashsig private"; break; + case HAL_KEY_TYPE_HASHSIG_PUBLIC: type_name = "hashsig public"; break; + case HAL_KEY_TYPE_HASHSIG_LMS: type_name = "hashsig lms"; break; + case HAL_KEY_TYPE_HASHSIG_LMOTS: type_name = "hashsig lmots"; break; } const char *curve_name = "unknown"; -- cgit v1.2.3 From 46fbe98ffe13484b2fc5e8cfe1e67a84f6be84da Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Thu, 19 Apr 2018 16:30:22 -0400 Subject: Reconstruct the hashsig hash tree(s) on device restart. This can take long enough (several minutes for h=10) that we do it in a background task, which is then converted to an RPC dispatch task. Also add a very limited form of free(), to free the topmost allocation in the sdram "heap". I don't want to deal with real heap management, but I do want to be able to recover memory upon deleting a hashsig key, if it's easy to do so. --- projects/hsm/hsm.c | 74 +++++++++++++++++++++++++++++++++++++++++++----------- spiflash_n25q128.c | 2 +- task.c | 22 ++++++++++++++-- task.h | 1 + 4 files changed, 82 insertions(+), 17 deletions(-) diff --git a/projects/hsm/hsm.c b/projects/hsm/hsm.c index 3f7a6fd..39cfa65 100644 --- a/projects/hsm/hsm.c +++ b/projects/hsm/hsm.c @@ -336,36 +336,73 @@ static void busy_task(void) } } -/* Allocate memory from SDRAM1. There is only malloc, no free, so we don't - * worry about fragmentation. */ -static uint8_t *sdram_malloc(size_t size) +#include "stm-fpgacfg.h" +#include "hashsig.h" + +static void hashsig_restart_task(void) { - /* end of variables declared with __attribute__((section(".sdram1"))) */ - extern uint8_t _esdram1 __asm ("_esdram1"); - /* end of SDRAM1 section */ - extern uint8_t __end_sdram1 __asm ("__end_sdram1"); + /* wait for the fpga to configure itself on cold-boot */ + while (fpgacfg_check_done() != CMSIS_HAL_OK) + task_yield(); - static uint8_t *sdram_heap = &_esdram1; + /* reinitialize the hashsig key structures after a device restart */ + hal_hashsig_ks_init(); + + /* done, convert this task to an RPC handler */ + task_mod((char *)task_get_cookie(NULL), dispatch_task, NULL); +} + +/* end of variables declared with __attribute__((section(".sdram1"))) */ +extern uint8_t _esdram1 __asm ("_esdram1"); +/* end of SDRAM1 section */ +extern uint8_t __end_sdram1 __asm ("__end_sdram1"); +static uint8_t *sdram_heap = &_esdram1; + +/* Allocate memory from SDRAM1. */ +static uint8_t *sdram_malloc(size_t size) +{ uint8_t *p = sdram_heap; #define pad(n) (((n) + 3) & ~3) size = pad(size); - if (p + size > &__end_sdram1) + if (p + size + sizeof(uint32_t) > &__end_sdram1) return NULL; - sdram_heap += size; + *(uint32_t *)p = (uint32_t)size; + p += sizeof(uint32_t); + + sdram_heap += size + sizeof(uint32_t); return p; } -/* Implement static memory allocation for libhal over sdram_malloc(). - * Once again, there's only alloc, not free. */ +/* A very limited form of free(), which only frees memory if it's at the + * top of the heap. + */ +static hal_error_t sdram_free(uint8_t *ptr) +{ + uint8_t *p = ptr - sizeof(uint32_t); + uint32_t size = *(uint32_t *)p; + if (ptr + size == sdram_heap) { + sdram_heap = p; + return LIBHAL_OK; + } + else + return HAL_ERROR_FORBIDDEN; +} +/* Implement static memory allocation for libhal over sdram_malloc(). + */ void *hal_allocate_static_memory(const size_t size) { return sdram_malloc(size); } +hal_error_t hal_free_static_memory(const void * const ptr) +{ + return sdram_free((uint8_t *)ptr); +} + /* Critical section start/end - temporarily disable interrupts. */ void hal_critical_section_start(void) @@ -420,8 +457,14 @@ int main(void) void *stack = (void *)sdram_malloc(TASK_STACK_SIZE); if (stack == NULL) Error_Handler(); - if (task_add(label[i], dispatch_task, &ibufs[i], stack, TASK_STACK_SIZE) == NULL) - Error_Handler(); + if (i == NUM_RPC_TASK - 1) { + if (task_add("hashsig_restart", hashsig_restart_task, label[i], stack, TASK_STACK_SIZE) == NULL) + Error_Handler(); + } + else { + if (task_add(label[i], dispatch_task, NULL, stack, TASK_STACK_SIZE) == NULL) + Error_Handler(); + } } /* Create the busy task. */ @@ -443,4 +486,7 @@ int main(void) /* Start the tasker */ task_yield(); + + /*NOTREACHED*/ + return 0; } diff --git a/spiflash_n25q128.c b/spiflash_n25q128.c index 5e10185..df53f19 100644 --- a/spiflash_n25q128.c +++ b/spiflash_n25q128.c @@ -197,7 +197,7 @@ HAL_StatusTypeDef n25q128_write_page(struct spiflash_ctx *ctx, uint32_t page_off } -static int n25q128_erase_something(struct spiflash_ctx *ctx, uint8_t command, uint32_t byte_offset) +static HAL_StatusTypeDef n25q128_erase_something(struct spiflash_ctx *ctx, uint8_t command, uint32_t byte_offset) { // check offset if (byte_offset >= N25Q128_NUM_BYTES) return HAL_ERROR; diff --git a/task.c b/task.c index 2e2ddec..0818226 100644 --- a/task.c +++ b/task.c @@ -119,6 +119,24 @@ tcb_t *task_add(char *name, funcp_t func, void *cookie, void *stack, size_t stac return t; } +/* Reinitalize the current task. + * NOTE: This will destroy any state in the running task. + * DO NOT CALL THIS UNLESS YOU ARE REALLY SURE THAT'S WHAT YOU WANT TO DO. + */ +void task_mod(char *name, funcp_t func, void *cookie) +{ + tcb_t *t = cur_task; + t->name = name; + t->func = func; + t->cookie = cookie; + t->state = TASK_INIT; + t->stack_ptr = t->stack_base + t->stack_len; + for (uint32_t *p = (uint32_t *)t->stack_base; p < (uint32_t *)t->stack_ptr; ++p) + *p = STACK_GUARD_WORD; + __set_MSP((uint32_t)cur_task->stack_ptr); + task_yield(); +} + /* Set the idle hook function pointer. * * This function is called repeatedly when the system is idle (there are @@ -200,11 +218,11 @@ void task_yield(void) /* If there are no other runnable tasks (and cur_task is runnable), * we don't need to context-switch. */ - if (next == cur_task) + if (next == cur_task && cur_task->state != TASK_INIT) return; /* Save current context, if there is one. */ - if (cur_task != NULL) { + if (cur_task != NULL && cur_task->state != TASK_INIT) { __asm("push {r0-r12, lr}"); cur_task->stack_ptr = (void *)__get_MSP(); diff --git a/task.h b/task.h index 6b45db8..e6bd15d 100644 --- a/task.h +++ b/task.h @@ -51,6 +51,7 @@ typedef struct { unsigned locked; } task_mutex_t; typedef void (*funcp_t)(void); extern tcb_t *task_add(char *name, funcp_t func, void *cookie, void *stack, size_t stack_len); +extern void task_mod(char *name, funcp_t func, void *cookie); extern void task_set_idle_hook(funcp_t func); -- cgit v1.2.3 From af127e807008b2153d597e756ff26da69daf9e45 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Mon, 26 Feb 2018 16:06:42 -0500 Subject: Implement hash-based signatures, per draft-mcgrew-hash-sigs-08.txt --- projects/hsm/hsm.c | 9 +-------- projects/hsm/mgmt-keystore.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/projects/hsm/hsm.c b/projects/hsm/hsm.c index f20ee64..d971f14 100644 --- a/projects/hsm/hsm.c +++ b/projects/hsm/hsm.c @@ -90,18 +90,11 @@ static uint8_t busy_stack[BUSY_STACK_SIZE]; #endif static uint8_t cli_stack[CLI_STACK_SIZE]; -#ifndef MAX_PKT_SIZE -/* An arbitrary number, more or less driven by the 4096-bit RSA - * keygen test. - */ -#define MAX_PKT_SIZE 4096 -#endif - /* RPC buffers. For each active request, there will be two - input and output. */ typedef struct rpc_buffer_s { size_t len; - uint8_t buf[MAX_PKT_SIZE]; + uint8_t buf[HAL_RPC_MAX_PKT_SIZE]; struct rpc_buffer_s *next; /* for ibuf queue linking */ } rpc_buffer_t; diff --git a/projects/hsm/mgmt-keystore.c b/projects/hsm/mgmt-keystore.c index b79a5fe..a7fdffe 100644 --- a/projects/hsm/mgmt-keystore.c +++ b/projects/hsm/mgmt-keystore.c @@ -180,6 +180,8 @@ static int cmd_keystore_delete_key(struct cli_def *cli, const char *command, cha return CLI_OK; } +#include "ks.h" + static int show_keys(struct cli_def *cli, const char *title) { const hal_client_handle_t client = { -1 }; @@ -198,6 +200,16 @@ static int show_keys(struct cli_def *cli, const char *title) cli_print(cli, title); + size_t avail; + if ((status = hal_ks_available(hal_ks_token, &avail)) == HAL_OK) + cli_print(cli, "Token keystore: %d available", avail); + else + cli_print(cli, "Error reading token keystore: %s", hal_error_string(status)); + if ((status = hal_ks_available(hal_ks_volatile, &avail)) == HAL_OK) + cli_print(cli, "Volatile keystore: %d available", avail); + else + cli_print(cli, "Error reading volatile keystore: %s", hal_error_string(status)); + while (!done) { if ((status = hal_rpc_pkey_match(client, session, HAL_KEY_TYPE_NONE, HAL_CURVE_NONE, @@ -248,6 +260,10 @@ static int show_keys(struct cli_def *cli, const char *title) case HAL_KEY_TYPE_RSA_PUBLIC: type_name = "RSA public"; break; case HAL_KEY_TYPE_EC_PRIVATE: type_name = "EC private"; break; case HAL_KEY_TYPE_EC_PUBLIC: type_name = "EC public"; break; + case HAL_KEY_TYPE_HASHSIG_PRIVATE: type_name = "hashsig private"; break; + case HAL_KEY_TYPE_HASHSIG_PUBLIC: type_name = "hashsig public"; break; + case HAL_KEY_TYPE_HASHSIG_LMS: type_name = "hashsig lms"; break; + case HAL_KEY_TYPE_HASHSIG_LMOTS: type_name = "hashsig lmots"; break; } const char *curve_name = "unknown"; -- cgit v1.2.3 From 0f55f31aaa35357b87e7ff817e2683ba1a277193 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Thu, 19 Apr 2018 16:30:22 -0400 Subject: Reconstruct the hashsig hash tree(s) on device restart. This can take long enough (several minutes for h=10) that we do it in a background task, which is then converted to an RPC dispatch task. Also add a very limited form of free(), to free the topmost allocation in the sdram "heap". I don't want to deal with real heap management, but I do want to be able to recover memory upon deleting a hashsig key, if it's easy to do so. --- projects/hsm/hsm.c | 74 +++++++++++++++++++++++++++++++++++++++++++----------- spiflash_n25q128.c | 2 +- task.c | 22 ++++++++++++++-- task.h | 1 + 4 files changed, 82 insertions(+), 17 deletions(-) diff --git a/projects/hsm/hsm.c b/projects/hsm/hsm.c index d971f14..c9d8d28 100644 --- a/projects/hsm/hsm.c +++ b/projects/hsm/hsm.c @@ -341,36 +341,73 @@ static void busy_task(void) } } -/* Allocate memory from SDRAM1. There is only malloc, no free, so we don't - * worry about fragmentation. */ -static uint8_t *sdram_malloc(size_t size) +#include "stm-fpgacfg.h" +#include "hashsig.h" + +static void hashsig_restart_task(void) { - /* end of variables declared with __attribute__((section(".sdram1"))) */ - extern uint8_t _esdram1 __asm ("_esdram1"); - /* end of SDRAM1 section */ - extern uint8_t __end_sdram1 __asm ("__end_sdram1"); + /* wait for the fpga to configure itself on cold-boot */ + while (fpgacfg_check_done() != CMSIS_HAL_OK) + task_yield(); - static uint8_t *sdram_heap = &_esdram1; + /* reinitialize the hashsig key structures after a device restart */ + hal_hashsig_ks_init(); + + /* done, convert this task to an RPC handler */ + task_mod((char *)task_get_cookie(NULL), dispatch_task, NULL); +} + +/* end of variables declared with __attribute__((section(".sdram1"))) */ +extern uint8_t _esdram1 __asm ("_esdram1"); +/* end of SDRAM1 section */ +extern uint8_t __end_sdram1 __asm ("__end_sdram1"); +static uint8_t *sdram_heap = &_esdram1; + +/* Allocate memory from SDRAM1. */ +static uint8_t *sdram_malloc(size_t size) +{ uint8_t *p = sdram_heap; #define pad(n) (((n) + 3) & ~3) size = pad(size); - if (p + size > &__end_sdram1) + if (p + size + sizeof(uint32_t) > &__end_sdram1) return NULL; - sdram_heap += size; + *(uint32_t *)p = (uint32_t)size; + p += sizeof(uint32_t); + + sdram_heap += size + sizeof(uint32_t); return p; } -/* Implement static memory allocation for libhal over sdram_malloc(). - * Once again, there's only alloc, not free. */ +/* A very limited form of free(), which only frees memory if it's at the + * top of the heap. + */ +static hal_error_t sdram_free(uint8_t *ptr) +{ + uint8_t *p = ptr - sizeof(uint32_t); + uint32_t size = *(uint32_t *)p; + if (ptr + size == sdram_heap) { + sdram_heap = p; + return LIBHAL_OK; + } + else + return HAL_ERROR_FORBIDDEN; +} +/* Implement static memory allocation for libhal over sdram_malloc(). + */ void *hal_allocate_static_memory(const size_t size) { return sdram_malloc(size); } +hal_error_t hal_free_static_memory(const void * const ptr) +{ + return sdram_free((uint8_t *)ptr); +} + /* Critical section start/end - temporarily disable interrupts. */ void hal_critical_section_start(void) @@ -430,8 +467,14 @@ int main(void) void *stack = (void *)sdram_malloc(TASK_STACK_SIZE); if (stack == NULL) Error_Handler(); - if (task_add(label[i], dispatch_task, &ibufs[i], stack, TASK_STACK_SIZE) == NULL) - Error_Handler(); + if (i == NUM_RPC_TASK - 1) { + if (task_add("hashsig_restart", hashsig_restart_task, label[i], stack, TASK_STACK_SIZE) == NULL) + Error_Handler(); + } + else { + if (task_add(label[i], dispatch_task, NULL, stack, TASK_STACK_SIZE) == NULL) + Error_Handler(); + } } /* Create the busy task. */ @@ -453,4 +496,7 @@ int main(void) /* Start the tasker */ task_yield(); + + /*NOTREACHED*/ + return 0; } diff --git a/spiflash_n25q128.c b/spiflash_n25q128.c index 5e10185..df53f19 100644 --- a/spiflash_n25q128.c +++ b/spiflash_n25q128.c @@ -197,7 +197,7 @@ HAL_StatusTypeDef n25q128_write_page(struct spiflash_ctx *ctx, uint32_t page_off } -static int n25q128_erase_something(struct spiflash_ctx *ctx, uint8_t command, uint32_t byte_offset) +static HAL_StatusTypeDef n25q128_erase_something(struct spiflash_ctx *ctx, uint8_t command, uint32_t byte_offset) { // check offset if (byte_offset >= N25Q128_NUM_BYTES) return HAL_ERROR; diff --git a/task.c b/task.c index 36e8580..34daa24 100644 --- a/task.c +++ b/task.c @@ -131,6 +131,24 @@ tcb_t *task_add(char *name, funcp_t func, void *cookie, void *stack, size_t stac return t; } +/* Reinitalize the current task. + * NOTE: This will destroy any state in the running task. + * DO NOT CALL THIS UNLESS YOU ARE REALLY SURE THAT'S WHAT YOU WANT TO DO. + */ +void task_mod(char *name, funcp_t func, void *cookie) +{ + tcb_t *t = cur_task; + t->name = name; + t->func = func; + t->cookie = cookie; + t->state = TASK_INIT; + t->stack_ptr = t->stack_base + t->stack_len; + for (uint32_t *p = (uint32_t *)t->stack_base; p < (uint32_t *)t->stack_ptr; ++p) + *p = STACK_GUARD_WORD; + __set_MSP((uint32_t)cur_task->stack_ptr); + task_yield(); +} + /* Set the idle hook function pointer. * * This function is called repeatedly when the system is idle (there are @@ -232,11 +250,11 @@ void task_yield(void) /* If there are no other runnable tasks (and cur_task is runnable), * we don't need to context-switch. */ - if (next == cur_task) + if (next == cur_task && cur_task->state != TASK_INIT) return; /* Save current context, if there is one. */ - if (cur_task != NULL) { + if (cur_task != NULL && cur_task->state != TASK_INIT) { __asm("push {r0-r12, lr}"); cur_task->stack_ptr = (void *)__get_MSP(); diff --git a/task.h b/task.h index 47d62d6..a71f2e4 100644 --- a/task.h +++ b/task.h @@ -51,6 +51,7 @@ typedef struct { unsigned locked; } task_mutex_t; typedef void (*funcp_t)(void); extern tcb_t *task_add(char *name, funcp_t func, void *cookie, void *stack, size_t stack_len); +extern void task_mod(char *name, funcp_t func, void *cookie); extern void task_set_idle_hook(funcp_t func); -- cgit v1.2.3 From 7e6a9f76d8a72dead4763fbb726cfd60fece7b03 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Tue, 24 Jul 2018 22:50:55 -0400 Subject: Add dummy hal_free_static_memory to cli-test, to avoid a link error. We really ought to rototill cli-test, but not today. --- projects/cli-test/cli-test.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c index 82946fa..c0fe57e 100644 --- a/projects/cli-test/cli-test.c +++ b/projects/cli-test/cli-test.c @@ -88,3 +88,9 @@ void *hal_allocate_static_memory(const size_t size) { return NULL; } + +int hal_free_static_memory(const void * const ptr) +{ + return 0; +} + -- cgit v1.2.3