Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ eight interface-isolation jobs. QEMU `virt` runs 20 positives/isolation jobs
across both profiles and engines. Versal cross-builds both engines, but its QEMU
model cannot provide the XMPU/RISAF isolation those runtime scenarios require.

`stm32h563_interface_footprint` builds the six default-profile API/engine pairs
with the same compiler, pinned FreeRTOS source, one application and production
PIN settings. Missing measurements fail the job. Each TPM/PKCS#11 total must
remain within 8 KiB of same-engine PSA; the uploaded CSV reports Secure,
application, total flash and RAM sections separately. This is a regression
ceiling, not a claim of exact parity.

The M33MU workflow (`m33mu.yml`) is label-selected the way wolfProvider's
`pr-osp-select.yml` is: a `select` job checks the routing table
(`scenario_matrix.py --selftest`), reads the PR's `ci:*` labels, the
Expand Down Expand Up @@ -72,7 +79,7 @@ test-target` also reads. The table below is a representative slice:
| `stm32h563_devstorage_<engine>` | `devstorage` | PSA ITS/PS conformance |
| `stm32h563_devcrypto_<engine>` | `devcrypto` | PSA Crypto conformance |
| `stm32h563_pkcs11_<zephyr\|freertos>_<engine>_<profile>` | `pkcs11` | each RTOS application runs the nine-case default or 40-case full PKCS#11 suite through `SERVICE_PKCS11` and the isolated provider |
| `stm32h563_tpm_<zephyr\|freertos>_<engine>_<profile>` | `tpm` | each RTOS application sends real TPM 2.0 commands through `SERVICE_TPM` to the isolated fwTPM guest |
| `stm32h563_tpm_<zephyr\|freertos>_<engine>_<profile>` | `tpm` | each RTOS application sends real TPM 2.0 commands through `SERVICE_TPM` to the Secure fwTPM partition |
| `stm32h563_pkcs11neg_<engine>_<profile>` | `pkcs11neg` | PKCS#11 partition-band isolation and provider recovery |
| `stm32h563_tpmneg_<engine>_<profile>` | `tpmneg` | TPM relay and fwTPM partition-band isolation |
| `stm32h563_vaultrecover_<engine>` | `vaultrecover` | #95 foreign pool reformatted |
Expand Down
54 changes: 51 additions & 3 deletions .github/workflows/m33mu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: m33mu-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
Expand Down Expand Up @@ -91,7 +91,7 @@ jobs:
name: stm32h563_${{ matrix.api }}_${{ matrix.os }}_${{ matrix.engine }}_${{ matrix.profile }}
if: >-
github.event_name != 'workflow_dispatch' ||
inputs.port == 'all' || inputs.port == 'stm32h563'
inputs.port == '' || inputs.port == 'all' || inputs.port == 'stm32h563'
runs-on: ubuntu-latest
strategy:
fail-fast: false
Expand Down Expand Up @@ -305,7 +305,7 @@ jobs:
name: stm32h563_${{ matrix.scenario }}_${{ matrix.engine }}_${{ matrix.profile }}
if: >-
github.event_name != 'workflow_dispatch' ||
inputs.port == 'all' || inputs.port == 'stm32h563'
inputs.port == '' || inputs.port == 'all' || inputs.port == 'stm32h563'
runs-on: ubuntu-latest
strategy:
fail-fast: false
Expand All @@ -331,6 +331,54 @@ jobs:
- name: Run the direct interface scenario
run: tests/target/run_suite.sh m33mu ${{ matrix.scenario }}

interface-footprint:
name: stm32h563_interface_footprint
if: >-
github.event_name != 'workflow_dispatch' ||
inputs.port == '' || inputs.port == 'all' || inputs.port == 'stm32h563'
runs-on: ubuntu-latest
timeout-minutes: 30
container:
image: ghcr.io/wolfssl/wolfboot-ci-m33mu:v1.15
env:
WT_CRYPTO_PROFILE: default
WT_LTO: 1
FREERTOS_REF: f4fcc3b228643144727e9257ba12db1cb632b6e6
steps:
- uses: actions/checkout@v4

- name: Initialize pinned dependencies
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
git config --global url."https://github.com/".insteadOf git@github.com:
git submodule update --init --single-branch
workspace=tests/firmware/zephyr-stm32h5/.workspace/freertos
git init "$workspace"
git -C "$workspace" remote add origin https://github.com/FreeRTOS/FreeRTOS.git
git -C "$workspace" fetch --depth 1 origin "$FREERTOS_REF"
git -C "$workspace" checkout --detach FETCH_HEAD
make -C tests/firmware/zephyr-stm32h5 freertos-workspace

- name: Measure all six API and engine combinations
run: bash tools/measure_interface_footprint.sh

- name: Compare total flash with same-engine PSA
run: |
python3 tools/check_interface_footprint.py \
build/interface-footprint/sizes.csv --max-overhead 8192 \
> build/interface-footprint/comparison.txt
cat build/interface-footprint/comparison.txt

- name: Upload size comparison
if: always()
uses: actions/upload-artifact@v4
with:
name: stm32h563-interface-footprint
path: |
build/interface-footprint/sizes.csv
build/interface-footprint/configuration.txt
build/interface-footprint/comparison.txt

# Label-selected, the wolfProvider way: one select job reads the ci:* labels
# (ci:stm32h563 or ci:imxrt700 for that port's full matrix when only that port
# changed, ci:all or ci:m33mu for everything after a core change, no label
Expand Down
12 changes: 12 additions & 0 deletions docs/Crypto-Profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ crypto for object protection even when related public mechanisms are absent.
TPM and PKCS#11 images link no wolfPSA Crypto implementation. Their `psa_call`
functions are the FF-M IPC boundary.

The basic selection also omits unused AES-CTR, CCM and deterministic-ECDSA
extensions from the Secure image. Full profiles and broader custom command or
mechanism selections restore those extensions. Required CFB and PIN primitives
remain enabled. The basic TPM image uses wolfCrypt's original ASN codec;
broader TPM profiles and PKCS#11 retain the template codec. Host tests cover
both codecs, malformed keys and signatures, and cross-codec key decoding.

HSM callback dispatch for basic TPM/PKCS#11 selections retains RNG, SHA-256
and P-256. It omits unrequested AES and HKDF dispatch after loading the complete
shared type definitions. Full and broader custom selections retain the original
callback. No dependency files or structure layouts are changed.

## Reference builds and verification

FreeRTOS guest builds use `WT_LTO=1` by default; `WT_LTO=0` disables it.
Expand Down
55 changes: 34 additions & 21 deletions docs/Interface-Footprint.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Application-interface footprint

Measured on 2026-10-26 for STM32H563. All six default-profile builds exercise
Measured on 2026-11-05 for STM32H563. All six default-profile builds exercise
RNG, SHA-256, P-256 key generation, signing, and verification. Every row has one
FreeRTOS application and one wolfTrust image. TPM and PKCS#11 run directly in
Secure partitions; no provider image, extra RTOS, or worker is built or loaded.
Expand All @@ -13,15 +13,15 @@ reserved partition's capacity.

| Engine | API | Secure | Application | Total | Above same-engine PSA |
| --- | --- | ---: | ---: | ---: | ---: |
| native | PSA | 94,208 | 33,488 | 127,696 | 0 |
| native | TPM | 116,332 | 15,476 | 131,808 | 4,112 |
| native | PKCS#11 | 125,276 | 11,052 | 136,328 | 8,632 |
| hsm | PSA | 118,076 | 43,156 | 161,232 | 0 |
| hsm | TPM | 160,960 | 15,476 | 176,436 | 15,204 |
| hsm | PKCS#11 | 164,384 | 11,052 | 175,436 | 14,204 |
| native | PSA | 94,400 | 33,488 | 127,888 | 0 |
| native | TPM | 114,284 | 15,476 | 129,760 | 1,872 |
| native | PKCS#11 | 123,260 | 11,052 | 134,312 | 6,424 |
| hsm | PSA | 118,204 | 43,156 | 161,360 | 0 |
| hsm | TPM | 154,044 | 15,476 | 169,520 | 8,160 |
| hsm | PKCS#11 | 158,208 | 11,052 | 169,260 | 7,900 |

The API-disabled Secure images exactly match the pinned base under these
settings: 94,208 bytes native and 118,076 bytes HSM. Disabling both optional
settings: 94,400 bytes native and 118,204 bytes HSM. Disabling both optional
interfaces adds no Secure flash cost. Vault, RNG, attestation, storage, and
update services remain enabled in every row.

Expand All @@ -39,16 +39,17 @@ token/session/object state, PIN protection, and wire handling.

## Reductions and retained operations

The previous default builds used a separate Cortex-M provider guest:
Compared with the pinned `wolfTrust-dev2` reference, using the same default
operations and workload:

| Engine | API | Previous total | Current total | Reduction |
| Engine | API | Base total | Current total | Reduction |
| --- | --- | ---: | ---: | ---: |
| native | TPM | 156,756 | 131,808 | 24,948 |
| native | PKCS#11 | 162,445 | 136,328 | 26,117 |
| hsm | TPM | 180,104 | 176,436 | 3,668 |
| hsm | PKCS#11 | 186,676 | 175,436 | 11,240 |
| native | TPM | 132,000 | 129,760 | 2,240 |
| native | PKCS#11 | 136,552 | 134,312 | 2,240 |
| hsm | TPM | 176,532 | 169,520 | 7,012 |
| hsm | PKCS#11 | 175,532 | 169,260 | 6,272 |

The new layout removes the provider guest, its scheduler, and asynchronous
Merged PR 76 removed the provider guest, its scheduler, and asynchronous
forwarding/polling. TPM executes each command in one copied call. PKCS#11
keeps bounded chunking for 4096-byte messages, with one execution call and no
worker polling. Native domains share stateless crypto code already in flash.
Expand Down Expand Up @@ -79,11 +80,13 @@ reserved slot size is a layout limit; the table counts only linked code/data.

## Reproduce

- Base: `7ae69b3cb6fae0a61e3d184264415d0ea0c01f36`.
- Base: `wolfTrust-dev2`, `4bda5987a3b28e32917471b8ccf307111bb37eea`.
- Compiler: Arm GNU Toolchain 15.2.Rel1, GCC 15.2.1.
- Container: `ghcr.io/wolfssl/wolfboot-ci-m33mu@sha256:f6b66c9240ecd94f99400565196f956d1b067059b659a66dbbe83581cc7bf4c7`.
- Cortex-M33, `-Os`, `WT_LTO=1`, one guest slot, default attestation, and
production PIN KDF settings. All rows use the same pinned dependencies.
- FreeRTOS: `f4fcc3b228643144727e9257ba12db1cb632b6e6`, kernel
`3a22924e0a9ddbbc8b0758881c33b3422a5cc20d`.

The PSA fixture uses guest 0's flash/RAM addresses and HSM client ID 1. Its
foreign-vector negative uses the other RAM window. The single-application
Expand All @@ -93,21 +96,30 @@ Initialize dependencies and the FreeRTOS workspace inside that container, then:

```sh
WT_CRYPTO_PROFILE=default bash tools/measure_interface_footprint.sh
python3 tools/check_interface_footprint.py build/interface-footprint/sizes.csv \
--max-overhead 8192
```

The output contains `sizes.csv`, compiler/source configuration, logs, generated
operation selections, symbol/section reports, and all measured ELFs. The first
argument chooses an output directory. `WT_CRYPTO_PROFILE=full` measures the
broader profile, whose reference workloads differ from the default.

The M33MU CI workflow runs this six-build default comparison on every PR.
It rejects missing/duplicate rows, inconsistent section totals, emulator-only
PIN settings, or total flash overhead above 8 KiB relative to same-engine PSA.
This is a regression ceiling. Current overhead is 1.5% to 5.1%; exact parity
and a minimum protocol implementation size have not been established.

Earlier 11,980-byte native PSA application figures covered RNG/hash without
P-256. They are not a comparable baseline for these builds.

## Validation

Implementation: [7c503777](https://github.com/aidangarske/wolfTrust-fork/commit/7c5037779d2129523f051f1a5ce32d1dd8ae03b8).
All 71 host suites and their C99 run pass. Six focused ASan/UBSan suites pass,
and four RT700 API/engine cross-builds pass their layout checks.
The aggregate host matrix includes both wolfCrypt ASN codecs, malformed DER
keys/signatures and cross-codec key decoding. The profile tests check actual
Secure settings for default, full and custom selections and parallel builds of
the generated HSM callback. Disabled PKCS#11 wire operations are also tested.

Local host tests exercise the synchronous production transports through the
FF-M runtime, including exact bounds, identity checks, zeroization, connection
Expand All @@ -118,5 +130,6 @@ FreeRTOS, and the bare-metal TPM isolation client.

Emulator-only PIN tests explicitly use 25 PBKDF2 rounds to bound execution
time. Size measurements retain 600,000 rounds. Emulator and cross-build results
are recorded separately from physical hardware qualification. Current branch
CI results are available in [PR 76 checks](https://github.com/wolfSSL/wolfTrust/pull/76/checks).
are recorded separately from physical hardware qualification. The
[PR 76 checks](https://github.com/wolfSSL/wolfTrust/pull/76/checks) are evidence
for the merged baseline; the follow-up requires its own qualification.
15 changes: 14 additions & 1 deletion docs/Testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ The dedicated guest configurations also exercise the PSA Crypto, Storage, and
Initial Attestation validation applications. Those are target scenarios, not
part of a plain `make test` result.

The `psa_storage_client` host suite checks the full destination range for ITS
and PS reads, including the oversized range used by Arm storage test `s008`.
Valid buffers larger than the copied-transfer budget still read successfully
and execute the storage request once. The `devstorage` target scenario runs
the pinned Arm storage suite through the production client and Secure gateway.

## M33MU scenarios

The baseline target command is:
Expand Down Expand Up @@ -646,7 +652,14 @@ The separate STM32H563 interface matrix runs the full cross product
`[native, hsm] x [psa, pkcs11, tpm] x [zephyr, freertos] x [default, full]`.
All 24 application rows run on every PR. TPM and PKCS#11 also have eight
isolation-negative rows across engines and profiles. QEMU runs 20 interface
and isolation rows across both engines and profiles. Dedicated API rows set `WT_REQUIRE_SCENARIO_PASS=1`: a skipped
and isolation rows across both engines and profiles. A separate footprint job
builds all six default-profile API/engine pairs with one FreeRTOS application
and production PIN settings. It compares Secure plus application flash with
same-engine PSA and rejects overhead above 8 KiB. This ceiling guards against
regressions; it does not establish exact size parity. See
[Interface-Footprint.md](Interface-Footprint.md) for the measurements.

Dedicated API rows set `WT_REQUIRE_SCENARIO_PASS=1`: a skipped
scenario or a missing terminal pass marker fails the job.
The full matrix runs on a
push to `main`, on the nightly schedule, on
Expand Down
12 changes: 10 additions & 2 deletions mk/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ WT_VNET_UNKNOWN_UCAST_FLOOD ?= 0
# tests/host/tpm_relay/ build regardless of this switch.
CONFIG_TPM ?= n

# PKCS#11 subsystem. The application-side C_* proxy and provider guest both
# use SERVICE_PKCS11; the provider reaches SERVICE_HSM with the hsm engine.
# PKCS#11 clients call SERVICE_PKCS11 in a managed Secure partition. Its
# implementation uses native wolfCrypt or the mediated wolfHSM engine.
CONFIG_PKCS11 ?= n
WT_INTERFACE_LOCAL_PROVIDER ?= 0

Expand Down Expand Up @@ -1793,6 +1793,10 @@ $(BUILD_DIR)/tpm_sec_raw_%.o: $(ROOT)/src/client/%.c $(WOLFHSM_CFG_H) $(BUILD_MO
$(BUILD_DIR)/tpm_wh_raw_%.o: $(WOLFHSM_DIR)/src/%.c $(WOLFHSM_CFG_H) $(BUILD_MODE_STAMP) | $(BUILD_DIR)
$(CC) $(HSM_WOLFHSM_CFLAGS) -UWC_NO_DEFAULT_DEVID -c -o $@ $<

$(BUILD_DIR)/tpm_wh_raw_wh_client_cryptocb.o: $(WT_CRYPTO_PROFILE_DIR)/hsm_callback.c \
$(WOLFHSM_DIR)/src/wh_client_cryptocb.c $(WOLFHSM_CFG_H) $(BUILD_MODE_STAMP)
$(CC) $(HSM_WOLFHSM_CFLAGS) -UWC_NO_DEFAULT_DEVID -c -o $@ $<

$(BUILD_DIR)/tpm_wh_%.o: $(BUILD_DIR)/tpm_wh_raw_%.o $(TPM_NAMESPACE_MAP)
$(OBJCOPY) --redefine-syms=$(TPM_NAMESPACE_MAP) $< $@

Expand Down Expand Up @@ -1833,6 +1837,10 @@ $(BUILD_DIR)/p11_wc_raw_%.o: $(WOLFSSL_DIR)/wolfcrypt/src/port/arm/%.c $(WOLFHSM
$(BUILD_DIR)/p11_wh_raw_%.o: $(WOLFHSM_DIR)/src/%.c $(WOLFHSM_CFG_H) $(BUILD_MODE_STAMP) | $(BUILD_DIR)
$(CC) $(HSM_WOLFHSM_CFLAGS) $(WOLFPKCS11_SECURE_CFLAGS) -c -o $@ $<

$(BUILD_DIR)/p11_wh_raw_wh_client_cryptocb.o: $(WT_CRYPTO_PROFILE_DIR)/hsm_callback.c \
$(WOLFHSM_DIR)/src/wh_client_cryptocb.c $(WOLFHSM_CFG_H) $(BUILD_MODE_STAMP)
$(CC) $(HSM_WOLFHSM_CFLAGS) $(WOLFPKCS11_SECURE_CFLAGS) -c -o $@ $<

$(P11_NAMESPACE_MAP): $(P11_WOLFCRYPT_RAW_OBJS) | $(BUILD_DIR)
@$(NM) -g --defined-only $^ | awk 'NF >= 2 && $$(NF - 1) ~ /^[A-ZTWV]$$/ { print $$NF, "wt_p11_" $$NF }' | LC_ALL=C sort -u > $@.tmp
@mv $@.tmp $@
Expand Down
3 changes: 3 additions & 0 deletions mk/crypto-profile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ $(WT_CRYPTO_PROFILE_DIR)/fwtpm_command.c: $(WT_CRYPTO_PROFILE_HEADER)

$(WT_CRYPTO_PROFILE_DIR)/pkcs11_crypto.c: $(WT_CRYPTO_PROFILE_HEADER)
@test -f $@

$(WT_CRYPTO_PROFILE_DIR)/hsm_callback.c: $(WT_CRYPTO_PROFILE_HEADER)
@test -f $@
Loading
Loading