Skip to content

IoT-Safe: serialize APDU transactions with a port mutex - #11246

Open
danielinux wants to merge 3 commits into
wolfSSL:masterfrom
danielinux:iotsafe-mutex
Open

IoT-Safe: serialize APDU transactions with a port mutex#11246
danielinux wants to merge 3 commits into
wolfSSL:masterfrom
danielinux:iotsafe-mutex

Conversation

@danielinux

@danielinux danielinux commented Aug 24, 2026

Copy link
Copy Markdown
Member

Description

All IoT-Safe operations share the file-scope static command/response buffers on a single CSIM channel. Concurrent operations (e.g. a random generation and an ECDSA sign callback from different TLS sessions) could overwrite each other's buffers and consume the wrong modem reply, corrupting cryptographic output or leaving the applet in a persistent error state.

Add a port-level mutex (active in multi-threaded builds, no-op when SINGLE_THREADED) held across each APDU transaction. The seven single-transaction operations get thin serialized wrappers. GetRandom locks after its lazy-init check, and the ECDH callback locks its APDU branch, calling the locked impls directly since it already holds the mutex (the software fallback never takes the lock). The mutex is created in iotsafe_init(); document the single-threaded init contract in the doxygen of wolfSSL_CTX_iotsafe_enable() and the CSIM callback setters.

Fixes F-10045.

Testing

Tested via existing iotsafe demos build

Checklist

  • added tests
  • updated/added doxygen
  • updated appropriate READMEs
  • Updated manual and documentation

All IoT-Safe operations share the file-scope static command/response
buffers on a single CSIM channel. Concurrent operations (e.g. a random
generation and an ECDSA sign callback from different TLS sessions)
could overwrite each other's buffers and consume the wrong modem
reply, corrupting cryptographic output or leaving the applet in a
persistent error state.

Add a port-level mutex (active in multi-threaded builds, no-op when
SINGLE_THREADED) held across each APDU transaction. The seven
single-transaction operations get thin serialized wrappers. GetRandom
locks after its lazy-init check, and the ECDH callback locks its APDU
branch, calling the locked impls directly since it already holds the
mutex (the software fallback never takes the lock). The mutex is
created in iotsafe_init(); document the single-threaded init contract
in the doxygen of wolfSSL_CTX_iotsafe_enable() and the CSIM callback
setters.

Fixes F-10045.
Copilot AI lite review requested due to automatic review settings August 24, 2026 09:42
@danielinux danielinux self-assigned this Aug 24, 2026

Copilot AI 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.

Pull request overview

This PR addresses concurrency hazards in the IoT-Safe port by serializing APDU transactions that share file-scope command/response buffers on a single CSIM channel, preventing concurrent TLS sessions from corrupting modem/appet state and cryptographic outputs.

Changes:

  • Introduces a port-level mutex and lock helpers to serialize APDU transactions in multi-threaded builds (no-op under SINGLE_THREADED).
  • Wraps single-transaction IoT-Safe operations with thin “serialized entry point” functions and updates the ECDH callback to hold the lock across its APDU sequence.
  • Updates Doxygen to document the single-threaded initialization contract and concurrent-use guarantees after initialization.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
wolfcrypt/src/port/iotsafe/iotsafe.c Adds mutex-based serialization for IoT-Safe APDU transactions and refactors operations into locked + serialized wrappers.
doc/dox_comments/header_files/iotsafe.h Documents initialization/threading requirements for IoT-Safe enablement and CSIM callback setters.
Suppressed comments (1)

wolfcrypt/src/port/iotsafe/iotsafe.c:101

  • iotsafe_unlock() should mirror iotsafe_lock()'s initialization guard; otherwise callers that hit an early-return/no-op lock path can still attempt to unlock an uninitialized mutex in multi-threaded builds.
static void iotsafe_unlock(void)
{
#if !defined(SINGLE_THREADED)
    wc_UnLockMutex(&iotsafe_mutex);
#endif

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread wolfcrypt/src/port/iotsafe/iotsafe.c
Comment thread wolfcrypt/src/port/iotsafe/iotsafe.c
Comment thread doc/dox_comments/header_files/iotsafe.h Outdated
- iotsafe_init(): free the mutex on the ATE0 and drain failure paths
  so a retried init never double-initializes it
- guard every exported API entry (wc_iotsafe_*, wolfIoTSafe_GetCert_ex,
  wolfIoTSafe_GetRandom) against locking an uninitialized mutex via
  iotsafe_ensure_init(), which lazy-initializes the port before locking
- doxygen: wolfIoTSafe_SetCSIM_write_cb param rf -> wf

Copilot AI 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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread wolfcrypt/src/port/iotsafe/iotsafe.c
wolfIoT_ecc_shared_secret(): ensure the port is initialized before the
APDU branch can lock iotsafe_mutex. The check sits before tmpKey
allocation (no leak on the early WC_HW_E return) and is gated on
iotsafe->enabled so the software fallback path never forces init.
@wolfSSL-Bot

Copy link
Copy Markdown

Can one of the admins verify this patch?

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