Skip to content

cpu/nrf9160dk Arm TrustZone-M support#22387

Draft
janthies wants to merge 68 commits into
RIOT-OS:masterfrom
janthies:feature/riot-sw
Draft

cpu/nrf9160dk Arm TrustZone-M support#22387
janthies wants to merge 68 commits into
RIOT-OS:masterfrom
janthies:feature/riot-sw

Conversation

@janthies

@janthies janthies commented Jun 16, 2026

Copy link
Copy Markdown

Contribution description

This PR adds an ARM TrustZone-M TEE (Trusted Execution Environment) as the backend for PSA Crypto

Cryptographic operations using PSA Crypto are funneled to the TEE so that cryptographic material like keys can stay hidden from the non secure world / application.

Parts of RIOT involved:

  • sys/psa_crypto — sealed-key location/type, a custom-random hook, AES-ECB
    support, and location/algorithm dispatch to the cryptoservice backend.
  • pkg/cryptoservice, pkg/riot-tee, pkg/tf-m — the secure-world CryptoService,
    the RIOT-TEE secure image, and the Trusted Firmware-M / cc3xx driver sources.
  • cpu/nrf9160, cpu/nrf5x_common, cpu/cortexm_common — non-secure peripheral
    selection via a new NRF_TRUSTZONE_NONSECURE compile macro, and TrustZone-M
    build support.
  • boards/nrf9160dk-ns — new board target for the non-secure image.
  • tests/sys/psa_riot_tee — unit tests exercising the TEE-backed PSA operations.

The initial implementation was done by Lena Boeckmann back in 2024. Lenas masters thesis explains a lot of the architectural work: https://inet.haw-hamburg.de/thesis/completed/ma_lena_boeckmann.pdf/view. I've picked up the stale work in early 2026 and have fixed "some details".

Some open issues are that the CryptoService API (PSA Crypto API backend) (authored by Lars Pfau) hasn't yet been merged into RIOT. As a workaround for now (with agreement from Thomas Schmidt and Lars), I'm providing a temporary version of CryptoService on my GitHub.

The idea was to check in whether this is actually something belonging into riot and to gauge how much more work needs to be poured into this.

Testing procedure

I have an nrf9160-DK board. Running the tests/sys/psa_riot_tee test results in 5 Tests passed. The tests cover key import / sign/verify, sealed key generation + sign/verify, AES-128 CBC/ECV round trips and SHA-256

Issues/PRs references

None

Declaration of AI-Tools / LLMs usage:

I've used claude code
I'm not aware of any AI usage in the commits by Lena Boeckmann.
I myself have used Claude (Opus 4.6 - 4.8) sparingly in the commits in march. Mostly as a sparing partner / for more quickly understanding the architecute.
Before opening the pull request i've let Claude Code (max effort) check the commits for any glaring problems. That's how the commits from 16th June 2026 have come up. Those commits were created in agent mode.

@github-actions github-actions Bot added Area: boards Area: Board ports Area: cpu Area: CPU/MCU ports Area: sys Area: System Area: examples Area: Example Applications Area: Kconfig Area: Kconfig integration labels Jun 16, 2026
@AnnsAnns AnnsAnns added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Jun 16, 2026
@janthies janthies changed the title Feature/riot sw Arm TrustZone-M support for nrf9160dk Jun 16, 2026
@riot-ci

riot-ci commented Jun 16, 2026

Copy link
Copy Markdown

Murdock results

FAILED

c35dbea treewide: use SPDX license headers for nRF9160 TEE files

Artifacts

@janthies janthies changed the title Arm TrustZone-M support for nrf9160dk cpu/nrf9160dk Arm TrustZone-M support Jun 16, 2026

@AnnsAnns AnnsAnns left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, thank you for your first PR to RIOT, we always welcome new people (esp. if they PR 2 years of work cough)

Please try to rebase your branch onto the newest RIOT as right now this will not pass Murdock (and I am guessing a lot has happened over that time).

Comment thread examples/blinky/main.c
@crasbe crasbe added the State: needs rebase State: The codebase was changed since the creation of the PR, making a rebase necessary label Jun 16, 2026

@crasbe crasbe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR, @AnnsAnns asked us to give a review.

First there are some code style aspects.

Comment on lines +1 to +7
/*
* Copyright (C) 2021 Mesotic SAS
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/*
* Copyright (C) 2021 Mesotic SAS
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/*
* SPDX-FileCopyrightText: 2021 Mesotic SAS
* SPDX-License-Identifier: LGPL-2.1-only
*/

The copyright headers should have the SPDX format, see #21515 for more information.

Please adapt the other newly added files too.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done c35dbea

Comment thread boards/nrf9160dk-ns/include/board.h Outdated
Comment on lines +19 to +20
#ifndef BOARD_H
#define BOARD_H

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We replaced the classic headerguards with #pragma once that is between the Copyright header and the Doxygen header, see #21335.

Please adapt all newly added header files yourself.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* @{
*/
#ifndef RTT_DEV
#define RTT_DEV (0) /**< NRF_RTC0_S */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#define RTT_DEV (0) /**< NRF_RTC0_S */
# define RTT_DEV (0) /**< NRF_RTC0_S */

The preprocessor commands between #ifndef and #endif should have indentation, see https://guides.riot-os.org/c_tutorials/coding_conventions/#indentation-of-preprocessor-directives for more information.

Please adapt all the newly added files. Added code to existing files that do not have the indentation yet should "fit in". That means that if it's a self contained block, it should have indentation but if it's code added to a big #if-#else if-#endif structure, the indentation can be omitted.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread boards/nrf9160dk-ns/doc.txt Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We switched from the doc.txt format to doc.md. Please check #21220 for more information.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread boards/nrf9160dk-ns/doc.txt Outdated
Comment on lines +31 to +33
```
make BOARD=nrf9160dk -C examples/hello-world term
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```
make BOARD=nrf9160dk -C examples/hello-world term
```
```shell
make BOARD=nrf9160dk-ns -C examples/hello-world term
```

Code blocks with backticks do not need indentation. You can also specify the language for syntax highlighting.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, the board should probably be nrf9160dk-ns.

Comment on lines 41 to 44

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TEST_ASSERT_PSA_SUCCESS(psa_sign_hash(privkey_id, ECC_ALG, hash, sizeof(hash),
signature, sizeof(signature), &sig_length));
/* verify on original message with internal hashing operation */
TEST_ASSERT_PSA_SUCCESS(psa_verify_message(pubkey_id, ECC_ALG, msg, sizeof(msg),
signature, sig_length));

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

d26d442

wrapped three more lines

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is missing the copyright and Doxygen headers.

Comment on lines 35 to 51

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please adapt the long lines accordingly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is missing the copyright and Doxygen headers.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#define TEST_ASSERT_PSA_SUCCESS(func_) TEST_ASSERT_MESSAGE(func_ == PSA_SUCCESS, #func_ " failed");

That would bring it to 100 characters total.

@crasbe crasbe added the Type: new feature The issue requests / The PR implemements a new feature for RIOT label Jun 16, 2026
@crasbe crasbe removed the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Jun 18, 2026
@crasbe

crasbe commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

To be honest I wonder if it even makes sense to create a separate nrf9160dk-ns board. The differences between nrf9160dk and nrf9160dk-ns are miniscule and could easily be handled by some #ifdefs.

Also I wondered if the NRF_TRUSTZONE_NONSECURE flag couldn't be a feature or pseudomodule instead, something like periph_trustzone_m.

Then the modules can extend FEATURES_OPTIONAL or FEATURES_REQUIRED in their Makefiles to make use of the Trust Zone support.

@crasbe

crasbe commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Also I wondered if the NRF_TRUSTZONE_NONSECURE flag couldn't be a feature or pseudomodule instead, something like periph_trustzone_m.

Then the modules can extend FEATURES_OPTIONAL or FEATURES_REQUIRED in their Makefiles to make use of the Trust Zone support.

Oh, there is already a trustzone_m feature defined. I also guess that TrustZone is not really a peripheral either.

@AnnsAnns AnnsAnns added the AI: Helped PR/Issue uses AI sparingly, e.g. code inline assistant, debugging with AI, etc. label Jul 6, 2026
@crasbe crasbe added the State: waiting for author State: Action by the author of the PR is required label Jul 9, 2026
@crasbe crasbe removed the State: waiting for author State: Action by the author of the PR is required label Jul 15, 2026
@janthies janthies closed this Jul 16, 2026
@janthies janthies reopened this Jul 16, 2026
@janthies

Copy link
Copy Markdown
Author

To be honest I wonder if it even makes sense to create a separate nrf9160dk-ns board. The differences between nrf9160dk and nrf9160dk-ns are miniscule and could easily be handled by some #ifdefs.

Also I wondered if the NRF_TRUSTZONE_NONSECURE flag couldn't be a feature or pseudomodule instead, something like periph_trustzone_m.

Then the modules can extend FEATURES_OPTIONAL or FEATURES_REQUIRED in their Makefiles to make use of the Trust Zone support.

I'm not sure if using trustzone_m is such a good idea because it's information whether a cpu supports trustzone, not whether a specific build is with a secure firmware and should thus be offset in memory. So, iiuc, the question is feature or pseudomodule?
Also, riotboot is already supported by the nrf9160. I guess this is the same mechanism and we should just copy it / draw inspiration from it?
I guess the duplication is already showing its weaknesses as the nrf9160dk-ns also inherited the riotboot feature from the original board which I doubt would work right now. So yeah, bringing them back together would probably be a smart idea

@crasbe

crasbe commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

I'm not sure if using trustzone_m is such a good idea because it's information whether a cpu supports trustzone, not whether a specific build is with a secure firmware and should thus be offset in memory. So, iiuc, the question is feature or pseudomodule?

The feature mechanism works like that: A CPU/board adds peripherals or "features" to the FEATURES_PROVIDED variable. That is usually stuff like RTC, SPI, I2C, RNG, ...
This just lists the features that are there to use, but it does not mean they are actually used.

Then usually a module will specify which features it requires to work with the FEATURES_REQUIRED variable. For example, a sensor driver might require periph_i2c. The feature resolution then checks if the CPU has that feature and if any other features are in conflict with it.

The application would typically specify add a module or pseudomodule to USEMODULE, but it is also possible to add FEATURES_REQUIRED to the application Makefile if you want to work directly with a peripheral.

Since your code doesn't really have the intermediate module/driver, it would be possible to define a PSEUDOMODULE and add a conditional to the $(RIOTBASE)/Makefile.dep to add the FEATURES_REQUIRED += trustzone_m to the list when the according PSEUDOMODULE is loaded.

ifneq (,$(filter trustzone_m,$(USEMODULE)))
  FEATURES_REQUIRED += trustzone_m
endif

It should be possible to add that to cpu/nrf9160/Makefile.dep too, which would be cleaner, but I haven't tried it out yet.

Perhaps there are better names than two times trustzone_m, idk.

@crasbe

crasbe commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

It should be possible to add that to cpu/nrf9160/Makefile.dep too, which would be cleaner, but I haven't tried it out yet.

Yes, that works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Helped PR/Issue uses AI sparingly, e.g. code inline assistant, debugging with AI, etc. Area: boards Area: Board ports Area: build system Area: Build system Area: cpu Area: CPU/MCU ports Area: doc Area: Documentation Area: examples Area: Example Applications Area: Kconfig Area: Kconfig integration Area: pkg Area: External package ports Area: sys Area: System Area: tests Area: tests and testing framework Platform: ARM Platform: This PR/issue effects ARM-based platforms State: needs rebase State: The codebase was changed since the creation of the PR, making a rebase necessary Type: new feature The issue requests / The PR implemements a new feature for RIOT

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants