Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduction of a subsystem that implements the PSA Secure Storage API #75275

Closed
tomi-font opened this issue Jul 1, 2024 · 24 comments · Fixed by #76222
Closed

Introduction of a subsystem that implements the PSA Secure Storage API #75275

tomi-font opened this issue Jul 1, 2024 · 24 comments · Fixed by #76222
Assignees
Labels
Architecture Review Discussion in the Architecture WG required area: mbedTLS / PSA Crypto area: Secure Storage Secure Storage area: Security Security area: TF-M ARM Trusted Firmware-M (TF-M) RFC Request For Comments: want input from the community

Comments

@tomi-font
Copy link
Collaborator

tomi-font commented Jul 1, 2024

Introduction

The aim is to introduce a subsystem that implements the Platform Security Architecture (PSA) Secure Storage API. The subsystem will be available only on platforms without Trusted Firmware-M (TF-M) or similar secure processing environment that already implements the API.

The subsystem will allow storing data of any kind to different kinds of non-volatile memories (NVM).
Optionally, depending on device-specific features and on a best-effort basis, it may provide security to the assets stored through the PSA Secure Storage API. This is highly dependent on the hardware capabilities that are available and used on every device.
In any case, regardless of the storage medium or the means employed to secure the data at rest, the subsystem will not provide the same the level of security than that of a secure processing environment like TF-M, which provides isolation and protection guarantees.

The subsystem is completely separate from TF-M, and aims at providing an implementation of the PSA Secure Storage API on platforms that don't have one.
As a consequence of that, the subsystem will also enable the use of persistent keys in the PSA Crypto API.

Problem description

PSA Crypto

Zephyr has decided to adopt the PSA Crypto API as the single API to be used for cryptographic operations (#43712), and recent efforts have been made towards that goal.

The PSA Crypto API contains key management functions that must be called to be able to perform cryptographic operations that make use of keys. Under the hood, those key management functions call into the PSA Internal Trusted Storage (ITS) API (which is part of the PSA Secure Storage API) to store the key material to persistent storage.

In Zephyr, Mbed TLS is the PSA Crypto provider. However it doesn't provide an implementation of the PSA ITS API. So the current state is that, on platforms without PSA ITS provider (such as TF-M), keys imported into PSA Crypto for use are kept in a volatile key store, which means that they must be imported into PSA after every power cycle.
In practice it's worse than that: pretty much every use of PSA Crypto keys in Zephyr imports (and destroys) keys for every cryptographic operation.

The PSA Crypto API is designed to use cryptographic keys only by reference (psa_key_id_t) to avoid having the calling code handle the key material for every cryptographic operation, because this is detrimental to the overall security.
Also, when writing code that relies on keys to perform cryptographic operations, a developer cannot currently just do the needed operations. The burden of key management is present everywhere those operations are called, and there is no standard way to provide any kind of security to the key material at rest. It's up to every developer to implement that, over and over again.

This is something that will change once the PSA ITS API is made available on all platforms.

Uniform storage solution

Additionally, Zephyr currently doesn't have a standardized API to store data to NVM with the possibility of providing device-specific protection guarantees (encryption, isolation, etc.).

Platforms with a PSA Secure Storage provider are already able to do that, but in a non-portable way that cannot be extended unconditionally to the whole codebase, which hurts its adoption for them as well.

Implementing and standardizing on the PSA Secure Storage API makes it possible to provide support for a generic solution for storing critical assets that code relies on for operation.
It will ensure there is a portable way to take advantage of different devices' security features for storage, including TF-M-enabled platforms.

Because the security that can be provided is inherently tied to the security features every device provides, the level of security of the storage solution will vary.
It is however in any case better than that current state of storing data in clear; the level of security increases along with the hardware features made available on a given device.

Also note that, because the goal is to standardize on an API and make it available on all the platforms, the implementation provided by Zephyr will not be fully compliant with the specification. PSA has a specific model in mind, and specifies certain requirements that are not compatible with all devices.

Proposed change

The subsystem will provide an implementation of the PSA Secure Storage API on all platforms that don't already have one such that the API will be usable on every platform, without hard requirement on security features.

The PSA Secure Storage API specification assumes security features are used to protect the stored assets. The level of security that can be claimed on a specific device is dependent on the security features that are available and enabled. If the device doesn't make its security features available to the API, then the implementation can't claim that it provides security. In this case it will only be providing functional support for the API.
Certifiability is also not in the scope of this proposal. It is the end users' responsibility to make sure that the implementation they use is fully compliant and certifiable, if it is so desired.

The initial proposed implementation is based on something that already exists and lives in the nRF Connect SDK (NCS) as the trusted storage library. A look can be taken to see its current architecture there, however it will be changed and NCS specifics such as the HUK part will be removed.

Detailed RFC

The intent is to have a customizable PSA Secure Storage provider so that different devices and use cases can be supported.

To this end, the subsystem will be modular and configurable with different implementations, including custom ones.

Proposed change (detailed)

Below is a proposal of the initial architecture of the subsystem.

Exposed interface

The interface exposed to Zephyr and application code by the subsystem is the PSA Secure Storage API, which consists of the Internal Trusted Storage (ITS) and the Protected Storage (PS) APIs.

From there the subsystem takes on the task of transforming and storing the data.

PSA ITS API implementation

The implementation calls into the (ITS-specific) modules described below. It handles the logic pertaining to the PSA ITS API and orchestrates the transformation and storage of the data.
It can be replaced with a custom implementation of the whole PSA ITS API if wanted.

Transformation of the data

This module is responsible for the transformation of the data before it's written to and after it's read from NVM. Any implementation may be used by simply implementing the relevant API, allowing to cater for device-specific capabilities. For instance, if a device chooses to store the ITS data to a hardware-protected secure element, it may not need to protect the data in any way before storing it.

Zephyr will provide an implementation of this module that uses authenticated encryption with associated data (AEAD), which can ensure the confidentiality, integrity and authenticity of the data, but only when a secure encryption key and a random entropy source are provided. How the encryption key is provided, what AEAD scheme is used and how nonces are provided are all separately configurable and custom implementations can replace the default ones by implementing the relevant functions.

Storage to NVM

This module is responsible for storing the data to and retrieving it from the storage medium.

It can be implemented with any type of backend for persistent storage, allowing for example to store data off-chip on a secure element.

Zephyr will provide some implementation(s) of this module using NVM API(s) like the settings subsystem.

Again, custom implementations may be used instead of the existing one(s) by implementing the relevant API (set/get/remove functions).

PSA PS API implementation

As of the initial implementation, the PS API won't have an implementation of its own and will by default call into that of the ITS API (a well-expected use case - see 2.4. The Internal Trusted Storage API: [...] it is expected that many platforms will have the Protected Storage API call directly into the Internal Trusted Storage API).

External flash support (that the PSA PS covers) will thus not be supported right away. It is one of the things that will be addressed by follow-up work to give the PS API its own implementation.

Anyhow, this is something that can already be circumvented by providing one's own implementation of the PSA PS API.

Dependencies

The PSA Crypto API is dependent on the PSA ITS API for a proper functioning.
Having a PSA ITS provider on all platforms will help Zephyr in its adoption of the PSA Crypto API.

Concerns and Unresolved Questions

Giving a false sense of security

The subsystem shall not give a false sense of security to the end users if no hardware security features are used to securely protect the data it stores.
Documentation should clearly explain this and warnings could be output at build and/or boot time if the implementation in use may not be truly secure.

ID collisions

When Mbed TLS's implementation of the PSA Crypto API will have access to the PSA ITS API, it will start storing all persistent keys using the provided psa_key_id_t as the psa_storage_uid_t when calling into the PSA ITS API.

This means that collisions will happen if the same numerical ID values are used for both PSA Crypto keys and PSA ITS entries. Different approaches to this are possible:

  • Not do anything about it. Document this as a limitation, possibly stating that to avoid collisions PSA ITS entry IDs should be > UINT32_MAX (because PSA Crypto's psa_key_id_t is 32 bits while PSA ITS's psa_storage_uid_t is 64 bits).

  • Try to enforce collisions not happening in a way that is transparent for the calling code, e.g. by forcefully setting one of the 32 upper bits of the PSA ITS entry UIDs when calls don't come from Mbed TLS. For that, some mechanism to differentiate non-Mbed TLS callers would be nedded. Could be done by:

    • Using GCC's __builtin_return_address() and guessing whether the call comes from Mbed TLS? GCC-specific and fragile.
    • Defining the PSA ITS API functions as macros for Mbed TLS. That would allow the implementation to differentiate when the call comes from there.
@tomi-font tomi-font added the RFC Request For Comments: want input from the community label Jul 1, 2024
Copy link

github-actions bot commented Jul 1, 2024

Hi @tomi-font! We appreciate you submitting your first issue for our open-source project. 🌟

Even though I'm a bot, I can assure you that the whole community is genuinely grateful for your time and effort. 🤖💙

@tomi-font
Copy link
Collaborator Author

Updated the proposal, specifically:

  • Updated Problem description.
  • Added PSA PS implementation.
  • Expanded on the ID collisons concern.

@ceolin
Copy link
Member

ceolin commented Jul 17, 2024

Some points from my side:

  1. It is not clear / defined the HW dependencies to guarantee confidentiality and authenticity. Where the AEAD key is stored / generated ?
  2. For the ID collision problem, the macro idea seems good to me. We can use upper bits to define Zephyr's namespace.
    The only possible drawback (but maybe it is not a problem) is that we are limited to one namespace for Zephyr's code and application.

The general proposal / idea looks great to me :)

@JordanYates
Copy link
Collaborator

It is not clear / defined the HW dependencies to guarantee confidentiality and authenticity. Where the AEAD key is stored / generated ?

From my understanding this is entirely dependent on the implementation and the hardware capabilities. A truly secure solution is not possible unless the HW provides a persistent storage location for encryption keys that cannot be accessed by software but can be used for crypto operations (i.e. nRF key storage/cryptocell).

But even if that is not available you can still do better than storing the data in plaintext. For example, my fallback solution for the key is to calculate a SHA-256 hash over the unique hardware ID, which at least means that data is not encrypted with the same key on any two devices.

@nashif nashif added the Architecture Review Discussion in the Architecture WG required label Jul 18, 2024
@tomi-font
Copy link
Collaborator Author

It is not clear / defined the HW dependencies to guarantee confidentiality and authenticity. Where the AEAD key is stored / generated ?

@JordanYates mostly already addressed this. The key isn't stored, it's generated when needed (when the API is called). The default behavior is to use the SHA-256 hash of a HW identifier if available via the HW info API, or of the UID of the entry being processed, which is admittedly not very secure as UIDs could be guessed, but still better than nothing. Some implementation must be available on all platforms for the API to be usable unconditionally.

For the ID collision problem, the macro idea seems good to me. We can use upper bits to define Zephyr's namespace.
The only possible drawback (but maybe it is not a problem) is that we are limited to one namespace for Zephyr's code and application.

Yeah. This limitation comes from the PSA Secure Storage API which defines entry UIDs as a single 64-bit field without defined ranges.
But if/when Zephyr code starts using key IDs/entry UIDs for persistent data, we could define ranges of values to be used by different callers that are not really aware of each other (different subsystems, application code...).

@Laczen
Copy link
Collaborator

Laczen commented Jul 23, 2024

@tomi-font from the documentation and your last remark it seems that the api to use secure storage is limited to using a identifier as a key for data storage. Although nvs could have been used like this for settings (limited to a 16bit identifier) it was never used in this way because it is not flexible enough to support multiple subsystems and varying keys (e.g. bt id's).

It would be good to include this limitation to validate whether this method should be considered as a method to securely store any kind of data.

@tomi-font
Copy link
Collaborator Author

@tomi-font from the documentation and your last remark it seems that the api to use secure storage is limited to using a identifier as a key for data storage. Although nvs could have been used like this for settings (limited to a 16bit identifier) it was never used in this way because it is not flexible enough to support multiple subsystems and varying keys (e.g. bt id's).

Though nothing forbids using NVS directly if wanted; an implementation of the storing module could do that by properly packing the UIDs into 16-bit identifiers, obviously introducing the constraint of less possible UIDs.

It would be good to include this limitation to validate whether this method should be considered as a method to securely store any kind of data.

I'm not following you here. Include what limitation and where? Validate what method?

@Laczen
Copy link
Collaborator

Laczen commented Jul 23, 2024

It would be good to include this limitation to validate whether this method should be considered as a method to securely store any kind of data.

I'm not following you here. Include what limitation and where?

The limitation of only being able to store data by a "integer" identifier. Suppose you would like to store data for some node that has an identifier e.g. a MAC address, this can very easily be mapped to "/net/AA:BB:CC:DD/prop1"=..., "/net/AA:BB:CC:DD/prop2"=..., ... while it is a lot more involving to map this to "integers" especially when it is needed to delete data from storage (keeping track of unused identifiers, ...).

Validate what method?

Validation of:
"The subsystem will allow securely storing data of any kind, with the actual security provided depending on what security features are available on a given platform.",
is the secure storage api (with its limitations) a good api to provide this.

@tomi-font
Copy link
Collaborator Author

The limitation of only being able to store data by a "integer" identifier. Suppose you would like to store data for some node that has an identifier e.g. a MAC address, this can very easily be mapped to "/net/AA:BB:CC:DD/prop1"=..., "/net/AA:BB:CC:DD/prop2"=..., ... while it is a lot more involving to map this to "integers" especially when it is needed to delete data from storage (keeping track of unused identifiers, ...).

This limitation is part of the PSA Secure Storage API: https://arm-software.github.io/psa-api/storage/1.0/api/api.html#c.psa_storage_uid_t

Validation of:
"The subsystem will allow securely storing data of any kind, with the actual security provided depending on what security features are available on a given platform.",
is the secure storage api (with its limitations) a good api to provide this.

The API is not a free choice, it's purely and simply the PSA Secure Storage API. And I think that we are past the point of wondering whether it's the right choice because

  • Zephyr is moving towards having the PSA Crypto API as the only API, and so is Mbed TLS;
  • Mbed TLS calls the PSA ITS API for storage of persistent keys;
  • TF-M implements and exposes the PSA Secure Storage API;
  • we don't want to create more fragmentation of APIs.

The limitation you are talking about can be solved by implementing a translation from e.g. string identifiers to the numerical psa_storage_uid_t ones. 64 bits is a lot.

Then, if there are serious limitations in the PSA API specification, I imagine we could participate in the discussion to shape its future.

@omkar3141
Copy link
Collaborator

One question:
#1 The secure storage subsystem could be incredibly useful not just for on chip storage, but also off-chip storage in external flash. Is external flash support considered here?

One suggestion
#1 IMO, settings subsystem as it is envisioned and implemented by various modules in zephyr is quite anti-embedded and inefficient. It has enormous amount of overhead in the form of (a current pattern established in zephyr) long file names (e.g. "bt/mesh/..." vs "bm/..."). Often to store couple of bytes of frequently changing state data, the overhead is 15+ bytes. For many practical secure embedded applications frequently changing state data needs to be stored (such as last known state of the light bulb with its various internal values, or replay protection sequence number for an incoming message from given address). Though not directly impacting the secure storage, but designing secure storage assuming existing settings subsystem is used as a storage mechanism could lead to some inefficiencies. Almost all of the data for commercial/industrial products can be classified as 'secure' and will end up requiring usage of this library. Bluetooth Mesh literally requires hundreds of 'settings' to be stored, some of them are frequently changing. Potentially many of them will be classified as 'security related'. Therefore, please consider - minimizing flash wear, duplicate detection, non-existing entry deletion, and reporting corrupted entry to top level application code (through some callbacks) - aspects in this design.

@str4t0m
Copy link
Collaborator

str4t0m commented Jul 23, 2024

I do have a question regarding the generation of the AEAD key. In Proposed change you write:

A look can be taken to see its current architecture there, however it is expected to change and NCS specifics such as the HUK part will be removed.

Do you really mean to remove the HUK part or do have the intention to define an API which different platforms can implement to derive such a key?

@henrikbrixandersen
Copy link
Member

Architecture WG 2024-07-23:

@tomi-font
Copy link
Collaborator Author

One question:
#1 The secure storage subsystem could be incredibly useful not just for on chip storage, but also off-chip storage in external flash. Is external flash support considered here?

It is. The PSA PS API is meant for external storage. Though, as stated in the RFC, the proposed initial implementation won't support external storage. The PSA PS API will still be available, but it will call directly into the ITS API.
This is to get the most important things in first and not have an overwhelming amount of changes at once. (The PSA PS depends on the PSA ITS for storage of replay protection values.)
But, seeing that there is strong interest for external storage, this would definitely be a follow-up item.

One suggestion
#1 IMO, settings subsystem as it is envisioned and implemented by various modules in zephyr is quite anti-embedded and inefficient. It has enormous amount of overhead in the form of (a current pattern established in zephyr) long file names (e.g. "bt/mesh/..." vs "bm/..."). Often to store couple of bytes of frequently changing state data, the overhead is 15+ bytes. For many practical secure embedded applications frequently changing state data needs to be stored (such as last known state of the light bulb with its various internal values, or replay protection sequence number for an incoming message from given address). Though not directly impacting the secure storage, but designing secure storage assuming existing settings subsystem is used as a storage mechanism could lead to some inefficiencies. Almost all of the data for commercial/industrial products can be classified as 'secure' and will end up requiring usage of this library. Bluetooth Mesh literally requires hundreds of 'settings' to be stored, some of them are frequently changing. Potentially many of them will be classified as 'security related'. Therefore, please consider - minimizing flash wear, duplicate detection, non-existing entry deletion, and reporting corrupted entry to top level application code (through some callbacks) - aspects in this design.

Thanks for the feedback. I get the concerns about the use of the settings subsystem. I didn't do much thinking about the storage solution and simply went with the option that had been chosen in NCS: the settings subsystem. The API it exposes is convenient (e.g. the setting names are not limited to a numerical value smaller than psa_storage_uid_t).
However one thing I can assure you is that its use is in no way baked into the secure storage subsystem. It's just one of the possible (storing module) implementations. It's just a matter of implementing set/get/remove functions.
One idea that has come up already by different parties is to use NVS directly. This (or any other storage solution) could be provided as an option in Zephyr. It's just that its implementation would be more complex than the settings subsystem one (need to shrink the entry UIDs or implement a way around it, consider the partitioning...).
So again, this can (and will) definitely be improved. I think it's more a matter of first getting something in. There has already been remarks that there are lots of changes in the PR.

@tomi-font
Copy link
Collaborator Author

Do you really mean to remove the HUK part or do have the intention to define an API which different platform can implement to derive such a key?

The initial implementation indeed doesn't have any mention of HUK. The HUK library in NCS is highly Nordic-specific.
Though I think it could be worth adding an API to Zephyr that would provide similar functionality, with drivers for different platforms (similarly to the HW info API).
However this would be a separate thing, e.g. follow-up work. cc @ceolin

@Laczen
Copy link
Collaborator

Laczen commented Jul 25, 2024

One suggestion #1 IMO, settings subsystem as it is envisioned and implemented by various modules in zephyr is quite anti-embedded and inefficient. It has enormous amount of overhead in the form of (a current pattern established in zephyr) long file names (e.g. "bt/mesh/..." vs "bm/..."). Often to store couple of bytes of frequently changing state data, the overhead is 15+ bytes. For many practical secure embedded applications frequently changing state data needs to be stored (such as last known state of the light bulb with its various internal values, or replay protection sequence number for an incoming message from given address). Though not directly impacting the secure storage, but designing secure storage assuming existing settings subsystem is used as a storage mechanism could lead to some inefficiencies. Almost all of the data for commercial/industrial products can be classified as 'secure' and will end up requiring usage of this library. Bluetooth Mesh literally requires hundreds of 'settings' to be stored, some of them are frequently changing. Potentially many of them will be classified as 'security related'. Therefore, please consider - minimizing flash wear, duplicate detection, non-existing entry deletion, and reporting corrupted entry to top level application code (through some callbacks) - aspects in this design.

This is dependent on the backend used to store data. When the nvs backend is used the following actions are taken to reduce the "inefficienties":

  1. The storage of data is split up in a "name" and a "value", the "name" will not be written each time when only the value changes only the value is written.
  2. When the same name and value are rewritten nothing is written to flash.
    The nvs backend is far from perfect though: using this split up between data and value makes it slower and as they reside on the same "volume" (which is a kind of flash circular buffer) the "name" data is copied when the buffer is fully used.

The non-existing entry deletion (is this no longer needed data) and corrupted entry reporting are something that should be done by the system that is using settings. If you have ideas on how to improve this proposals are always welcome.

@Laczen
Copy link
Collaborator

Laczen commented Jul 25, 2024

@tomi-font I did some reading on the PSA Secure Storage and I think we shouldn't/can't implement this in zephyr:

  1. The subsystem is optional and not required by PSA-Crypto,
  2. The PSA Secure Storage is dedicated to the ARM secure architecture that not all systems can provide,
  3. When implementing the PSA secure storage on systems with the ARM secure architecture it is needed to follow the requirements (which is not done in the proposed PR),
  4. The used uids for storage are out of control by zephyr which makes it impossible to guarantee that subsystems that are using the secure storage will not need changes in future,
  5. The proposed PR makes the "promise" of being secure while this is entirely based on the key derivation being secure,

However I do think it would be good to have a solution to save (derived) keys with the properties as defined in the PSA secure storage for fast retrieval. And it would also be good to provide encrypted and authenticated data in the settings subsystem. I would therefore propose to define a "zephyr" key storage and retrieval system that would be based on the settings subsystem (using the same methodology: encrypt and authenticate using chacha20poly1305) based on a "zephyr" key derivator that can be a hardware (HUK) or a software HKDF (incorporating a device id and e.g. efuse data). Whether the storage would be secure would be dependent on this key derivator but for the storage in settings I would just call the routines: settings_save_encrypted and settings_save_encrypted_authenticated which does not make a "secure" promise.

@tomi-font tomi-font changed the title Introduction of a secure storage subsystem Introduction of a subsystem that implements the PSA Secure Storage API Jul 25, 2024
@tomi-font tomi-font added area: Storage Storage subsystem area: TF-M ARM Trusted Firmware-M (TF-M) labels Jul 25, 2024
@frkv
Copy link
Collaborator

frkv commented Jul 25, 2024

@tomi-font I did some reading on the PSA Secure Storage and I think we shouldn't/can't implement this in zephyr:

  1. The subsystem is optional and not required by PSA-Crypto,

Persistent key support is a requirement for cryptographic keys (and certificates). Loading a key each time means the key is forever easily accessible in a less trusted scope (because it needs to be imported every time). Effectively stating that "this subsystem is optional" makes it difficult to add support for proper handling of key and sensitive data e.g. on secure element, trusted enclaves etc. This RFC tries to give the functional support to handle key store in the de-facto methodology that Mbed TLS expects. It is fine to state that PSA crypto makes persistent key storage optional, but not supporting it (with a subsystem like this) makes persistent key using PSA crypto APIs impossible. I hope you aren't trying to argue against this...

  1. The PSA Secure Storage is dedicated to the ARM secure architecture that not all systems can provide,

No it is not. Arm PSA and the PSA Secure Storage APIs is not tied to TrustZone enabled devices or any Arm specific product or architecture. Even in Mbed TLS the attachment point for PSA ITS is just the PSA ITS APIs. In its documentation it is called "Native Internal Trusted Storage support" if you provide it in your RTOS and it does not require or rely on anything from TF-M. The only thing that we provide here is the API compatibility of PSA secure storage APIs giving a portable solution that works well with PSA crypto (defacto crypto API in Zephyr) on both TF-M and non TF-M enabled devices.

You can certify using Arm PSA for your product based on an in-house solution (that is not an Arm product), This also include devices with secure elements and/or trusted enclaves.

  1. When implementing the PSA secure storage on systems with the ARM secure architecture it is needed to follow the requirements (which is not done in the proposed PR),

The level of security that different devices can provide will vary widely, and it can even vary on devices that has ARMv8 security extension (TrustZone). The level of security you have as a target for your product is something the end-customer decides, in the end. You might end up having no security, and only functional support for these APIs (meaning you are using portable code, but that is it)

Some companies obviously will consider certifying said solution (e.g. through Arm PSA certification) or using other types of adjunct reviews to ensure that the product is up to speed on supporting regulatory requirements in different markets, or to have a edge on the competition. For Arm devices that have TrustZone then a certified version using TF-M is a "peace of mind" with regards to regulatory requirements

But there exists a world outside of TF-M and Arm PSA. Secure Storage can be provided by a secure element or a trusted enclave, for instance In the latter case you might even have specific PSA crypto driver implementation to support your special hardware, and in this case you don't need to rely on TrustZone if you don't have it or don't want to use it.

_Zephyrs choice is to standardize on PSA crypto as the defacto API. We shouldn't block people from integrating. and the integration point for storage is "native internal trusted storage" support which is part of Mbed TLS (not TF-M). The integration point for the crypto implementation is the PSA crypto driver interface _

  1. The used uids for storage are out of control by zephyr which makes it impossible to guarantee that subsystems that are using the secure storage will not need changes in future,

This can be handled with name-spacing. PSA crypto supports this by allowing for designating different storage location and there are possibilities to use designated bit-masks to ensure different components aren't hunting for the same identifiers for stored items. This is a topic we want to discuss and get very in depth with for the RFC! We absolutely don't want something out-of-control!

  1. The proposed PR makes the "promise" of being secure while this is entirely based on the key derivation being secure,

It does not make a promise of being secure. It points out that the features you have can give you security, but this is not guaranteed for every type of device. There will be an update on this in the RFC when @tomi-font has had time to finalize it

However I do think it would be good to have a solution to save (derived) keys with the properties as defined in the PSA secure storage for fast retrieval. And it would also be good to provide encrypted and authenticated data in the settings subsystem. I would therefore propose to define a "zephyr" key storage and retrieval system that would be based on the settings subsystem (using the same methodology: encrypt and authenticate using chacha20poly1305) based on a "zephyr" key derivator that can be a hardware (HUK) or a software HKDF (incorporating a device id and e.g. efuse data). Whether the storage would be secure would be dependent on this key derivator but for the storage in settings I would just call the routines: settings_save_encrypted and settings_save_encrypted_authenticated which does not make a "secure" promise.

Whatever your system can provide for hiding a hardware key, the process of how you derive keys from it and the possibility to e.g. provide monotonic counters (to protect against replay attacks) is going to set the bar for what security you can claim. And it is not about just about having hardware that can support it, you must integrate it to the storage solution and make sure you make use of it!

Final words

I would argue against a different (and proprietary) zephyr key storage and retrieval system (based on settings system). The PSA secure storage APIs are chosen with intent, and this methodology is accepted by the Zephyr Security Committee. A zephyr-proprietary key storage solution with any other type of API will not be portable with and without TF-M (TF-M is a standard component in Zephyr).

Mbed TLS is provided as-is in Zephyr, it is the standard component that gives you support for the de-facto crypto API in zephyr: PSA crypto. Mbed TLS has explicit integration point for persistent key storage (It uses PSA ITS). The PSA crypto APIs have been designed to ensure that keys doesn't need to be passed in regular RAM (e.g. in an NS image). It supports keys-by-reference, and this is something that a internal usage of ITS will give you some level of isolation for. Of course the best solution is something that is hidden behind a secure service (e.g. in TF-M), but there is a case to be made that this can be facilitated for a secure element as well.

We recommend adding the PSA PS as well, as this is something that is portable with or without TF-M and Zephyr doesn't have anything that compares to this, with the expressive focus on security features, e.g for certificate storage which Mbed TLS relies on for TLS/DTLS support

@Laczen
Copy link
Collaborator

Laczen commented Jul 25, 2024

@frkv, thanks for your comments. I am just expressing my concerns about the introduction of this subsystem and whether it should be used as a generic API for secure storage and/or as just a subsystem for secure storage of keys, certificates, ...

I have been reading the documents on PSA Certified Secure Storage API, and this is tightly coupled to the ARM security platform. I have not come across any documentation regarding the Native Internal Trusted/Secure Storage API. If there are specifications for this we need to monitor if the implementation does adhere to the specifications set in this document. It is vital that we do not just rely on the PSA Crypto API's to ensure that keys are passed securely (closing all our front doors) while just providing obfuscation on storage (leaving the back doors open). In some cases it might be better not to provide persistent keys (and no ITS), force a new key agreement phase when required, use and destroy the key.

Using the settings backend as storage does come with some limitations, the most important being that everyone has access to everything in it. On top of this it is not guaranteed to be on internal storage.

The ideal solution would be to provide a API that conforms with the PSA Certified Secure Storage API when possible (on specific platforms) while providing a "more" relaxed methods on other platforms.

@frkv
Copy link
Collaborator

frkv commented Jul 25, 2024

@frkv, thanks for your comments. I am just expressing my concerns about the introduction of this subsystem and whether it should be used as a generic API for secure storage and/or as just a subsystem for secure storage of keys, certificates, ...

Unfortunately Mbed TLS has made the Native ITS support somewhat difficult to find
Please follow the else-case here: https:/Mbed-TLS/mbedtls/blob/f938f4ff063a6714caa64be454728a501f01be5a/tf-psa-crypto/core/psa_crypto_storage.c#L22 As you see here it is an implementation detail to provide PSA ITS

In fact Mbed TLS provides a C File abstraction API, but I would not recommend that for any embedded device (we can make it much more efficient with other NVM mechanisms and we can also address issues like wear-leveling, code and data size optimizations etc.)

If TF-M is enabled then PSA ITS is provided out-of-the box as a secure service inside the PSA Platform Root of Trust (one of the mandatory services to use)

We make a strong case that PSA ITS is not supposed to be accessed and used directly as it would forgo the key-by-reference abstraction in case you have the ability to set up a Trusted Execution Environment (TEE) (e.g. what TF-M provide with its Secure Processing Environment (SPE). We recommend all management of cryptographic keys go through the PSA crypto key management APIs, and if this is the case then PSA ITS is a de-facto dependency in the system.

I have been reading the documents on PSA Certified Secure Storage API, and this is tightly coupled to the ARM security platform. I have not come across any documentation regarding the Native Internal Trusted/Secure Storage API. If there are specifications for this we need to monitor if the implementation does adhere to the specifications set in this document. It is vital that we do not just rely on the PSA Crypto API's to ensure that keys are passed securely (closing all our front doors) while just providing obfuscation on storage (leaving the back doors open). In some cases it might be better not to provide persistent keys (and no ITS), force a new key agreement phase when required, use and destroy the key.

It is still viable to certify without using Arms TrustZone (ARMv8 security extension), in fact it is possible to certify you secure storage solution using e.g. a CPU-inaccessible key tied to a HW crypto engine providing the type of encryption we will showcase in this submodule.

That being said, the simplest approach for customers is likely to enable TF-M (if they can) and certify their product this way.

_But certification is not a requirement, this is up to each end-user. _

The level of security is going to be on available and enabled features. The same would be the case if there was a competing API that provides methodology to enable security features.

Using the settings backend as storage does come with some limitations, the most important being that everyone has access to everything in it. On top of this it is not guaranteed to be on internal storage.

This is a valid point and something we will delve into when we start discussing different means of providing instancing of storage (very relevant for the topic of ensuring that we don't hunt for the same UID across different product functionality (BLE, vs other protocols vs application-scope identifiers). There are options there, if you look at the type of backends you want to support. It pretty much gets down to a question of "routing".

The ideal solution would be to provide a API that conforms with the PSA Certified Secure Storage API when possible (on specific platforms) while providing a "more" relaxed methods on other platforms.

We still argue that as long as the compliance to the API is in place then the question on what kind of certifiability you have on your product becomes a second consideration. By standardization on the the PSA secure storage APIs then we bring TF-M support many steps ahead, at the same time as we try to cater to existing devices with fewer security options on a pure functional level. Do note that adopting to use PSA crypto has been heavily hindered by the fact that PSA crypto support has been lackluster in Zephyr. One of the reasons have been the lack of a standardized way of persistently stored keys.

Instead of coming up with a competing solution (a different API), why not resolve this in the naming of this subsystem and description of what kind of security you get in given device types

My company has a forked version of Zephyr and we have been able to introduce PSA crypto on non TF-M devices in our SDK ahead of Zephyr....

@omkar3141
Copy link
Collaborator

omkar3141 commented Jul 25, 2024

while just providing obfuscation on storage (leaving the back doors open).

@Laczen why are you assuming that storage will be just obfuscated? As @frkv mentioned ability to store this on flash (internal or external) in encrypted form could vary depending on the capabilities of the hardware platform.

In some cases it might be better not to provide persistent keys (and no ITS), force a new key
agreement phase when required, use and destroy the key.

Bluetooth mesh use case is exactly opposite. In mesh, keys required to establish the secure over-the-air channel are derived once at the beginning of lifecycle of the node using ECDH. Then this channel is used to distribute bunch of pre-generated keys required for application and networking use-cases. These keys (and their derivatives) then should be securely stored by the node until they are removed explicitly with over-the-air commands at some point of time later.

Similar concepts are used in Bluetooth's paired connections for Long Term Keys.

So, for Bluetooth application secured key + data (such as replay list) storage is a must for viable product that satisfies certain security requirements in various markets.

@Laczen
Copy link
Collaborator

Laczen commented Jul 25, 2024

@frkv, in the reference to the "native" support I only see calls to psa_its_set, ... there is no reference to a native implementation of psa_its_set, ... and especially not any reference to what is required from the psa_its_set, ... routines. If these requirements are the requirements detailed in the PSA Certified secure storage then the proposal is not honoring them. It would be good to share how you have introduced the PSA crypto and especially the psa_its_... part in your zephyr fork (of course without any details).

@omkar3141, I have no idea if BT-mesh is applying extra hardware based protection on the keys, replay lists, ... before storing them in settings. If they are not the "must" is simply not there.

@omkar3141
Copy link
Collaborator

@Laczen as stated in the earlier comment, requirements vary based on application, intended end-usage and markets. I feel, higher layer subsystems should not be inventing their own secure storage mechanism. I am refraining from centering this discussion around settings subsystem limitations because this could be changed tomorrow as more complex needs arise. This discussion is future looking and I see this becoming a necessity in near future. I also see the need for secure storage of not just keys and certificates but any arbitrary data that OEM developer deems important. I consider this as a major lacking feature in Zephyr RTOS.

@frkv
Copy link
Collaborator

frkv commented Jul 26, 2024

@frkv, in the reference to the "native" support I only see calls to psa_its_set, ... there is no reference to a native implementation of psa_its_set, ... and especially not any reference to what is required from the psa_its_set, ... routines. If these requirements are the requirements detailed in the PSA Certified secure storage then the proposal is not honoring them. It would be good to share how you have introduced the PSA crypto and especially the psa_its_... part in your zephyr fork (of course without any details).

Mbed TLS doesn't state anything about certified implementation of PSA secure storage APIs in their documentation. One of the options is to use C file APIs, which has nothing to do about certifiable scope (implemented directly in Mbed TLS) In the documentation fo the configurations related to persistent storage it says this:

image

The only requirement listed is a "native implementation of the PSA ITS interface", hence it is needed for any non TF-M implementation for Mbed TLS. The only other alternative is a implementation that is emulating support for it, which is mostly intended for CI purposes (I've asked)

Mbed TLS exists and is usable for devices that don't do TF-M. The same goes for PSA crypto support altogether. We add this for non TF-M devices regardless of any certifiability

@tomi-font
Copy link
Collaborator Author

I have reworked the RFC to clarify the intent, the scope and the limitations. I invite everyone to give a read to the updated version.

Architecture WG 2024-07-23:

I realized that I should have focused more on explaining the different components that are at play and consider more that the audience was likely not familiar with those topics.
Please let me know what you think of the revised RFC.

tomi-font added a commit to tomi-font/zephyr that referenced this issue Jul 29, 2024
tomi-font added a commit to tomi-font/zephyr that referenced this issue Jul 29, 2024
tomi-font added a commit to tomi-font/zephyr that referenced this issue Aug 2, 2024
@tomi-font tomi-font removed the area: Storage Storage subsystem label Aug 2, 2024
@tomi-font tomi-font linked a pull request Sep 4, 2024 that will close this issue
tomi-font added a commit to tomi-font/zephyr that referenced this issue Sep 10, 2024
Implements RFC zephyrproject-rtos#75275.
See the added documentation for more information.

Signed-off-by: Tomi Fontanilles <[email protected]>
tomi-font added a commit to tomi-font/zephyr that referenced this issue Sep 11, 2024
Implements RFC zephyrproject-rtos#75275.

See also the added documentation and the PR
(zephyrproject-rtos#76222)
for more information.

Signed-off-by: Tomi Fontanilles <[email protected]>
tomi-font added a commit to tomi-font/zephyr that referenced this issue Sep 13, 2024
tomi-font added a commit to tomi-font/zephyr that referenced this issue Sep 13, 2024
tomi-font added a commit to tomi-font/zephyr that referenced this issue Sep 13, 2024
tomi-font added a commit to tomi-font/zephyr that referenced this issue Sep 13, 2024
Implements RFC zephyrproject-rtos#75275.

See also the PR (zephyrproject-rtos#76222)
for more information.

Signed-off-by: Tomi Fontanilles <[email protected]>
tomi-font added a commit to tomi-font/zephyr that referenced this issue Sep 25, 2024
Implements RFC zephyrproject-rtos#75275.

See also the PR (zephyrproject-rtos#76222)
for more information.

Signed-off-by: Tomi Fontanilles <[email protected]>
@tomi-font tomi-font added the area: Secure Storage Secure Storage label Oct 7, 2024
carlescufi pushed a commit that referenced this issue Oct 7, 2024
Implements RFC #75275.

See also the PR (#76222)
for more information.

Signed-off-by: Tomi Fontanilles <[email protected]>
HubertYGuan pushed a commit to HubertYGuan/zephyr that referenced this issue Oct 10, 2024
Implements RFC zephyrproject-rtos#75275.

See also the PR (zephyrproject-rtos#76222)
for more information.

Signed-off-by: Tomi Fontanilles <[email protected]>
coreboot-org-bot pushed a commit to coreboot/zephyr-cros that referenced this issue Oct 11, 2024
Implements RFC zephyrproject-rtos/zephyr#75275.

See also the PR (zephyrproject-rtos/zephyr#76222)
for more information.

(cherry picked from commit bf0e6d7)

Original-Signed-off-by: Tomi Fontanilles <[email protected]>
GitOrigin-RevId: bf0e6d7
Cr-Build-Id: 8734380568354140561
Cr-Build-Url: https://cr-buildbucket.appspot.com/build/8734380568354140561
Copybot-Job-Name: zephyr-main-copybot-downstream
Change-Id: I1babaa0d25b3a12261f2bbc68ddbe7ca16124b14
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/zephyr/+/5914244
Tested-by: Jeremy Bettis <[email protected]>
Tested-by: ChromeOS Prod (Robot) <[email protected]>
Reviewed-by: Jeremy Bettis <[email protected]>
ycsin pushed a commit to ycsin/zephyr that referenced this issue Oct 12, 2024
Implements RFC zephyrproject-rtos#75275.

See also the PR (zephyrproject-rtos#76222)
for more information.

Signed-off-by: Tomi Fontanilles <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Architecture Review Discussion in the Architecture WG required area: mbedTLS / PSA Crypto area: Secure Storage Secure Storage area: Security Security area: TF-M ARM Trusted Firmware-M (TF-M) RFC Request For Comments: want input from the community
Projects
Status: Done
Status: Done
Status: Done
Development

Successfully merging a pull request may close this issue.

10 participants