Skip to content

Commit 9f824fd

Browse files
committed
STM32C5A3ZG wolfIP port: TLS 1.3 mutual-auth with DHUK-protected identity key + shared STM32 wolfssl.mk
1 parent 3f25c79 commit 9f824fd

22 files changed

Lines changed: 3942 additions & 97 deletions

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ CPPCHECK_FLAGS=--enable=warning,performance,portability,missingInclude \
133133
--suppress=constParameterCallback \
134134
--suppress=toomanyconfigs \
135135
--suppress=unmatchedSuppression --inconclusive \
136+
--suppress=comparePointers:src/port/stm32c5a3/startup.c \
137+
--suppress=comparePointers:src/port/stm32c5a3/syscalls.c \
136138
--suppress=comparePointers:src/port/stm32h563/startup.c \
137139
--suppress=comparePointers:src/port/stm32h563/syscalls.c \
138140
--suppress=comparePointers:src/port/stm32h753/startup.c \
@@ -149,6 +151,7 @@ CPPCHECK_FLAGS=--enable=warning,performance,portability,missingInclude \
149151
--suppress=comparePointers:src/port/rp2350_cyw43439/startup_hazard3.c \
150152
--suppress=comparePointers:src/port/rp2350_cyw43439/syscalls.c \
151153
--suppress=unknownMacro:src/port/stm32h563/dot1x_client.c \
154+
--suppress=unknownMacro:src/port/stm32c5a3/startup.c \
152155
--suppress=preprocessorErrorDirective:src/supplicant/supplicant_features.h \
153156
--disable=style \
154157
--std=c99 --language=c \

src/port/stm32/PORTING.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Porting wolfIP to a new STM32
2+
3+
This tree is layered so a new STM32 wolfIP port is a small set of per-chip
4+
files plus shared infrastructure. Existing ports: `stm32c5a3` (M33, TLS 1.3 +
5+
DHUK), `stm32h753` (M7, TLS + HTTPS), `stm32h563` (M33, TLS + SSH + MQTT +
6+
dot1x + FreeRTOS), `stm32f439` (M4, network only), `stm32n6` (M55, network
7+
only).
8+
9+
## Shared -- reuse as-is
10+
11+
| File | What it gives you |
12+
|------|-------------------|
13+
| `src/port/stm32/stm32_eth.c` / `.h` | Synopsys DWC GMAC MAC+DMA+PHY driver for H5/H7/N6 (and C5, via a one-line `STM32C5 -> STM32H5` alias). ETH1 at `0x40028000` on H5/C5. |
14+
| `src/port/stm32/wolfssl.mk` | `WOLFSSL_ROOT`/`WOLFMQTT_ROOT` defaults, the `WOLFSSL_SRCS` TLS-1.3 source list, the optional `WOLFSSL_LOG_SRCS` (logging/error/wc_encrypt) group, and the `$(WOLFSSL_ROOT)/%.o` relaxed-warning rule. `include` it from a port Makefile. |
15+
| `src/port/wolfssl_io.c` | wolfIP <-> wolfSSL I/O callbacks (EAGAIN -> WANT_READ/WRITE, `-1` -> CONN_CLOSE). |
16+
| `src/port/certs.h` | Embedded test certificates (for the HTTPS/server ports). |
17+
| `src/wolfip.c` | The stack itself. |
18+
19+
## Per-chip -- supply these
20+
21+
| File | Notes |
22+
|------|-------|
23+
| `startup.c` (+ `ivt.c`) | Vendor vector table + reset. Genuinely per-silicon (different peripheral IRQ set). C5A3 folds the full M33 vector table into `startup.c` (no separate `ivt.c`). |
24+
| `target.ld` | Memory map (flash/RAM addresses + sizes). Add an `.eth_buffers` output section in RAM for the GMAC descriptors + RX/TX buffers. |
25+
| `main.c` | The per-chip register sequences: `clock_init`, `uart_init`, `eth_gpio_init` (RMII pinmux + SYSCFG/SBS PHY-interface select + RCC ETH gates), `rng_init`. Plus the wolfIP init + poll loop (mostly copyable between ports). |
26+
| `config.h` | wolfIP sizing (sockets, buffers, static IP). |
27+
| `user_settings.h` | wolfSSL config: the shared TLS-1.3 base + a per-chip HW-crypto arm (`STM32_HASH` / `STM32_CRYPTO` / `WOLFSSL_STM32_PKA` / RNG, gated on the chip define). |
28+
| `Makefile` | Thin: CPU flags, device `-D`, includes, `include ../stm32/wolfssl.mk`, board sources, feature source lists, flash command. |
29+
30+
## Makefile pattern
31+
32+
```make
33+
CFLAGS := -mcpu=cortex-mXX ... -D<CHIP>
34+
CFLAGS_WOLFSSL := $(filter-out -Werror,$(CFLAGS)) -Wno-unused-variable -Wno-unused-function
35+
include $(ROOT)/src/port/stm32/wolfssl.mk # WOLFSSL_SRCS + %.o rule + defaults
36+
...
37+
ifeq ($(ENABLE_TLS),1)
38+
WOLFSSL_SRCS += $(WOLFSSL_LOG_SRCS) # unless you strip logging/error to save flash
39+
SRCS += $(WOLFSSL_SRCS)
40+
endif
41+
```
42+
43+
- A port that needs feature defines on the wolfSSL objects (e.g. SSH/dot1x) sets `WOLFSSL_EXTRA_DEFS` -- the shared `%.o` rule appends it (see `stm32h563/Makefile`).
44+
- Keep `all:`/`clean:`/`size:`/`flash:` in the port; `wolfssl.mk` intentionally defines only variables and the `%.o` pattern rule so it never hijacks the default goal.
45+
46+
## New-port checklist (things that bite)
47+
48+
- **`_sbrk` must use the linker `.heap` region**, not `_ebss.._estack`. On a port whose linker places `.eth_buffers` after `.bss`, an `_ebss`-based heap hands out malloc memory that overlaps the Ethernet DMA buffers, and packet DMA silently corrupts heap objects (seen on C5A3: garbage `WOLFSSL_CTX->method` -> bus fault deep in TLS).
49+
- **Add the port to the root `Makefile` cppcheck suppression list** (`comparePointers` for `startup.c`/`syscalls.c`, and `unknownMacro` for a CMSIS vendor `startup.c`). A cleaner alternative for new code: cast the `_sbrk` bounds compare to `uintptr_t` so no `comparePointers` suppression is needed.
50+
- **RMII alternate-function numbers are not uniform** -- check each pin against the CubeMX/HAL board example (on C5A3, RXD0/RXD1 are AF12/AF13 while the rest are AF10). A wrong AF on an RX pin leaves the link up (MDIO works) but drops all RX.
51+
- **DMA buffers must be in DMA-reachable RAM** (not DTCM on H7); place them via the `.eth_buffers` section.
52+
- **Wire MSPLIM** to the linker's real stack-limit symbol (`PROVIDE(__STACK_LIMIT = __StackLimit)` if the CMSIS startup uses `__STACK_LIMIT`) so a stack overflow faults cleanly instead of corrupting the heap.
53+
- The `../wolfssl` object tree is shared: ports at different FP ABIs (hard vs soft float) clobber each other's `.o` files. `make clean` (or delete `$(WOLFSSL_ROOT)/**/*.o`) between such builds.
54+
55+
## Known de-duplication opportunity (not yet done)
56+
57+
`tls_client.c` is currently a per-port file. The three TLS ports share a common
58+
handshake state machine, but they diverge in real behavior -- `stm32c5a3` does
59+
mutual auth with a client certificate + the DHUK PK sign callback, while
60+
`stm32h753`/`stm32h563` are plain one-way clients with no client cert. A shared
61+
`src/port/tls_client.c` would need config guards for cert-loading / DHUK / SNI /
62+
debug; worthwhile as a focused follow-up (with an on-hardware re-test of each
63+
board), but deliberately left per-port for now to avoid an unverifiable change.

src/port/stm32/stm32_eth.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,16 @@
1111
#include "config.h"
1212
#include "stm32_eth.h"
1313

14+
/* STM32C5 (Cortex-M33) uses a DWC GMAC that is byte-for-byte identical to
15+
* the STM32H5: same ETH_BASE (0x40028000), same register layout, same NS
16+
* access model, and the same MDIO clock-range divider (CR=4) at HCLK 144MHz.
17+
* Alias it onto the H5 path so it reuses every H5 value and code arm. */
18+
#if defined(STM32C5) && !defined(STM32H5)
19+
#define STM32H5
20+
#endif
21+
1422
#if !defined(STM32H5) && !defined(STM32H7) && !defined(STM32N6)
15-
#error "Define STM32H5, STM32H7 or STM32N6 for stm32_eth.c"
23+
#error "Define STM32C5, STM32H5, STM32H7 or STM32N6 for stm32_eth.c"
1624
#endif
1725

1826
#if defined(STM32H5)

src/port/stm32/wolfssl.mk

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# wolfssl.mk -- shared wolfSSL/wolfCrypt build plumbing for the STM32 bare-metal
2+
# wolfIP ports (stm32c5a3, stm32h753, stm32h563, ...).
3+
#
4+
# Copyright (C) 2026 wolfSSL Inc.
5+
#
6+
# `include $(ROOT)/src/port/stm32/wolfssl.mk` from a port Makefile. Provides:
7+
# - WOLFSSL_ROOT / WOLFMQTT_ROOT sibling defaults (a port may set WOLFSSL_ROOT
8+
# earlier with ?= to point at a worktree; that still wins).
9+
# - WOLFSSL_SRCS: the minimal wolfSSL/wolfCrypt source set for a TLS 1.3 client
10+
# (ECC + AES-GCM) plus the ChaCha20-Poly1305 / RSA-verify / logging groups
11+
# the ports share. Add to SRCS from inside the port's ENABLE_TLS block.
12+
# - the $(WOLFSSL_ROOT)/%.o relaxed-warning compile rule (uses the port's
13+
# CFLAGS_WOLFSSL, which the port defines and appends its own -D flags to).
14+
#
15+
# Only variables and a pattern rule live here -- no explicit targets -- so the
16+
# including Makefile keeps ownership of the default goal and of all/clean/size/
17+
# flash. Include it AFTER the port has set CFLAGS (and, if used, its own
18+
# WOLFSSL_ROOT ?= override); the port defines CFLAGS_WOLFSSL itself.
19+
20+
WOLFSSL_ROOT ?= $(ROOT)/../wolfssl
21+
WOLFMQTT_ROOT ?= $(ROOT)/../wolfmqtt
22+
23+
# Minimal wolfSSL/wolfCrypt source set for a TLS 1.3 client with ECC + AES-GCM.
24+
WOLFSSL_SRCS := \
25+
$(WOLFSSL_ROOT)/wolfcrypt/src/aes.c \
26+
$(WOLFSSL_ROOT)/wolfcrypt/src/sha.c \
27+
$(WOLFSSL_ROOT)/wolfcrypt/src/sha256.c \
28+
$(WOLFSSL_ROOT)/wolfcrypt/src/sha512.c \
29+
$(WOLFSSL_ROOT)/wolfcrypt/src/hmac.c \
30+
$(WOLFSSL_ROOT)/wolfcrypt/src/hash.c \
31+
$(WOLFSSL_ROOT)/wolfcrypt/src/kdf.c \
32+
$(WOLFSSL_ROOT)/wolfcrypt/src/random.c \
33+
$(WOLFSSL_ROOT)/wolfcrypt/src/ecc.c \
34+
$(WOLFSSL_ROOT)/wolfcrypt/src/asn.c \
35+
$(WOLFSSL_ROOT)/wolfcrypt/src/coding.c \
36+
$(WOLFSSL_ROOT)/wolfcrypt/src/wc_port.c \
37+
$(WOLFSSL_ROOT)/wolfcrypt/src/memory.c \
38+
$(WOLFSSL_ROOT)/wolfcrypt/src/wolfmath.c \
39+
$(WOLFSSL_ROOT)/wolfcrypt/src/sp_int.c \
40+
$(WOLFSSL_ROOT)/wolfcrypt/src/sp_c32.c \
41+
$(WOLFSSL_ROOT)/wolfcrypt/src/sp_cortexm.c \
42+
$(WOLFSSL_ROOT)/src/ssl.c \
43+
$(WOLFSSL_ROOT)/src/tls.c \
44+
$(WOLFSSL_ROOT)/src/tls13.c \
45+
$(WOLFSSL_ROOT)/src/internal.c \
46+
$(WOLFSSL_ROOT)/src/keys.c \
47+
$(WOLFSSL_ROOT)/src/wolfio.c
48+
49+
# ChaCha20-Poly1305 (fallback suite).
50+
WOLFSSL_SRCS += \
51+
$(WOLFSSL_ROOT)/wolfcrypt/src/chacha.c \
52+
$(WOLFSSL_ROOT)/wolfcrypt/src/chacha20_poly1305.c \
53+
$(WOLFSSL_ROOT)/wolfcrypt/src/poly1305.c
54+
55+
# RSA for peer certificate verification.
56+
WOLFSSL_SRCS += \
57+
$(WOLFSSL_ROOT)/wolfcrypt/src/rsa.c \
58+
$(WOLFSSL_ROOT)/wolfcrypt/src/signature.c
59+
60+
# Logging / error-strings / encrypt-helpers group. Kept separate because a
61+
# size-tight port may omit it (e.g. with NO_ERROR_STRINGS + logging off). Ports
62+
# that want it do: WOLFSSL_SRCS += $(WOLFSSL_LOG_SRCS)
63+
WOLFSSL_LOG_SRCS := \
64+
$(WOLFSSL_ROOT)/wolfcrypt/src/logging.c \
65+
$(WOLFSSL_ROOT)/wolfcrypt/src/error.c \
66+
$(WOLFSSL_ROOT)/wolfcrypt/src/wc_encrypt.c
67+
68+
# wolfSSL objects build with relaxed warnings (third-party, heavily #ifdef'd).
69+
# CFLAGS_WOLFSSL is defined by the including port Makefile. WOLFSSL_EXTRA_DEFS
70+
# lets a port add feature defines that the wolfSSL objects need (e.g. H563's
71+
# -DWOLFSSL_WOLFSSH / -DHAVE_PBKDF2 for its SSH / dot1x builds); it is empty by
72+
# default.
73+
$(WOLFSSL_ROOT)/%.o: $(WOLFSSL_ROOT)/%.c
74+
$(CC) $(CFLAGS_WOLFSSL) -DWOLFSSL_USER_SETTINGS $(WOLFSSL_EXTRA_DEFS) -I$(WOLFSSL_ROOT) -c $< -o $@

src/port/stm32c5a3/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Build artifacts
2+
*.o
3+
app.elf
4+
app.bin
5+
6+
# Generated TLS test host material (contains a throwaway test private key).
7+
# Regenerate with: python3 gen_certs.py (also rewrites tls_certs.h)
8+
tls-certs/

0 commit comments

Comments
 (0)