Fix private scalar handling under ECC key blinding and add CI coverage - #11233
Open
dgarske wants to merge 1 commit into
Open
Fix private scalar handling under ECC key blinding and add CI coverage#11233dgarske wants to merge 1 commit into
dgarske wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes incorrect use of wc_ecc_key_get_priv() when WOLFSSL_ECC_BLIND_K is enabled (where the accessor returns a regenerated scratch value rather than the stored scalar share), and adds CI coverage to ensure the blinded configuration is exercised.
Changes:
- Add
ecc_get_k_raw()(writable handle to the stored scalar share) andecc_forcezero_k()(wipe stored shares + scratch under blinding) and update relevant call sites to stop writing/zeroing viawc_ecc_key_get_priv(). - Harden ECC blinding internals by zero-extending operands before constant-time XORs and adding consistent “fail closed” behavior.
- Add a Linux CI config entry that enables
WOLFSSL_ECC_BLIND_Kto prevent regressions.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
wolfssl/wolfcrypt/ecc.h |
Adds new raw-scalar accessor macro and forcezero helper API to avoid misuse of the read-only blinded accessor. |
wolfcrypt/src/ecc.c |
Updates blinding XOR paths to ensure operands are grown/zero-extended; adds ecc_forcezero_k() implementation. |
src/pk_ec.c |
Fixes OpenSSL-compat EC key copy/import paths to write/copy the stored scalar share and (re)install blinding safely. |
wolfcrypt/src/sakke.c |
Fixes SAKKE keygen/import to write the stored scalar share and then install a blind. |
wolfcrypt/src/eccsi.c |
Fixes ECCSI decode/import and ensures private material is erased via the correct helper under blinding. |
wolfcrypt/src/wc_pkcs11.c |
Ensures ECC private scalar is actually wiped when clear is requested, even under blinding. |
wolfcrypt/src/port/silabs/silabs_ecc.c |
Updates Silicon Labs key import path to write the stored scalar share and install a blind. |
.github/configs/os-check-linux.json |
Adds a CI configuration that defines WOLFSSL_ECC_BLIND_K (and enables pkcs11) to cover these code paths. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
dgarske
force-pushed
the
ecc_blind_k_fixes
branch
from
August 21, 2026 15:54
1dde6ae to
addd5ea
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
With key blinding on,
wc_ecc_key_get_priv()resolves toecc_get_k(), which recomputeskey->ku = key->k XOR key->kband returns&key->ku. It is a read-only accessor over a regenerated scratch value: writes through it are recomputed over on the next call, and zeroing it leaves the secret itself in memory. WithoutWOLFSSL_ECC_BLIND_Kthe accessor is just(key)->k, and nothing in CI defined it, so the misuse accumulated.What was broken
sakke.cwc_MakeSakkeKey()RNG_FAILURE_E. SAKKE key generation did not work at all.sakke.cx2,eccsi.cx2eccsi.c"Erase v", "erase j"src/pk_ec.cwolfssl_ec_key_int_copy()wc_ecc_key_get_priv(dst)called beforedst->dpwas set: NULL dereference, segfault intest_wolfSSL_EC_KEY_dup.src/pk_ec.cSetECKeyInternal()ECDSA_do_sign,EC_KEY_set_private_key,ECDH_compute_keyandd2i_ECPrivateKey.wc_pkcs11.cmp_forcezero()through the accessor left the private scalar in memory.port/silabs/silabs_ecc.cApproach
Rather than per-site
#ifdefs, the existingecc_get_k()/ecc_blind_k_rng()family inecc.hgains two members, so every call site is a one-liner with no conditional compilation:ecc_get_k_raw(key)- writable handle on the stored scalar; a write is followed byecc_blind_k_rng(), which is already a no-op (0) without blinding.ecc_forcezero_k(key)- erases the scalar, its blind and the scratch together; plainmp_forcezero()without blinding.The FIPS-header compat shims in the touched files get matching fallbacks. The one remaining
#ifdefis the blind copy inwolfssl_ec_key_int_copy(), wheredst->dpis not yet set so a fresh blind cannot be installed.CI
Adds
all-ecc-blind-k(--enable-all CPPFLAGS=-DWOLFSSL_ECC_BLIND_K) to.github/configs/os-check-linux.json. Distinct from the existingblind-private-keyentry, which setsWOLFSSL_BLIND_PRIVATE_KEYand does not imply this macro.Testing
--enable-all --enable-lmswith and without-DWOLFSSL_ECC_BLIND_K:testwolfcryptclean and the full unit suite passes, includingtest_wolfSSL_EC_KEY_dup(previously a segfault), SAKKE and ECCSI. Note the blinded config did not pass on master before this batch:ecc_mulmod_test()(fixed in #11172), theEC_KEY_dupsegfault, and SAKKE key generation - the last two are fixed here.The Silicon Labs and PKCS#11 changes have no host build and were made by inspection; they follow the same pattern as the rest.