I would like to understand what TrustedFirmware-M is with an emphasis on how it works with an emphasis on the Zephyr operating system. I read the official documentation but everything is described there like on an advertising brochure. I don’t want to see another drawing that there are secure and non-secure blocks. I really want to understand how it works when using a board with /ns. What I really give is CONFIG_BUILD_WITH_TFM=y.
Alright I’ll bite.
I’m more Familiar with TrustZone on FreeRTOS and bare metal, but I assume Zephyr is working similar. I also took a look at the documentation they provided.
TrustZone is built with two separate images, so it’s as if there’s two binaries running on ur chip. One is the non secure region, where you should keep most of your app. But for the stuff you really don’t want people potentially accessing, you have the SPE or secure region. There are elevated permissions, and generally speaking the SPE region has more access to memory and resources on your chip(although I’ve seen instances where you can actually lock out the SPE region from parts of the insecure image as well, all depends on how you setup).
Generally speaking your device will boot into the SPE region by default, then all the insecure stuff is configured. Then you jump into the insecure region where most of your app sits. Typically the RTOS kernel and most peripheral access is in the insecure region. Then whenever you need to touch sensitive data you make a vector call to a function in the secure region. When that function completes calling, it returns back to the insecure region. Good engineering philosophy is to keep the secure region as small as possible to prevent potential holes in security(more code = more vulnerabilities).
Looks like what Zephyr does is move all ur crypto and “sensitive information” code into the “SPE” or secure region. Then the rest of the app runs in the insecure side. This means even if your insecure region is compromised, no one can steal your juicy certs since it will all stay on the secure side.
TrustZone-M is a feature present in most ARMv8-M MCUs. It divides your mapped memory (including Flash and RAM) and peripherals into two separate domains “Secure” and “Non-Secure”. Think about it as another level of hardware assisted isolation, on top of Process vs. OS depending on the control bit.
Indeed the two images are separate. The device typically starts with the secure-mode firmware which can set up the domains mapping via the trust-zone controller and the SAU, and then jump into non-secure domain firmware.
The non-secure domain firmware will not see the parts of memory that are mapped as secure. However, it’s possible for the secure firmware to expose some sort of “hypercalls”. These are in a specific area which is like the secure one, but can be called by the non-secure space, and it’s referred to as non-secure callable. This code executes in secure mode and can access the secure-mapped memory and peripherals.
Gcc has some compiler flags + special sections to add NSC entry points to the secure firmware. An additional object is created for the non-secure application to link to, and contains the stubs in non-secure space to create the cross-domain call.
For basic understanding of the mechanism and the isolation in practice, switching and staging across the domains, defining and using NSCs, check these examples (disclaimer: they are taken from Chapter11 of a book I recently authored. The code is freely available on github):
https://github.com/PacktPublishing/Embedded-Systems-Architecture-Second-Edition/tree/main/Chapter11
TF-M is a possible implementation of a trustzone-m “supervisor”, separating some operations and regulating access to some resources. In such a scenario I would guess that the OS will run in non-secure domain, with most of the peripherals unlocked, but still being forced to use specific NSC interfaces to access some functionality (e.g. crypto via a cross-domain PSA interface…).
Don’t really have anything to add other than somewhat in the same boat with TF-A
This is a great explanation, the only thing I would add is that depending on what MCU you are using, securing peripherals might vary. From my experience with the stm32u5, ST has implemented what they call a global TrustZone controller that you can configure which allows you to set various peripherals as secure or non-secure. Additionally some peripherals are “TrustZone aware” which just means you can set them as secure usually by setting a bit in the register of that peripheral.
For anyone trying to learn how to implement TrustZone I found the best resource for how TrustZone works on the M33 core to be this book
“Definitive Guide to Arm Cortex-M23 and Cortex-M33 Processors”
And to understand the nuances of your specific MCU the reference manual is the best place to find information.
This means even if your insecure region is compromised, no one can steal your juicy certs since it will all stay on the secure side.
This is true, but with one issue: they can still use those private keys for the allowed operations. So they can use the key in the same ways your firmware can, just on their data.
Also certs are public by definition, you don’t keep them on the secure side. You have to be able to sharee them with the verifying system, after all!
What’s the point of this in place of using mpu regions to lock things down? Is this just yet another case of hardware trying to cover for software written in C with all the caveats and holes that comes with or is there some actual data/papers showing how this provides some legitimate value and not just pseudoscience security?
I somewhat touched on it when I referred to resources but yea, most peripherals are essentially memory mapped, and depending on how the chipmaker architected it all you have “some” control over what peripherals can be managed in the secure and insecure regions. Often times any crypto stuff like side loading is only the secure region.
I think they mean like the private keys for start communication with whatever iOT servers that you might be using. And yea if your insecure region is unleashed it means someone might be able to hijack the active connection. There are two ways to think about it
-
At least no one can export your security keys and create more devices with your keys. They are stuck basically with only the one portal to your servers. This at least prevents Chinese knockoff companies from trying to use your cloud stack and pricey servers for their own products.
-
If you really don’t want someone into your cloud at all, you could try to move the entire communication exchange to the secure region. Its really hard and opens up more attack vectors if done wrong… But the company I work for is so paranoid so we are the lunatics trying to move the entire cloud interaction layer into the secure region. This is especially hard since generally speaking WiFi and bluetooth drivers themselves are exposed in the insecure space so we need to find a way to hook it all.
From my understanding TrustZone enables you to have a proper “Root of Trust” on the MCU. If used correctly you can properly lock down the bootloader such that even privileged code cannot view or modify the bootloader.
An MPU alone for example can only divide your code into privileged and non privileged code. Where things like interrupt handlers are always running in a privileged mode, meaning they have full access to other privileged memory and peripherals. In this case if a bad actor is able to jump and execute malicious code from something like an ISR then their code will also run at the higher privileged level and have access to privileged memory and peripherals.
With TrustZone the secure and non-secure code operate in 2 completely different execution environments. This allows you to better isolate secure code and other secrets from the non-secure code. So if someone manages to execute malicious code on any privilege level on the non-secure side they still won’t have access to anything on the secure side
This and a MPU are one and the same more or less. This is for ARM M series chips, and up until recently we didn’t even have an MPU haha. Arm TrustZone is just a really small MPU and an architecture to allow us to utilize our basic MPU. Secure and Insecure regions can’t/shouldn’t touch each other, and are memory locked. They even sit in different address spaces.
I think FreeRTOS even found a way to use some more of the TrustZone features to put different threads in their own memory spaces, but frankly the MPU included in modern ARM M chips is still so primitive compared to A series chip, or modern x86 chips to really have the same kind of memory isolation that modern linux machines utilize.
**EDIT spelling theirs → threads