-
Notifications
You must be signed in to change notification settings - Fork 6.6k
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
Comments
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. 🤖💙 |
Updated the proposal, specifically:
|
Some points from my side:
The general proposal / idea looks great to me :) |
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. |
@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.
Yeah. This limitation comes from the PSA Secure Storage API which defines entry UIDs as a single 64-bit field without defined ranges. |
@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. |
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.
I'm not following you here. Include what limitation and where? Validate what method? |
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, ...).
Validation of: |
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
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
The limitation you are talking about can be solved by implementing a translation from e.g. string identifiers to the numerical Then, if there are serious limitations in the PSA API specification, I imagine we could participate in the discussion to shape its future. |
One question: One suggestion |
I do have a question regarding the generation of the AEAD key. In Proposed change you write:
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? |
Architecture WG 2024-07-23:
|
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.
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 |
The initial implementation indeed doesn't have any mention of HUK. The HUK library in NCS is highly Nordic-specific. |
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":
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. |
@tomi-font I did some reading on the PSA Secure Storage and I think we shouldn't/can't implement this in zephyr:
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: |
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...
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.
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 _
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!
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
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 |
@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. |
Unfortunately Mbed TLS has made the Native ITS support somewhat difficult to find 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.
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.
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".
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.... |
@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.
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. |
@frkv, in the reference to the "native" support I only see calls to @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. |
@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. |
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: 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 |
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.
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. |
Implements zephyrproject-rtos#75275. Signed-off-by: Tomi Fontanilles <[email protected]>
Resolves zephyrproject-rtos#75275. Signed-off-by: Tomi Fontanilles <[email protected]>
Implements RFC zephyrproject-rtos#75275. Signed-off-by: Tomi Fontanilles <[email protected]>
Implements RFC zephyrproject-rtos#75275. See the added documentation for more information. Signed-off-by: Tomi Fontanilles <[email protected]>
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]>
Implements RFC zephyrproject-rtos#75275. See also the PR (zephyrproject-rtos#76222) for more information.
Implements RFC zephyrproject-rtos#75275. See also the PR (zephyrproject-rtos#76222) for more information.
Implements RFC zephyrproject-rtos#75275. See also the PR (zephyrproject-rtos#76222) for more information.
Implements RFC zephyrproject-rtos#75275. See also the PR (zephyrproject-rtos#76222) for more information. Signed-off-by: Tomi Fontanilles <[email protected]>
Implements RFC zephyrproject-rtos#75275. See also the PR (zephyrproject-rtos#76222) for more information. Signed-off-by: Tomi Fontanilles <[email protected]>
Implements RFC #75275. See also the PR (#76222) for more information. Signed-off-by: Tomi Fontanilles <[email protected]>
Implements RFC zephyrproject-rtos#75275. See also the PR (zephyrproject-rtos#76222) for more information. Signed-off-by: Tomi Fontanilles <[email protected]>
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]>
Implements RFC zephyrproject-rtos#75275. See also the PR (zephyrproject-rtos#76222) for more information. Signed-off-by: Tomi Fontanilles <[email protected]>
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'spsa_key_id_t
is 32 bits while PSA ITS'spsa_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:
__builtin_return_address()
and guessing whether the call comes from Mbed TLS? GCC-specific and fragile.The text was updated successfully, but these errors were encountered: