Skip to content

net: tls_credentials: Fix TLS credentials library loading with secure-only variant#111837

Open
PavelVPV wants to merge 2 commits into
zephyrproject-rtos:mainfrom
PavelVPV:fix_tls_credentials_library_loading_with_secure_only_variant
Open

net: tls_credentials: Fix TLS credentials library loading with secure-only variant#111837
PavelVPV wants to merge 2 commits into
zephyrproject-rtos:mainfrom
PavelVPV:fix_tls_credentials_library_loading_with_secure_only_variant

Conversation

@PavelVPV

Copy link
Copy Markdown
Contributor

This PR addresses 2 issues:

  1. It allows to use tls_credentials_trusted backend with secure-only variants by using Secure Storage.
  2. Fixes loading issue for secure-only variants by changing TLS credentials library initialization from SYS_INIT to lazy loading.

See corresponding commits for details.

@PavelVPV PavelVPV marked this pull request as ready for review June 23, 2026 09:56
@PavelVPV PavelVPV requested a review from rlubos June 23, 2026 10:28

@rlubos rlubos left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, not sure how this PR got no reviewers/assignees added...

@rlubos rlubos requested review from jukkar and tomi-font June 23, 2026 10:40
@PavelVPV

Copy link
Copy Markdown
Contributor Author

LGTM, not sure how this PR got no reviewers/assignees added...

Probably because there are no maintainers for this area. It is excluded from Networking area and not added to anywhere:

- subsys/net/lib/tls_credentials/

@PavelVPV PavelVPV force-pushed the fix_tls_credentials_library_loading_with_secure_only_variant branch from 01da9f8 to e9971b8 Compare June 23, 2026 11:48
PavelVPV added 2 commits June 23, 2026 14:30
The protected storage credentials backend only uses the PSA Protected
Storage API (psa_ps_*), which Zephyr's Secure Storage subsystem provides
without TF-M. Allow selecting the backend when SECURE_STORAGE is enabled,
not only with TF-M, so secure-only builds (for example nRF54L cpuapp) can
persist TLS credentials across reboot instead of being limited to the
volatile backend.

The backend builds storage UIDs that use the full 64-bit range (see
tls_credential_get_uid()). TF-M's Protected Storage supports that
natively, but Zephyr's Secure Storage defaults to a 30-bit UID, which
makes psa_ps_set() reject the credential UIDs (observed as -EIO). Select
SECURE_STORAGE_64_BIT_UID when using Secure Storage so the backend works.

Assisted-by: Claude:claude-opus-4.8
Signed-off-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no>
The protected storage backend read its Table of Contents (ToC) from a
SYS_INIT hook at POST_KERNEL priority 0. With TF-M, Protected Storage is
provided by the secure domain and is available that early, so this
worked. Without TF-M the backend is layered on Zephyr's Secure Storage,
and the ToC read then runs far too early in the boot sequence:

  - The RRAM/MRAM (non-volatile memory) flash drivers initialize at
    POST_KERNEL, KERNEL_INIT_PRIORITY_DEVICE (priority 50).
  - On top of that, the Secure Storage PSA ITS settings store mounts the
    settings subsystem (settings_subsys_init()) from its own SYS_INIT at
    APPLICATION level.
  - Only after that is psa_ps_get()/psa_ps_set() actually backed by
    persistent storage.

credentials_init() at POST_KERNEL/0 therefore ran before storage was
usable: psa_ps_get() returned "does not exist", the ToC was treated as
empty, and the first credential write then overwrote the persisted ToC,
dropping all previously stored credentials across reboot.

Simply moving the SYS_INIT to APPLICATION level only swaps one fragile
ordering for another: it would have to run after Secure Storage's own
APPLICATION-level settings mount, at the same init priority, making
correctness depend on link order. That priority coupling is the wrong
way to express the dependency.

Instead, drop the boot-time SYS_INIT and load the ToC lazily on first
access:

  - credentials_ensure_loaded() runs credentials_init() exactly once,
    under credential_lock, and records the result in credentials_loaded.
  - The public API (tls_credential_add/get/delete) calls it and returns
    -EACCES if storage is still not usable, so callers get a real error
    instead of silently operating on an empty ToC.
  - credentials_lock() also calls it. The internal iteration API used by
    the TLS handshake (credential_get(), credential_next_get(),
    credential_next_tag_get()) returns a pointer / sec_tag and has no way
    to report an error, so it cannot trigger or surface a failed load on
    its own. Performing the load in credentials_lock() - which
    sockets_tls takes before iterating - is what guarantees the ToC is
    loaded for that path; the getters additionally log a warning and
    return empty if it is somehow still not loaded.

The inability of the internal getter API to return an error is a
pre-existing limitation, also implemented downstreams; changing its
signature is left for a follow-up so this change stays self-contained.

Assisted-by: Claude:claude-opus-4.8
Signed-off-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no>
@PavelVPV PavelVPV force-pushed the fix_tls_credentials_library_loading_with_secure_only_variant branch from e9971b8 to c5c05e5 Compare June 23, 2026 12:31
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants