diff options
-rw-r--r-- | Makefile | 47 | ||||
-rw-r--r-- | projects/cli-test/Makefile | 2 | ||||
-rw-r--r-- | projects/cli-test/cli-test.c | 20 | ||||
-rw-r--r-- | projects/cli-test/mgmt-cli.c | 4 | ||||
-rw-r--r-- | projects/cli-test/mgmt-keystore.c | 344 | ||||
-rw-r--r-- | projects/cli-test/mgmt-masterkey.c | 22 | ||||
-rw-r--r-- | projects/cli-test/mgmt-show.c | 2 | ||||
-rw-r--r-- | projects/cli-test/test-mkmif.c | 12 | ||||
-rwxr-xr-x | projects/hsm/cryptech_upload | 27 | ||||
-rw-r--r-- | projects/hsm/hsm.c | 8 | ||||
-rw-r--r-- | projects/hsm/mgmt-cli.c | 2 | ||||
-rw-r--r-- | projects/hsm/mgmt-keystore.c | 368 | ||||
-rw-r--r-- | projects/hsm/mgmt-masterkey.c | 20 | ||||
-rw-r--r-- | spiflash_n25q128.c | 91 | ||||
-rw-r--r-- | spiflash_n25q128.h | 7 | ||||
-rw-r--r-- | stm-fpgacfg.c | 2 | ||||
-rw-r--r-- | stm-keystore.c | 27 | ||||
-rw-r--r-- | stm-keystore.h | 3 |
18 files changed, 490 insertions, 518 deletions
@@ -85,8 +85,19 @@ export OBJCOPY=$(PREFIX)objcopy export OBJDUMP=$(PREFIX)objdump export SIZE=$(PREFIX)size +# The Alpha is a development platform, so set GCC optimization to a +# level suitable for debugging. Recent versions of GCC have a special +# optimization setting -Og for exactly this purpose, so we use it, along +# with the flag to enable gdb symbols. +# +# If you really want optimization without debugging support, try -O2 or +# (maybe) -O3. + +#STM32_CFLAGS_OPTIMIZATION ?= -O2 +STM32_CFLAGS_OPTIMIZATION ?= -ggdb -Og + # whew, that's a lot of cflags -CFLAGS = -ggdb -O2 -Wall -Warray-bounds #-Wextra +CFLAGS = $(STM32_CFLAGS_OPTIMIZATION) -Wall -Warray-bounds #-Wextra CFLAGS += -mcpu=cortex-m4 -mthumb -mlittle-endian -mthumb-interwork CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 CFLAGS += -DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F429xx @@ -110,37 +121,37 @@ export CFLAGS all: board-test cli-test libhal-test hsm bootloader -$(MBED_DIR)/libstmf4.a: +$(MBED_DIR)/libstmf4.a: .FORCE $(MAKE) -C $(MBED_DIR) -board-test: $(BOARD_OBJS) $(LIBS) +board-test: $(BOARD_OBJS) $(LIBS) .FORCE $(MAKE) -C projects/board-test -cli-test: $(BOARD_OBJS) $(LIBS) $(LIBCLI_BLD)/libcli.a $(LIBHAL_BLD)/libhal.a $(RTOS_DIR)/librtos.a +cli-test: $(BOARD_OBJS) $(LIBS) $(LIBCLI_BLD)/libcli.a $(LIBHAL_BLD)/libhal.a $(RTOS_DIR)/librtos.a .FORCE $(MAKE) -C projects/cli-test -$(RTOS_DIR)/librtos.a: +$(RTOS_DIR)/librtos.a: .FORCE $(MAKE) -C $(RTOS_DIR) -rtos-test: $(RTOS_OBJS) $(LIBS) $(RTOS_DIR)/librtos.a +rtos-test: $(RTOS_OBJS) $(LIBS) $(RTOS_DIR)/librtos.a .FORCE $(MAKE) -C projects/rtos-test -$(LIBTFM_BLD)/libtfm.a: +$(LIBTFM_BLD)/libtfm.a: .FORCE $(MAKE) -C $(LIBTFM_BLD) PREFIX=$(PREFIX) -$(LIBHAL_BLD)/libhal.a: $(LIBTFM_BLD)/libtfm.a +$(LIBHAL_BLD)/libhal.a: $(LIBTFM_BLD)/libtfm.a .FORCE $(MAKE) -C $(LIBHAL_BLD) IO_BUS=fmc RPC_MODE=server RPC_TRANSPORT=serial KS=flash libhal.a -$(LIBCLI_BLD)/libcli.a: +$(LIBCLI_BLD)/libcli.a: .FORCE $(MAKE) -C $(LIBCLI_BLD) -libhal-test: $(BOARD_OBJS) $(LIBS) $(LIBHAL_BLD)/libhal.a +libhal-test: $(BOARD_OBJS) $(LIBS) $(LIBHAL_BLD)/libhal.a .FORCE $(MAKE) -C projects/libhal-test -hsm: $(BOARD_OBJS) $(LIBS) $(LIBHAL_BLD)/libhal.a $(RTOS_DIR)/librtos.a $(LIBCLI_BLD)/libcli.a +hsm: $(BOARD_OBJS) $(LIBS) $(LIBHAL_BLD)/libhal.a $(RTOS_DIR)/librtos.a $(LIBCLI_BLD)/libcli.a .FORCE $(MAKE) -C projects/hsm -bootloader: $(BOARD_OBJS) $(LIBS) $(LIBHAL_BLD)/libhal.a +bootloader: $(BOARD_OBJS) $(LIBS) $(LIBHAL_BLD)/libhal.a .FORCE $(MAKE) -C projects/bootloader # don't automatically delete objects, to avoid a lot of unnecessary rebuilding @@ -148,17 +159,27 @@ bootloader: $(BOARD_OBJS) $(LIBS) $(LIBHAL_BLD)/libhal.a .PHONY: board-test rtos-test libhal-test cli-test hsm bootloader +# We don't (and shouldn't) know enough about libraries and projects to +# know whether they need rebuilding or not, so we let their Makefiles +# decide that. Which means we always need to run all the sub-makes. +# We could do this with .PHONY (which is supposedly more "efficient") +# but using a .FORCE target is simpler once one takes inter-library +# dependency specifications into account. + +.FORCE: # (sic) + clean: rm -f $(BOARD_OBJS) + $(MAKE) -C $(LIBHAL_BLD) clean $(MAKE) -C projects/board-test clean $(MAKE) -C projects/cli-test clean $(MAKE) -C projects/rtos-test clean $(MAKE) -C projects/libhal-test clean $(MAKE) -C projects/hsm clean + $(MAKE) -C projects/bootloader clean distclean: clean $(MAKE) -C $(MBED_DIR) clean $(MAKE) -C $(RTOS_DIR) clean - $(MAKE) -C $(LIBHAL_BLD) clean $(MAKE) -C $(LIBTFM_BLD) clean $(MAKE) -C $(LIBCLI_BLD) clean diff --git a/projects/cli-test/Makefile b/projects/cli-test/Makefile index 11c1737..1f7faf1 100644 --- a/projects/cli-test/Makefile +++ b/projects/cli-test/Makefile @@ -33,7 +33,7 @@ BOARD_OBJS = \ CFLAGS += -I$(LIBCLI_SRC) -I$(LIBHAL_SRC) CFLAGS += -I$(RTOS_DIR)/rtos -I$(RTOS_DIR)/rtx/TARGET_CORTEX_M -LIBS += $(LIBCLI_BLD)/libcli.a $(LIBHAL_BLD)/libhal.a $(RTOS_DIR)/librtos.a +LIBS += $(LIBCLI_BLD)/libcli.a $(LIBHAL_BLD)/libhal.a $(LIBTFM_BLD)/libtfm.a $(RTOS_DIR)/librtos.a all: $(TEST:=.elf) diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c index d04371b..17b85cd 100644 --- a/projects/cli-test/cli-test.c +++ b/projects/cli-test/cli-test.c @@ -67,3 +67,23 @@ main() /* NOT REACHED */ Error_Handler(); } + + +/* + * Dummy to solve link problem. Not obvious to me that a program + * called "cli-test" should be duplicating all of the HSM keystore + * logic, let alone that it should be doing it badly, but, whatever. + * + * We could just copy the sdram_malloc() code from hsm.c, but since + * one of the other commands linked into cli-test goes merrily stomping + * all over the entire SDRAM chip, that might not work out so well. + * + * Issue deferred until somebody cares. + */ + +#warning hal_allocate_static_memory() stubbed out in cli-test, see source code + +void *hal_allocate_static_memory(const size_t size) +{ + return NULL; +} diff --git a/projects/cli-test/mgmt-cli.c b/projects/cli-test/mgmt-cli.c index 8f5db9d..b513ddc 100644 --- a/projects/cli-test/mgmt-cli.c +++ b/projects/cli-test/mgmt-cli.c @@ -164,9 +164,9 @@ hal_user_t user; static int check_auth(const char *username, const char *password) { - if (strcasecmp(username, "ct") != 0) + if (strcmp(username, "ct") != 0) return CLI_ERROR; - if (strcasecmp(password, "ct") != 0) + if (strcmp(password, "ct") != 0) return CLI_ERROR; return CLI_OK; } diff --git a/projects/cli-test/mgmt-keystore.c b/projects/cli-test/mgmt-keystore.c index 72cc5da..457abc2 100644 --- a/projects/cli-test/mgmt-keystore.c +++ b/projects/cli-test/mgmt-keystore.c @@ -45,7 +45,7 @@ #undef HAL_OK #define LIBHAL_OK HAL_OK #include "hal.h" -#define HAL_STATIC_PKEY_STATE_BLOCKS 6 +#warning Really should not be including hal_internal.h here, fix API instead of bypassing it #include "hal_internal.h" #undef HAL_OK @@ -55,29 +55,23 @@ static int cmd_keystore_set_pin(struct cli_def *cli, const char *command, char *argv[], int argc) { - const hal_ks_keydb_t *db; hal_user_t user; hal_error_t status; hal_client_handle_t client = { -1 }; - db = hal_ks_get_keydb(); - - if (db == NULL) { - cli_print(cli, "Could not get a keydb from libhal"); - return CLI_OK; - } - if (argc != 2) { cli_print(cli, "Wrong number of arguments (%i).", argc); cli_print(cli, "Syntax: keystore set pin <user|so|wheel> <pin>"); return CLI_ERROR; } - user = HAL_USER_NONE; - if (strcmp(argv[0], "user") == 0) user = HAL_USER_NORMAL; - if (strcmp(argv[0], "so") == 0) user = HAL_USER_SO; - if (strcmp(argv[0], "wheel") == 0) user = HAL_USER_WHEEL; - if (user == HAL_USER_NONE) { + if (!strcmp(argv[0], "user")) + user = HAL_USER_NORMAL; + else if (!strcmp(argv[0], "so")) + user = HAL_USER_SO; + else if (!strcmp(argv[0], "wheel")) + user = HAL_USER_WHEEL; + else { cli_print(cli, "First argument must be 'user', 'so' or 'wheel' - not '%s'", argv[0]); return CLI_ERROR; } @@ -93,17 +87,9 @@ static int cmd_keystore_set_pin(struct cli_def *cli, const char *command, char * static int cmd_keystore_clear_pin(struct cli_def *cli, const char *command, char *argv[], int argc) { - const hal_ks_keydb_t *db; hal_user_t user; - hal_ks_pin_t pin; hal_error_t status; - - db = hal_ks_get_keydb(); - - if (db == NULL) { - cli_print(cli, "Could not get a keydb from libhal"); - return CLI_OK; - } + hal_client_handle_t client = { -1 }; if (argc != 1) { cli_print(cli, "Wrong number of arguments (%i).", argc); @@ -111,19 +97,21 @@ static int cmd_keystore_clear_pin(struct cli_def *cli, const char *command, char return CLI_ERROR; } - user = HAL_USER_NONE; - if (strcmp(argv[0], "user") == 0) user = HAL_USER_NORMAL; - if (strcmp(argv[0], "so") == 0) user = HAL_USER_SO; - if (strcmp(argv[0], "wheel") == 0) user = HAL_USER_WHEEL; - if (user == HAL_USER_NONE) { + if (!strcmp(argv[0], "user")) + user = HAL_USER_NORMAL; + else if (!strcmp(argv[0], "so")) + user = HAL_USER_SO; + else if (!strcmp(argv[0], "wheel")) + user = HAL_USER_WHEEL; + else { cli_print(cli, "First argument must be 'user', 'so' or 'wheel' - not '%s'", argv[0]); return CLI_ERROR; } - memset(&pin, 0x0, sizeof(pin)); - if ((status = hal_ks_set_pin(user, &pin)) != LIBHAL_OK) { - cli_print(cli, "Failed clearing PIN: %s", hal_error_string(status)); - return CLI_ERROR; + status = hal_rpc_set_pin(client, user, "", 0); + if (status != LIBHAL_OK) { + cli_print(cli, "Failed setting PIN: %s", hal_error_string(status)); + return CLI_ERROR; } return CLI_OK; @@ -140,7 +128,7 @@ static int cmd_keystore_set_pin_iterations(struct cli_def *cli, const char *comm return CLI_ERROR; } - status = hal_set_pin_default_iterations(client, strtol(argv[0], NULL, 0)); + status = hal_set_pin_default_iterations(client, strtoul(argv[0], NULL, 0)); if (status != LIBHAL_OK) { cli_print(cli, "Failed setting iterations: %s", hal_error_string(status)); return CLI_ERROR; @@ -149,6 +137,20 @@ static int cmd_keystore_set_pin_iterations(struct cli_def *cli, const char *comm return CLI_OK; } +/* + * This is badly broken under either old or new keystore API: + * + * + DER is a binary format, it's not safe to read it this way, + * and strlen() will not do what anybody wants; + * + * + As written, this stores an EC public key on no known curve, + * ie, useless nonsense. + * + * The usual text format for DER objects is Base64, often with + * so-called "PEM" header and footer lines. Key type, curve, etcetera + * would be extra command line parameters. + */ +#if 0 static int cmd_keystore_set_key(struct cli_def *cli, const char *command, char *argv[], int argc) { hal_error_t status; @@ -175,104 +177,34 @@ static int cmd_keystore_set_key(struct cli_def *cli, const char *command, char * return CLI_OK; } - -static int key_by_index(struct cli_def *cli, char *str, const uint8_t **name, size_t *name_len, hal_key_type_t *type) -{ - char *end; - long index; - - /* base=0, because someone will try to be clever, and enter '0x0001' */ - index = strtol(str, &end, 0); - - /* If strtol converted the whole string, it's an index. - * Otherwise, it could be something like "3Mustaphas3". - */ - if (*end == '\0') { - const hal_ks_keydb_t *db = hal_ks_get_keydb(); - if (index < 0 || index >= sizeof(db->keys)/sizeof(*db->keys)) { - cli_print(cli, "Index %ld out of range", index); - return CLI_ERROR_ARG; - } - if (! db->keys[index].in_use) { - cli_print(cli, "Key %ld not in use", index); - return CLI_ERROR_ARG; - } - *name = db->keys[index].name; - *name_len = db->keys[index].name_len; - *type = db->keys[index].type; - return CLI_OK; - } - return CLI_ERROR; -} +#endif /* 0 */ static int cmd_keystore_delete_key(struct cli_def *cli, const char *command, char *argv[], int argc) { + const hal_client_handle_t client = { HAL_HANDLE_NONE }; + const hal_session_handle_t session = { HAL_HANDLE_NONE }; + hal_pkey_handle_t pkey = { HAL_HANDLE_NONE }; hal_error_t status; - int hint = 0; - const uint8_t *name; - size_t name_len; - hal_key_type_t type; + hal_uuid_t name; if (argc != 1) { cli_print(cli, "Wrong number of arguments (%i).", argc); - cli_print(cli, "Syntax: keystore delete key <name or index>"); + cli_print(cli, "Syntax: keystore delete key <name>"); return CLI_ERROR; } - switch (key_by_index(cli, argv[0], &name, &name_len, &type)) { - case CLI_OK: - break; - case CLI_ERROR: - name = (uint8_t *)argv[0]; - name_len = strlen(argv[0]); - type = HAL_KEY_TYPE_EC_PUBLIC; - break; - default: - return CLI_ERROR; - } - - if ((status = hal_ks_delete(type, name, name_len, &hint)) != LIBHAL_OK) { - cli_print(cli, "Failed deleting key: %s", hal_error_string(status)); + if ((status = hal_uuid_parse(&name, argv[0])) != LIBHAL_OK) { + cli_print(cli, "Couldn't parse key name: %s", hal_error_string(status)); return CLI_ERROR; } - cli_print(cli, "Deleted key %i", hint); - - return CLI_OK; -} - -static int cmd_keystore_rename_key(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - hal_error_t status; - int hint = 0; - const uint8_t *name; - size_t name_len; - hal_key_type_t type; - - if (argc != 2) { - cli_print(cli, "Wrong number of arguments (%i).", argc); - cli_print(cli, "Syntax: keystore rename key <name or index> <new name>"); - return CLI_ERROR; - } - - switch (key_by_index(cli, argv[0], &name, &name_len, &type)) { - case CLI_OK: - break; - case CLI_ERROR: - name = (uint8_t *)argv[0]; - name_len = strlen(argv[0]); - type = HAL_KEY_TYPE_EC_PUBLIC; - break; - default: - return CLI_ERROR; - } - - if ((status = hal_ks_rename(type, name, name_len, (uint8_t *)argv[1], strlen(argv[1]), &hint)) != LIBHAL_OK) { - cli_print(cli, "Failed renaming key: %s", hal_error_string(status)); + if ((status = hal_rpc_pkey_open(client, session, &pkey, &name, HAL_KEY_FLAG_TOKEN)) != LIBHAL_OK || + (status = hal_rpc_pkey_delete(pkey)) != LIBHAL_OK) { + cli_print(cli, "Failed deleting key: %s", hal_error_string(status)); return CLI_ERROR; } - cli_print(cli, "Renamed key %i", hint); + cli_print(cli, "Deleted key %s", argv[0]); return CLI_OK; } @@ -299,94 +231,125 @@ static int cmd_keystore_show_data(struct cli_def *cli, const char *command, char return CLI_OK; } -static int cmd_keystore_show_keys(struct cli_def *cli, const char *command, char *argv[], int argc) +static int show_keys(struct cli_def *cli, const char *title, const hal_key_flags_t qflags) { - const hal_ks_keydb_t *db; - uint8_t name[HAL_RPC_PKEY_NAME_MAX + 1]; - char *type; + const hal_client_handle_t client = { -1 }; + const hal_session_handle_t session = { HAL_HANDLE_NONE }; + char key_name[HAL_UUID_TEXT_SIZE]; + hal_uuid_t previous_uuid = {{0}}; + hal_pkey_handle_t pkey; + hal_curve_name_t curve; + hal_key_flags_t flags; + hal_key_type_t type; + hal_error_t status; + hal_uuid_t uuids[50]; + unsigned n; + int done = 0; - db = hal_ks_get_keydb(); + cli_print(cli, title); - if (db == NULL) { - cli_print(cli, "Could not get a keydb from libhal"); - return CLI_OK; - } + while (!done) { + + if ((status = hal_rpc_pkey_match(client, session, HAL_KEY_TYPE_NONE, HAL_CURVE_NONE, + qflags, NULL, 0, uuids, &n, sizeof(uuids)/sizeof(*uuids), + &previous_uuid)) != LIBHAL_OK) { + cli_print(cli, "Could not fetch UUID list: %s", hal_error_string(status)); + return 0; + } - cli_print(cli, "Sizeof db->keys is %i, sizeof one key is %i\n", sizeof(db->keys), sizeof(*db->keys)); - - for (int i = 0; i < sizeof(db->keys)/sizeof(*db->keys); i++) { - if (! db->keys[i].in_use) { - cli_print(cli, "Key %i, not in use", i); - } else { - switch (db->keys[i].type) { - case HAL_KEY_TYPE_RSA_PRIVATE: - type = "RSA private"; - break; - case HAL_KEY_TYPE_RSA_PUBLIC: - type = "RSA public"; - break; - case HAL_KEY_TYPE_EC_PRIVATE: - type = "EC private"; - break; - case HAL_KEY_TYPE_EC_PUBLIC: - type = "EC public"; - break; - default: - type = "unknown"; - break; - } - /* name is nul-terminated */ - memcpy(name, db->keys[i].name, db->keys[i].name_len); - name[db->keys[i].name_len] = '\0'; - cli_print(cli, "Key %i, type %s, name '%s'", i, type, name); + done = n < sizeof(uuids)/sizeof(*uuids); + + if (!done) + previous_uuid = uuids[sizeof(uuids)/sizeof(*uuids) - 1]; + + for (int i = 0; i < n; i++) { + + if ((status = hal_uuid_format(&uuids[i], key_name, sizeof(key_name))) != LIBHAL_OK) { + cli_print(cli, "Could not convert key name: %s", + hal_error_string(status)); + return 0; + } + + if ((status = hal_rpc_pkey_open(client, session, &pkey, &uuids[i], qflags)) != LIBHAL_OK) { + cli_print(cli, "Could not open key %s: %s", + key_name, hal_error_string(status)); + return 0; + } + + if ((status = hal_rpc_pkey_get_key_type(pkey, &type)) != LIBHAL_OK || + (status = hal_rpc_pkey_get_key_curve(pkey, &curve)) != LIBHAL_OK || + (status = hal_rpc_pkey_get_key_flags(pkey, &flags)) != LIBHAL_OK) + cli_print(cli, "Could not fetch metadata for key %s: %s", + key_name, hal_error_string(status)); + + if (status == LIBHAL_OK) + status = hal_rpc_pkey_close(pkey); + else + (void) hal_rpc_pkey_close(pkey); + + if (status != LIBHAL_OK) + return 0; + + const char *type_name = "unknown"; + switch (type) { + case HAL_KEY_TYPE_NONE: type_name = "none"; break; + case HAL_KEY_TYPE_RSA_PRIVATE: type_name = "RSA private"; break; + 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; + } + + const char *curve_name = "unknown"; + switch (curve) { + case HAL_CURVE_NONE: curve_name = "none"; break; + case HAL_CURVE_P256: curve_name = "P-256"; break; + case HAL_CURVE_P384: curve_name = "P-384"; break; + case HAL_CURVE_P521: curve_name = "P-521"; break; + } + + cli_print(cli, "Key %2i, name %s, type %s, curve %s, flags 0x%lx", + i, key_name, type_name, curve_name, (unsigned long) flags); } } - cli_print(cli, "\nPins:"); - cli_print(cli, "Wheel iterations: 0x%lx", db->wheel_pin.iterations); - cli_print(cli, "pin"); - uart_send_hexdump(STM_UART_MGMT, db->wheel_pin.pin, 0, sizeof(db->wheel_pin.pin) - 1); - cli_print(cli, "\nsalt"); - uart_send_hexdump(STM_UART_MGMT, db->wheel_pin.salt, 0, sizeof(db->wheel_pin.salt) - 1); - cli_print(cli, ""); - - cli_print(cli, "SO iterations: 0x%lx", db->so_pin.iterations); - cli_print(cli, "pin"); - uart_send_hexdump(STM_UART_MGMT, db->so_pin.pin, 0, sizeof(db->so_pin.pin) - 1); - cli_print(cli, "\nsalt"); - uart_send_hexdump(STM_UART_MGMT, db->so_pin.salt, 0, sizeof(db->so_pin.salt) - 1); - cli_print(cli, ""); - - cli_print(cli, "User iterations: 0x%lx", db->user_pin.iterations); - cli_print(cli, "pin"); - uart_send_hexdump(STM_UART_MGMT, db->user_pin.pin, 0, sizeof(db->user_pin.pin) - 1); - cli_print(cli, "\nsalt"); - uart_send_hexdump(STM_UART_MGMT, db->user_pin.salt, 0, sizeof(db->user_pin.salt) - 1); - cli_print(cli, ""); - cli_print(cli, "\n"); + return 1; +} - return CLI_OK; +static int cmd_keystore_show_keys(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + int ok = 1; + ok &= show_keys(cli, "Memory keystore:", 0); + ok &= show_keys(cli, "Token keystore:", HAL_KEY_FLAG_TOKEN); + return ok ? CLI_OK : CLI_ERROR; } static int cmd_keystore_erase(struct cli_def *cli, const char *command, char *argv[], int argc) { + hal_error_t err; int status; - if (argc != 1) { + if (argc != 1 || strcmp(argv[0], "YesIAmSure") != 0) { cli_print(cli, "Syntax: keystore erase YesIAmSure"); return CLI_ERROR; } - if (strcmp(argv[0], "YesIAmSure") == 0) { - if ((status = keystore_erase_sectors(0, 1)) != 1) { - cli_print(cli, "Failed erasing keystore: %i", status); - } else { - cli_print(cli, "Keystore erased (first two sectors at least)"); - } - } else { - cli_print(cli, "Keystore NOT erased"); + cli_print(cli, "OK, erasing keystore, this might take a while..."); + if ((status = keystore_erase_sectors(0, KEYSTORE_NUM_SECTORS - 1)) != 1) { + cli_print(cli, "Failed erasing token keystore: %i", status); + return CLI_ERROR; } + if ((err = hal_ks_init(hal_ks_token_driver, 0)) != LIBHAL_OK) { + cli_print(cli, "Failed to reinitialize token keystore: %s", hal_error_string(err)); + return CLI_ERROR; + } + + if ((err = hal_ks_init(hal_ks_volatile_driver, 0)) != LIBHAL_OK) { + cli_print(cli, "Failed to reinitialize memory keystore: %s", hal_error_string(err)); + return CLI_ERROR; + } + + cli_print(cli, "Keystore erased"); return CLI_OK; } @@ -394,14 +357,14 @@ void configure_cli_keystore(struct cli_def *cli) { struct cli_command *c = cli_register_command(cli, NULL, "keystore", NULL, 0, 0, NULL); - struct cli_command *c_set = cli_register_command(cli, c, "set", NULL, 0, 0, NULL); - struct cli_command *c_clear = cli_register_command(cli, c, "clear", NULL, 0, 0, NULL); + struct cli_command *c_set = cli_register_command(cli, c, "set", NULL, 0, 0, NULL); + struct cli_command *c_clear = cli_register_command(cli, c, "clear", NULL, 0, 0, NULL); struct cli_command *c_delete = cli_register_command(cli, c, "delete", NULL, 0, 0, NULL); - struct cli_command *c_rename = cli_register_command(cli, c, "rename", NULL, 0, 0, NULL); - struct cli_command *c_show = cli_register_command(cli, c, "show", NULL, 0, 0, NULL); + struct cli_command *c_show = cli_register_command(cli, c, "show", NULL, 0, 0, NULL); /* keystore erase */ cli_register_command(cli, c, "erase", cmd_keystore_erase, 0, 0, "Erase the whole keystore"); + /* keystore set pin */ struct cli_command *c_set_pin = cli_register_command(cli, c_set, "pin", cmd_keystore_set_pin, 0, 0, "Set either 'wheel', 'user' or 'so' PIN"); @@ -411,19 +374,18 @@ void configure_cli_keystore(struct cli_def *cli) /* keystore clear pin */ cli_register_command(cli, c_clear, "pin", cmd_keystore_clear_pin, 0, 0, "Clear either 'wheel', 'user' or 'so' PIN"); +#if 0 /* keystore set key */ cli_register_command(cli, c_set, "key", cmd_keystore_set_key, 0, 0, "Set a key"); +#endif /* keystore delete key */ cli_register_command(cli, c_delete, "key", cmd_keystore_delete_key, 0, 0, "Delete a key"); - /* keystore rename key */ - cli_register_command(cli, c_rename, "key", cmd_keystore_rename_key, 0, 0, "Rename a key"); - /* keystore show data */ cli_register_command(cli, c_show, "data", cmd_keystore_show_data, 0, 0, "Dump the first page from the keystore memory"); /* keystore show keys */ - cli_register_command(cli, c_show, "keys", cmd_keystore_show_keys, 0, 0, "Show what PINs and keys are in the keystore"); + cli_register_command(cli, c_show, "keys", cmd_keystore_show_keys, 0, 0, "Show what keys are in the keystore"); } diff --git a/projects/cli-test/mgmt-masterkey.c b/projects/cli-test/mgmt-masterkey.c index 69dc430..623d19b 100644 --- a/projects/cli-test/mgmt-masterkey.c +++ b/projects/cli-test/mgmt-masterkey.c @@ -42,14 +42,12 @@ #undef HAL_OK #define LIBHAL_OK HAL_OK #include <hal.h> -#include <masterkey.h> +#warning Refactor so we do not need to include hal_internal here +#include <hal_internal.h> #undef HAL_OK #include <stdlib.h> -#define KEK_LENGTH (256 / 8) - - static char * _status2str(const hal_error_t status) { switch (status) { @@ -87,17 +85,17 @@ static int cmd_masterkey_status(struct cli_def *cli, const char *command, char * cli_print(cli, "Status of master key:\n"); - status = masterkey_volatile_read(NULL, 0); + status = hal_mkm_volatile_read(NULL, 0); cli_print(cli, " volatile: %s / %s", _status2str(status), hal_error_string(status)); - status = masterkey_flash_read(NULL, 0); + status = hal_mkm_flash_read(NULL, 0); cli_print(cli, " flash: %s / %s", _status2str(status), hal_error_string(status)); /* XXX Temporary gaping security hole while developing the master key functionality. * REMOVE READ-OUT OF MASTER KEY. */ - status = masterkey_volatile_read(&buf[0], sizeof(buf)); + status = hal_mkm_volatile_read(&buf[0], sizeof(buf)); if (status == LIBHAL_OK || status == HAL_ERROR_MASTERKEY_NOT_SET) { cli_print(cli, "\nVolatile read-out:\n"); uart_send_hexdump(STM_UART_MGMT, buf, 0, sizeof(buf) - 1); @@ -106,7 +104,7 @@ static int cmd_masterkey_status(struct cli_def *cli, const char *command, char * cli_print(cli, "Failed reading from volatile memory: %s", hal_error_string(status)); } - status = masterkey_flash_read(&buf[0], sizeof(buf)); + status = hal_mkm_flash_read(&buf[0], sizeof(buf)); if (status == LIBHAL_OK || status == HAL_ERROR_MASTERKEY_NOT_SET) { cli_print(cli, "\nFlash read-out:\n"); uart_send_hexdump(STM_UART_MGMT, buf, 0, sizeof(buf) - 1); @@ -133,7 +131,7 @@ static int cmd_masterkey_set(struct cli_def *cli, const char *command, char *arg uart_send_hexdump(STM_UART_MGMT, buf, 0, sizeof(buf) - 1); cli_print(cli, "\n"); - if ((err = masterkey_volatile_write(buf, sizeof(buf))) == LIBHAL_OK) { + if ((err = hal_mkm_volatile_write(buf, sizeof(buf))) == LIBHAL_OK) { cli_print(cli, "Master key set in volatile memory"); } else { cli_print(cli, "Failed writing key to volatile memory: %s", hal_error_string(err)); @@ -145,7 +143,7 @@ static int cmd_masterkey_erase(struct cli_def *cli, const char *command, char *a { hal_error_t err; - if ((err = masterkey_volatile_erase(KEK_LENGTH)) == LIBHAL_OK) { + if ((err = hal_mkm_volatile_erase(KEK_LENGTH)) == LIBHAL_OK) { cli_print(cli, "Erased master key from volatile memory"); } else { cli_print(cli, "Failed erasing master key from volatile memory: %s", hal_error_string(err)); @@ -168,7 +166,7 @@ static int cmd_masterkey_unsecure_set(struct cli_def *cli, const char *command, uart_send_hexdump(STM_UART_MGMT, buf, 0, sizeof(buf) - 1); cli_print(cli, "\n"); - if ((err = masterkey_flash_write(buf, sizeof(buf))) == LIBHAL_OK) { + if ((err = hal_mkm_flash_write(buf, sizeof(buf))) == LIBHAL_OK) { cli_print(cli, "Master key set in unsecure flash memory"); } else { cli_print(cli, "Failed writing key to unsecure flash memory: %s", hal_error_string(err)); @@ -180,7 +178,7 @@ static int cmd_masterkey_unsecure_erase(struct cli_def *cli, const char *command { hal_error_t err; - if ((err = masterkey_flash_erase(KEK_LENGTH)) == LIBHAL_OK) { + if ((err = hal_mkm_flash_erase(KEK_LENGTH)) == LIBHAL_OK) { cli_print(cli, "Erased unsecure master key from flash"); } else { cli_print(cli, "Failed erasing unsecure master key from flash: %s", hal_error_string(err)); diff --git a/projects/cli-test/mgmt-show.c b/projects/cli-test/mgmt-show.c index 7d6b509..5cca8b7 100644 --- a/projects/cli-test/mgmt-show.c +++ b/projects/cli-test/mgmt-show.c @@ -71,7 +71,7 @@ static int cmd_show_fpga_status(struct cli_def *cli, const char *command, char * static int cmd_show_fpga_cores(struct cli_def *cli, const char *command, char *argv[], int argc) { - const hal_core_t *core; + hal_core_t *core; const hal_core_info_t *info; if (! fpgacfg_check_done()) { diff --git a/projects/cli-test/test-mkmif.c b/projects/cli-test/test-mkmif.c index 5ceb376..bb41b4d 100644 --- a/projects/cli-test/test-mkmif.c +++ b/projects/cli-test/test-mkmif.c @@ -27,7 +27,7 @@ typedef union { uint32_t word; } byteword_t; -static hal_error_t sclk_test(struct cli_def *cli, const hal_core_t *core, const uint32_t divisor) +static hal_error_t sclk_test(struct cli_def *cli, hal_core_t *core, const uint32_t divisor) { uint32_t readback; hal_error_t err; @@ -49,7 +49,7 @@ static hal_error_t sclk_test(struct cli_def *cli, const hal_core_t *core, const return LIBHAL_OK; } -static hal_error_t init_test(struct cli_def *cli, const hal_core_t *core) +static hal_error_t init_test(struct cli_def *cli, hal_core_t *core) { hal_error_t err; @@ -63,7 +63,7 @@ static hal_error_t init_test(struct cli_def *cli, const hal_core_t *core) return LIBHAL_OK; } -static hal_error_t write_test(struct cli_def *cli, const hal_core_t *core) +static hal_error_t write_test(struct cli_def *cli, hal_core_t *core) { uint32_t write_data; uint32_t write_address; @@ -86,7 +86,7 @@ static hal_error_t write_test(struct cli_def *cli, const hal_core_t *core) return LIBHAL_OK; } -static hal_error_t read_test(struct cli_def *cli, const hal_core_t *core) +static hal_error_t read_test(struct cli_def *cli, hal_core_t *core) { uint32_t read_data; uint32_t read_address; @@ -109,7 +109,7 @@ static hal_error_t read_test(struct cli_def *cli, const hal_core_t *core) return LIBHAL_OK; } -static hal_error_t write_read_test(struct cli_def *cli, const hal_core_t *core) +static hal_error_t write_read_test(struct cli_def *cli, hal_core_t *core) { uint32_t data; uint32_t readback; @@ -139,7 +139,7 @@ static hal_error_t write_read_test(struct cli_def *cli, const hal_core_t *core) int cmd_test_mkmif(struct cli_def *cli, const char *command, char *argv[], int argc) { - const hal_core_t *core = hal_core_find(MKMIF_NAME, NULL); + hal_core_t *core = hal_core_find(MKMIF_NAME, NULL); hal_error_t res; if (core == NULL) { diff --git a/projects/hsm/cryptech_upload b/projects/hsm/cryptech_upload index f5fefaa..d8d1186 100755 --- a/projects/hsm/cryptech_upload +++ b/projects/hsm/cryptech_upload @@ -105,16 +105,28 @@ def parse_args(): type = argparse.FileType("rb"), help = "Explicit source image file for upload, overrides firmware tarball") + parser.add_argument("--separate-pins", + action = "store_true", + help = "Prompt separately for each PIN required during upload") + + parser.add_argument("--debug", + action = "store_true", + help = "Enable debugging of upload protocol", + ) + return parser.parse_args() def _write(dst, data): + numeric = isinstance(data, (int, long)) + if numeric: + data = struct.pack("<I", data) dst.write(data) - #if len(data) == 4: - # print("Wrote 0x{!s}".format(data.encode("hex"))) - #else: - # print("Wrote {!r}".format(data)) - + if args.debug: + if numeric: + print("Wrote 0x{!s}".format(data.encode("hex"))) + else: + print("Wrote {!r}".format(data)) def _read(dst): res = "" @@ -124,7 +136,8 @@ def _read(dst): while x: res += x x = dst.read(1) - #print ("Read {!r}".format(res)) + if args.debug: + print ("Read {!r}".format(res)) return res pin = None @@ -137,7 +150,7 @@ def _execute(dst, cmd): _write(dst, args.username + "\r") prompt = _read(dst) if prompt.endswith("Password: "): - if not pin: + if not pin or args.separate_pins: pin = getpass.getpass("{} PIN: ".format(args.username)) _write(dst, pin + "\r") prompt = _read(dst) diff --git a/projects/hsm/hsm.c b/projects/hsm/hsm.c index f2f1b12..971d460 100644 --- a/projects/hsm/hsm.c +++ b/projects/hsm/hsm.c @@ -220,6 +220,14 @@ static uint8_t *sdram_malloc(size_t size) return p; } +/* Implement static memory allocation for libhal over sdram_malloc(). + * Once again, there's only alloc, not free. */ + +void *hal_allocate_static_memory(const size_t size) +{ + return sdram_malloc(size); +} + #if NUM_RPC_TASK > 1 /* Critical section start/end, currently used just for hal_core_alloc/_free. */ diff --git a/projects/hsm/mgmt-cli.c b/projects/hsm/mgmt-cli.c index ee1b31b..3c1a3bc 100644 --- a/projects/hsm/mgmt-cli.c +++ b/projects/hsm/mgmt-cli.c @@ -54,6 +54,8 @@ #undef HAL_OK #define HAL_OK LIBHAL_OK #include "hal.h" +#warning Refactor so we do not need to include hal_internal.h here +#include "hal_internal.h" #undef HAL_OK #ifndef CLI_UART_RECVBUF_SIZE diff --git a/projects/hsm/mgmt-keystore.c b/projects/hsm/mgmt-keystore.c index c7e20b0..6ee6cf3 100644 --- a/projects/hsm/mgmt-keystore.c +++ b/projects/hsm/mgmt-keystore.c @@ -44,7 +44,7 @@ #undef HAL_OK #define LIBHAL_OK HAL_OK #include "hal.h" -#define HAL_STATIC_PKEY_STATE_BLOCKS 6 +#warning Really should not be including hal_internal.h here, fix API instead of bypassing it #include "hal_internal.h" #undef HAL_OK @@ -55,29 +55,23 @@ static int cmd_keystore_set_pin(struct cli_def *cli, const char *command, char *argv[], int argc) { - const hal_ks_keydb_t *db; hal_user_t user; hal_error_t status; hal_client_handle_t client = { -1 }; - db = hal_ks_get_keydb(); - - if (db == NULL) { - cli_print(cli, "Could not get a keydb from libhal"); - return CLI_OK; - } - if (argc != 2) { cli_print(cli, "Wrong number of arguments (%i).", argc); cli_print(cli, "Syntax: keystore set pin <user|so|wheel> <pin>"); return CLI_ERROR; } - user = HAL_USER_NONE; - if (strcmp(argv[0], "user") == 0) user = HAL_USER_NORMAL; - if (strcmp(argv[0], "so") == 0) user = HAL_USER_SO; - if (strcmp(argv[0], "wheel") == 0) user = HAL_USER_WHEEL; - if (user == HAL_USER_NONE) { + if (strcmp(argv[0], "user") == 0) + user = HAL_USER_NORMAL; + else if (strcmp(argv[0], "so") == 0) + user = HAL_USER_SO; + else if (strcmp(argv[0], "wheel") == 0) + user = HAL_USER_WHEEL; + else { cli_print(cli, "First argument must be 'user', 'so' or 'wheel' - not '%s'", argv[0]); return CLI_ERROR; } @@ -93,17 +87,9 @@ static int cmd_keystore_set_pin(struct cli_def *cli, const char *command, char * static int cmd_keystore_clear_pin(struct cli_def *cli, const char *command, char *argv[], int argc) { - const hal_ks_keydb_t *db; hal_user_t user; - hal_ks_pin_t pin; hal_error_t status; - - db = hal_ks_get_keydb(); - - if (db == NULL) { - cli_print(cli, "Could not get a keydb from libhal"); - return CLI_OK; - } + hal_client_handle_t client = { -1 }; if (argc != 1) { cli_print(cli, "Wrong number of arguments (%i).", argc); @@ -112,16 +98,18 @@ static int cmd_keystore_clear_pin(struct cli_def *cli, const char *command, char } user = HAL_USER_NONE; - if (strcmp(argv[0], "user") == 0) user = HAL_USER_NORMAL; - if (strcmp(argv[0], "so") == 0) user = HAL_USER_SO; - if (strcmp(argv[0], "wheel") == 0) user = HAL_USER_WHEEL; - if (user == HAL_USER_NONE) { + if (strcmp(argv[0], "user") == 0) + user = HAL_USER_NORMAL; + else if (strcmp(argv[0], "so") == 0) + user = HAL_USER_SO; + else if (strcmp(argv[0], "wheel") == 0) + user = HAL_USER_WHEEL; + else { cli_print(cli, "First argument must be 'user', 'so' or 'wheel' - not '%s'", argv[0]); return CLI_ERROR; } - memset(&pin, 0x0, sizeof(pin)); - if ((status = hal_ks_set_pin(user, &pin)) != LIBHAL_OK) { + if ((status = hal_rpc_set_pin(client, user, "", 0)) != LIBHAL_OK) { cli_print(cli, "Failed clearing PIN: %s", hal_error_string(status)); return CLI_ERROR; } @@ -149,244 +137,159 @@ static int cmd_keystore_set_pin_iterations(struct cli_def *cli, const char *comm return CLI_OK; } -#if 0 -static int cmd_keystore_set_key(struct cli_def *cli, const char *command, char *argv[], int argc) +static int cmd_keystore_delete_key(struct cli_def *cli, const char *command, char *argv[], int argc) { + const hal_client_handle_t client = { -1 }; + const hal_session_handle_t session = { HAL_HANDLE_NONE }; + hal_pkey_handle_t pkey = { HAL_HANDLE_NONE }; hal_error_t status; - int hint = 0; + hal_uuid_t name; - if (argc != 2) { + if (argc != 1) { cli_print(cli, "Wrong number of arguments (%i).", argc); - cli_print(cli, "Syntax: keystore set key <name> <der>"); + cli_print(cli, "Syntax: keystore delete key <name>"); return CLI_ERROR; } - if ((status = hal_ks_store(HAL_KEY_TYPE_EC_PUBLIC, - HAL_CURVE_NONE, - 0, - (uint8_t *) argv[0], strlen(argv[0]), - (uint8_t *) argv[1], strlen(argv[1]), - &hint)) != LIBHAL_OK) { - - cli_print(cli, "Failed storing key: %s", hal_error_string(status)); + if ((status = hal_uuid_parse(&name, argv[0])) != LIBHAL_OK) { + cli_print(cli, "Couldn't parse key name: %s", hal_error_string(status)); return CLI_ERROR; } - cli_print(cli, "Stored key %i", hint); - - return CLI_OK; -} -#endif - -static int key_by_index(struct cli_def *cli, char *str, const uint8_t **name, size_t *name_len, hal_key_type_t *type) -{ - char *end; - long index; - - /* base=0, because someone will try to be clever, and enter '0x0001' */ - index = strtol(str, &end, 0); - - /* If strtol converted the whole string, it's an index. - * Otherwise, it could be something like "3Mustaphas3". - */ - if (*end == '\0') { - const hal_ks_keydb_t *db = hal_ks_get_keydb(); - if (index < 0 || index >= sizeof(db->keys)/sizeof(*db->keys)) { - cli_print(cli, "Index %ld out of range", index); - return CLI_ERROR_ARG; - } - if (! db->keys[index].in_use) { - cli_print(cli, "Key %ld not in use", index); - return CLI_ERROR_ARG; - } - *name = db->keys[index].name; - *name_len = db->keys[index].name_len; - *type = db->keys[index].type; - return CLI_OK; - } - return CLI_ERROR; -} - -static int cmd_keystore_delete_key(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - hal_error_t status; - int hint = 0; - const uint8_t *name; - size_t name_len; - hal_key_type_t type; + status = hal_rpc_pkey_open(client, session, &pkey, &name, HAL_KEY_FLAG_TOKEN); - if (argc != 1) { - cli_print(cli, "Wrong number of arguments (%i).", argc); - cli_print(cli, "Syntax: keystore delete key <name or index>"); - return CLI_ERROR; - } + if (status == HAL_ERROR_KEY_NOT_FOUND) + status = hal_rpc_pkey_open(client, session, &pkey, &name, 0); - switch (key_by_index(cli, argv[0], &name, &name_len, &type)) { - case CLI_OK: - break; - case CLI_ERROR: - name = (uint8_t *)argv[0]; - name_len = strlen(argv[0]); - type = HAL_KEY_TYPE_EC_PUBLIC; - break; - default: - return CLI_ERROR; - } - - if ((status = hal_ks_delete(type, name, name_len, &hint)) != LIBHAL_OK) { - if (status == HAL_ERROR_KEY_NOT_FOUND) { - /* sigh, try again including the terminal nul */ - if ((status = hal_ks_delete(type, name, name_len+1, &hint)) == LIBHAL_OK) { - cli_print(cli, "Deleted key %i", hint); - return CLI_OK; - } - } + if (status != LIBHAL_OK || (status = hal_rpc_pkey_delete(pkey)) != LIBHAL_OK) { cli_print(cli, "Failed deleting key: %s", hal_error_string(status)); return CLI_ERROR; } - cli_print(cli, "Deleted key %i", hint); + cli_print(cli, "Deleted key %s", argv[0]); return CLI_OK; } -static int cmd_keystore_rename_key(struct cli_def *cli, const char *command, char *argv[], int argc) +static int show_keys(struct cli_def *cli, const char *title, const hal_key_flags_t qflags) { - hal_error_t status; - int hint = 0; - const uint8_t *name; - size_t name_len; + const hal_client_handle_t client = { -1 }; + const hal_session_handle_t session = { HAL_HANDLE_NONE }; + char key_name[HAL_UUID_TEXT_SIZE]; + hal_uuid_t previous_uuid = {{0}}; + hal_pkey_handle_t pkey; + hal_curve_name_t curve; + hal_key_flags_t flags; hal_key_type_t type; + hal_error_t status; + hal_uuid_t uuids[50]; + unsigned n; + int done = 0; - if (argc != 2) { - cli_print(cli, "Wrong number of arguments (%i).", argc); - cli_print(cli, "Syntax: keystore rename key <name or index> <new name>"); - return CLI_ERROR; - } - - switch (key_by_index(cli, argv[0], &name, &name_len, &type)) { - case CLI_OK: - break; - case CLI_ERROR: - name = (uint8_t *)argv[0]; - name_len = strlen(argv[0]); - type = HAL_KEY_TYPE_EC_PUBLIC; - break; - default: - return CLI_ERROR; - } - - if ((status = hal_ks_rename(type, name, name_len, (uint8_t *)argv[1], strlen(argv[1]), &hint)) != LIBHAL_OK) { - if (status == HAL_ERROR_KEY_NOT_FOUND) { - /* sigh, try again including the terminal nul */ - if ((status = hal_ks_rename(type, name, name_len+1, (uint8_t *)argv[1], strlen(argv[1]), &hint)) == LIBHAL_OK) { - cli_print(cli, "Renamed key %i", hint); - return CLI_OK; - } - } - cli_print(cli, "Failed renaming key: %s", hal_error_string(status)); - return CLI_ERROR; - } - - cli_print(cli, "Renamed key %i", hint); - - return CLI_OK; -} - -static int cmd_keystore_show_keys(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - const hal_ks_keydb_t *db; - char *type; + cli_print(cli, title); - db = hal_ks_get_keydb(); + while (!done) { - if (db == NULL) { - cli_print(cli, "Could not get a keydb from libhal"); - return CLI_OK; - } + if ((status = hal_rpc_pkey_match(client, session, HAL_KEY_TYPE_NONE, HAL_CURVE_NONE, + qflags, NULL, 0, uuids, &n, sizeof(uuids)/sizeof(*uuids), + &previous_uuid)) != LIBHAL_OK) { + cli_print(cli, "Could not fetch UUID list: %s", hal_error_string(status)); + return 0; + } - /* cli_print(cli, "Sizeof db->keys is %i, sizeof one key is %i\n", sizeof(db->keys), sizeof(*db->keys)); */ - - for (int i = 0; i < sizeof(db->keys)/sizeof(*db->keys); i++) { - if (! db->keys[i].in_use) { - cli_print(cli, "Key %i, not in use", i); - } else { - switch (db->keys[i].type) { - case HAL_KEY_TYPE_RSA_PRIVATE: - type = "RSA private"; - break; - case HAL_KEY_TYPE_RSA_PUBLIC: - type = "RSA public"; - break; - case HAL_KEY_TYPE_EC_PRIVATE: - type = "EC private"; - break; - case HAL_KEY_TYPE_EC_PUBLIC: - type = "EC public"; - break; - default: - type = "unknown"; - break; - } - int printable = 1; - for (int j = 0; j < db->keys[i].name_len; ++j) { - if (!isprint(db->keys[i].name[j])) { - printable = 0; - break; - } - } - if (printable) { - /* name may not be nul-terminated in the db, and %*s - * doesn't seem to be working properly, so copy it - */ - uint8_t name[db->keys[i].name_len + 1]; - memcpy(name, db->keys[i].name, db->keys[i].name_len); - name[db->keys[i].name_len] = '\0'; - cli_print(cli, "Key %i, type %s, name '%s'", i, type, name); - } - else { - /* hexdump name */ - uint8_t name[db->keys[i].name_len * 3]; - for (int j = 0; j < db->keys[i].name_len; ++j) { - uint8_t b = db->keys[i].name[j]; - #define hexify(n) (((n) < 10) ? ((n) + '0') : ((n) - 10 + 'A')) - name[j*3] = hexify((b & 0xf0) >> 4); - name[j*3+1] = hexify(b & 0x0f); - name[j*3+2] = ':'; - } - name[sizeof(name)-1] = '\0'; - cli_print(cli, "Key %i, type %s, name %s", i, type, name); - } + done = n < sizeof(uuids)/sizeof(*uuids); + + if (!done) + previous_uuid = uuids[sizeof(uuids)/sizeof(*uuids) - 1]; + + for (int i = 0; i < n; i++) { + + if ((status = hal_uuid_format(&uuids[i], key_name, sizeof(key_name))) != LIBHAL_OK) { + cli_print(cli, "Could not convert key name: %s", + hal_error_string(status)); + return 0; + } + + if ((status = hal_rpc_pkey_open(client, session, &pkey, &uuids[i], qflags)) != LIBHAL_OK) { + cli_print(cli, "Could not open key %s: %s", + key_name, hal_error_string(status)); + return 0; + } + + if ((status = hal_rpc_pkey_get_key_type(pkey, &type)) != LIBHAL_OK || + (status = hal_rpc_pkey_get_key_curve(pkey, &curve)) != LIBHAL_OK || + (status = hal_rpc_pkey_get_key_flags(pkey, &flags)) != LIBHAL_OK) + cli_print(cli, "Could not fetch metadata for key %s: %s", + key_name, hal_error_string(status)); + + if (status == LIBHAL_OK) + status = hal_rpc_pkey_close(pkey); + else + (void) hal_rpc_pkey_close(pkey); + + if (status != LIBHAL_OK) + return 0; + + const char *type_name = "unknown"; + switch (type) { + case HAL_KEY_TYPE_NONE: type_name = "none"; break; + case HAL_KEY_TYPE_RSA_PRIVATE: type_name = "RSA private"; break; + 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; + } + + const char *curve_name = "unknown"; + switch (curve) { + case HAL_CURVE_NONE: curve_name = "none"; break; + case HAL_CURVE_P256: curve_name = "P-256"; break; + case HAL_CURVE_P384: curve_name = "P-384"; break; + case HAL_CURVE_P521: curve_name = "P-521"; break; + } + + cli_print(cli, "Key %2i, name %s, type %s, curve %s, flags 0x%lx", + i, key_name, type_name, curve_name, (unsigned long) flags); } } - cli_print(cli, "\nPins:"); - cli_print(cli, "Wheel iterations: 0x%lx", db->wheel_pin.iterations); - cli_print(cli, "SO iterations: 0x%lx", db->so_pin.iterations); - cli_print(cli, "User iterations: 0x%lx", db->user_pin.iterations); + return 1; +} - return CLI_OK; +static int cmd_keystore_show_keys(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + int ok = 1; + ok &= show_keys(cli, "Memory keystore:", 0); + ok &= show_keys(cli, "Token keystore:", HAL_KEY_FLAG_TOKEN); + return ok ? CLI_OK : CLI_ERROR; } static int cmd_keystore_erase(struct cli_def *cli, const char *command, char *argv[], int argc) { + hal_error_t err; int status; - if (argc != 1) { + if (argc != 1 || strcmp(argv[0], "YesIAmSure") != 0) { cli_print(cli, "Syntax: keystore erase YesIAmSure"); return CLI_ERROR; } - if (strcmp(argv[0], "YesIAmSure") == 0) { - if ((status = keystore_erase_sectors(0, 1)) != 1) { - cli_print(cli, "Failed erasing keystore: %i", status); - } else { - cli_print(cli, "Keystore erased (first two sectors at least)"); - } - } else { - cli_print(cli, "Keystore NOT erased"); + cli_print(cli, "OK, erasing keystore, this might take a while..."); + if ((status = keystore_erase_sectors(0, KEYSTORE_NUM_SECTORS - 1)) != 1) { + cli_print(cli, "Failed erasing token keystore: %i", status); + return CLI_ERROR; } + if ((err = hal_ks_init(hal_ks_token_driver, 0)) != LIBHAL_OK) { + cli_print(cli, "Failed to reinitialize token keystore: %s", hal_error_string(err)); + return CLI_ERROR; + } + + if ((err = hal_ks_init(hal_ks_volatile_driver, 0)) != LIBHAL_OK) { + cli_print(cli, "Failed to reinitialize memory keystore: %s", hal_error_string(err)); + return CLI_ERROR; + } + + cli_print(cli, "Keystore erased"); return CLI_OK; } @@ -394,11 +297,10 @@ void configure_cli_keystore(struct cli_def *cli) { struct cli_command *c = cli_register_command(cli, NULL, "keystore", NULL, 0, 0, NULL); - struct cli_command *c_show = cli_register_command(cli, c, "show", NULL, 0, 0, NULL); - struct cli_command *c_set = cli_register_command(cli, c, "set", NULL, 0, 0, NULL); - struct cli_command *c_clear = cli_register_command(cli, c, "clear", NULL, 0, 0, NULL); + struct cli_command *c_show = cli_register_command(cli, c, "show", NULL, 0, 0, NULL); + struct cli_command *c_set = cli_register_command(cli, c, "set", NULL, 0, 0, NULL); + struct cli_command *c_clear = cli_register_command(cli, c, "clear", NULL, 0, 0, NULL); struct cli_command *c_delete = cli_register_command(cli, c, "delete", NULL, 0, 0, NULL); - struct cli_command *c_rename = cli_register_command(cli, c, "rename", NULL, 0, 0, NULL); /* keystore show keys */ cli_register_command(cli, c_show, "keys", cmd_keystore_show_keys, 0, 0, "Show what PINs and keys are in the keystore"); @@ -412,14 +314,6 @@ void configure_cli_keystore(struct cli_def *cli) /* keystore clear pin */ cli_register_command(cli, c_clear, "pin", cmd_keystore_clear_pin, 0, 0, "Clear either 'wheel', 'user' or 'so' PIN"); -#if 0 - /* keystore set key */ - cli_register_command(cli, c_set, "key", cmd_keystore_set_key, 0, 0, "Set a key"); -#endif - - /* keystore rename key */ - cli_register_command(cli, c_rename, "key", cmd_keystore_rename_key, 0, 0, "Rename a key"); - /* keystore delete key */ cli_register_command(cli, c_delete, "key", cmd_keystore_delete_key, 0, 0, "Delete a key"); diff --git a/projects/hsm/mgmt-masterkey.c b/projects/hsm/mgmt-masterkey.c index 33ce395..9f5e4d0 100644 --- a/projects/hsm/mgmt-masterkey.c +++ b/projects/hsm/mgmt-masterkey.c @@ -42,14 +42,12 @@ #undef HAL_OK #define LIBHAL_OK HAL_OK #include <hal.h> -#include <masterkey.h> +#warning Refactor so we do not need to include hal_internal.h here +#include <hal_internal.h> #undef HAL_OK #include <stdlib.h> -#define KEK_LENGTH (256 / 8) - - static char * _status2str(const hal_error_t status) { switch (status) { @@ -86,17 +84,17 @@ static int cmd_masterkey_status(struct cli_def *cli, const char *command, char * cli_print(cli, "Status of master key:\n"); - status = masterkey_volatile_read(NULL, 0); + status = hal_mkm_volatile_read(NULL, 0); cli_print(cli, " volatile: %s / %s", _status2str(status), hal_error_string(status)); - status = masterkey_flash_read(NULL, 0); + status = hal_mkm_flash_read(NULL, 0); cli_print(cli, " flash: %s / %s", _status2str(status), hal_error_string(status)); return CLI_OK; } static int _masterkey_set(struct cli_def *cli, char *argv[], int argc, - char *label, hal_error_t (*writer)(uint8_t *, size_t)) + char *label, hal_error_t (*writer)(const uint8_t * const, const size_t)) { uint8_t buf[KEK_LENGTH] = {0}; hal_error_t err; @@ -134,14 +132,14 @@ static int _masterkey_set(struct cli_def *cli, char *argv[], int argc, static int cmd_masterkey_set(struct cli_def *cli, const char *command, char *argv[], int argc) { - return _masterkey_set(cli, argv, argc, "volatile", masterkey_volatile_write); + return _masterkey_set(cli, argv, argc, "volatile", hal_mkm_volatile_write); } static int cmd_masterkey_erase(struct cli_def *cli, const char *command, char *argv[], int argc) { hal_error_t err; - if ((err = masterkey_volatile_erase(KEK_LENGTH)) == LIBHAL_OK) { + if ((err = hal_mkm_volatile_erase(KEK_LENGTH)) == LIBHAL_OK) { cli_print(cli, "Erased master key from volatile memory"); } else { cli_print(cli, "Failed erasing master key from volatile memory: %s", hal_error_string(err)); @@ -151,14 +149,14 @@ static int cmd_masterkey_erase(struct cli_def *cli, const char *command, char *a static int cmd_masterkey_unsecure_set(struct cli_def *cli, const char *command, char *argv[], int argc) { - return _masterkey_set(cli, argv, argc, "flash", masterkey_flash_write); + return _masterkey_set(cli, argv, argc, "flash", hal_mkm_flash_write); } static int cmd_masterkey_unsecure_erase(struct cli_def *cli, const char *command, char *argv[], int argc) { hal_error_t err; - if ((err = masterkey_flash_erase(KEK_LENGTH)) == LIBHAL_OK) { + if ((err = hal_mkm_flash_erase(KEK_LENGTH)) == LIBHAL_OK) { cli_print(cli, "Erased unsecure master key from flash"); } else { cli_print(cli, "Failed erasing unsecure master key from flash: %s", hal_error_string(err)); diff --git a/spiflash_n25q128.c b/spiflash_n25q128.c index 6e35a41..c23f244 100644 --- a/spiflash_n25q128.c +++ b/spiflash_n25q128.c @@ -43,6 +43,14 @@ #define _n25q128_deselect(ctx) HAL_GPIO_WritePin(ctx->cs_n_port, ctx->cs_n_pin, GPIO_PIN_SET); +#define N25Q128_NUM_BYTES (N25Q128_PAGE_SIZE * N25Q128_NUM_PAGES) + +#if N25Q128_SECTOR_SIZE * N25Q128_NUM_SECTORS != N25Q128_NUM_BYTES || \ + N25Q128_SUBSECTOR_SIZE * N25Q128_NUM_SUBSECTORS != N25Q128_NUM_BYTES +#error Inconsistant definitions for pages / sectors / subsectors +#endif + + int _n25q128_get_wel_flag(struct spiflash_ctx *ctx); @@ -208,18 +216,30 @@ int n25q128_get_wip_flag(struct spiflash_ctx *ctx) return (spi_rx[1] & 1); } +/* Wait until the flash memory is done writing (wip = Write In Progress) */ +inline int _wait_while_wip(struct spiflash_ctx *ctx, uint32_t timeout) +{ + int i; + while (timeout--) { + i = n25q128_get_wip_flag(ctx); + if (i < 0) return 0; + if (! i) break; + HAL_Delay(10); + } + return 1; +} -int n25q128_erase_sector(struct spiflash_ctx *ctx, uint32_t sector_offset) +static int n25q128_erase_something(struct spiflash_ctx *ctx, uint8_t command, uint32_t byte_offset) { + // check offset + if (byte_offset >= N25Q128_NUM_BYTES) return 0; + // tx buffer uint8_t spi_tx[4]; // result HAL_StatusTypeDef ok; - // check offset - if (sector_offset >= N25Q128_NUM_SECTORS) return 0; - // enable writing spi_tx[0] = N25Q128_COMMAND_WRITE_ENABLE; @@ -236,14 +256,11 @@ int n25q128_erase_sector(struct spiflash_ctx *ctx, uint32_t sector_offset) int wel = _n25q128_get_wel_flag(ctx); if (wel != 1) return 0; - // calculate byte address - sector_offset *= N25Q128_SECTOR_SIZE; - - // send ERASE SUBSECTOR command - spi_tx[0] = N25Q128_COMMAND_ERASE_SECTOR; - spi_tx[1] = (uint8_t)(sector_offset >> 16); - spi_tx[2] = (uint8_t)(sector_offset >> 8); - spi_tx[3] = (uint8_t)(sector_offset >> 0); + // send command (ERASE SECTOR or ERASE SUBSECTOR) + spi_tx[0] = command; + spi_tx[1] = (uint8_t)(byte_offset >> 16); + spi_tx[2] = (uint8_t)(byte_offset >> 8); + spi_tx[3] = (uint8_t)(byte_offset >> 0); // activate, send command, deselect _n25q128_select(ctx); @@ -254,11 +271,29 @@ int n25q128_erase_sector(struct spiflash_ctx *ctx, uint32_t sector_offset) // check if (ok != HAL_OK) return 0; + // wait for erase to finish + + if (! _wait_while_wip(ctx, 2000)) return 0; + // done return 1; } +int n25q128_erase_sector(struct spiflash_ctx *ctx, uint32_t sector_offset) +{ + return n25q128_erase_something(ctx, N25Q128_COMMAND_ERASE_SECTOR, + sector_offset * N25Q128_SECTOR_SIZE); +} + + +int n25q128_erase_subsector(struct spiflash_ctx *ctx, uint32_t subsector_offset) +{ + return n25q128_erase_something(ctx, N25Q128_COMMAND_ERASE_SUBSECTOR, + subsector_offset * N25Q128_SUBSECTOR_SIZE); +} + + int _n25q128_get_wel_flag(struct spiflash_ctx *ctx) { // tx, rx buffers @@ -284,21 +319,8 @@ int _n25q128_get_wel_flag(struct spiflash_ctx *ctx) return ((spi_rx[1] >> 1) & 1); } -/* Wait until the flash memory is done writing (wip = Write In Progress) */ -inline int _wait_while_wip(struct spiflash_ctx *ctx, uint32_t timeout) -{ - int i; - while (timeout--) { - i = n25q128_get_wip_flag(ctx); - if (i < 0) return 0; - if (! i) break; - HAL_Delay(10); - } - return 1; -} - /* This function performs erasure if needed, and then writing of a number of pages to the flash memory */ -int n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t *buf, const uint32_t len) +int n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t *buf, const uint32_t len, const int auto_erase) { uint32_t page; @@ -306,8 +328,15 @@ int n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t if ((offset % N25Q128_PAGE_SIZE) != 0) return -1; if ((len % N25Q128_PAGE_SIZE) != 0) return -2; - if ((offset % N25Q128_SECTOR_SIZE) == 0) { - /* first page in sector, need to erase sector */ + if (auto_erase && (offset % N25Q128_SECTOR_SIZE) == 0) { + /* + * first page in sector, need to erase sector + * + * So why do we only do this when the buffer starts on the + * sector, as opposed to performing this check for every page? + * Also, might be better to do this by subsectors rather than + * sectors. + */ if (! _wait_while_wip(ctx, 1000)) return -3; @@ -330,6 +359,12 @@ int n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t */ } + /* + * Wait until last write finishes. + */ + + if (! _wait_while_wip(ctx, 1000)) return -7; + return 1; } diff --git a/spiflash_n25q128.h b/spiflash_n25q128.h index fefcb0d..c696911 100644 --- a/spiflash_n25q128.h +++ b/spiflash_n25q128.h @@ -45,6 +45,7 @@ #define N25Q128_COMMAND_READ_STATUS 0x05 #define N25Q128_COMMAND_WRITE_ENABLE 0x06 #define N25Q128_COMMAND_ERASE_SECTOR 0xD8 +#define N25Q128_COMMAND_ERASE_SUBSECTOR 0x20 #define N25Q128_COMMAND_PAGE_PROGRAM 0x02 #define N25Q128_PAGE_SIZE 0x100 // 256 @@ -53,6 +54,9 @@ #define N25Q128_SECTOR_SIZE 0x10000 // 65536 #define N25Q128_NUM_SECTORS 0x100 // 256 +#define N25Q128_SUBSECTOR_SIZE 0x1000 // 4096 +#define N25Q128_NUM_SUBSECTORS 0x1000 // 4096 + #define N25Q128_SPI_TIMEOUT 1000 #define N25Q128_ID_MANUFACTURER 0x20 @@ -70,7 +74,8 @@ extern int n25q128_get_wip_flag(struct spiflash_ctx *ctx); extern int n25q128_read_page(struct spiflash_ctx *ctx, uint32_t page_offset, uint8_t *page_buffer); extern int n25q128_write_page(struct spiflash_ctx *ctx, uint32_t page_offset, const uint8_t *page_buffer); extern int n25q128_erase_sector(struct spiflash_ctx *ctx, uint32_t sector_offset); +extern int n25q128_erase_subsector(struct spiflash_ctx *ctx, uint32_t subsector_offset); -extern int n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t *buf, const uint32_t len); +extern int n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t *buf, const uint32_t len, const int auto_erase); extern int n25q128_read_data(struct spiflash_ctx *ctx, uint32_t offset, uint8_t *buf, const uint32_t len); #endif /* __STM32_SPIFLASH_N25Q128_H */ diff --git a/stm-fpgacfg.c b/stm-fpgacfg.c index 6f6114d..1f15f88 100644 --- a/stm-fpgacfg.c +++ b/stm-fpgacfg.c @@ -48,7 +48,7 @@ int fpgacfg_check_id() int fpgacfg_write_data(uint32_t offset, const uint8_t *buf, const uint32_t len) { - return n25q128_write_data(&fpgacfg_ctx, offset, buf, len); + return n25q128_write_data(&fpgacfg_ctx, offset, buf, len, 1); } void fpgacfg_access_control(enum fpgacfg_access_ctrl access) diff --git a/stm-keystore.c b/stm-keystore.c index 43e22fa..d5d8adb 100644 --- a/stm-keystore.c +++ b/stm-keystore.c @@ -52,17 +52,18 @@ int keystore_read_data(uint32_t offset, uint8_t *buf, const uint32_t len) int keystore_write_data(uint32_t offset, const uint8_t *buf, const uint32_t len) { - return n25q128_write_data(&keystore_ctx, offset, buf, len); + return n25q128_write_data(&keystore_ctx, offset, buf, len, 0); } -int keystore_erase_sectors(uint32_t start, uint32_t stop) +static int keystore_erase_something(uint32_t start, uint32_t stop, uint32_t limit, + int (*eraser)(struct spiflash_ctx *, uint32_t)) { - uint32_t sector; + uint32_t something; - if (start > N25Q128_NUM_SECTORS) return -2; - if (stop > N25Q128_NUM_SECTORS || stop < start) return -3; + if (start > limit) return -2; + if (stop > limit || stop < start) return -3; - for (sector = start; sector <= stop; sector++) { + for (something = start; something <= stop; something++) { int timeout = 200; /* times 10ms = 2 seconds timeout */ while (timeout--) { int i = n25q128_get_wip_flag(&keystore_ctx); @@ -72,9 +73,21 @@ int keystore_erase_sectors(uint32_t start, uint32_t stop) } if (! timeout) return 0; - if (! n25q128_erase_sector(&keystore_ctx, sector)) { + if (! eraser(&keystore_ctx, something)) { return -1; } } return 1; } + +int keystore_erase_sectors(uint32_t start, uint32_t stop) +{ + return keystore_erase_something(start, stop, N25Q128_NUM_SECTORS, + n25q128_erase_sector); +} + +int keystore_erase_subsectors(uint32_t start, uint32_t stop) +{ + return keystore_erase_something(start, stop, N25Q128_NUM_SUBSECTORS, + n25q128_erase_subsector); +} diff --git a/stm-keystore.h b/stm-keystore.h index 0c04481..9054db5 100644 --- a/stm-keystore.h +++ b/stm-keystore.h @@ -41,6 +41,8 @@ #define KEYSTORE_PAGE_SIZE N25Q128_PAGE_SIZE #define KEYSTORE_SECTOR_SIZE N25Q128_SECTOR_SIZE #define KEYSTORE_NUM_SECTORS N25Q128_NUM_SECTORS +#define KEYSTORE_SUBSECTOR_SIZE N25Q128_SUBSECTOR_SIZE +#define KEYSTORE_NUM_SUBSECTORS N25Q128_NUM_SUBSECTORS /* Pins connected to the FPGA config memory (SPI flash) */ #define KSM_PROM_CS_N_Pin GPIO_PIN_0 @@ -58,5 +60,6 @@ extern int keystore_check_id(void); extern int keystore_read_data(uint32_t offset, uint8_t *buf, const uint32_t len); extern int keystore_write_data(uint32_t offset, const uint8_t *buf, const uint32_t len); extern int keystore_erase_sectors(uint32_t start, uint32_t stop); +extern int keystore_erase_subsectors(uint32_t start, uint32_t stop); #endif /* __STM32_KEYSTORE_H */ |