Skip to content

Commit

Permalink
secure_storage: introduce the secure storage subsystem
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
tomi-font authored and Chromeos LUCI committed Oct 11, 2024
1 parent e9d42ba commit 95ffbed
Show file tree
Hide file tree
Showing 25 changed files with 1,713 additions and 0 deletions.
8 changes: 8 additions & 0 deletions MAINTAINERS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4116,6 +4116,14 @@ RTIO:
tests:
- rtio

Secure storage:
status: maintained
maintainers:
- tomi-font
files:
- subsys/secure_storage/
labels:
- "area: Secure storage"
Storage:
status: odd fixes
files:
Expand Down
1 change: 1 addition & 0 deletions subsys/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ add_subdirectory_ifdef(CONFIG_MODEM_MODULES modem)
add_subdirectory_ifdef(CONFIG_NETWORKING net)
add_subdirectory_ifdef(CONFIG_PROFILING profiling)
add_subdirectory_ifdef(CONFIG_RETENTION retention)
add_subdirectory_ifdef(CONFIG_SECURE_STORAGE secure_storage)
add_subdirectory_ifdef(CONFIG_SENSING sensing)
add_subdirectory_ifdef(CONFIG_SETTINGS settings)
add_subdirectory_ifdef(CONFIG_SHELL shell)
Expand Down
1 change: 1 addition & 0 deletions subsys/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ source "subsys/random/Kconfig"
source "subsys/retention/Kconfig"
source "subsys/rtio/Kconfig"
source "subsys/sd/Kconfig"
source "subsys/secure_storage/Kconfig"
source "subsys/sensing/Kconfig"
source "subsys/settings/Kconfig"
source "subsys/shell/Kconfig"
Expand Down
48 changes: 48 additions & 0 deletions subsys/secure_storage/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# SPDX-License-Identifier: Apache-2.0

zephyr_library()
zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)
zephyr_library_include_directories(include/internal) # secure_storage headers
add_subdirectory(src)

# Make the subsystem's PSA Secure Storage API headers available only when it's enabled.
zephyr_include_directories(
include
)

# Make the secure_storage headers available to the application only when it's implementing the relevant APIs.
function(make_available header)
if (NOT header STREQUAL "common.h")
make_available(common.h)
endif()
if ((header MATCHES "^its") AND NOT (header STREQUAL "its/common.h"))
make_available(its/common.h)
endif()
configure_file(include/internal/zephyr/secure_storage/${header}
${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/secure_storage/${header}
COPYONLY)
endfunction()

if (CONFIG_SECURE_STORAGE_ITS_IMPLEMENTATION_CUSTOM)
make_available(its.h)
endif()

if (CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_CUSTOM)
make_available(ps.h)
endif()

if (CONFIG_SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_CUSTOM
OR (CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_CUSTOM
AND CONFIG_SECURE_STORAGE_ITS_TRANSFORM_MODULE))
make_available(its/transform.h)
endif()

if (CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_CUSTOM)
make_available(its/store.h)
endif()

if (CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_CUSTOM
OR CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_CUSTOM
OR CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER_CUSTOM)
make_available(its/transform/aead_get.h)
endif()
102 changes: 102 additions & 0 deletions subsys/secure_storage/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Copyright (c) 2024 Nordic Semiconductor
# SPDX-License-Identifier: Apache-2.0

menuconfig SECURE_STORAGE
bool "Secure storage subsystem"
depends on !BUILD_WITH_TFM
select EXPERIMENTAL
help
The secure storage subsystem provides an implementation of the PSA Secure Storage API
functions on board targets that don't already have one.
It allows making use of the PSA Secure Storage API and persistent keys in the PSA Crypto
API in a standard and portable way.
It is configurable and different implementations can be used to accommodate the varying
capabilities of different devices.
In addition to providing functional support for the PSA Secure Storage API, depending on
the device-specific security features that are available and used, the subsystem may
secure the data stored through it at rest.
This is however highly dependent on the device and configuration in use, and not a
guarantee of the subsystem.

if SECURE_STORAGE

module = SECURE_STORAGE
module-str = secure_storage
source "subsys/logging/Kconfig.template.log_config"

choice SECURE_STORAGE_ITS_IMPLEMENTATION
prompt "Internal Trusted Storage (ITS) API implementation"

config SECURE_STORAGE_ITS_IMPLEMENTATION_ZEPHYR
bool "Zephyr's ITS implementation"
select SECURE_STORAGE_ITS_TRANSFORM_MODULE
select SECURE_STORAGE_ITS_STORE_MODULE
help
Use Zephyr's implementation of the ITS API.
It calls into the transform and store modules, which
can be configured and have custom implementations.

config SECURE_STORAGE_ITS_IMPLEMENTATION_CUSTOM
bool "Custom ITS implementation"
help
A custom implementation of the ITS API is present.
Implement the functions declared in <zephyr/secure_storage/its.h>.
The header is made available when this Kconfig option is enabled.

endchoice # SECURE_STORAGE_ITS_IMPLEMENTATION

config SECURE_STORAGE_ITS_MAX_DATA_SIZE
int "Maximum data size of an ITS entry in bytes"
default 128
help
The maximum size, in bytes, that the data of an ITS entry can be.
Increasing this value increases the stack usage when serving PSA ITS API calls.

menuconfig SECURE_STORAGE_ITS_TRANSFORM_MODULE
bool "ITS transform module"
help
The module that handles the transformation and validation of the
ITS data before it's written to and after it's read from NVM.
Zephyr's ITS implementation calls into it.

if SECURE_STORAGE_ITS_TRANSFORM_MODULE
rsource "Kconfig.its_transform"
endif

menuconfig SECURE_STORAGE_ITS_STORE_MODULE
bool "ITS store module"
imply FLASH # for FLASH_HAS_DRIVER_ENABLED
help
The module that handles the storage/retrieval of the ITS data to/from NVM.
Zephyr's ITS implementation calls into it.

if SECURE_STORAGE_ITS_STORE_MODULE
rsource "Kconfig.its_store"
endif

choice SECURE_STORAGE_PS_IMPLEMENTATION
prompt "Protected Storage (PS) API implementation"
default SECURE_STORAGE_PS_IMPLEMENTATION_ITS

config SECURE_STORAGE_PS_IMPLEMENTATION_ITS
bool "PS calls directly into the ITS"
help
The PS API doesn't have an implementation of its own, and directly calls into the ITS API.
This means that the implementation of the PS API will be identical to that of the ITS API.

config SECURE_STORAGE_PS_IMPLEMENTATION_CUSTOM
bool "Custom PS implementation"
help
A custom implementation of the PS API is present.
Implement the functions declared in <zephyr/secure_storage/ps.h>.
The header is made available when this Kconfig option is enabled.

endchoice # SECURE_STORAGE_PS_IMPLEMENTATION

config SECURE_STORAGE_PS_SUPPORTS_SET_EXTENDED
bool "PS API implementation supports psa_ps_create() and psa_ps_set_extended()"
depends on SECURE_STORAGE_PS_IMPLEMENTATION_CUSTOM
help
Whether the psa_ps_create() and psa_ps_set_extended() functions are implemented.

endif # SECURE_STORAGE
34 changes: 34 additions & 0 deletions subsys/secure_storage/Kconfig.its_store
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (c) 2024 Nordic Semiconductor
# SPDX-License-Identifier: Apache-2.0

choice SECURE_STORAGE_ITS_STORE_IMPLEMENTATION
prompt "ITS store module implementation"

config SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS
bool "ITS store module implementation using the settings subsystem for storage"
DT_STORAGE_PARTITION := $(dt_nodelabel_path,storage_partition)
depends on FLASH_HAS_DRIVER_ENABLED \
&& $(dt_path_enabled,$(DT_STORAGE_PARTITION)) \
&& $(dt_node_has_compat,$(dt_node_parent,$(DT_STORAGE_PARTITION)),fixed-partitions)
imply FLASH_MAP
imply NVS
select SETTINGS

config SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_NONE
bool "No ITS store module implementation"

config SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_CUSTOM
bool "Custom ITS store module implementation"
help
Implement the functions declared in <zephyr/secure_storage/its/store.h>.
The header is made available when this Kconfig option is enabled.

endchoice # SECURE_STORAGE_ITS_STORE_IMPLEMENTATION

if SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS

config SECURE_STORAGE_ITS_STORE_SETTINGS_PREFIX
string "Subtree in which to store the settings, with a trailing slash. Can be empty."
default "its/"

endif # SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS
134 changes: 134 additions & 0 deletions subsys/secure_storage/Kconfig.its_transform
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Copyright (c) 2024 Nordic Semiconductor
# SPDX-License-Identifier: Apache-2.0

choice SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION
prompt "ITS transform module implementation"

config SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_AEAD
bool "ITS transform module implementation using AEAD to protect the data"
imply HWINFO # for HWINFO_HAS_DRIVER

config SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_CUSTOM
bool "Custom ITS transform module implementation"
help
Implement the functions declared in <zephyr/secure_storage/its/transform.h>
and set CONFIG_SECURE_STORAGE_ITS_TRANSFORM_OUTPUT_OVERHEAD appropriately.
The header is made available when this Kconfig option is enabled.

endchoice # SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION

config SECURE_STORAGE_ITS_TRANSFORM_OUTPUT_OVERHEAD
int "Overhead, in bytes, associated with the transformation of an entry's data for storage"
range 0 1000
# authentication tag (16) + nonce (12)
default 28 if SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_AEAD \
&& SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE = 12
default -1
help
This indicates how many more bytes an ITS entry's data will be once it
has been processed by the secure_storage_its_transform_to_store() function.

if SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_AEAD

choice SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME
prompt "AEAD ITS transform module scheme"
default SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_AES_GCM
help
The AEAD scheme used to encrypt and authenticate the data.

config SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_AES_GCM
bool "AES-GCM AEAD scheme"
select PSA_WANT_KEY_TYPE_AES
select PSA_WANT_ALG_GCM

config SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_CHACHA20_POLY1305
bool "ChaCha20-Poly1305 AEAD scheme"
depends on SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE = 12
select PSA_WANT_KEY_TYPE_CHACHA20
select PSA_WANT_ALG_CHACHA20_POLY1305

config SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_CUSTOM
bool "Custom AEAD scheme"
help
Implement the secure_storage_its_transform_aead_get_scheme() function
declared in <zephyr/secure_storage/its/transform/aead_get.h>
and set CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE appropriately.
The header is made available when this Kconfig option is enabled.

endchoice # SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME

choice SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER
prompt "AEAD ITS transform module encryption key provider"
default SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_DEVICE_ID_HASH if HWINFO_HAS_DRIVER
default SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_ENTRY_UID_HASH if !HWINFO_HAS_DRIVER

config SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_DEVICE_ID_HASH
bool "Hash of the device ID returned by the HW info API (not necessarily secure)"
depends on HWINFO_HAS_DRIVER
select PSA_WANT_ALG_SHA_256
help
This key provider generates keys by hashing the following:
- the device EUI64 as returned by hwinfo_get_device_eui64() as first choice;
- the device ID as returned by hwinfo_get_device_uuid() as second choice.
In addition to the device ID, it adds the UID of the ITS entry
for which it is generating a key to the data hashed as a salt.
This is not necessarily secure as the device ID may be easily readable
by an attacker, not unique, and/or guessable, depending on the device.

config SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_ENTRY_UID_HASH
bool "Hash of the ITS entry UID (not secure)"
select PSA_WANT_ALG_SHA_256
help
This key provider generates keys by hashing the UID of the ITS entry for which it is
generating a key. This is not secure, and only intended for functional support,
because the UIDs are easily guessable and even stored in clear by the store module.
Use a secure key provider if possible.

config SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_CUSTOM
bool "Custom key provider"
help
Implement the secure_storage_its_transform_aead_get_key() function
declared in <zephyr/secure_storage/its/transform/aead_get.h>.
The header is made available when this Kconfig option is enabled.

endchoice # SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER

config SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE
int "AEAD ITS transform module encryption key size in bytes"
default 32

if !SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_CUSTOM

config SECURE_STORAGE_ITS_TRANSFORM_AEAD_NO_INSECURE_KEY_WARNING
bool "Silence the insecure ITS encryption key warnings"

endif

choice SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER
prompt "AEAD ITS transform module nonce provider"

config SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER_DEFAULT
bool "Default nonce provider"
help
The default nonce provider generates a random number for the first nonce with
psa_generate_random(), then increments it for every subsequent nonce. A random
source that doesn't repeat values between reboots is required for this to be secure.

config SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER_CUSTOM
bool "Custom nonce provider"
help
Implement the secure_storage_its_transform_aead_get_nonce() function
declared in <zephyr/secure_storage/its/transform/aead_get.h>.
The header is made available when this Kconfig option is enabled.

endchoice # SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER

config SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE
int "AEAD ITS transform module nonce size in bytes"
range 4 24
default 12
help
Make sure to update CONFIG_SECURE_STORAGE_ITS_TRANSFORM_OUTPUT_OVERHEAD
appropriately when changing the value of this option.

endif # SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_AEAD
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SECURE_STORAGE_COMMON_H
#define SECURE_STORAGE_COMMON_H

/** @file zephyr/secure_storage/common.h Common definitions of the secure storage subsystem. */
#include <stdint.h>

/* A size-optimized version of `psa_storage_create_flags_t`. Used for storing the `create_flags`. */
typedef uint8_t secure_storage_packed_create_flags_t;

#define SECURE_STORAGE_ALL_CREATE_FLAGS \
(PSA_STORAGE_FLAG_NONE | \
PSA_STORAGE_FLAG_WRITE_ONCE | \
PSA_STORAGE_FLAG_NO_CONFIDENTIALITY | \
PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION)

#endif
Loading

0 comments on commit 95ffbed

Please sign in to comment.