Skip to content

Thread safety and private key handling - #11172

Open
dgarske wants to merge 5 commits into
wolfSSL:masterfrom
dgarske:fenrir_threadsafety_keys
Open

Thread safety and private key handling#11172
dgarske wants to merge 5 commits into
wolfSSL:masterfrom
dgarske:fenrir_threadsafety_keys

Conversation

@dgarske

@dgarske dgarske commented Aug 13, 2026

Copy link
Copy Markdown
Member

Thread safety and private key handling

Part 3 of 4 from an internal automated source review. Independent of parts 1 and 2. Part 4 builds on this branch and should merge after it.

Report Summary
F-1514 ECC fixed point cache mutex initialization
F-1515 ECC OID cache mutex initialization
F-1946 netRandom mutex initialization
F-1380 Crypto callback device table entry publication order
F-1930 ECC private key checks on import
F-1931 ECC raw private key checks on import
F-2636 SE050 port private key buffer release
F-2972 RSA blinding factor inversion

Notes for reviewers

One-time mutex initialization. Three lazy check-then-set sites could double-initialize a mutex. They now share wc_local_InitMutexOnce() in wc_port.c, using the three-state compare-exchange already used by the SP ECC cache locks (0 uninitialized, 1 in progress, 2 ready). Losers of the race wait for the winner rather than returning a retryable error, so no caller needs a retry path. Only compiled when WOLFSSL_MUTEX_INITIALIZER is undefined, i.e. non-pthread targets.

ECC private key import. The private scalar is now range checked against [1, n-1] on every import rather than only under WOLFSSL_VALIDATE_ECC_IMPORT. The check is two comparisons - no scalar multiply, no curve specification load - so the default-build cost is negligible. The expensive public key consistency check stays behind the existing macro. It reads the scalar through ecc_get_k() so it is correct on either side of key blinding, and is skipped for NXP CAAM black keys, whose k holds an encrypted blob rather than a scalar.

RSA blinding. The blinding factor was inverted with mp_invmod(), a binary extended Euclidean variant whose iteration count tracks its input. It is now inverted under a fresh multiplicative mask which is divided back out. Measured cost: no measurable change on the default and fastmath backends; -11% RSA-2048 private on the deprecated heapmath backend, which makes no timing-resistance claim.

Crypto callback registry. Entries are filled before devId is stored and cleared after it is retired. Store ordering only, no barrier - serializing register/unregister against in-flight operations remains the caller's responsibility, and the comment now says so.

Also fixed: the HAVE_WNR build did not compile (wc_GenerateSeed() referenced an identifier that exists nowhere in the tree), and wc_InitNetRandom() returned uninitialized stack data on success.

Testing

make check passes on --enable-all, --enable-all --enable-lms, --enable-all -DWOLFSSL_TEST_NO_MUTEX_INITIALIZER (the configuration that actually compiles the one-time mutex code), --enable-all -DWOLFSSL_CHECK_MEM_ZERO, --enable-cryptocb --enable-all, --enable-fastmath, --enable-heapmath and --enable-smallstack.

New test: ECC private key range rejection without WOLFSSL_VALIDATE_ECC_IMPORT (tests/api/test_ecc.c).

The NXP SE050 port has no host build and was reviewed by hand.

Copilot AI lite review requested due to automatic review settings August 13, 2026 22:42
@dgarske dgarske self-assigned this Aug 13, 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 (part 3/4 of an internal automated review series) hardens wolfCrypt’s thread-safety for lazy mutex initialization paths and strengthens private-key handling across ECC imports and select hardware ports, alongside a timing-hardening adjustment in RSA blinding and a small CryptoCb publication-order fix.

Changes:

  • Add a shared one-time mutex initialization helper (wc_local_InitMutexOnce) and migrate ECC caches + netRandom mutex init sites to use it.
  • Enforce ECC private scalar range checking ([1, n-1]) on all import paths by default, with a new API test covering the rejection behavior.
  • Mask RSA blinding-factor inversion to avoid input-dependent mp_invmod() behavior; also adjust CryptoCb device-table publication order and wipe SE050 private-key DER buffers before freeing.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.

Show a summary per file
File Description
wolfssl/wolfcrypt/wc_port.h Declares wc_local_InitMutexOnce() and introduces wc_MutexOnceFlag for one-time mutex init election state.
wolfcrypt/src/wc_port.c Implements wc_local_InitMutexOnce() with an atomic three-state election (0/1/2) and wait-on-winner behavior.
wolfcrypt/src/ecc.c Adds unconditional private-scalar range validation on import and converts ECC cache mutex init/free to the once-init helper.
wolfcrypt/src/random.c Fixes netRandom mutex init by using the shared once-init helper; fixes uninitialized ret and a bad identifier usage.
wolfcrypt/src/rsa.c Hardens RSA blinding inversion by inverting a masked value and dividing the mask back out.
wolfcrypt/src/cryptocb.c Adjusts device table entry publication/retirement ordering and updates documentation accordingly.
wolfcrypt/src/port/nxp/se050_port.c Ensures private key DER buffers are wiped before free in RSA sign/decrypt paths.
wolfcrypt/test/test.c Updates ECC mulmod test setup to avoid using private-key import paths for curve constants.
tests/api/test_ecc.h Registers the new ECC private-key range test in the API test suite.
tests/api/test_ecc.c Adds test_wc_ecc_import_privkey_range() and updates related ECC tests to align with new import behavior.

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

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

gcc-arm-cortex-m0plus

  • FLASH: .text +140 B (+0.2%, 65,023 B / 262,144 B, total: 25% used)

gcc-arm-cortex-m4-baremetal

  • FLASH: .text +128 B (+0.2%, 67,555 B / 262,144 B, total: 26% used)

gcc-arm-cortex-m4-openssl-compat

  • FLASH: .text +256 B (+0.0%, 775,932 B / 1,048,576 B, total: 74% used)

gcc-arm-cortex-m4-sp-math

  • FLASH: .text +128 B (+0.2%, 62,533 B / 262,144 B, total: 24% used)

gcc-arm-cortex-m7-tls13

  • FLASH: .text +256 B (+0.1%, 238,689 B / 262,144 B, total: 91% used)

linuxkm-pie

  • Data: __patchable_function_entries +8 B (+0.0%, 26,576 B)

linuxkm-standard

@dgarske
dgarske force-pushed the fenrir_threadsafety_keys branch from dda9fec to 3380dd2 Compare August 14, 2026 15:00
@dgarske
dgarske requested a review from douzzer August 14, 2026 15:37
Comment thread wolfcrypt/src/cryptocb.c
}
#endif

/* Publish the entry last. */

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.

For ordered reads and writes, we want a WC_BARRIER to keep the optimizer from reordering things.

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