Description
The default AEAD nonce provider for the PSA Internal Trusted Storage transform module, secure_storage_its_transform_aead_get_nonce() in subsys/secure_storage/src/its/transform/aead_get.c, stores its nonce counter in unsynchronized function-local static variables (s_nonce and s_nonce_initialized). Every ITS write obtains its AES-GCM or ChaCha20-Poly1305 nonce here via secure_storage_its_transform_to_store().

Because the function held no lock, two threads calling it concurrently race on the shared statics: the initialization path (psa_generate_random() followed by memcpy()) and the non-atomic increment-then-copy path can each hand the same nonce value to two distinct encryption operations, and can lose increments so the counter repeats values it was designed never to repeat. The ITS layer (secure_storage_its_set() in subsys/secure_storage/src/its/implementation.c) performs no serialization of its own, so concurrent same-UID writes reach the racy provider directly.

Reusing a nonce with the same key under AES-GCM or ChaCha20-Poly1305 is a catastrophic AEAD failure: it leaks the XOR of the two plaintexts (ITS routinely stores secrets, including PSA persistent keys) and, for GCM, exposes the authentication key, enabling forgery of stored entries. Because the AEAD key is derived per entry UID, the security-relevant collision is two concurrent writes to the same UID both receiving the same nonce; an adversary able to read the raw backing storage can then exploit the reuse.

Both ITS store back-ends shipped with Zephyr, zms.c and the settings/NVS back-end in settings.c, are log-structured flash stores with deferred garbage collection, so an entry superseded by a rewrite remains physically present in the partition until its sector is reclaimed. Two same-UID writes that race therefore leave both ciphertexts readable in the raw image at once, which is the condition the nonce reuse needs to be exploitable. The trigger remains narrow: both built-in key providers (DEVICE_ID_HASH and ENTRY_UID_HASH) salt the derived key with the entry UID, so reuse across different UIDs is harmless, and the exposure requires an application that writes the same UID concurrently from two threads.

The fix serializes the provider with a K_MUTEX_DEFINE(s_nonce_mutex) held for the duration of nonce generation.
Published: 2026-09-21
Score: 5.3 Medium
EPSS: n/a
KEV: No
Impact: Nonce reuse compromising confidentiality and integrity
Action: Immediate Patch
AI Analysis

Impact

An unsynchronised static counter in Zephyr's default AEAD nonce provider causes concurrent writes to the same UID to receive an identical nonce for the same key. Reusing a nonce with AES‑GCM or ChaCha20‑Poly1305 compromises confidentiality by exposing the XOR of the two plaintexts and, in the case of GCM, reveals the authentication key, enabling forgery of stored entries. The vulnerability is limited to applications that perform parallel writes to the same UID; the AES‑GCM and ChaCha20‑Poly1305 keys are derived per‑UID, so nonce collisions across different UIDs are harmless.

Affected Systems

Zephyr RTOS, specifically the secure_storage ITS transform module (secure_storage_its_transform_aead_get_nonce) within the secure_storage subsystem. No specific version range is listed, so any release before the patch that introduces mutex protection is susceptible.

Risk and Exploitability

With a CVSS score of 5.3 the vulnerability is considered medium severity. The EPSS score is not available, and it is not listed in CISA’s KEV catalogue. The likely attack vector requires an application that can trigger concurrent writes to the same UID and access the raw flash backing store to read the leaked ciphertexts; therefore, the exploitation risk is limited to environments where the underlying storage can be read by an adversary. The supplied fix serialises nonce generation with a mutex, preventing the race condition.

Generated by OpenCVE AI on September 21, 2026 at 22:26 UTC.

Remediation

No vendor fix or workaround currently provided.

OpenCVE Recommended Actions

  • Upgrade Zephyr to a version that includes the mutex protection for the AEAD nonce provider.
  • If an upgrade is not immediately possible, modify the application to serialize writes to the same UID or avoid concurrent updates to that UID.
  • Ensure that raw flash storage is protected from untrusted reads; consider using hardware encryption or restricting access if feasible.

Generated by OpenCVE AI on September 21, 2026 at 22:26 UTC.

Tracking

Sign in to view the affected projects.

Advisories

No advisories yet.

History

Mon, 21 Sep 2026 22:45:00 +0000

Type Values Removed Values Added
First Time appeared Zephyrproject
Zephyrproject zephyr
Vendors & Products Zephyrproject
Zephyrproject zephyr

Mon, 21 Sep 2026 21:30:00 +0000

Type Values Removed Values Added
Description The default AEAD nonce provider for the PSA Internal Trusted Storage transform module, secure_storage_its_transform_aead_get_nonce() in subsys/secure_storage/src/its/transform/aead_get.c, stores its nonce counter in unsynchronized function-local static variables (s_nonce and s_nonce_initialized). Every ITS write obtains its AES-GCM or ChaCha20-Poly1305 nonce here via secure_storage_its_transform_to_store(). Because the function held no lock, two threads calling it concurrently race on the shared statics: the initialization path (psa_generate_random() followed by memcpy()) and the non-atomic increment-then-copy path can each hand the same nonce value to two distinct encryption operations, and can lose increments so the counter repeats values it was designed never to repeat. The ITS layer (secure_storage_its_set() in subsys/secure_storage/src/its/implementation.c) performs no serialization of its own, so concurrent same-UID writes reach the racy provider directly. Reusing a nonce with the same key under AES-GCM or ChaCha20-Poly1305 is a catastrophic AEAD failure: it leaks the XOR of the two plaintexts (ITS routinely stores secrets, including PSA persistent keys) and, for GCM, exposes the authentication key, enabling forgery of stored entries. Because the AEAD key is derived per entry UID, the security-relevant collision is two concurrent writes to the same UID both receiving the same nonce; an adversary able to read the raw backing storage can then exploit the reuse. Both ITS store back-ends shipped with Zephyr, zms.c and the settings/NVS back-end in settings.c, are log-structured flash stores with deferred garbage collection, so an entry superseded by a rewrite remains physically present in the partition until its sector is reclaimed. Two same-UID writes that race therefore leave both ciphertexts readable in the raw image at once, which is the condition the nonce reuse needs to be exploitable. The trigger remains narrow: both built-in key providers (DEVICE_ID_HASH and ENTRY_UID_HASH) salt the derived key with the entry UID, so reuse across different UIDs is harmless, and the exposure requires an application that writes the same UID concurrently from two threads. The fix serializes the provider with a K_MUTEX_DEFINE(s_nonce_mutex) held for the duration of nonce generation.
Title AEAD nonce reuse in Zephyr secure_storage ITS default nonce provider due to missing thread synchronization
Weaknesses CWE-323
CWE-362
References
Metrics cvssV3_1

{'score': 5.3, 'vector': 'CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:L/A:N'}


Subscriptions

Zephyrproject Zephyr
cve-icon MITRE

Status: PUBLISHED

Assigner: zephyr

Published:

Updated: 2026-09-21T21:16:04.169Z

Reserved: 2026-07-15T17:38:06.560Z

Link: CVE-2026-15890

cve-icon Vulnrichment

No data.

cve-icon NVD

Status : Received

Published: 2026-09-21T22:16:56.143

Modified: 2026-09-21T22:16:56.143

Link: CVE-2026-15890

cve-icon Redhat

No data.

cve-icon OpenCVE Enrichment

Updated: 2026-09-21T22:30:12Z

Weaknesses
  • CWE-323

    Reusing a Nonce, Key Pair in Encryption

  • CWE-362

    Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')