Multiple storage backends support in PSA ITS #714

Open
opened 2026-03-16 00:28:55 -05:00 by Harshal5 · 4 comments
Harshal5 commented 2026-03-16 00:28:55 -05:00 (Migrated from github.com)

PSA ITS File Backend: Support for Multiple Storage Locations / Filesystems

The file-based PSA Internal Trusted Storage implementation (core/psa_its_file.c, enabled with MBEDTLS_PSA_ITS_FILE_C) uses a single compile-time path prefix, PSA_ITS_STORAGE_PREFIX, for all ITS files. All operations use that one prefix, so in practice only one storage location (one directory/filesystem) is supported.

I would like to request multiple storage locations or filesystems at runtime (e.g. different key types on different mounts) while continuing to use the upstream file-based implementation as the storage backend.

Current Behaviour

  • Storage path is derived only from PSA_ITS_STORAGE_PREFIX and the UID (e.g. prefix + "%08x%08x" + ".psa_its").
  • There is no abstraction over "where to store"; the code uses fopen/fread/fwrite/etc. with that single prefix.
  • So all ITS items live on one directory/filesystem. Choosing a different storage backend per a persistent key is not supported.

Desired Behaviour / Use Case

  • Use the file-based ITS implementation but allow different ITS items to be stored in different directories or filesystems at runtime.
  • Use case — multiple filesystem types: Some keys need to be stored on a FATFS filesystem, others on SPIFFS, and others on different non-volatile storage systems. The application should be able to route ITS items to the appropriate backend (e.g. by UID range or by key location) so that each storage type can be used where it fits (e.g. size limits, wear, or integration with existing data).

Possible Approaches (for feedback from the maintainers)

Here are some of the ways that I can think of to support multiple storage locations or backends without changing the public PSA ITS API.

1. Routing in the persistent key storage layer (above ITS)

Routing is implemented in the layer that calls ITS (e.g. psa_crypto_storage.c or equivalent). That layer has key attributes (including lifetime/location) at save/load/destroy time and dispatches to different "storage backends" (each of which may call an ITS-like API) based on psa_key_location_t. The file-based ITS backend then remains a single-backend implementation; multiple backends are composed above it.

To support one ITS (or storage backend) per filesystem, the key storage layer would need explicit support for routing key location to the appropriate ITS (or backend). For example: a way to register a storage backend per psa_key_location_t (e.g. “location A -> file ITS with prefix /fat/”, “location B -> file ITS with prefix /spiffs/”) and to resolve location -> backend when storing, loading, or destroying a key. The user would register an ITS (or ITS-like backend) per filesystem, and the key storage layer would dispatch to the right one based on the key’s location.

2. User-registered callbacks (user-managed UID-to-storage mapping)

We reserve some user application key ID range for custom (non-default) storage keys. The user registers four callbacks with the ITS layer (write, read, erase, get_info). When these callbacks are registered, the ITS implementation invokes them for ITS operations instead of using the default filesystem APIs only if the UID lies in the custom range.
The user’s callback implementation is responsible for deciding where each UID is stored: it can map different UIDs to different backends (e.g. FATFS, SPIFFS, NVS, or other non-volatile storage) in any way it chooses (ranges, lookup table, etc.). No UID ranges are reserved by the library; mapping is entirely under the application’s control.

Questions for Maintainers

  1. Is supporting multiple storage locations / filesystems for the file-based ITS backend something the project would consider (as an optional extension)?
  2. If yes, is there a preferred approach that fits the project's API and design goals?
## PSA ITS File Backend: Support for Multiple Storage Locations / Filesystems The file-based PSA Internal Trusted Storage implementation (`core/psa_its_file.c`, enabled with `MBEDTLS_PSA_ITS_FILE_C`) uses a single compile-time path prefix, `PSA_ITS_STORAGE_PREFIX`, for all ITS files. All operations use that one prefix, so in practice only one storage location (one directory/filesystem) is supported. I would like to request **multiple storage locations or filesystems at runtime** (e.g. different key types on different mounts) while continuing to use the upstream file-based implementation as the storage backend. ### Current Behaviour - Storage path is derived only from `PSA_ITS_STORAGE_PREFIX` and the UID (e.g. `prefix + "%08x%08x" + ".psa_its"`). - There is no abstraction over "where to store"; the code uses `fopen`/`fread`/`fwrite`/etc. with that single prefix. - So all ITS items live on one directory/filesystem. Choosing a different storage backend per a persistent key is not supported. ### Desired Behaviour / Use Case - Use the file-based ITS implementation but allow different ITS items to be stored in **different directories or filesystems** at runtime. - **Use case — multiple filesystem types:** Some keys need to be stored on a FATFS filesystem, others on SPIFFS, and others on different non-volatile storage systems. The application should be able to route ITS items to the appropriate backend (e.g. by UID range or by key location) so that each storage type can be used where it fits (e.g. size limits, wear, or integration with existing data). ### Possible Approaches (for feedback from the maintainers) Here are some of the ways that I can think of to support multiple storage locations or backends without changing the public PSA ITS API. #### 1. Routing in the persistent key storage layer (above ITS) Routing is implemented in the layer that calls ITS (e.g. `psa_crypto_storage.c` or equivalent). That layer has key attributes (including lifetime/location) at save/load/destroy time and dispatches to different "storage backends" (each of which may call an ITS-like API) based on `psa_key_location_t`. The file-based ITS backend then remains a single-backend implementation; multiple backends are composed above it. To support one ITS (or storage backend) per filesystem, the key storage layer would need explicit support for routing key location to the appropriate ITS (or backend). For example: a way to register a storage backend per `psa_key_location_t` (e.g. “location A -> file ITS with prefix /fat/”, “location B -> file ITS with prefix /spiffs/”) and to resolve location -> backend when storing, loading, or destroying a key. The user would register an ITS (or ITS-like backend) per filesystem, and the key storage layer would dispatch to the right one based on the key’s location. #### 2. User-registered callbacks (user-managed UID-to-storage mapping) We reserve some user application key ID range for custom (non-default) storage keys. The user registers four callbacks with the ITS layer (write, read, erase, get_info). When these callbacks are registered, the ITS implementation invokes them for ITS operations instead of using the default filesystem APIs only if the UID lies in the custom range. The **user’s callback implementation** is responsible for deciding where each UID is stored: it can map different UIDs to different backends (e.g. FATFS, SPIFFS, NVS, or other non-volatile storage) in any way it chooses (ranges, lookup table, etc.). No UID ranges are reserved by the library; mapping is entirely under the application’s control. ### Questions for Maintainers 1. Is supporting multiple storage locations / filesystems for the file-based ITS backend something the project would consider (as an optional extension)? 2. If yes, is there a preferred approach that fits the project's API and design goals?
gilles-peskine-arm commented 2026-03-19 07:14:28 -05:00 (Migrated from github.com)

API designer here. This is something the API was designed to support: when creating keys, place them in one of several trusted storage partitions based on the location value. (When looking up a key by ID, you have to check all locations since the key ID doesn't include the location.) The set of supported partitions, and their trusted storage backend, would be registered at compile time in TF-PSA-Crypto. So basically your proposal 1.

We haven't implemented it yet because so far there hasn't been any explicit demand for it. Even the ITS-over-file backend isn't properly productized (putting keys in the current directory doesn't really make sense in the real world).

While your proposal 1 is aligned with our project's goals, it's not currently on our roadmap and I can't make any promises as to when we could schedule it.

While it would be possible to create partitions based on persistent key IDs, it reduces portability and backward compatibility, so I don't see us going this route.

We've also discussed extending the trusted storage interface with some form of directories. But we haven;t yet found a good compromise between having a useful feature set, and not being too much of a burden for very constrained environments.

API designer here. This is something the API was designed to support: when creating keys, place them in one of several trusted storage partitions based on the location value. (When looking up a key by ID, you have to check all locations since the key ID doesn't include the location.) The set of supported partitions, and their trusted storage backend, would be registered at compile time in TF-PSA-Crypto. So basically your proposal 1. We haven't implemented it yet because so far there hasn't been any explicit demand for it. Even the ITS-over-file backend isn't properly productized (putting keys in the current directory doesn't really make sense in the real world). While your proposal 1 is aligned with our project's goals, it's not currently on our roadmap and I can't make any promises as to when we could schedule it. While it would be possible to create partitions based on persistent key IDs, it reduces portability and backward compatibility, so I don't see us going this route. We've also discussed extending the trusted storage interface with some form of directories. But we haven;t yet found a good compromise between having a useful feature set, and not being too much of a burden for very constrained environments.
Harshal5 commented 2026-03-26 06:44:58 -05:00 (Migrated from github.com)

Hi @gilles-peskine-arm ,

Thank you for the feedback on this issue - it's encouraging to know that location-based routing aligns with the original PSA design intent.
I'd like to understand more about your planned approach so that we can avoid forward-compatibility problems on our side. We are currently blocked on this requirement and need to implement a solution, so any insight into your design plans and how you envision the implementation would be very helpful.

Based on this discussion I plan to consider implementing the design that you envision or design an interim solution that would be forward-compatible in the future.

Thanks!

Hi @gilles-peskine-arm , Thank you for the feedback on this issue - it's encouraging to know that location-based routing aligns with the original PSA design intent. I'd like to understand more about your planned approach so that we can avoid forward-compatibility problems on our side. We are currently blocked on this requirement and need to implement a solution, so any insight into your design plans and how you envision the implementation would be very helpful. Based on this discussion I plan to consider implementing the design that you envision or design an interim solution that would be forward-compatible in the future. Thanks!
gilles-peskine-arm commented 2026-03-26 09:07:13 -05:00 (Migrated from github.com)

I've given some thought to the high-level feature set, but not to how the parts fit together, or to what should be configurable in TF-PSA-Crypto.

Some use cases that the PSA APIs should be able to support:

  • A device has different levels of “system reset” which involve wiping different sets of keys (e.g. tenant vs owner for building automation). This is where the name “persistence level” comes from.
  • A device has multiple partitions/directories of keys managed by different entities.
  • A device has a very small amount of physically protected storage (“internal trusted storage”), and a larger amount of storage which needs to be cryptographically protected (“protected storage”).
  • A cryptography subsystem can access other subsystems through a system bus, with each subsystem storing its own keys.

We don't necessarily want to support all of this in TF-PSA-Crypto. And I don't know at what level this should be configured. The PSA storage API doesn't have any concept of partition or directory, but it effectively defines two storage partitions: ITS (internal trusted storage) and PS (protected storage). Should we expand the storage API to support partitions, or should TF-PSA-Crypto support additional storage backends?

If you'd like for us to progress on the design, we need to have a conversation involving our product manager. Otherwise, you can obviously make your own patch, but I can't promise that it'll look like what we'll do in the future.

I've given some thought to the high-level feature set, but not to how the parts fit together, or to what should be configurable in TF-PSA-Crypto. Some use cases that the PSA APIs should be able to support: * A device has different levels of “system reset” which involve wiping different sets of keys (e.g. tenant vs owner for building automation). This is where the name “persistence level” comes from. * A device has multiple partitions/directories of keys managed by different entities. * A device has a very small amount of physically protected storage (“internal trusted storage”), and a larger amount of storage which needs to be cryptographically protected (“protected storage”). * A cryptography subsystem can access other subsystems through a system bus, with each subsystem storing its own keys. We don't necessarily want to support all of this in TF-PSA-Crypto. And I don't know at what level this should be configured. The [PSA storage API](https://arm-software.github.io/psa-api/storage/1.0/) doesn't have any concept of partition or directory, but it effectively defines two storage partitions: ITS (internal trusted storage) and PS (protected storage). Should we expand the storage API to support partitions, or should TF-PSA-Crypto support additional storage backends? If you'd like for us to progress on the design, we need to have a conversation involving our product manager. Otherwise, you can obviously make your own patch, but I can't promise that it'll look like what we'll do in the future.
Harshal5 commented 2026-03-27 06:41:45 -05:00 (Migrated from github.com)

Thank you for the detailed breakdown of the use cases, these are directly relevant to us as well.
It would be very helpful if you could progress on the design. I'd be happy to be involved in the discussion to help move this forward. Understanding the upstream direction would allow us to align our work rather than risk diverging.

Thank you for the detailed breakdown of the use cases, these are directly relevant to us as well. It would be very helpful if you could progress on the design. I'd be happy to be involved in the discussion to help move this forward. Understanding the upstream direction would allow us to align our work rather than risk diverging.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-Mbed-TLS/TF-PSA-Crypto#714
No description provided.