ac6-formation, un département d'Ac6 SAS
EN
EnglishFrench
go-up

ac6 ac6-formation

TrustZone on Cortex-M: isolation, TF-M and what PSA really guarantees

TrustZone on Cortex-M carries the same name as on Cortex-A, but it is not the same technology. On Cortex-A, isolation rests on a processor state bit and a software monitor arbitrating transitions. On Cortex-M it is spatial: every memory address statically belongs to one world, and the processor switches by crossing the boundary. Confusing the two leads to architectures that do not hold up.

How memory attribution works

Two units decide which world an address belongs to.

The IDAU, implementation defined attribution unit, is hardwired by the silicon vendor. It splits the address space into predefined regions, and you cannot change it.

The SAU, security attribution unit, is programmable, typically with 4 or 8 regions. It refines what the IDAU defined.

The combination rule is the one that catches people out: the most restrictive result wins. The SAU cannot make non-secure a region the IDAU declares secure. A lot of time gets lost attempting a memory map the silicon forbids, before someone reads the IDAU documentation carefully.

Every address falls into one of three states: secure, non-secure, or non-secure callable. That third state is the key to the mechanism.

Transitions, and the SG instruction

Non-secure code cannot jump anywhere it likes in the secure world. It can only enter a region marked NSC, non-secure callable, and only on an SG, secure gateway, instruction. Any other attempt raises a security fault.

In practice the NSC region only contains vestibules: an SG instruction, then a branch to the real secure function. The compiler generates them from cmse_nonsecure_entry attributes, and the linker produces an import library the non-secure project uses to know the entry points.

The return uses BXNS or BLXNS, with one often overlooked detail: core registers are cleared automatically when returning to the non-secure world, to prevent secrets leaking. But that covers registers only. Anything your secure code left in a stack or a shared buffer remains readable.

The real cost of a secure call

A transition is not free. Rough order of magnitude on a Cortex-M33:

OperationTypical cost
Ordinary function calla few cycles
Non-secure to secure transition20 to 50 cycles
Full TF-M service callseveral hundred to a few thousand cycles

The figures in this section are observed orders of magnitude, not specifications. They depend on silicon, compiler and configuration. Measure your own before sizing a product on them.

The gap between the last two rows comes from what TF-M adds on top of the hardware mechanism: validating caller-supplied pointers, switching partition context, marshalling parameters.

The design consequence is clear: you do not cross the boundary inside a loop. An architecture calling a secure service for every sample of a 10 kHz stream collapses. The pattern that works is to move blocks rather than bytes, and to keep bulk processing on the same side as its data.

What TF-M brings, and what it costs

Trusted Firmware-M is the reference implementation of the secure world. It provides three main services, protected storage, internal trusted storage and crypto, plus initial attestation.

Its value is not only avoiding rewriting those services. It is the isolated partition model: each service runs in its own context, with its own stack, and an overflow in one does not compromise the others. Three isolation levels exist, from the simplest, separating secure from non-secure, to the strictest, isolating each secure partition from the others.

The cost is real: budget several tens of kilobytes of flash and RAM for TF-M alone, depending on enabled services and isolation level. The only reliable measurement is your own configuration; the TF-M documentation details which options weigh most. On a 256 KB microcontroller, that is not a trivial decision.

What PSA Certified guarantees, and what it does not

PSA certification comes in levels, and confusion about their scope is common.

Level 1 is a self-assessment questionnaire, reviewed by a lab. It attests that the requirements were considered, not that an attack was attempted.

Level 2 adds a lab evaluation against advanced software attacks, over a limited time budget.

Level 3 additionally covers hardware attacks: fault injection, power analysis.

The point to keep: PSA certifies a platform, not your product. A PSA level 2 microcontroller running TF-M does not make your application compliant if you store a key in the clear in the non-secure world. Certification moves the trust boundary, it does not remove it.

The most frequent architecture mistakes

Putting too much code in the secure world. Every line there becomes privileged attack surface, and code review must be far stricter. The secure world should stay small and auditable.

Trusting pointers coming from the non-secure world. A secure service receiving a buffer address must check that it belongs to the non-secure world and that the whole range is accessible. The TT instructions and the cmse_check_address_range helpers exist for this. Without that check, the caller gets secure code to read or write any secure address on its behalf.

Forgetting that peripherals also have an attribution. A DMA controller programmed from the non-secure world can, if the silicon does not filter it, read secure memory. Protection depends on a bus filter on the peripheral side, not on TrustZone alone.

References

Going further

These mechanisms become tangible once you have programmed a SAU, traced a security fault on a malformed transition, and measured the real cost of a service call. That is what our advanced embedded security and ARM Cortex-M architecture courses cover.