From e55c0f23e980003e473be94ebadae3126131661d Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Fri, 14 Aug 2026 09:05:16 -0400 Subject: [PATCH] Implement wolfcrypt + wolfHAL example --- .github/actions/wolfhal-build/action.yml | 45 ++++ .github/examples-manifest.yml | 6 + .github/scripts/manifest.py | 1 + .github/workflows/nightly.yml | 6 + .github/workflows/wolfhal.yml | 81 ++++++++ .gitmodules | 3 + wolfHAL/.gitignore | 1 + wolfHAL/Makefile | 88 ++++++++ wolfHAL/README.md | 44 ++++ wolfHAL/boards/stm32wb55xx_nucleo/board.c | 191 +++++++++++++++++ wolfHAL/boards/stm32wb55xx_nucleo/board.h | 163 +++++++++++++++ wolfHAL/boards/stm32wb55xx_nucleo/board.mk | 57 ++++++ wolfHAL/boards/stm32wb55xx_nucleo/ivt.c | 216 ++++++++++++++++++++ wolfHAL/boards/stm32wb55xx_nucleo/linker.ld | 173 ++++++++++++++++ wolfHAL/main.c | 69 +++++++ wolfHAL/syscalls.c | 112 ++++++++++ wolfHAL/user_settings.h | 84 ++++++++ wolfHAL/wolfHAL | 1 + 18 files changed, 1341 insertions(+) create mode 100644 .github/actions/wolfhal-build/action.yml create mode 100644 .github/workflows/wolfhal.yml create mode 100644 wolfHAL/.gitignore create mode 100644 wolfHAL/Makefile create mode 100644 wolfHAL/README.md create mode 100644 wolfHAL/boards/stm32wb55xx_nucleo/board.c create mode 100644 wolfHAL/boards/stm32wb55xx_nucleo/board.h create mode 100644 wolfHAL/boards/stm32wb55xx_nucleo/board.mk create mode 100644 wolfHAL/boards/stm32wb55xx_nucleo/ivt.c create mode 100644 wolfHAL/boards/stm32wb55xx_nucleo/linker.ld create mode 100644 wolfHAL/main.c create mode 100644 wolfHAL/syscalls.c create mode 100644 wolfHAL/user_settings.h create mode 160000 wolfHAL/wolfHAL diff --git a/.github/actions/wolfhal-build/action.yml b/.github/actions/wolfhal-build/action.yml new file mode 100644 index 000000000..4c02c610f --- /dev/null +++ b/.github/actions/wolfhal-build/action.yml @@ -0,0 +1,45 @@ +name: 'Build a wolfHAL board' +description: 'Cross-build the wolfHAL example for one board and assert the port is linked' + +inputs: + board: + description: 'directory name under wolfHAL/boards' + required: true + wolfssl-root: + description: 'path to the wolfSSL source tree to compile wolfCrypt from' + required: false + default: '/tmp/wolfssl' + +runs: + using: composite + steps: + - shell: bash + run: | + set -euo pipefail + board='${{ inputs.board }}' + [ -f "wolfHAL/boards/$board/board.mk" ] \ + || { echo "no such board: wolfHAL/boards/$board/board.mk"; exit 1; } + + make -C wolfHAL BOARD="$board" WOLFSSL_ROOT='${{ inputs.wolfssl-root }}' -j"$(nproc)" + + # The board declares its own toolchain, so ask make rather than assume + # a prefix here. + cross=$(make -s -C wolfHAL BOARD="$board" print-CROSS_COMPILE) + elf=wolfHAL/wolfcrypt_test.elf + arch=$(file -b "$elf") + echo "$arch" + case "$arch" in + *x86-64*) echo "FAIL: host binary, the cross toolchain was not used"; exit 1 ;; + esac + + # A build with the port configured away would still link and still be + # the right arch, so assert the callback is registered and reaches a + # driver. Which modes are offloaded is the board's choice, so accept any. + "${cross}nm" "$elf" | grep -q ' T wc_wolfHAL_RegisterDevice' \ + || { echo "FAIL: wolfHAL port not linked"; exit 1; } + modes=$("${cross}objdump" -d "$elf" --disassemble=wc_wolfHAL_CryptoDevCb \ + | grep -oE 'whal_Aes(Ecb|Cbc|Gcm|Ccm)_Oneshot' | sort -u | tr '\n' ' ') + [ -n "$modes" ] || { echo "FAIL: no AES mode dispatched to wolfHAL"; exit 1; } + echo "$board offloads: $modes" + + make -C wolfHAL BOARD="$board" clean >/dev/null diff --git a/.github/examples-manifest.yml b/.github/examples-manifest.yml index 8fdef6150..fafbc2e52 100644 --- a/.github/examples-manifest.yml +++ b/.github/examples-manifest.yml @@ -1650,3 +1650,9 @@ examples: path: utasker mode: skip reason: "uTasker project task files; no standalone build" + + - id: wolfhal + path: wolfHAL + tier: cross + profile: all + mode: build-only diff --git a/.github/scripts/manifest.py b/.github/scripts/manifest.py index 583980392..01e08c257 100644 --- a/.github/scripts/manifest.py +++ b/.github/scripts/manifest.py @@ -136,6 +136,7 @@ def job_built_paths(): ("java", "java/https-url"), ("rt1060", "RT1060"), ("csharp", "CSharp/wolfSSL-TLS-pq-Client"), ("psa", "psa"), + ("wolfhal", "wolfHAL"), ("bsdkm", "kernel/bsdkm"), ("cmake", "cmake")): if job in jobs_seen: diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 97e567944..c47d4577e 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -151,6 +151,12 @@ jobs: with: caller_run_id: ${{ github.run_id }} + wolfhal: + needs: [refs] + uses: ./.github/workflows/wolfhal.yml + with: + caller_run_id: ${{ github.run_id }} + ebpf: needs: [refs] uses: ./.github/workflows/ebpf.yml diff --git a/.github/workflows/wolfhal.yml b/.github/workflows/wolfhal.yml new file mode 100644 index 000000000..65e2af25b --- /dev/null +++ b/.github/workflows/wolfhal.yml @@ -0,0 +1,81 @@ +name: wolfHAL + +on: + push: + branches: [master] + paths: + - 'wolfHAL/**' + - '.github/workflows/wolfhal.yml' + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + paths: + - 'wolfHAL/**' + - '.github/workflows/wolfhal.yml' + # No cron: nightly.yml calls this, so the nightly stays one run and one triage writer + workflow_call: + inputs: + caller_run_id: + description: 'run id of the calling workflow; keeps a called run in its own concurrency group' + type: string + default: '' + workflow_dispatch: + +# github.workflow is the CALLER's name in a called workflow, so hardcode ours +concurrency: + group: ${{ inputs.caller_run_id && format('wolfhal-call-{0}', inputs.caller_run_id) || format('wolfhal-{0}', github.ref) }} + cancel-in-progress: ${{ !inputs.caller_run_id }} + +permissions: + contents: read + +jobs: + resolve: + uses: ./.github/workflows/_resolve-wolfssl.yml + with: + # master only: the wolfHAL crypto-callback port (wolfcrypt/src/port/wolfHAL) + # is not in any released tag + refs: master + + wolfhal: + needs: resolve + name: Build / wolfHAL boards, wolfSSL ${{ matrix.wolfssl_ref }} + if: github.event_name != 'pull_request' || github.event.pull_request.draft == false + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + wolfssl_ref: ${{ fromJson(needs.resolve.outputs.refs_json) }} + timeout-minutes: 30 + steps: + # The wolfHAL drivers come from the pinned submodule at wolfHAL/wolfHAL. + - uses: actions/checkout@v5 + with: + submodules: true + + - uses: ./.github/actions/apt-update + + # Every toolchain any board under wolfHAL/boards needs, installed once for + # the whole run. A board added with a different target adds its packages + # here; the per-board prefix comes from that board's CROSS_COMPILE. + - name: Install toolchains + run: | + set -euo pipefail + sudo apt-get install -y --no-install-recommends \ + gcc-arm-none-eabi binutils-arm-none-eabi libnewlib-arm-none-eabi + + - name: Fetch wolfSSL + run: | + set -euo pipefail + # --branch, or every leg silently clones the default branch and the + # stable leg builds master + bash "$GITHUB_WORKSPACE/.github/scripts/git-clone-retry.sh" -q --depth 1 --branch '${{ matrix.wolfssl_ref }}' \ + https://github.com/wolfSSL/wolfssl /tmp/wolfssl + git -C /tmp/wolfssl log -1 --format='wolfssl at ${{ matrix.wolfssl_ref }}: %h %s' + + # One step per board. A new board is not tested until it is listed + # here; `if: !cancelled()` keeps a broken board from hiding the rest. + - name: Build stm32wb55xx_nucleo + if: '!cancelled()' + uses: ./.github/actions/wolfhal-build + with: + board: stm32wb55xx_nucleo diff --git a/.gitmodules b/.gitmodules index e1baf2e6d..ff066e363 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "android/wolfcryptjni-ndk-gradle/wolfcrypt-jni"] path = android/wolfcryptjni-ndk-gradle/wolfcrypt-jni url = https://github.com/wolfssl/wolfcrypt-jni +[submodule "wolfHAL/wolfHAL"] + path = wolfHAL/wolfHAL + url = https://github.com/wolfSSL/wolfHAL.git diff --git a/wolfHAL/.gitignore b/wolfHAL/.gitignore new file mode 100644 index 000000000..8d9b0694d --- /dev/null +++ b/wolfHAL/.gitignore @@ -0,0 +1 @@ +wolfcrypt_test.bin diff --git a/wolfHAL/Makefile b/wolfHAL/Makefile new file mode 100644 index 000000000..466a309a6 --- /dev/null +++ b/wolfHAL/Makefile @@ -0,0 +1,88 @@ +# Makefile for the wolfCrypt + wolfHAL example +# +# Usage: +# make +# make BOARD=stm32wb55xx_nucleo +# make flash + +BOARD ?= stm32wb55xx_nucleo + +WOLFSSL_ROOT ?= $(abspath ../../wolfssl) +WHAL_DIR ?= $(abspath wolfHAL) +GCC_PATH ?= + +TARGET = wolfcrypt_test +IMAGE ?= $(TARGET).bin + +# Toolchain, the direct-API-mapping selection, the wolfHAL drivers this board +# needs (BOARD_SOURCE) and the linker script. +include boards/$(BOARD)/board.mk + +CFLAGS += -I. -I$(WHAL_DIR) -I$(WOLFSSL_ROOT) -DWOLFSSL_USER_SETTINGS + +# Application +SRC = main.c +SRC += syscalls.c + +# Board and wolfHAL drivers +SRC += $(BOARD_SOURCE) + +# wolfCrypt core +SRC += $(WOLFSSL_ROOT)/wolfcrypt/src/wc_port.c +SRC += $(WOLFSSL_ROOT)/wolfcrypt/src/memory.c +SRC += $(WOLFSSL_ROOT)/wolfcrypt/src/aes.c +SRC += $(WOLFSSL_ROOT)/wolfcrypt/src/cryptocb.c +SRC += $(WOLFSSL_ROOT)/wolfcrypt/src/sha256.c +SRC += $(WOLFSSL_ROOT)/wolfcrypt/src/hash.c +SRC += $(WOLFSSL_ROOT)/wolfcrypt/src/random.c +SRC += $(WOLFSSL_ROOT)/wolfcrypt/src/logging.c +SRC += $(WOLFSSL_ROOT)/wolfcrypt/src/error.c +SRC += $(WOLFSSL_ROOT)/wolfcrypt/src/wc_encrypt.c +SRC += $(WOLFSSL_ROOT)/wolfcrypt/src/sp_int.c +SRC += $(WOLFSSL_ROOT)/wolfcrypt/test/test.c +SRC += $(WOLFSSL_ROOT)/wolfcrypt/benchmark/benchmark.c + +# wolfSSL's wolfHAL port +SRC += $(WOLFSSL_ROOT)/wolfcrypt/src/port/wolfHAL/wolfhal.c + +# Objects go under build/ with their path flattened into the name. Compiling in +# place would drop ARM objects into the wolfSSL and wolfHAL checkouts, where +# they collide with those trees' own builds. +OBJDIR = build +objname = $(OBJDIR)/$(subst /,_,$(patsubst /%,%,$(basename $(1)))).o +OBJ = $(foreach s,$(SRC),$(call objname,$(s))) + +all: $(TARGET).bin + $(SIZE) $(TARGET).elf + +$(TARGET).elf: $(OBJ) + $(GCC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +$(TARGET).bin: $(TARGET).elf + $(OBJCOPY) -O binary $< $@ + +$(OBJDIR): + mkdir -p $@ + +define compile_rule +$(call objname,$(1)): $(1) | $(OBJDIR) + $$(GCC) $$(CFLAGS) -c -o $$@ $$< +endef +$(foreach s,$(SRC),$(eval $(call compile_rule,$(s)))) + +# Flash via openocd (ST-LINK on the Nucleo). +flash: $(TARGET).bin + openocd -f interface/stlink.cfg -f target/stm32wbx.cfg \ + -c "program $(TARGET).bin 0x08000000 verify reset exit" + +clean: + rm -rf $(OBJDIR) $(TARGET).elf $(TARGET).bin + +# Query a variable, e.g. `make -s BOARD=x print-CROSS_COMPILE`. Lets CI ask the +# board for its toolchain rather than keeping a second copy of that mapping. +print-%: + @echo "$($*)" + +.PHONY: all flash clean + +-include $(OBJ:.o=.d) diff --git a/wolfHAL/README.md b/wolfHAL/README.md new file mode 100644 index 000000000..33d998504 --- /dev/null +++ b/wolfHAL/README.md @@ -0,0 +1,44 @@ +# wolfCrypt + wolfHAL Example + +Runs the wolfCrypt test suite and benchmark on bare metal, with AES and the RNG +served by the board's hardware. + +[wolfHAL](https://github.com/wolfSSL/wolfHAL) is a portable hardware abstraction +layer with no OS, toolchain or platform dependencies. It provides a common API +for accessing hardware functionality, with the platform-specific configuration +kept in board files. + +wolfSSL reaches it through `wolfcrypt/src/port/wolfHAL`, which registers a +crypto callback at `wolfCrypt_Init()`. wolfCrypt then routes AES to the +accelerator and falls back to software for anything the board does not offload. + +## Supported boards + +| Board | Offloaded | +| --- | --- | +| `stm32wb55xx_nucleo` | AES-ECB/CBC/GCM/CCM on AES1, RNG | + +Each lives in `boards//` and owns its clock, pin and device setup, its +toolchain, and its linker script. + +## Building + +Needs `arm-none-eabi-gcc` and a wolfSSL checkout beside this repository: + +```sh +sudo apt install gcc-arm-none-eabi binutils-arm-none-eabi libnewlib-arm-none-eabi +git submodule update --init wolfHAL # the wolfHAL drivers +make # or: make BOARD= +make flash +``` + +`WOLFSSL_ROOT` defaults to `../../wolfssl` and `WHAL_DIR` to the submodule; +override either on the command line. wolfCrypt is compiled from source rather +than linked, so no installed `libwolfssl` is involved. + +## Adding a board + +Copy `boards/stm32wb55xx_nucleo/` and adjust `board.h` (device initializers plus +the `WC_WOLFHAL_*_DEV` macros naming what to offload), `board.c` (bring-up), +`board.mk` (toolchain, driver list), `linker.ld` and `ivt.c`. Then add a build +step for it in `.github/workflows/wolfhal.yml`. diff --git a/wolfHAL/boards/stm32wb55xx_nucleo/board.c b/wolfHAL/boards/stm32wb55xx_nucleo/board.c new file mode 100644 index 000000000..23a0e6b50 --- /dev/null +++ b/wolfHAL/boards/stm32wb55xx_nucleo/board.c @@ -0,0 +1,191 @@ +/* board.c + * + * Board bring-up for the STM32WB55 Nucleo — wolfCrypt + wolfHAL example. + * + * Board_Init() must run before wolfCrypt_Init(): wolfCrypt_Init() registers the + * wolfHAL crypto callback, and the callback expects the peripherals to be live. + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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. + * + * wolfSSL 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 + */ + +#include "board.h" + +volatile uint32_t g_tick = 0; + +void SysTick_Handler(void) +{ + g_tick++; +} + +uint32_t Board_GetTick(void) +{ + return g_tick; +} + +/* Bounds the AES and RNG status-flag polls: a wedged peripheral surfaces as + * WC_TIMEOUT_E instead of hanging the test run. */ +whal_Timeout g_whalTimeout = { + .timeoutTicks = 1000, /* 1 s at the 1 ms SysTick */ + .GetTick = Board_GetTick, +}; + +whal_Uart g_whalUart = { + .base = WHAL_STM32WB55_UART1_BASE, + /* .driver: direct API mapping */ + + .cfg = &(whal_Stm32wb_Uart_Cfg) { + .brr = WHAL_STM32WB_UART_BRR(64000000, 115200), + .timeout = &g_whalTimeout, + }, +}; + +static const whal_Stm32wb_Rcc_PeriphClk g_periphClks[] = { + {WHAL_STM32WB55_GPIOB_GATE}, + {WHAL_STM32WB55_UART1_GATE}, + {WHAL_STM32WB55_RNG_GATE}, + {WHAL_STM32WB55_AES1_GATE}, +}; +#define PERIPH_CLK_COUNT (sizeof(g_periphClks) / sizeof(g_periphClks[0])) + +whal_Error Board_Init(void) +{ + whal_Error err; + size_t i; + + /* Wait states first — the core would outrun flash once SYSCLK passes + * ~16 MHz, and the fetch faults before anything else can report it. */ + err = whal_Stm32wb_Flash_Ext_SetLatency(BOARD_FLASH_DEV, + WHAL_STM32WB_FLASH_LATENCY_3); + if (err) + return err; + + /* MSI 4 MHz -> VCO 128 MHz -> PLLR /2 = 64 MHz SYSCLK. */ + err = whal_Stm32wb_Rcc_EnableMsi(WHAL_STM32WB_RCC_MSIRANGE_4MHz); + if (err) + return err; + + err = whal_Stm32wb_Rcc_EnablePll(&(whal_Stm32wb_Rcc_PllCfg){ + .clkSrc = WHAL_STM32WB_RCC_PLLCLK_SRC_MSI, + .n = 32, .m = 0, .r = 1, .q = 0, .p = 0, + }); + if (err) + return err; + + /* The RNG is clocked from HSI48, not SYSCLK. */ + err = whal_Stm32wb_Rcc_EnableOsc( + &(whal_Stm32wb_Rcc_OscCfg){WHAL_STM32WB_RCC_HSI48_CFG}); + if (err) + return err; + + err = whal_Stm32wb_Rcc_SetSysClock(WHAL_STM32WB_RCC_SYSCLK_SRC_PLL); + if (err) + return err; + + for (i = 0; i < PERIPH_CLK_COUNT; i++) { + err = whal_Stm32wb_Rcc_EnablePeriphClk(&g_periphClks[i]); + if (err) + return err; + } + + err = whal_Gpio_Init(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Uart_Init(&g_whalUart); + if (err) + return err; + + /* Before the peripherals that poll against it. */ + err = whal_Timer_Init(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Timer_Start(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Rng_Init(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Crypto_Init(WHAL_INTERNAL_DEV); + if (err) + return err; + + return WHAL_SUCCESS; +} + +whal_Error Board_Deinit(void) +{ + whal_Error err; + size_t i; + + err = whal_Crypto_Deinit(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Rng_Deinit(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Timer_Stop(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Timer_Deinit(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Uart_Deinit(&g_whalUart); + if (err) + return err; + + err = whal_Gpio_Deinit(WHAL_INTERNAL_DEV); + if (err) + return err; + + /* Unwind the clock tree in reverse: gates, then SYSCLK back to MSI, then + * the sources. MSI stays on as the fallback. */ + for (i = PERIPH_CLK_COUNT; i-- > 0; ) { + err = whal_Stm32wb_Rcc_DisablePeriphClk(&g_periphClks[i]); + if (err) + return err; + } + + err = whal_Stm32wb_Rcc_SetSysClock(WHAL_STM32WB_RCC_SYSCLK_SRC_MSI); + if (err) + return err; + + err = whal_Stm32wb_Rcc_DisablePll(); + if (err) + return err; + + err = whal_Stm32wb_Rcc_DisableOsc( + &(whal_Stm32wb_Rcc_OscCfg){WHAL_STM32WB_RCC_HSI48_CFG}); + if (err) + return err; + + /* Latency back down only after the clock is slow again. */ + err = whal_Stm32wb_Flash_Ext_SetLatency(BOARD_FLASH_DEV, + WHAL_STM32WB_FLASH_LATENCY_0); + if (err) + return err; + + return WHAL_SUCCESS; +} diff --git a/wolfHAL/boards/stm32wb55xx_nucleo/board.h b/wolfHAL/boards/stm32wb55xx_nucleo/board.h new file mode 100644 index 000000000..7c37a2d17 --- /dev/null +++ b/wolfHAL/boards/stm32wb55xx_nucleo/board.h @@ -0,0 +1,163 @@ +/* board.h + * + * Board configuration for the STM32WB55 Nucleo — wolfCrypt + wolfHAL example. + * + * Scoped to what the wolfCrypt test needs: a 64 MHz clock, UART1 for output, + * SysTick for timeouts, and the AES1 and RNG peripherals. wolfHAL's own + * boards/stm32wb55xx_nucleo brings up SPI, I2C, PKA and more. + * + * Two sets of macros matter here: + * + * WHAL_CFG_*_DEV wolfHAL's driver TUs #include "board.h" and expand these + * to define their device singletons. + * WC_WOLFHAL_*_DEV wolfSSL's wolfhal.c reads these to pick the device it + * dispatches each algorithm on. A mode left out here falls + * back to wolfCrypt's software implementation. + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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. + * + * wolfSSL 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 + */ + +#ifndef BOARD_H +#define BOARD_H + +#include +#include + +#include +#include +#include + +extern whal_Uart g_whalUart; +extern whal_Timeout g_whalTimeout; +extern volatile uint32_t g_tick; + +enum { + LED_PIN, + UART_TX_PIN, + UART_RX_PIN, + PIN_COUNT, +}; + +#define BOARD_FLASH_DEV ((whal_Flash *)&whal_Stm32wb_Flash_Dev) + +/* GPIO — LED on PB5, UART1 TX/RX on PB6/PB7. */ +#define WHAL_CFG_STM32WB_GPIO_DEV { \ + .base = WHAL_STM32WB55_GPIO_BASE, \ + /* .driver: direct API mapping */ \ + .cfg = (void *)&(const whal_Stm32wb_Gpio_Cfg){ \ + .pinCfg = (const whal_Stm32wb_Gpio_PinCfg[PIN_COUNT]){ \ + [LED_PIN] = WHAL_STM32WB_GPIO_PIN( \ + WHAL_STM32WB_GPIO_PORT_B, 5, WHAL_STM32WB_GPIO_MODE_OUT, \ + WHAL_STM32WB_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB_GPIO_SPEED_LOW, \ + WHAL_STM32WB_GPIO_PULL_UP, 0), \ + [UART_TX_PIN] = WHAL_STM32WB_GPIO_PIN( \ + WHAL_STM32WB_GPIO_PORT_B, 6, WHAL_STM32WB_GPIO_MODE_ALTFN, \ + WHAL_STM32WB_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB_GPIO_SPEED_FAST, \ + WHAL_STM32WB_GPIO_PULL_UP, 7), \ + [UART_RX_PIN] = WHAL_STM32WB_GPIO_PIN( \ + WHAL_STM32WB_GPIO_PORT_B, 7, WHAL_STM32WB_GPIO_MODE_ALTFN, \ + WHAL_STM32WB_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB_GPIO_SPEED_FAST, \ + WHAL_STM32WB_GPIO_PULL_UP, 7), \ + }, \ + .pinCount = PIN_COUNT, \ + }, \ +} + +/* Flash — only needed to raise the wait states before the clock goes to 64 MHz. */ +#define WHAL_CFG_STM32WB_FLASH_DEV { \ + .driver = WHAL_STM32WB55_FLASH_DRIVER, \ + .base = WHAL_STM32WB55_FLASH_BASE, \ + .cfg = (void *)&(const whal_Stm32wb_Flash_Cfg){ \ + .timeout = &g_whalTimeout, \ + .startAddr = 0x08000000, \ + .size = 0x80000, /* 512 KB; upper half reserved for the BLE stack */ \ + }, \ +} + +/* SysTick at 1 ms — drives the timeout the AES and RNG polls are bounded by. */ +#define WHAL_CFG_SYSTICK_DEV { \ + .base = WHAL_CORTEX_M4_SYSTICK_BASE, \ + /* .driver: direct API mapping */ \ + .cfg = (void *)&(const whal_SysTick_Cfg){ \ + .cyclesPerTick = 64000000 / 1000, \ + .clkSrc = WHAL_SYSTICK_CLKSRC_SYSCLK, \ + .tickInt = WHAL_SYSTICK_TICKINT_ENABLED, \ + }, \ +} + +/* RNG. */ +#define WHAL_CFG_STM32WB_RNG_DEV { \ + .base = WHAL_STM32WB55_RNG_BASE, \ + /* .driver: direct API mapping */ \ + .cfg = (void *)&(const whal_Stm32wb_Rng_Cfg){ \ + .timeout = &g_whalTimeout, \ + }, \ +} + +/* AES1. stm32wb_aes.c defines all seven devices unconditionally, so every + * initializer has to be present even though only four are dispatched below. + * The GCM and CCM state buffers are static in that TU. */ +#define WHAL_CFG_STM32WB_AES_DEV { \ + .base = WHAL_STM32WB55_AES1_BASE, \ + /* .driver: direct API mapping */ \ + .cfg = (void *)&(const whal_Stm32wb_Aes_Cfg){ \ + .timeout = &g_whalTimeout, \ + }, \ +} + +#define WHAL_CFG_STM32WB_AES_ECB_DEV { \ + .crypto = (whal_Crypto *)&whal_Stm32wb_Aes_Dev, \ +} + +#define WHAL_CFG_STM32WB_AES_CBC_DEV { \ + .crypto = (whal_Crypto *)&whal_Stm32wb_Aes_Dev, \ +} + +#define WHAL_CFG_STM32WB_AES_CTR_DEV { \ + .crypto = (whal_Crypto *)&whal_Stm32wb_Aes_Dev, \ +} + +#define WHAL_CFG_STM32WB_AES_GCM_DEV { \ + .crypto = (whal_Crypto *)&whal_Stm32wb_Aes_Dev, \ + .state = &g_stm32wbAesGcmDevState, \ +} + +#define WHAL_CFG_STM32WB_AES_GMAC_DEV { \ + .crypto = (whal_Crypto *)&whal_Stm32wb_Aes_Dev, \ +} + +#define WHAL_CFG_STM32WB_AES_CCM_DEV { \ + .crypto = (whal_Crypto *)&whal_Stm32wb_Aes_Dev, \ + .state = &g_stm32wbAesCcmDevState, \ +} + +/* What wolfSSL's wolfhal.c dispatches each algorithm on. CTR and GMAC are + * deliberately absent — wolfCrypt has no crypto-callback path for them, and + * anything not named here runs in software. */ +#define WC_WOLFHAL_AES_ECB_DEV ((whal_AesEcb *)&whal_Stm32wb_AesEcb_Dev) +#define WC_WOLFHAL_AES_CBC_DEV ((whal_AesCbc *)&whal_Stm32wb_AesCbc_Dev) +#define WC_WOLFHAL_AES_GCM_DEV ((whal_AesGcm *)&whal_Stm32wb_AesGcm_Dev) +#define WC_WOLFHAL_AES_CCM_DEV ((whal_AesCcm *)&whal_Stm32wb_AesCcm_Dev) +#define WC_WOLFHAL_RNG_DEV ((whal_Rng *)&whal_Stm32wb_Rng_Dev) + +whal_Error Board_Init(void); +whal_Error Board_Deinit(void); +uint32_t Board_GetTick(void); + +#endif /* BOARD_H */ diff --git a/wolfHAL/boards/stm32wb55xx_nucleo/board.mk b/wolfHAL/boards/stm32wb55xx_nucleo/board.mk new file mode 100644 index 000000000..27f1879c9 --- /dev/null +++ b/wolfHAL/boards/stm32wb55xx_nucleo/board.mk @@ -0,0 +1,57 @@ +# board.mk — STM32WB55 Nucleo +# +# Toolchain, the direct-API-mapping selection, and the wolfHAL drivers this +# board needs. Only the peripherals the wolfCrypt test uses are built. + +_BOARD_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) + +CROSS_COMPILE = arm-none-eabi- + +GCC = $(GCC_PATH)$(CROSS_COMPILE)gcc +OBJCOPY = $(GCC_PATH)$(CROSS_COMPILE)objcopy +SIZE = $(GCC_PATH)$(CROSS_COMPILE)size + +# Each WHAL_CFG_*_DIRECT_API_MAPPING binds a generic whal__* entry point +# straight to this part's driver, so there is no vtable indirection at runtime. +# Drop one and that subsystem falls back to pointer dispatch, which needs the +# matching .driver field in the board.h device initializer. +CFLAGS += -Wall -Werror -g3 -Os \ + -ffreestanding -nostdlib -mcpu=cortex-m4 -mthumb \ + -ffunction-sections -fdata-sections \ + -MMD -MP \ + -DPLATFORM_STM32WB \ + -DWHAL_CFG_STM32WB_RCC_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB_GPIO_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB_UART_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB_RNG_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB_AES_INIT_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB_AES_ECB_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB_AES_CBC_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB_AES_CTR_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB_AES_GCM_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB_AES_GMAC_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB_AES_CCM_DIRECT_API_MAPPING \ + -DWHAL_CFG_SYSTICK_TIMER_DIRECT_API_MAPPING + +LINKER_SCRIPT ?= $(_BOARD_DIR)/linker.ld + +# Link through gcc rather than ld so newlib is available for the test suite's +# printf. -lnosys resolves the stubs syscalls.c does not provide. +LDFLAGS += -nostdlib -mcpu=cortex-m4 -mthumb -Wl,--gc-sections -T $(LINKER_SCRIPT) +LDLIBS += -Wl,--start-group -lc -lm -lgcc -lnosys -Wl,--end-group + +# board.h has to be reachable by quoted include: wolfHAL's driver TUs and +# wolfSSL's wolfhal.c both pull it in that way. +CFLAGS += -I$(_BOARD_DIR) + +BOARD_SOURCE = $(_BOARD_DIR)/board.c +BOARD_SOURCE += $(_BOARD_DIR)/ivt.c + +# wolfHAL drivers +BOARD_SOURCE += $(WHAL_DIR)/src/reg.c +BOARD_SOURCE += $(WHAL_DIR)/src/gpio/stm32wb_gpio.c +BOARD_SOURCE += $(WHAL_DIR)/src/uart/stm32wb_uart.c +BOARD_SOURCE += $(WHAL_DIR)/src/rng/stm32wb_rng.c +BOARD_SOURCE += $(WHAL_DIR)/src/crypto/stm32wb_aes.c +BOARD_SOURCE += $(WHAL_DIR)/src/flash/stm32wb_flash.c +BOARD_SOURCE += $(WHAL_DIR)/src/timer/systick.c diff --git a/wolfHAL/boards/stm32wb55xx_nucleo/ivt.c b/wolfHAL/boards/stm32wb55xx_nucleo/ivt.c new file mode 100644 index 000000000..a8b8d8902 --- /dev/null +++ b/wolfHAL/boards/stm32wb55xx_nucleo/ivt.c @@ -0,0 +1,216 @@ +#include +#include + +extern uint32_t _estack[]; +extern uint32_t _sidata[]; +extern uint32_t _sdata[]; +extern uint32_t _edata[]; +extern uint32_t _sbss[]; +extern uint32_t _ebss[]; + +extern void main(); + +void __attribute__((naked,noreturn)) Default_Handler() +{ + while(1); +} + +void Reset_Handler() __attribute__((weak)); +void NMI_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void HardFault_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void MemManage_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void BusFault_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void UsageFault_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void SVC_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DebugMon_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void PendSV_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void SysTick_Handler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void WWDG_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void PVD_PVM_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TAMP_STAMP_LSECSS_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void RTC_WKUP_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void FLASH_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void RCC_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI0_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI2_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI3_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI4_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA1_Channel1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA1_Channel2_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA1_Channel3_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA1_Channel4_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA1_Channel5_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA1_Channel6_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA1_Channel7_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void ADC1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void USB_HP_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void USB_LP_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void C2SEV_PWR_C2H_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void COMP_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI9_5_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM1_BRK_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM1_UP_TIM16_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM1_TRG_COM_TIM17_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM1_CC_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM2_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void PKA_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void I2C1_EV_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void I2C1_ER_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void I2C3_EV_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void I2C3_ER_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void SPI1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void SPI2_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void USART1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void LPUART1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void SAI1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void TSC_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void EXTI15_10_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void RTC_Alarm_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void CRS_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void IPCC_C1_RX_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void IPCC_C1_TX_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void HSEM_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void LPTIM1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void LPTIM2_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void LCD_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void QUADSPI_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void AES1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void AES2_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void RNG_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void FPU_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA2_Channel1_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA2_Channel2_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA2_Channel3_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA2_Channel4_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA2_Channel5_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA2_Channel6_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA2_Channel7_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMAMUX1_OVR_IRQHandler() __attribute__((weak, noreturn, alias("Default_Handler"))); + +#define RESERVED Default_Handler + +void (* const interrupt_vector_table[])() __attribute__((section(".isr_vector"))) = { + (void (*)())_estack, + Reset_Handler, + NMI_Handler, + HardFault_Handler, + MemManage_Handler, + BusFault_Handler, + UsageFault_Handler, + RESERVED, + RESERVED, + RESERVED, + RESERVED, + SVC_Handler, + DebugMon_Handler, + RESERVED, + PendSV_Handler, + SysTick_Handler, + WWDG_IRQHandler, + PVD_PVM_IRQHandler, + TAMP_STAMP_LSECSS_IRQHandler, + RTC_WKUP_IRQHandler, + FLASH_IRQHandler, + RCC_IRQHandler, + EXTI0_IRQHandler, + EXTI1_IRQHandler, + EXTI2_IRQHandler, + EXTI3_IRQHandler, + EXTI4_IRQHandler, + DMA1_Channel1_IRQHandler, + DMA1_Channel2_IRQHandler, + DMA1_Channel3_IRQHandler, + DMA1_Channel4_IRQHandler, + DMA1_Channel5_IRQHandler, + DMA1_Channel6_IRQHandler, + DMA1_Channel7_IRQHandler, + ADC1_IRQHandler, + USB_HP_IRQHandler, + USB_LP_IRQHandler, + C2SEV_PWR_C2H_IRQHandler, + COMP_IRQHandler, + EXTI9_5_IRQHandler, + TIM1_BRK_IRQHandler, + TIM1_UP_TIM16_IRQHandler, + TIM1_TRG_COM_TIM17_IRQHandler, + TIM1_CC_IRQHandler, + TIM2_IRQHandler, + PKA_IRQHandler, + I2C1_EV_IRQHandler, + I2C1_ER_IRQHandler, + I2C3_EV_IRQHandler, + I2C3_ER_IRQHandler, + SPI1_IRQHandler, + SPI2_IRQHandler, + USART1_IRQHandler, + LPUART1_IRQHandler, + SAI1_IRQHandler, + TSC_IRQHandler, + EXTI15_10_IRQHandler, + RTC_Alarm_IRQHandler, + CRS_IRQHandler, + PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler, + IPCC_C1_RX_IRQHandler, + IPCC_C1_TX_IRQHandler, + HSEM_IRQHandler, + LPTIM1_IRQHandler, + LPTIM2_IRQHandler, + LCD_IRQHandler, + QUADSPI_IRQHandler, + AES1_IRQHandler, + AES2_IRQHandler, + RNG_IRQHandler, + FPU_IRQHandler, + DMA2_Channel1_IRQHandler, + DMA2_Channel2_IRQHandler, + DMA2_Channel3_IRQHandler, + DMA2_Channel4_IRQHandler, + DMA2_Channel5_IRQHandler, + DMA2_Channel6_IRQHandler, + DMA2_Channel7_IRQHandler, + DMAMUX1_OVR_IRQHandler, +}; + +void *memcpy(void *dest, const void *src, size_t n) +{ + unsigned char *d = dest; + const unsigned char *s = src; + + for (size_t i = 0; i < n; i++) + d[i] = s[i]; + + return dest; +} + +void *memset(void *s, int c, size_t n) +{ + unsigned char *p = s; + unsigned char v = (unsigned char)c; + + for (size_t i = 0; i < n; i++) + p[i] = v; + + return s; +} + +void __attribute__((naked)) Reset_Handler() +{ + __asm__("ldr r0, =_estack\n\t" + "mov sp, r0"); + + // Copy data section from flash memory to ram + uint32_t data_section_size = _edata - _sdata; + memcpy(_sdata, _sidata, data_section_size*4); + + // Zero out bss + uint32_t bss_section_size = _ebss - _sbss; + memset(_sbss, 0, bss_section_size*4); + + // Set Interrupt Vector Table Offset + uint32_t *vtor = (uint32_t *)0xE000ED08; + *vtor = (uint32_t)interrupt_vector_table; + + main(); +} diff --git a/wolfHAL/boards/stm32wb55xx_nucleo/linker.ld b/wolfHAL/boards/stm32wb55xx_nucleo/linker.ld new file mode 100644 index 000000000..b41c578f1 --- /dev/null +++ b/wolfHAL/boards/stm32wb55xx_nucleo/linker.ld @@ -0,0 +1,173 @@ +/* +***************************************************************************** +** +** File : linker.ld +** +** Abstract : System Workbench Minimal System calls file +** +** For more information about which c-functions +** need which of these lowlevel functions +** please consult the Newlib libc-manual +** +** Environment : System Workbench for MCU +** +** Distribution: The file is distributed “as is,” without any warranty +** of any kind. +** +***************************************************************************** +** +**

© COPYRIGHT(c) 2019 Ac6

+** +** Redistribution and use in source and binary forms, with or without modification, +** are permitted provided that the following conditions are met: +** 1. Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** 3. Neither the name of Ac6 nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20030000; /* end of RAM */ +/* Generate a link error if the stack don't fit into RAM */ +_Min_Stack_Size = 0x500; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K +RAM1 (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000 +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM1 AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM1 + + /* Heap grows up from _ebss, stack grows down from _estack */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = ABSOLUTE(_estack) - _Min_Stack_Size; + _heap_limit = .; + . = ALIGN(8); + } >RAM1 + + /* .ARM.attributes 0 : { *(.ARM.attributes) } */ + /* MAPPING_TABLE (NOLOAD) : { *(MAPPING_TABLE) } >RAM_SHARED */ + /* MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED */ + /* MB_MEM2 (NOLOAD) : { _sMB_MEM2 = . ; *(MB_MEM2) ; _eMB_MEM2 = . ; } >RAM_SHARED */ +} diff --git a/wolfHAL/main.c b/wolfHAL/main.c new file mode 100644 index 000000000..f40ecd0f9 --- /dev/null +++ b/wolfHAL/main.c @@ -0,0 +1,69 @@ +/* main.c + * + * wolfCrypt + wolfHAL example — runs the wolfCrypt test suite using + * hardware-accelerated crypto via wolfHAL. + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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. + * + * wolfSSL 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 + */ + +#include +#include +#include +#include + +#include "board.h" + +double current_time(int reset) +{ + uint32_t timeMs = Board_GetTick(); + double timeNow; + + (void)reset; + + timeNow = (double)(timeMs / 1000); /* seconds */ + timeNow += (double)(timeMs % 1000) / 1000.0; /* milliseconds */ + + return timeNow; +} + +void main(void) +{ + int ret; + + /* Initialize board hardware (clocks, peripherals) */ + if (Board_Init() != 0) { + while (1); + } + + /* Registers the wolfHAL crypto callback via wc_wolfHAL_RegisterDevice(), + * so the peripherals Board_Init() brought up are already live. */ + ret = wolfCrypt_Init(); + if (ret != 0) { + while (1); + } + + /* Correctness first, then throughput */ + wolfcrypt_test(NULL); + benchmark_test(NULL); + + wolfCrypt_Cleanup(); + Board_Deinit(); + + while (1); +} diff --git a/wolfHAL/syscalls.c b/wolfHAL/syscalls.c new file mode 100644 index 000000000..6284acf9a --- /dev/null +++ b/wolfHAL/syscalls.c @@ -0,0 +1,112 @@ +/* syscalls.c + * + * Minimal libc stubs for bare-metal. Routes stdout through wolfHAL UART. + * + * Copyright (C) 2006-2026 wolfSSL Inc. + */ + +#include +#include +#include +#include + +#include "board.h" + +/* From the board's linker script: the heap runs from the end of .bss up to + * where the stack is reserved. */ +extern uint32_t _ebss; +extern uint32_t _heap_limit; + +static char *heap_end; + +int _write(int file, const char *ptr, int len) +{ + (void)file; + if (len > 0) { + whal_Uart_Send(&g_whalUart, ptr, (size_t)len); + if (ptr[len - 1] == '\n') + whal_Uart_Send(&g_whalUart, "\r", 1); + } + return len; +} + +int _close(int file) +{ + (void)file; + return -1; +} + +int _fstat(int file, struct stat *st) +{ + (void)file; + if (st == NULL) { + errno = EINVAL; + return -1; + } + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) +{ + (void)file; + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + (void)file; + (void)ptr; + (void)dir; + return 0; +} + +int _read(int file, char *ptr, int len) +{ + (void)file; + (void)ptr; + (void)len; + return 0; +} + +void *_sbrk(ptrdiff_t incr) +{ + char *prev; + + if (heap_end == 0) + heap_end = (char *)&_ebss; + prev = heap_end; + if ((heap_end + incr) >= (char *)&_heap_limit) { + errno = ENOMEM; + return (void *)-1; + } + heap_end += incr; + return prev; +} + +void _exit(int status) +{ + (void)status; + while (1) { } +} + +int _kill(int pid, int sig) +{ + (void)pid; + (void)sig; + errno = EINVAL; + return -1; +} + +int _getpid(void) +{ + return 1; +} + +void _init(void) +{ +} + +void _fini(void) +{ +} diff --git a/wolfHAL/user_settings.h b/wolfHAL/user_settings.h new file mode 100644 index 000000000..8e9aa404e --- /dev/null +++ b/wolfHAL/user_settings.h @@ -0,0 +1,84 @@ +/* user_settings.h + * + * wolfCrypt configuration for the STM32WB55 Nucleo + wolfHAL example. + * AES is offloaded to the AES1 peripheral, SHA-256 stays in software. + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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. + * + * wolfSSL 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 + */ + +#ifndef USER_SETTINGS_H +#define USER_SETTINGS_H + +/* wolfHAL port. Enabling it pulls in wolfhal_settings.h, which turns on + * WOLF_CRYPTO_CB and points WC_USE_DEVID at the wolfHAL device, so the stock + * wolfcrypt test routes through the hardware without changes. */ +#define WOLFSSL_WOLFHAL + +/* Hardware RNG. random.c expands CUSTOM_RAND_GENERATE_BLOCK without seeing + * wolfhal.h, so the prototype has to be visible here. */ +#define WOLFSSL_WOLFHAL_RNG +extern int wc_wolfHAL_GenerateBlock(unsigned char* output, unsigned int sz); +#define CUSTOM_RAND_GENERATE_BLOCK wc_wolfHAL_GenerateBlock + +/* wolfCrypt only — no TLS */ +#define WOLFCRYPT_ONLY + +/* Small embedded target */ +#define SINGLE_THREADED +#define NO_FILESYSTEM +#define NO_WOLFSSL_DIR +#define NO_WRITEV +#define NO_MAIN_DRIVER +#define NO_DEV_RANDOM + +/* Benchmark: BENCH_EMBEDDED shrinks the working buffers, WOLFSSL_USER_CURRTIME + * makes benchmark.c call the current_time() this example supplies rather than + * reaching for a host clock it has no way to find. */ +#define BENCH_EMBEDDED +#define WOLFSSL_USER_CURRTIME + +/* AES — offloaded to AES1 via wolfHAL. board.h names a device for each of + * these, so all four are dispatched to hardware; a mode left unnamed there + * would fall back to wolfCrypt's software implementation instead. */ +#define HAVE_AES_CBC +#define HAVE_AESGCM +#define HAVE_AESCCM +#define HAVE_AES_ECB +#define WOLFSSL_AES_DIRECT +#define NO_AES_192 + +/* Disable everything else */ +#define NO_RSA +#define NO_DSA +#define NO_DH +#define NO_RC4 +#define NO_MD4 +#define NO_MD5 +#define NO_SHA +#define NO_DES3 +#define NO_PSK +#define NO_PWDBASED +#define NO_OLD_TLS +#define NO_ASN +#define NO_CODING +#define NO_SIG_WRAPPER +#define NO_HMAC +#define WOLFSSL_NO_PEM + +#endif /* USER_SETTINGS_H */ diff --git a/wolfHAL/wolfHAL b/wolfHAL/wolfHAL new file mode 160000 index 000000000..5302069e8 --- /dev/null +++ b/wolfHAL/wolfHAL @@ -0,0 +1 @@ +Subproject commit 5302069e8d7baacefeeada94c4c8e5ef7426c1db