From cfbd7a0f7f0c491fae1e10a1871f7bbb3346bb9d Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Wed, 1 Oct 2025 14:38:16 +0100 Subject: [PATCH] Add wolfBoot testing to wolfPKCS11 wolfBoot implements its own storage, we need to make sure we don't break it. --- .github/workflows/clang-tidy.yml | 12 +- .github/workflows/wolfboot-build.yml | 71 +++++ .gitignore | 1 + Docker/include.am | 2 + Docker/wolfboot/Dockerfile | 45 +++ README.md | 6 +- configure.ac | 32 ++ src/crypto.c | 2 +- src/include.am | 7 +- src/wolfboot_store_adapter.c | 460 +++++++++++++++++++++++++++ src/wolfpkcs11.c | 6 +- tests/debug_test.c | 9 + tests/include.am | 27 +- tests/object_id_uniqueness_test.c | 9 + tests/pkcs11mtt.c | 7 + tests/pkcs11str.c | 9 +- tests/pkcs11test.c | 7 + tests/rsa_session_persistence_test.c | 9 + tests/storage_helpers.h | 85 +++++ tests/token_path_test.c | 14 +- tests/unit.h | 1 - 21 files changed, 791 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/wolfboot-build.yml create mode 100644 Docker/wolfboot/Dockerfile create mode 100644 src/wolfboot_store_adapter.c create mode 100644 tests/storage_helpers.h diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index 6829dd7b..73db6ec1 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -76,6 +76,14 @@ jobs: sudo ldconfig cd .. + # Fetch wolfBoot sources for custom store builds + - name: Fetch wolfBoot sources + run: | + WOLFBOOT_DIR="${RUNNER_TEMP:-/tmp}/wolfBoot" + rm -rf "$WOLFBOOT_DIR" + git clone --depth 1 --branch master https://github.com/wolfSSL/wolfBoot.git "$WOLFBOOT_DIR" + echo "WOLFBOOT_DIR=$WOLFBOOT_DIR" >> "$GITHUB_ENV" + # Setup IBM Software TPM (only if TPM enabled) - name: Setup IBM Software TPM if: contains(matrix.config.configure_flags, '--enable-tpm') @@ -109,9 +117,9 @@ jobs: run: | ./autogen.sh if [ -n "${{ matrix.config.configure_flags }}" ]; then - CC=clang CXX=clang++ ./configure --enable-all --enable-debug ${{ matrix.config.configure_flags }} + CC=clang CXX=clang++ ./configure --enable-all --enable-debug --with-wolfboot="${WOLFBOOT_DIR}" ${{ matrix.config.configure_flags }} else - CC=clang CXX=clang++ ./configure --enable-all --enable-debug + CC=clang CXX=clang++ ./configure --enable-all --enable-debug --with-wolfboot="${WOLFBOOT_DIR}" fi bear -- make -j$(nproc) diff --git a/.github/workflows/wolfboot-build.yml b/.github/workflows/wolfboot-build.yml new file mode 100644 index 00000000..c50f1f54 --- /dev/null +++ b/.github/workflows/wolfboot-build.yml @@ -0,0 +1,71 @@ +name: Build wolfBoot integration + +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + workflow_dispatch: + +jobs: + build: + name: Build wolfPKCS11 with wolfBoot store + runs-on: ubuntu-24.04 + env: + DEBIAN_FRONTEND: noninteractive + LD_LIBRARY_PATH: /usr/local/lib + PKG_CONFIG_PATH: /usr/local/lib/pkgconfig + WOLFSSL_REF: v5.8.0-stable + WOLFBOOT_REF: master + WOLFBOOT_DIR: /tmp/wolfBoot + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + autoconf \ + automake \ + build-essential \ + ca-certificates \ + git \ + libssl-dev \ + libtool \ + make \ + pkg-config \ + python3 \ + gdb + + - name: Build and install wolfSSL + run: | + git clone --depth 1 --branch "${WOLFSSL_REF}" https://github.com/wolfSSL/wolfssl.git /tmp/wolfssl + cd /tmp/wolfssl + ./autogen.sh + ./configure --enable-debug --enable-aescfb --enable-cryptocb --enable-rsapss --enable-keygen \ + --enable-pwdbased --enable-scrypt "C_EXTRA_FLAGS=-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT -DHAVE_AES_ECB -DHAVE_AES_KEYWRAP" + make -j"$(nproc)" + sudo make install + sudo ldconfig + + - name: Fetch wolfBoot sources + run: | + git clone --depth 1 --branch "${WOLFBOOT_REF}" https://github.com/wolfSSL/wolfBoot.git "${WOLFBOOT_DIR}" + + - name: Build wolfPKCS11 + run: | + ./autogen.sh + ./configure --enable-debug --with-wolfboot="${WOLFBOOT_DIR}" CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib" + make -j"$(nproc)" + + - name: Run tests + run: make test + + - name: Archive test-suite.log on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: wolfboot-test-suite-log + path: test-suite.log + if-no-files-found: ignore diff --git a/.gitignore b/.gitignore index ca0a60dd..45051f1a 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,7 @@ examples/mech_info examples/obj_list examples/slot_info examples/token_info +examples/nss_pkcs12_pbe_example store/wp11* store/object store/pkcs11mtt diff --git a/Docker/include.am b/Docker/include.am index e40d0a61..a80e7636 100644 --- a/Docker/include.am +++ b/Docker/include.am @@ -1 +1,3 @@ EXTRA_DIST+= Docker/packaging/debian/Dockerfile +EXTRA_DIST+= Docker/firefox/Dockerfile +EXTRA_DIST+= Docker/wolfboot/Dockerfile diff --git a/Docker/wolfboot/Dockerfile b/Docker/wolfboot/Dockerfile new file mode 100644 index 00000000..1e21788d --- /dev/null +++ b/Docker/wolfboot/Dockerfile @@ -0,0 +1,45 @@ +FROM ubuntu:24.04 + +ARG WOLFSSL_REF=v5.8.0-stable +ARG WOLFBOOT_REF=master + +ENV DEBIAN_FRONTEND=noninteractive +ENV LD_LIBRARY_PATH=/usr/local/lib +ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig + +RUN apt-get update && apt-get install -y --no-install-recommends \ + autoconf \ + automake \ + build-essential \ + ca-certificates \ + git \ + libssl-dev \ + libtool \ + make \ + pkg-config \ + python3 \ + gdb \ + && rm -rf /var/lib/apt/lists/* + +# Build and install wolfSSL +RUN git clone --depth 1 --branch ${WOLFSSL_REF} https://github.com/wolfSSL/wolfssl.git /tmp/wolfssl \ + && cd /tmp/wolfssl \ + && ./autogen.sh \ + && ./configure --enable-debug --enable-aescfb --enable-cryptocb --enable-rsapss --enable-keygen \ + --enable-pwdbased --enable-scrypt "C_EXTRA_FLAGS=-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT -DHAVE_AES_ECB -DHAVE_AES_KEYWRAP" \ + && make -j"$(nproc)" \ + && make install \ + && ldconfig \ + && rm -rf /tmp/wolfssl + +# Fetch wolfBoot sources that provide the custom store implementation +RUN git clone --depth 1 --branch ${WOLFBOOT_REF} https://github.com/wolfSSL/wolfBoot.git /opt/wolfBoot + +WORKDIR /wolfpkcs11 +COPY . /wolfpkcs11 + +RUN ./autogen.sh \ + && ./configure --enable-debug --with-wolfboot=/opt/wolfBoot CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib" \ + && make -j"$(nproc)" + +#RUN make check diff --git a/README.md b/README.md index 39de4a66..47bc130e 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,11 @@ Enables debugging printf's for store. Removes default implementation of storage functions. See wolfpkcs11/store.h for prototypes of functions to implement. +To exercise the wolfBoot storage backend during host-based testing, configure +with `./configure --with-wolfboot=/path/to/wolfBoot`. This enables +`WOLFPKCS11_CUSTOM_STORE` automatically and links the test harness against the +wolfBoot implementation of the store API. + #### Define WOLFPKCS11_KEYPAIR_GEN_COMMON_LABEL Sets the private key's label against the public key when generating key pairs. @@ -287,4 +292,3 @@ Adds backend support for TPM 2.0 using wolfTPM. Adds AES CBC key wrap / unwrap s ### wolfPKCS11 Release 1.0 (October 20, 2021) * Initial PKCS11 support - diff --git a/configure.ac b/configure.ac index a574875b..5b54ccfd 100644 --- a/configure.ac +++ b/configure.ac @@ -31,6 +31,8 @@ AC_PROG_INSTALL AC_ARG_PROGRAM AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([wolfpkcs11/config.h]) +m4_ifndef([AS_MESSAGE_LOG_FD],[m4_define([AS_MESSAGE_LOG_FD],[0])]) +m4_pattern_allow([AS_MESSAGE_LOG_FD]) # shared library versioning # The three numbers in the libpkcs11.so.*.*.* file name. Unfortunately @@ -78,6 +80,36 @@ AC_CHECK_SIZEOF([long], 4) AC_CHECK_FUNCS([gethostbyname getaddrinfo gettimeofday inet_ntoa memset socket getpid]) AC_CHECK_LIB([network],[socket]) +WOLFBOOT_CPPFLAGS="" +WOLFBOOT_STORE_ENABLED=no + +AC_ARG_WITH([wolfboot], + [AS_HELP_STRING([--with-wolfboot=PATH], + [Enable the wolfBoot-backed test storage adapter using the wolfBoot sources located at PATH])], + [with_wolfboot="$withval"], + [with_wolfboot=""]) + +AS_IF([test "x$with_wolfboot" = "xyes"], + [AC_MSG_ERROR([--with-wolfboot requires a path to the wolfBoot source tree])]) + +AS_IF([test "x$with_wolfboot" != "x" && test "x$with_wolfboot" != "xno"], + [if test ! -d "$with_wolfboot"; then + echo "configure: error: wolfBoot source directory $with_wolfboot not found" >&2 + exit 1 + fi + if test ! -f "$with_wolfboot/src/pkcs11_store.c"; then + echo "configure: error: wolfBoot PKCS#11 store source not found in $with_wolfboot/src" >&2 + exit 1 + fi + AC_DEFINE([HAVE_WOLFBOOT_STORE], [1], + [Define to 1 if wolfBoot custom storage support is enabled]) + AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFPKCS11_CUSTOM_STORE -DWOLFPKCS11_WOLFBOOT_STORE" + WOLFBOOT_CPPFLAGS="-I$with_wolfboot/include -I$with_wolfboot/src -I$with_wolfboot/tools/unit-tests" + WOLFBOOT_STORE_ENABLED=yes]) + +AM_CONDITIONAL([HAVE_WOLFBOOT_STORE], [test "x$WOLFBOOT_STORE_ENABLED" = "xyes"]) +AC_SUBST([WOLFBOOT_CPPFLAGS]) + # DEBUG DEBUG_CFLAGS="-g -O0 -DDEBUG_WOLFPKCS11" diff --git a/src/crypto.c b/src/crypto.c index cc924331..80cabea7 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -6411,7 +6411,6 @@ CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, case CKP_PKCS5_PBKD2_HMAC_SHA512: hashType = WC_SHA512; break; -#endif #ifndef WOLFSSL_NOSHA512_224 case CKP_PKCS5_PBKD2_HMAC_SHA512_224: hashType = WC_SHA512_224; @@ -6421,6 +6420,7 @@ CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, case CKP_PKCS5_PBKD2_HMAC_SHA512_256: hashType = WC_SHA512_256; break; +#endif #endif default: return CKR_MECHANISM_PARAM_INVALID; diff --git a/src/include.am b/src/include.am index f54ea410..9c0cdf58 100644 --- a/src/include.am +++ b/src/include.am @@ -10,8 +10,13 @@ src_libwolfpkcs11_la_SOURCES = \ src/slot.c \ src/crypto.c +if HAVE_WOLFBOOT_STORE +src_libwolfpkcs11_la_SOURCES += \ + src/wolfboot_store_adapter.c +endif + src_libwolfpkcs11_la_CFLAGS = -DBUILDING_WOLFPKCS11 $(AM_CFLAGS) -src_libwolfpkcs11_la_CPPFLAGS = -DBUILDING_WOLFPKCS11 $(AM_CPPFLAGS) +src_libwolfpkcs11_la_CPPFLAGS = -DBUILDING_WOLFPKCS11 $(AM_CPPFLAGS) $(WOLFBOOT_CPPFLAGS) src_libwolfpkcs11_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-number ${WOLFPKCS11_LIBRARY_VERSION} #src_libwolfpkcs11_la_DEPENDENCIES = diff --git a/src/wolfboot_store_adapter.c b/src/wolfboot_store_adapter.c new file mode 100644 index 00000000..7bb3e329 --- /dev/null +++ b/src/wolfboot_store_adapter.c @@ -0,0 +1,460 @@ +/* wolfboot_store_adapter.c + * + * Copyright (C) 2006-2025 wolfSSL Inc. + * + * This file is part of wolfPKCS11. + * + * wolfPKCS11 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfPKCS11 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Adapter that pulls in wolfBoot's PKCS#11 storage implementation so it can + * satisfy the wolfPKCS11 custom store API when built for host-based testing. + * + * The implementation mirrors the wolfBoot unit test harness by defining the + * storage backing as an in-memory flash image. The wolfBoot source tree is + * expected to be provided at configure time via --with-wolfboot so the + * pkcs11_store.c source can be included directly. + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +WP11_API int wolfboot_store_test_init(const char* path); +WP11_API void wolfboot_store_test_reset(void); +WP11_API void wolfboot_store_test_cleanup(void); + +/* Ensure the wolfBoot store compiles in test mode and without hardware + * dependencies. */ +#ifndef UNIT_TEST + #define UNIT_TEST +#endif +#ifndef SECURE_PKCS11 + #define SECURE_PKCS11 +#endif +#ifndef MOCK_PARTITIONS + #define MOCK_PARTITIONS +#endif +#ifndef MOCK_KEYVAULT + #define MOCK_KEYVAULT +#endif +#if !defined(ARCH_x86_64) && defined(__x86_64__) + #define ARCH_x86_64 +#endif +#if !defined(ARCH_aarch64) && defined(__aarch64__) + #define ARCH_aarch64 +#endif +#if !defined(ARCH_64BIT) && (defined(ARCH_x86_64) || defined(ARCH_aarch64)) + #define ARCH_64BIT +#endif + +#include + +#ifndef __has_include + #define __has_include(x) 0 +#endif + +#if __has_include() + #include +#else + typedef uintptr_t haladdr_t; +#endif + +/* wolfBoot's pkcs11_store.c expects this symbol when compiled with + * UNIT_TEST. */ +static const uintptr_t wolfboot_vault_addr = 0xCF000000UL; + +uint8_t* vault_base = NULL; + +static uint8_t* wolfboot_store_region = NULL; +static size_t wolfboot_store_region_sz = 0; +static int wolfboot_flash_locked = 1; +static int wolfboot_store_mapped = 0; + +static const char* wolfboot_store_backing_path(void) +{ + static char path[PATH_MAX]; + static int initialized = 0; + const char* token_path; + + if (!initialized) { + token_path = getenv("WOLFPKCS11_TOKEN_PATH"); + if (token_path != NULL && token_path[0] != '\0') { + size_t len = strlen(token_path); + int need_sep = (len > 0 && token_path[len - 1] != '/') ? 1 : 0; + + if ((size_t)snprintf(path, sizeof(path), "%s%s%s", token_path, + need_sep ? "/" : "", "wolfboot_store.bin") < sizeof(path)) { + initialized = 1; + } + } + if (!initialized) { + (void)snprintf(path, sizeof(path), "%s", "/tmp/wolfboot_store.bin"); + initialized = 1; + } + } + + return path; +} + +static int wolfboot_store_mkdir_p(const char* dir) +{ + char tmp[PATH_MAX]; + size_t len; + char* p; + + if (dir == NULL) + return -1; + + len = strlen(dir); + if (len == 0 || len >= sizeof(tmp)) + return -1; + + memcpy(tmp, dir, len + 1); + for (p = tmp + 1; *p != '\0'; ++p) { + if (*p == '/') { + *p = '\0'; + if (mkdir(tmp, 0777) != 0 && errno != EEXIST) + return -1; + *p = '/'; + } + } + + if (mkdir(tmp, 0777) != 0 && errno != EEXIST) + return -1; + + return 0; +} + +static void wolfboot_store_ensure_backing_dir(const char* file_path) +{ + const char* slash; + size_t dir_len; + char dir[PATH_MAX]; + + if (file_path == NULL) + return; + + slash = strrchr(file_path, '/'); + if (slash == NULL) + return; + + dir_len = (size_t)(slash - file_path); + if (dir_len == 0 || dir_len >= sizeof(dir)) + return; + + memcpy(dir, file_path, dir_len); + dir[dir_len] = '\0'; + + (void)wolfboot_store_mkdir_p(dir); +} + +static void wolfboot_store_flush(void) +{ + const char* path; + FILE* file; + + if (vault_base == NULL || wolfboot_store_region_sz == 0) + return; + + path = wolfboot_store_backing_path(); + wolfboot_store_ensure_backing_dir(path); + file = fopen(path, "wb"); + if (file == NULL) + return; + + (void)fwrite(vault_base, 1, wolfboot_store_region_sz, file); + (void)fflush(file); + fclose(file); +} + +static void wolfboot_store_load(void) +{ + const char* path; + FILE* file; + size_t read_sz; + + if (vault_base == NULL || wolfboot_store_region_sz == 0) + return; + + path = wolfboot_store_backing_path(); + file = fopen(path, "rb"); + if (file == NULL) + return; + + read_sz = fread(vault_base, 1, wolfboot_store_region_sz, file); + if (read_sz < wolfboot_store_region_sz) { + memset(vault_base + read_sz, 0xFF, + wolfboot_store_region_sz - read_sz); + } + fclose(file); +} + +static int wolfboot_address_valid(uintptr_t address, size_t len) +{ + const uint8_t* start = (const uint8_t*)address; + const uint8_t* end; + + if (wolfboot_store_region == NULL || len == 0) + return 0; + + end = start + len; + return (start >= wolfboot_store_region) && + (end <= wolfboot_store_region + wolfboot_store_region_sz); +} + +void hal_init(void) +{ +} + +void hal_prepare_boot(void) +{ +} + +void hal_flash_unlock(void) +{ + wolfboot_flash_locked = 0; +} + +void hal_flash_lock(void) +{ + wolfboot_flash_locked = 1; +} + +int hal_flash_erase(haladdr_t address, int len) +{ + if (wolfboot_flash_locked || len <= 0) + return -1; + if (!wolfboot_address_valid((uintptr_t)address, (size_t)len)) + return -1; + + memset((void*)(uintptr_t)address, 0xFF, (size_t)len); + return 0; +} + +int hal_flash_write(haladdr_t address, const uint8_t* data, int len) +{ + if (wolfboot_flash_locked || len <= 0 || data == NULL) + return -1; + if (!wolfboot_address_valid((uintptr_t)address, (size_t)len)) + return -1; + + memcpy((void*)(uintptr_t)address, data, (size_t)len); + return 0; +} + +/* Suppress warnings from the wolfBoot sources pulled in below. */ +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +#endif + +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wsign-compare" +#ifndef __clang__ +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif +#pragma GCC diagnostic ignored "-Wcpp" +#endif + +static int wolfBoot_Store_Open_impl(int type, CK_ULONG id1, CK_ULONG id2, + int read, void** store); +static void wolfBoot_Store_Close_impl(void* store); +static int wolfBoot_Store_Read_impl(void* store, unsigned char* buffer, + int len); +static int wolfBoot_Store_Write_impl(void* store, unsigned char* buffer, + int len); +static int wolfBoot_Store_Remove_impl(int type, CK_ULONG id1, CK_ULONG id2); + +#define wolfPKCS11_Store_Open wolfBoot_Store_Open_impl +#define wolfPKCS11_Store_Close wolfBoot_Store_Close_impl +#define wolfPKCS11_Store_Read wolfBoot_Store_Read_impl +#define wolfPKCS11_Store_Write wolfBoot_Store_Write_impl +#define wolfPKCS11_Store_Remove wolfBoot_Store_Remove_impl + +/* Pull in the wolfBoot PKCS#11 storage implementation. The include path is + * provided by configure's --with-wolfboot option. */ +#include "pkcs11_store.c" /* NOLINT(bugprone-suspicious-include) */ + +#undef wolfPKCS11_Store_Open +#undef wolfPKCS11_Store_Close +#undef wolfPKCS11_Store_Read +#undef wolfPKCS11_Store_Write +#undef wolfPKCS11_Store_Remove + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +static void wolfboot_store_ensure_init(void) +{ + if (wolfboot_store_region == NULL) + (void)wolfboot_store_test_init(NULL); +} + +WP11_LOCAL int wolfPKCS11_Store_Remove(int type, CK_ULONG id1, CK_ULONG id2) +{ + wolfboot_store_ensure_init(); + return wolfBoot_Store_Remove_impl(type, id1, id2); +} + +WP11_LOCAL int wolfPKCS11_Store_Open(int type, CK_ULONG id1, CK_ULONG id2, + int read, void** store) +{ + wolfboot_store_ensure_init(); + return wolfBoot_Store_Open_impl(type, id1, id2, read, store); +} + +WP11_LOCAL void wolfPKCS11_Store_Close(void* store) +{ + wolfBoot_Store_Close_impl(store); +} + +static int wolfboot_sector_valid(struct store_handle* handle) +{ + uintptr_t addr; + uint32_t offset; + + if (handle == NULL || handle->buffer == NULL) + return 0; + + offset = ((uintptr_t)handle->buffer + handle->in_buffer_offset) % + WOLFBOOT_SECTOR_SIZE; + addr = (uintptr_t)handle->buffer + handle->in_buffer_offset - offset; + + return wolfboot_address_valid(addr, WOLFBOOT_SECTOR_SIZE); +} + +WP11_LOCAL int wolfPKCS11_Store_Read(void* store, unsigned char* buffer, + int len) +{ + struct store_handle* handle = (struct store_handle*)store; + + wolfboot_store_ensure_init(); + if (!wolfboot_sector_valid(handle)) + return NOT_AVAILABLE_E; + + return wolfBoot_Store_Read_impl(store, buffer, len); +} + +WP11_LOCAL int wolfPKCS11_Store_Write(void* store, unsigned char* buffer, + int len) +{ + struct store_handle* handle = (struct store_handle*)store; + int ret; + + wolfboot_store_ensure_init(); + if (!wolfboot_sector_valid(handle)) + return NOT_AVAILABLE_E; + + ret = wolfBoot_Store_Write_impl(store, buffer, len); + if (ret >= 0) + wolfboot_store_flush(); + return ret; +} + +static size_t wolfboot_store_calc_size(void) +{ + size_t objects = (size_t)KEYVAULT_MAX_ITEMS * (size_t)KEYVAULT_OBJ_SIZE; + size_t overhead = (size_t)WOLFBOOT_SECTOR_SIZE * 2; + return objects + overhead; +} + +WP11_API int wolfboot_store_test_init(const char* path) +{ + (void)path; + + if (vault_base != NULL) + return 0; + + wolfboot_store_region_sz = wolfboot_store_calc_size(); + wolfboot_store_region = (uint8_t*)mmap((void*)wolfboot_vault_addr, + wolfboot_store_region_sz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + if (wolfboot_store_region == MAP_FAILED) { + wolfboot_store_region = (uint8_t*)malloc(wolfboot_store_region_sz); + if (wolfboot_store_region == NULL) + return -ENOMEM; + wolfboot_store_mapped = 0; + } + else { + wolfboot_store_mapped = 1; + } + + vault_base = wolfboot_store_region; + memset(vault_base, 0xFF, wolfboot_store_region_sz); + wolfboot_store_load(); + wolfboot_flash_locked = 1; + + return 0; +} + +WP11_API void wolfboot_store_test_reset(void) +{ + if (vault_base != NULL) { + memset(vault_base, 0xFF, wolfboot_store_region_sz); + wolfboot_store_flush(); + } + wolfboot_flash_locked = 1; +} + +WP11_API void wolfboot_store_test_cleanup(void) +{ + if (wolfboot_store_region != NULL) { + wolfboot_store_flush(); + if (wolfboot_store_mapped) + munmap(wolfboot_store_region, wolfboot_store_region_sz); + else + free(wolfboot_store_region); + wolfboot_store_region = NULL; + } + vault_base = NULL; + wolfboot_store_region_sz = 0; + wolfboot_flash_locked = 1; +} + +static void __attribute__((constructor)) wolfboot_store_ctor(void) +{ + if (wolfboot_store_region == NULL) + (void)wolfboot_store_test_init(NULL); +} + +static void __attribute__((destructor)) wolfboot_store_dtor(void) +{ + if (wolfboot_store_region != NULL) + wolfboot_store_test_cleanup(); +} diff --git a/src/wolfpkcs11.c b/src/wolfpkcs11.c index d0134c9e..29f9c625 100644 --- a/src/wolfpkcs11.c +++ b/src/wolfpkcs11.c @@ -124,7 +124,8 @@ CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) return ret; } -#if (defined(WOLFPKCS11_NSS) && !defined(WOLFPKCS11_NO_STORE)) +#if (defined(WOLFPKCS11_NSS) && !defined(WOLFPKCS11_NO_STORE) && \ + !defined(WOLFPKCS11_CUSTOM_STORE)) /* * Parse a string of NSS configuration parameters. For now only the * configdir parameter is supported. @@ -211,7 +212,8 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs) if (args != NULL) { WOLFPKCS11_MSG("Warning: C_Initialize called with arguments, but most " "are ignored."); -#if (defined(WOLFPKCS11_NSS) && !defined(WOLFPKCS11_NO_STORE)) +#if (defined(WOLFPKCS11_NSS) && !defined(WOLFPKCS11_NO_STORE) && \ + !defined(WOLFPKCS11_CUSTOM_STORE)) if (args->LibraryParameters != NULL) { char* configdir = NULL; size_t configdirLen = 0; diff --git a/tests/debug_test.c b/tests/debug_test.c index 6c22dfa4..c1237155 100644 --- a/tests/debug_test.c +++ b/tests/debug_test.c @@ -40,6 +40,8 @@ #endif #include +#include "storage_helpers.h" + #ifdef DEBUG_WOLFPKCS11 #ifndef HAVE_PKCS11_STATIC #include @@ -163,6 +165,13 @@ int main(void) CK_RV rv; int debug_found; const char* library = "./src/.libs/libwolfpkcs11.so"; + int init_ret; + + init_ret = unit_init_storage(); + if (init_ret != 0) { + fprintf(stderr, "wolfBoot storage init failed: %d\n", init_ret); + return 1; + } #ifndef WOLFPKCS11_NO_ENV if (!XGETENV("WOLFPKCS11_TOKEN_PATH")) { diff --git a/tests/include.am b/tests/include.am index ad3ad4b9..244060d5 100644 --- a/tests/include.am +++ b/tests/include.am @@ -4,50 +4,39 @@ check_PROGRAMS += tests/pkcs11test noinst_PROGRAMS += tests/pkcs11test tests_pkcs11test_SOURCES = tests/pkcs11test.c -tests_pkcs11test_LDADD = +tests_pkcs11test_LDADD = src/libwolfpkcs11.la check_PROGRAMS += tests/pkcs11mtt noinst_PROGRAMS += tests/pkcs11mtt tests_pkcs11mtt_SOURCES = tests/pkcs11mtt.c -tests_pkcs11mtt_LDADD = +tests_pkcs11mtt_LDADD = src/libwolfpkcs11.la check_PROGRAMS += tests/pkcs11str noinst_PROGRAMS += tests/pkcs11str tests_pkcs11str_SOURCES = tests/pkcs11str.c -tests_pkcs11str_LDADD = +tests_pkcs11str_LDADD = src/libwolfpkcs11.la check_PROGRAMS += tests/token_path_test noinst_PROGRAMS += tests/token_path_test tests_token_path_test_SOURCES = tests/token_path_test.c -tests_token_path_test_LDADD = +tests_token_path_test_LDADD = src/libwolfpkcs11.la check_PROGRAMS += tests/rsa_session_persistence_test noinst_PROGRAMS += tests/rsa_session_persistence_test tests_rsa_session_persistence_test_SOURCES = tests/rsa_session_persistence_test.c -tests_rsa_session_persistence_test_LDADD = +tests_rsa_session_persistence_test_LDADD = src/libwolfpkcs11.la check_PROGRAMS += tests/debug_test noinst_PROGRAMS += tests/debug_test tests_debug_test_SOURCES = tests/debug_test.c -tests_debug_test_LDADD = +tests_debug_test_LDADD = src/libwolfpkcs11.la check_PROGRAMS += tests/object_id_uniqueness_test noinst_PROGRAMS += tests/object_id_uniqueness_test tests_object_id_uniqueness_test_SOURCES = tests/object_id_uniqueness_test.c -tests_object_id_uniqueness_test_LDADD = - -if BUILD_STATIC -tests_pkcs11test_LDADD += src/libwolfpkcs11.la -tests_pkcs11mtt_LDADD += src/libwolfpkcs11.la -tests_pkcs11str_LDADD += src/libwolfpkcs11.la -tests_token_path_test_LDADD += src/libwolfpkcs11.la -tests_rsa_session_persistence_test_LDADD += src/libwolfpkcs11.la -tests_debug_test_LDADD += src/libwolfpkcs11.la -tests_object_id_uniqueness_test_LDADD += src/libwolfpkcs11.la -else -tests_object_id_uniqueness_test_LDADD += src/libwolfpkcs11.la -endif +tests_object_id_uniqueness_test_LDADD = src/libwolfpkcs11.la EXTRA_DIST += tests/unit.h \ tests/testdata.h \ + tests/storage_helpers.h \ tests/README.md diff --git a/tests/object_id_uniqueness_test.c b/tests/object_id_uniqueness_test.c index 3321cb16..3a5e1ddf 100644 --- a/tests/object_id_uniqueness_test.c +++ b/tests/object_id_uniqueness_test.c @@ -37,6 +37,8 @@ #endif #include +#include "storage_helpers.h" + #ifndef HAVE_PKCS11_STATIC #include #endif @@ -488,6 +490,13 @@ int main(int argc, char* argv[]) { #if (!defined(WOLFPKCS11_NO_STORE) && !defined(NO_RSA) && !defined(NO_HMAC)) CK_RV ret; + int init_ret; + + init_ret = unit_init_storage(); + if (init_ret != 0) { + fprintf(stderr, "wolfBoot storage init failed: %d\n", init_ret); + return 1; + } #ifndef WOLFPKCS11_NO_ENV if (!XGETENV("WOLFPKCS11_TOKEN_PATH")) { diff --git a/tests/pkcs11mtt.c b/tests/pkcs11mtt.c index c58cea02..9ba7362a 100644 --- a/tests/pkcs11mtt.c +++ b/tests/pkcs11mtt.c @@ -45,6 +45,7 @@ #define TEST_MULTITHREADED #include "unit.h" +#include "storage_helpers.h" #include "testdata.h" #define PKCS11MTT_CASE(func) \ @@ -6785,6 +6786,12 @@ int pkcs11test_mtt(int argc, char* argv[]) int closeDl = 1; int i; + ret = unit_init_storage(); + if (ret != 0) { + fprintf(stderr, "wolfBoot storage init failed: %d\n", ret); + return 1; + } + #ifndef WOLFPKCS11_NO_ENV XSETENV("WOLFPKCS11_TOKEN_PATH", "./store/pkcs11mtt", 1); #endif diff --git a/tests/pkcs11str.c b/tests/pkcs11str.c index e08a17d6..12ec0545 100644 --- a/tests/pkcs11str.c +++ b/tests/pkcs11str.c @@ -34,6 +34,8 @@ #endif #include +#include "storage_helpers.h" + #ifndef HAVE_PKCS11_STATIC #include #endif @@ -1071,6 +1073,12 @@ int pkcs11test_str(int argc, char* argv[]) int setPin = 1; int closeDl = 1; + ret = unit_init_storage(); + if (ret != 0) { + fprintf(stderr, "wolfBoot storage init failed: %d\n", ret); + return 1; + } + #ifndef WOLFPKCS11_NO_ENV if (!XGETENV("WOLFPKCS11_TOKEN_PATH")) { XSETENV("WOLFPKCS11_TOKEN_PATH", "./store/str", 1); @@ -1145,4 +1153,3 @@ int pkcs11test_str(int argc, char* argv[]) ret = 1; return ret; } - diff --git a/tests/pkcs11test.c b/tests/pkcs11test.c index 547a2d75..88d050c6 100644 --- a/tests/pkcs11test.c +++ b/tests/pkcs11test.c @@ -39,6 +39,7 @@ #endif #include "unit.h" +#include "storage_helpers.h" #include "testdata.h" #include @@ -16172,6 +16173,12 @@ int pkcs11test_test(int argc, char* argv[]) int closeDl = 1; int i; + ret = unit_init_storage(); + if (ret != 0) { + fprintf(stderr, "wolfBoot storage init failed: %d\n", ret); + return 1; + } + #ifndef WOLFPKCS11_NO_ENV XSETENV("WOLFPKCS11_TOKEN_PATH", "./store/pkcs11test", 1); #endif diff --git a/tests/rsa_session_persistence_test.c b/tests/rsa_session_persistence_test.c index 0ffd5683..8af32cf5 100644 --- a/tests/rsa_session_persistence_test.c +++ b/tests/rsa_session_persistence_test.c @@ -39,6 +39,8 @@ #endif #include +#include "storage_helpers.h" + #ifndef HAVE_PKCS11_STATIC #include #endif @@ -640,6 +642,13 @@ int main(int argc, char* argv[]) { #if !defined(NO_RSA) && !defined(WOLFPKCS11_NO_STORE) CK_RV ret; + int init_ret; + + init_ret = unit_init_storage(); + if (init_ret != 0) { + fprintf(stderr, "wolfBoot storage init failed: %d\n", init_ret); + return 1; + } #ifndef WOLFPKCS11_NO_ENV if (!XGETENV("WOLFPKCS11_TOKEN_PATH")) { diff --git a/tests/storage_helpers.h b/tests/storage_helpers.h new file mode 100644 index 00000000..4a194e09 --- /dev/null +++ b/tests/storage_helpers.h @@ -0,0 +1,85 @@ +/* storage_helpers.h + * + * Copyright (C) 2006-2025 wolfSSL Inc. + * + * This file is part of wolfPKCS11. + * + * wolfPKCS11 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfPKCS11 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Lightweight helpers for tests that need to initialise wolfBoot-backed + * storage without pulling in the full unit test harness. + */ + +#ifndef TESTS_STORAGE_HELPERS_H +#define TESTS_STORAGE_HELPERS_H + +#include + +#if defined(__GNUC__) + #define TESTS_UNUSED __attribute__((unused)) + #define TESTS_WEAK __attribute__((weak)) +#else + #define TESTS_UNUSED + #define TESTS_WEAK +#endif + +#ifdef WOLFPKCS11_WOLFBOOT_STORE + #include + + WP11_API int wolfboot_store_test_init(const char* path) TESTS_WEAK; + WP11_API void wolfboot_store_test_cleanup(void) TESTS_WEAK; + WP11_API void wolfboot_store_test_reset(void) TESTS_WEAK; + + static inline TESTS_UNUSED int unit_init_storage(void) + { + static int cleanup_registered = 0; + int ret = 0; + + if (wolfboot_store_test_init == NULL || wolfboot_store_test_reset == NULL) + return 0; + + ret = wolfboot_store_test_init(NULL); + + if (ret != 0) + return ret; + + wolfboot_store_test_reset(); + if (!cleanup_registered && wolfboot_store_test_cleanup != NULL) { + atexit(wolfboot_store_test_cleanup); + cleanup_registered = 1; + } + + return 0; + } + + static inline TESTS_UNUSED void unit_reset_storage(void) + { + if (wolfboot_store_test_reset != NULL) + wolfboot_store_test_reset(); + } +#else + static inline TESTS_UNUSED int unit_init_storage(void) + { + return 0; + } + + static inline TESTS_UNUSED void unit_reset_storage(void) + { + (void)0; + } +#endif + +#endif /* TESTS_STORAGE_HELPERS_H */ diff --git a/tests/token_path_test.c b/tests/token_path_test.c index ac82fee8..1a80a8c4 100644 --- a/tests/token_path_test.c +++ b/tests/token_path_test.c @@ -34,6 +34,8 @@ #endif #include +#include "storage_helpers.h" + #ifndef HAVE_PKCS11_STATIC #include #endif @@ -390,12 +392,20 @@ int main(int argc, char* argv[]) const char* libName = WOLFPKCS11_DLL_FILENAME; CK_RV ret; int result = 0; + int init_ret; - #if defined(WOLFPKCS11_TPM_STORE) || defined(WOLFPKCS11_NO_STORE) - printf("Skipped for TPM storage\n"); + #if defined(WOLFPKCS11_TPM_STORE) || defined(WOLFPKCS11_NO_STORE) || \ + defined(WOLFPKCS11_CUSTOM_STORE) + printf("Skipped due to file storage not in use\n"); return 77; #endif + init_ret = unit_init_storage(); + if (init_ret != 0) { + fprintf(stderr, "wolfBoot storage init failed: %d\n", init_ret); + return 1; + } + /* Parse command line arguments */ argc--; argv++; diff --git a/tests/unit.h b/tests/unit.h index 3a2ec870..6853be20 100644 --- a/tests/unit.h +++ b/tests/unit.h @@ -430,4 +430,3 @@ static int string_matches(const char* arg, const char* str) verbose = 1; #endif -