Skip to content

TF M Compatibility

github-actions[bot] edited this page Oct 2, 2026 · 6 revisions

TF-M Compatibility

wolfTrust implements the PSA interfaces needed by its reference applications without linking the Trusted Firmware-M runtime. Compatibility is at the C API and service-behavior level; image layout, manifests, build integration, and the SPM implementation are wolfTrust-specific.

This register describes the code in the repository. It is not a certification statement, and a declaration in a vendored header does not mean every optional algorithm or feature is enabled in every build.

Measured Secure-image footprint

The following table records local builds, not published reference figures. The wolfTrust rows use the STM32H563 reference manifest with isolation_profile set to 3 and include Internal Trusted Storage, Protected Storage, Firmware Update, vault services, and COSE attestation. The TF-M rows are the standard Small, Medium, and Large profiles built for AN521.

Secure image Profile and enabled services Flash Static RAM
wolfTrust native wolfTrust profile 3; Crypto, Internal Trusted Storage, Protected Storage, Firmware Update, vault, COSE attestation 86,848 bytes 27,253 bytes
wolfTrust wolfHSM Same services plus the wolfHSM server 106,432 bytes 59,073 bytes
TF-M Small Level 1; Crypto, Internal Trusted Storage, Initial Attestation; Protected Storage and Firmware Update off 50,968 bytes 14,296 bytes
TF-M Medium Level 2; Crypto, Internal Trusted Storage, Protected Storage, Initial Attestation; Firmware Update off 67,332 bytes 42,468 bytes
TF-M Large Level 3; Crypto, Internal Trusted Storage, Protected Storage, Initial Attestation; Firmware Update off 115,460 bytes 45,756 bytes

In these builds, native wolfTrust uses about 25% less flash than TF-M Large and less static RAM than TF-M Medium while also including firmware update. The wolfHSM engine remains smaller in flash than TF-M Large but uses more static RAM because it adds per-guest server state and stacks. These results do not imply that the projects, platforms, or enabled feature sets are identical.

Methodology

All five images were built on wolf-prec5560 with arm-none-eabi-gcc (15:13.2.rel1-2) 13.2.1 20231009. Footprint was read from the linked Secure ELF with arm-none-eabi-size and calculated as:

Flash      = text + data
Static RAM = data + bss

The wolfTrust rows were reproduced on 2026-09-18 from the source tree containing this page with the exact dependency set below.

Component Pinned revision Git description
wolfCOSE f907071b10127f3ae2dd7719749a91b039ff04a1 v2.0.0
wolfHSM a0323156606282448f00473a3fcb7aaa69361921 wolfHSM-v1.4.0-171-ga032315
wolfIP 146de4b6362c3a076787e27332f50daa0a445cf5 v1.0-91-g146de4b
wolfPSA 1b9ec29706bc63f785682ad688350195a33b22e8 v5.9.1-129-g1b9ec29
wolfSSL 22e505bcfad8ce21067ee4232128728543767a95 v5.9.1-stable-1088-g22e505bcf
wolfHAL 2bc2938b0bbcc977177153a7f38393710702bf70 No reachable tag

The wolfTrust images used -Os and the following commands; all other build variables retained their repository defaults:

git submodule update --init --recursive
make BUILD_DIR=build_size_native WT_ENGINE=native secure-image
make BUILD_DIR=build_size_hsm WT_ENGINE=hsm secure-image
arm-none-eabi-size build_size_native/wolftrust.elf \
    build_size_hsm/wolftrust.elf

The measured wolfTrust files were the two wolftrust.elf outputs. Their raw text, data, and bss values are recorded in Crypto Engines.

The TF-M source was the TF-Mv2.1.1-LTS tag at commit 02bf279913439a07082dd581df033f370a8fbb92. The following commands reproduce the AN521 GNU Arm builds with BL2 enabled and no regression tests:

for profile in small medium large; do
    cmake -S . -B "build_${profile}" \
        -DTFM_PLATFORM=arm/mps2/an521 \
        -DTFM_TOOLCHAIN_FILE=toolchain_GNUARM.cmake \
        -DTFM_PROFILE="profile_${profile}" \
        -DCMAKE_BUILD_TYPE=MinSizeRel \
        -DBL2=ON
    cmake --build "build_${profile}" --parallel
done
arm-none-eabi-size build_small/bin/tfm_s.elf \
    build_medium/bin/tfm_s.elf \
    build_large/bin/tfm_s.elf

The measured TF-M file in each case was tfm_s.elf.

Only the Secure runtime ELF is counted. wolfBoot and Non-secure wolfTrust guests are excluded; TF-M BL2 and its Non-secure application are likewise excluded. Although the TF-M configurations had BL2=ON, the separate BL2 image is not part of tfm_s.elf and therefore is not in the table.

The TF-M builds target AN521 while wolfTrust targets STM32H563, and their profiles do not enable the same services. Treat the table as a reproducible local build comparison, not a platform-normalized benchmark. See Crypto Engines for the measured cost within wolfTrust, where the platform and feature set are held constant.

Compatibility register

API or behavior Version Status Repository evidence
FF-M client API 1.0 with the scoped deviations below Connection-based IPC is implemented include/psa/client.h and src/client/psa_ffm_client.c
Secure Partition IPC API FF-M 1.0 plus a wolfTrust-specific backport of psa_irq_enable() from Arm's FF-M 1.1 Extension Beta, Issue 0 Supported for scheduled IPC partitions; wolfTrust still reports framework version 0x0100 and does not accept 1.1 manifests include/psa/service.h, include/psa/client.h, and src/arch/common/spm_sp_api.c
Framework and service discovery 1.0 Supported psa_framework_version and psa_version
Copied input and output vectors FF-M 1.0 Supported, with at most four vectors total and a 1024-byte aggregate budget across input bytes and declared output capacity include/wolftrust/ffm.h and src/ffm.c
Manifest validation wolfTrust format 1 Supported for immutable generated C data tools/manifest/generate.py, src/manifest.c, and port/stm32h563/manifest.json
PSA Crypto 1.4 header Supported through wolfPSA; algorithms depend on the guest profile lib/wolfPSA/wolfpsa/psa/crypto.h and both reference guest settings
Internal Trusted Storage 1.0 Core set/get/get-info/remove subset with the WRITE_ONCE lifecycle deviation below include/psa/internal_trusted_storage.h and src/services/wolfhsm/wt_hsm_vault.c
Protected Storage 1.0 Core set/get/get-info/remove subset; optional create/set-extended absent and the WRITE_ONCE lifecycle deviation below applies include/psa/protected_storage.h and src/services/storage_service.c
Initial Attestation 1.0 API subset with a nonconformant RFC 9783-derived token Token and exact-size operations are supported, but the advertised TF-M profile has the claim-semantic deviations below lib/wolfPSA/wolfpsa/psa/initial_attestation.h and src/services/initial_attestation.c
Firmware Update 1.0 subset Single-component staging and authenticated reboot supported, with the status deviation below include/psa/update.h and src/services/fwu_service.c
RoT lifecycle query FF-M 1.0 Secure Partition only; there is no Non-secure adapter or veneer include/psa/lifecycle.h and src/arch/common/spm_sp_api.c
Secure Partition signals and IRQ APIs FF-M 1.0 plus one wolfTrust-specific beta-extension backport The 1.0 signal APIs and psa_eoi are supported; only psa_irq_enable() is backported from the FF-M 1.1 Extension Beta, Issue 0, while psa_irq_status_t, psa_irq_is_enabled, psa_irq_disable, and psa_irq_restore are absent include/psa/service.h and the Armv8-M SVC implementation
Guest identity FF-M convention Non-secure guest N is client -(N + 1) src/arch/armv8m/ffm_nsc.c

Intentional differences

Difference Classification Reason and impact
wolfTrust exposes the FF-M Non-secure client API through one five-function CMSE gateway. Implementation detail The gateway exports framework version, service version, connect, call, and close; Secure Partition entry points are a separate manifest concern.
Only connection-based IPC services are enabled. Scoped The production manifest requests only WT_MANIFEST_FEATURE_IPC. SFN, stateless services, and memory-mapped I/O vectors are rejected by the runtime.
IPC uses fixed copied buffers. Scoped safety bound Calls are limited to four vectors and a 1024-byte transfer budget. Services apply smaller bounds. Applications must chunk larger data.
A Non-secure connect, call, or close cannot remain pending after the scheduler reaches quiescence for that dispatch. Scoped deviation An incomplete message becomes a client error. If already claimed, the service retains its message until reply or partition fault; late output is discarded. A late call reply releases the message, but the connection remains in error until the client requests close. If close was already requested, the late reply allows deferred disconnection to proceed. Shipped Non-secure-facing services reply within the dispatch; Secure Partition callers use the begin/finish path when scheduling another partition is required.
Secure services are linked in one image. Scoped isolation difference Service writable state is isolated by unprivileged threads and Secure MPU domains, but executable text is shared rather than separately linked.
All shipped service loops run as scheduled coroutines. Implementation difference Service code uses the standard Secure Partition API; privileged hardware access goes through identity-pinned SVC gates.
Abnormal Non-secure guest termination reclaims the guest's connections without delivering PSA_IPC_DISCONNECT to the affected services. Scoped deviation Fault-handler cleanup cannot dispatch a Secure service inline without re-entering the scheduler. Shipped services do not use psa_set_rhandle() for per-connection cleanup, but a ported service that depends on disconnect cleanup must account for this behavior.
PSA Crypto mechanisms are build-selected. Standard profile behavior The wolfPSA 1.4 header is present, while each guest's wolfCrypt settings determine available keys and algorithms.
Protected Storage does not implement create or set-extended. Scoped psa_ps_get_support() returns zero and both optional operations return PSA_ERROR_NOT_SUPPORTED.
Protected Storage always applies confidentiality and replay protection even when NO_CONFIDENTIALITY or NO_REPLAY_PROTECTION is requested. Known metadata deviation Objects remain sealed and counter-bound, but psa_ps_get_info() echoes the requested hint flags instead of reporting the stronger protection actually applied, which differs from the PSA Secure Storage 1.0 requirement.
ITS and Protected Storage always enforce PSA_STORAGE_FLAG_WRITE_ONCE. Known lifecycle deviation The request path does not receive lifecycle state and always rejects modification or removal. PSA Secure Storage 1.0 requires the flag not to be enforced during PSA_ROT_PROVISIONING.
Initial Attestation's public header omits PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE. Known header deviation The service limit is 640 bytes, but callers cannot obtain that maximum from the public PSA header.
A non-NULL attestation token buffer with zero capacity returns PSA_ERROR_INVALID_ARGUMENT. Known status deviation PSA Initial Attestation 1.0 specifies PSA_ERROR_BUFFER_TOO_SMALL for an undersized token buffer. Nonzero undersized buffers return PSA_ERROR_BUFFER_TOO_SMALL.
The attestation token advertises tag:psacertified.org,2023:psa#tfm but does not implement that profile's claim semantics. Known token-profile deviation The boot seed is deterministic across equivalent boots; software-component measurement type and description values are reversed; signer ID hashes the literal name wolfBoot rather than identifying the signing key; and implementation ID hashes a software label rather than identifying the immutable PSA RoT hardware assembly. A distinct derived profile identifier is required until these claims conform to RFC 9783.
Firmware Update has no persistent trial-accept flow. Scoped Installation commits only after wolfBoot authenticates the swapped image at reboot; psa_fwu_accept() returns PSA_ERROR_NOT_SUPPORTED.
The firmware-update detached manifest is a 32-bit version word. Scoped integration Passing NULL, 0 instead binds the version from the staged wolfBoot header. Other manifest encodings require an adapter.
Firmware Update reports unknown component IDs as PSA_ERROR_INVALID_ARGUMENT. Known API deviation PSA Firmware Update 1.0 specifies PSA_ERROR_DOES_NOT_EXIST for unknown component IDs. Unaligned block sizes are padded to the backend write alignment.
Secure memory uses no dynamic allocation. Stronger resource policy Fixed pools and buffers can reject excess work rather than expanding at runtime.
Manifests use wolfTrust JSON and generated C. Integration difference Existing TF-M manifests are not consumed directly. Security resources and services must be represented in the wolfTrust schema.
Secure Partition entry functions are bound at build time instead of being selected by each manifest's entry_point field. Integration difference The numeric field validates an executable window, but adding a service also requires a compiled entry wrapper and an explicit start call in wt_ffm_boot_start_sched().
Service IDs are generated from the selected manifest. Integration difference Applications should include generated psa_manifest/sid.h instead of hard-coding target-specific values.

Isolation-profile interpretation

The STM32H563 manifest sets isolation_profile to WT_ISOLATION_PROFILE_LEVEL_3 and declares the capabilities checked by the manifest validator. Only level 3 is implemented, so the generator and the validator refuse levels 1 and 2. The manifest declares its Non-secure guests privileged, matching the runtime, which initializes CONTROL_NS.nPRIV to zero. It declares every Secure Partition unprivileged, and the generator and the validator refuse a privileged one. TrustZone protects Secure state, GTZC isolates peer guest RAM, and unprivileged Secure threads use per-partition Secure MPU regions. The guest Non-secure MPU and interrupt masks are scheduling policy because a privileged guest can reprogram them.

The current single-image layout still shares Secure executable text; every partition's writable state is its own, and the crypto, vault, and attestation partitions interact only through FF-M IPC. Treat the profile field as a requested and validated wolfTrust policy level, not by itself as proof of independent TF-M isolation certification. Security Model describes the actual boundary.

Migrating an application

  1. Keep application calls on standard PSA headers where wolfTrust provides the corresponding Non-secure adapter: FF-M client, Crypto, ITS, Protected Storage, and Firmware Update. The lifecycle function is Secure-Partition-only.
  2. Link src/client/psa_ffm_client.c and the generated secure_cmse_implib.o from the selected Secure-image BUILD_DIR, then add the adapter required by each API: wolfPSA plus src/client/crypto_native_client.c for the native Crypto configuration, or wolfPSA, the wolfHSM client, and src/client/hsm_psa_transport.c for the hsm configuration; src/client/psa_storage_client.c for ITS and Protected Storage, src/client/psa_fwu_client.c for Firmware Update, and src/client/vnet_psa_transport.c for optional VNET.
  3. Initial Attestation currently has only the Zephyr-specific adapter at tests/firmware/zephyr-stm32h5/module/wolftrust-tee/src/wolftrust_attestation_client.c. The vendored lib/wolfPSA/src/psa_attestation.c is a stub that returns PSA_ERROR_NOT_SUPPORTED and must not be linked instead of or alongside that adapter.
  4. Include the psa_manifest/sid.h generated for the selected target and manifest.
  5. Check data-size assumptions against the copied IPC and service limits. Stream update images in blocks no larger than PSA_FWU_MAX_WRITE_SIZE. For wolfTrust, the image offset must be aligned to 1 << PSA_FWU_LOG2_WRITE_ALIGN. An unaligned final block is padded by the service to the backend write alignment.
  6. Check optional APIs before use. In particular, treat Protected Storage create/set-extended and Firmware Update accept as unsupported.
  7. Express Secure services, dependencies, memory, interrupts, restart policy, guest launch requirements, and minimum versions in the wolfTrust manifest.
  8. Replace TF-M build and image assembly with the wolfBoot and wolfTrust flow. Patch guest measurement records before signing wolfTrust.
  9. Run host tests, target conformance under M33MU, and the hardware suite separately. An emulator pass does not establish silicon attribution.

See API Reference, Porting, and Testing for integration details.

Clone this wiki locally