From b58cbd9c1a2a07a7dc490eccdecc43ffaada224c Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:10:43 -0600 Subject: [PATCH 1/3] add NVM provisioning tool --- .../workflows/build-and-test-whnvmtool.yml | 39 ++ port/posix/posix_transport_shm.c | 6 +- src/wh_flash_ramsim.c | 8 +- src/wh_server_keystore.c | 2 +- tools/whnvmtool/.gitignore | 4 + tools/whnvmtool/Makefile | 92 +++ tools/whnvmtool/README.md | 105 ++++ tools/whnvmtool/test/Makefile | 69 +++ tools/whnvmtool/test/data/key1.bin | 1 + tools/whnvmtool/test/data/key2.bin | 1 + tools/whnvmtool/test/data/obj1.bin | 1 + tools/whnvmtool/test/data/obj2.bin | 1 + tools/whnvmtool/test/nvminit/test.nvminit | 8 + tools/whnvmtool/test/test_whnvmtool.c | 431 +++++++++++++ tools/whnvmtool/user_settings.h | 160 +++++ tools/whnvmtool/whnvmtool.c | 583 ++++++++++++++++++ tools/whnvmtool/wolfhsm_cfg.h | 46 ++ wolfhsm/wh_flash_ramsim.h | 3 +- 18 files changed, 1553 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/build-and-test-whnvmtool.yml create mode 100644 tools/whnvmtool/.gitignore create mode 100644 tools/whnvmtool/Makefile create mode 100644 tools/whnvmtool/README.md create mode 100644 tools/whnvmtool/test/Makefile create mode 100644 tools/whnvmtool/test/data/key1.bin create mode 100644 tools/whnvmtool/test/data/key2.bin create mode 100644 tools/whnvmtool/test/data/obj1.bin create mode 100644 tools/whnvmtool/test/data/obj2.bin create mode 100644 tools/whnvmtool/test/nvminit/test.nvminit create mode 100644 tools/whnvmtool/test/test_whnvmtool.c create mode 100644 tools/whnvmtool/user_settings.h create mode 100644 tools/whnvmtool/whnvmtool.c create mode 100644 tools/whnvmtool/wolfhsm_cfg.h diff --git a/.github/workflows/build-and-test-whnvmtool.yml b/.github/workflows/build-and-test-whnvmtool.yml new file mode 100644 index 00000000..503280a6 --- /dev/null +++ b/.github/workflows/build-and-test-whnvmtool.yml @@ -0,0 +1,39 @@ +name: whnvmtool build and test + +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + # List host CPU info + - name: Host CPU info + run: cat /proc/cpuinfo + + # List compiler version + - name: List compiler version + run: gcc --version + + # pull and build wolfssl + - name: Checkout wolfssl + uses: actions/checkout@v4 + with: + repository: wolfssl/wolfssl + path: wolfssl + + # Build and test standard build of whnvmtool + - name: Build and test NVM tool + run: cd tools/whnvmtool && make clean && make check WOLFSSL_DIR=../../wolfssl + + # Build and test ASAN + - name: Build and test NVM tool with ASAN + run: cd tools/whnvmtool && make clean && make check WOLFSSL_DIR=../../wolfssl ASAN=1 + diff --git a/port/posix/posix_transport_shm.c b/port/posix/posix_transport_shm.c index 0ecbe9dc..d558f5fc 100644 --- a/port/posix/posix_transport_shm.c +++ b/port/posix/posix_transport_shm.c @@ -1,4 +1,3 @@ - #include /* For O_* constants */ #include /* For shm_open, mmap */ #include /* For mode constants */ @@ -7,6 +6,7 @@ #include /* For exit */ #include /* For memset */ #include +#include #include "wolfhsm/wh_error.h" #include "wolfhsm/wh_utils.h" @@ -370,7 +370,7 @@ int posixTransportShm_ServerInit(void* c, const void* cf, if (ret == WH_ERROR_OK) { memset(ctx, 0, sizeof(*ctx)); - strncpy(ctx->name, config->name, sizeof(ctx->name)); + snprintf(ctx->name, sizeof(ctx->name), "%s", config->name); ctx->connectcb = connectcb; ctx->connectcb_arg = connectcb_arg; @@ -416,7 +416,7 @@ int posixTransportShm_ClientInit(void* c, const void* cf, } memset(ctx, 0, sizeof(*ctx)); - strncpy(ctx->name, config->name, sizeof(ctx->name)); + snprintf(ctx->name, sizeof(ctx->name), "%s", config->name); ctx->connectcb = connectcb; ctx->connectcb_arg = connectcb_arg; diff --git a/src/wh_flash_ramsim.c b/src/wh_flash_ramsim.c index c5316e24..3f4b0e10 100644 --- a/src/wh_flash_ramsim.c +++ b/src/wh_flash_ramsim.c @@ -74,8 +74,12 @@ int whFlashRamsim_Init(void* context, const void* config) return WH_ERROR_BADARGS; } - /* Simulate starting from erased flash */ - memset(ctx->memory, ctx->erasedByte, ctx->size); + /* Initialize memory based on initData or simulate starting from erased flash */ + if (cfg->initData != NULL) { + memcpy(ctx->memory, cfg->initData, ctx->size); + } else { + memset(ctx->memory, ctx->erasedByte, ctx->size); + } return WH_ERROR_OK; } diff --git a/src/wh_server_keystore.c b/src/wh_server_keystore.c index 642240bf..c9212162 100644 --- a/src/wh_server_keystore.c +++ b/src/wh_server_keystore.c @@ -529,7 +529,7 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, ret = hsmCacheKey(server, meta, in); } if (ret == 0) { - /* remove the cleint_id, client may set type */ + /* remove the client_id, client may set type */ packet->keyCacheRes.id = WH_KEYID_ID(meta->id); *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyCacheRes); } diff --git a/tools/whnvmtool/.gitignore b/tools/whnvmtool/.gitignore new file mode 100644 index 00000000..3d2de7b6 --- /dev/null +++ b/tools/whnvmtool/.gitignore @@ -0,0 +1,4 @@ +whnvmtool +whNvmImage.bin +whNvmImage.hex +test/test_whnvmtool diff --git a/tools/whnvmtool/Makefile b/tools/whnvmtool/Makefile new file mode 100644 index 00000000..653b25d8 --- /dev/null +++ b/tools/whnvmtool/Makefile @@ -0,0 +1,92 @@ +TARGET = whnvmtool +CC ?= gcc + +# wolfHSM source files +WOLFHSM_DIR ?= $(CURDIR)/../../ +WOLFHSM_SRC = $(wildcard $(WOLFHSM_DIR)/src/*.c) +WOLFHSM_SRC += $(wildcard $(WOLFHSM_DIR)/port/posix/*.c) + +# wolfCrypt source files +WOLFSSL_DIR ?= $(CURDIR)/../../../wolfssl +WOLFCRYPT_SRC = \ + $(WOLFSSL_DIR)/wolfcrypt/src/wc_port.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/memory.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/misc.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/cryptocb.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/random.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/asn.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/coding.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/wolfmath.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/tfm.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/fe_operations.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/rsa.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/curve25519.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/hash.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/sha256.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/aes.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/ecc.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/cmac.c + + +SRC = \ + $(WOLFHSM_SRC) \ + $(WOLFCRYPT_SRC) \ + $(TARGET).c + + +INCLUDE_DIRS = \ + -I$(WOLFHSM_DIR) \ + -I$(WOLFSSL_DIR) \ + -I. + +LIBS = \ + -lm \ + -lpthread + +LIB_DIRS = + +CFLAGS = -Wall $(INCLUDE_DIRS) +CFLAGS += -DWOLFSSL_USER_SETTINGS +CFLAGS += -std=c90 -D_GNU_SOURCE -Wno-cpp + +CFLAGS_EXTRA = # Additional CFLAGS from the command line +LDFLAGS = $(LIB_DIRS) $(LIBS) +OUT = $(TARGET) # Output executable name + +# DEBUG flag +ifeq ($(DEBUG), 1) + CFLAGS += -g -O0 -DDEBUG -ggdb3 +else + CFLAGS += -O2 +endif + +ifeq ($(ASAN), 1) + CFLAGS_EXTRA += -fsanitize=address +endif + +# Targets +all: $(OUT) + +$(OUT): $(SRC) + $(CC) $(CFLAGS) $(CFLAGS_EXTRA) $(SRC) -o $(OUT) $(LDFLAGS) + +# Generate the test NVM image +test-gen: $(OUT) + rm -f whNvmImage.bin whNvmImage.hex + ./$(OUT) --test test/nvminit/test.nvminit --invert-erased-byte + +# Run the test suite, which requires first generating the test NVM image +check: test +test: $(OUT) test-gen + $(MAKE) -C test/ CFLAGS_EXTRA="-DFLASH_ERASED_BYTE=0x00 $(CFLAGS_EXTRA)" WOLFSSL_DIR=$$(realpath $(WOLFSSL_DIR)) + cd test && ./test_whnvmtool + +clean: clean-test + rm -f whNvmImage.bin whNvmImage.hex + rm -f $(OUT) + +clean-test: + $(MAKE) -C test clean + +# PHONY targets +.PHONY: all clean test-gen test diff --git a/tools/whnvmtool/README.md b/tools/whnvmtool/README.md new file mode 100644 index 00000000..b0788de9 --- /dev/null +++ b/tools/whnvmtool/README.md @@ -0,0 +1,105 @@ +# whnvmtool + +## Overview +`whnvmtool` is a utility for creating Non-Volatile Memory (NVM) images for wolfHSM. It allows users to create NVM images with predefined objects and keys, which can be used for provisioning a wolfHSM device. THe tool creates an NVM image and loads it with objects and keys specified by the user in a configuration file. The generated image can then be loaded into device memory, or used for to initialize an instance of a `whNvmFlash` provider. + +## Supported NVM Providers + +Currently, `whnvmtool` only supports the `whNvmFlash` provider. + +## Usage + +``` +./whnvmtool [--test] [--image[=]] [--size ] [--invert-erased-byte] +``` + +- `--image[=]`: Specifies the output NVM image file. If not provided, defaults to `whNvmImage.bin`. +- `--size `: Sets the partition size for the NVM image. Can be specified in decimal or hexadecimal (with '0x' prefix). +- `--invert-erased-byte`: Inverts the erased byte value (default is 0xFF, this option changes it to 0x00). +- `--test`: Enables test mode. In this mode, the tool generates an intermediate file (`nvm_metadata.txt`) containing comma separated metadata ID/file path pairs, associating each object ID with the file path containing the object's original data. This option is used by the `whnvmtool` tests to verify the contents of the generated NVM image, and is not required for normal operation. + +## Configuration File Schema + +The configuration file follows a specific schema for defining objects and keys to be stored in the NVM image. Each line in the file represents either an object or a key entry. The schema also supports comments and empty lines for readability. Comments use the `#` character, and all text after the `#` on a line is ignored. There are no multi-line comments. + +### Object Entry Format + +Lines beginning with `obj` define objects to be stored in the NVM image. The format of an object entry is as follows: + +``` +obj