Skip to content

Keep secret values out of the variable-time inversion in ECC, ECCSI, SAKKE and BN - #12023

Open
dgarske wants to merge 12 commits into
wolfSSL:masterfrom
dgarske:ecc_ct_inverse
Open

dgarske wants to merge 12 commits into
wolfSSL:masterfrom
dgarske:ecc_ct_inverse

Conversation

@dgarske

@dgarske dgarske commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

Description

Hardens secret-handling in ECC, ECCSI, SAKKE and the OpenSSL compatibility BN layer against timing side channels. Takes over #11159; its commits keep their author.

  • ECCSI signing and SAKKE RSK derivation blind before inverting; SAKKE pairing and exponentiation use a Fermat inverse.
  • Generic scalar multiplication with map set uses the constant-time map. SP curve paths are unchanged. Two-scalar EC_POINT_mul() keeps Shamir's trick, which is variable time, and is documented as not for secret scalars.
  • FP_ECC under ECC_TIMING_RESISTANT uses a new constant-time comb.
  • wolfSSL_BN_mod_inverse() blinds its operand when an RNG is available.
  • Heap-math _ct primitives no longer branch on reduced operands, and ConstantCompare() loads are volatile and used for the ATECC GCM tag check.

Behavior changes

  • FP_ECC with ECC_TIMING_RESISTANT: key generation, ECDH and signing are slower than the old variable-time comb, and FP_LUT defaults to 6 rather than 8, making ecc_mul2add() slower with a smaller table. --enable-sp remains fastest for the curves it covers. Heap math, a scalar longer than the modulus and a modulus too large for the comb use the ladder.
  • wc_MakeSakkeRsk() instantiates an RNG per call and can fail on RNG errors; wc_MakeSakkeRsk_ex() is added to pass one. SAKKE with WC_NO_RNG is now a build error, configure and CMake reject it, and --enable-all-crypto leaves SAKKE off with --disable-rng.
  • WOLFSSL_MP_INVMOD_CONSTANT_TIME is removed and has no effect. DSA signing and RSA key generation always use their blinded or Fermat inverse, so builds that defined it now draw one more random value per DSA signature.
  • Heap-math mp_addmod_ct(), mp_submod_ct() and mp_div_2_mod_ct() return MP_VAL for a negative operand or one wider than the modulus.
  • WOLFSSL_NO_CONST_CMP is no longer defined automatically. Minimal WOLFCRYPT_ONLY builds define WC_NO_CONST_CMP_API instead, leaving out only wc_ConstantCompare().

Resolves F-7097, F-7098, F-7099, F-7426, F-7427, F-15120, F-16129. ZD 22745. Reported by Alexandre Laroche.

@dgarske dgarske self-assigned this Nov 5, 2026
Copilot AI balanced review requested due to automatic review settings November 5, 2026 18:48
@dgarske dgarske mentioned this pull request Nov 5, 2026
@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

MemBrowse Memory Report · Explore what changed →

gcc-arm-cortex-m0plus

  • FLASH: .text +20 B (+0.0%, 71,215 B / 262,144 B, total: 27% used)

gcc-arm-cortex-m3

  • FLASH: .text -56 B (-0.0%, 132,173 B / 262,144 B, total: 50% used)

gcc-arm-cortex-m4

  • FLASH: .text -64 B (-0.0%, 209,484 B / 262,144 B, total: 80% used)

gcc-arm-cortex-m4-crypto-only

  • FLASH: .text -64 B (-0.0%, 182,227 B / 262,144 B, total: 70% used)

gcc-arm-cortex-m4-openssl-compat

  • FLASH: .text +256 B (+0.0%, 802,436 B / 1,048,576 B, total: 77% used)

gcc-arm-cortex-m4-pq

  • FLASH: .text -64 B (-0.0%, 313,360 B / 1,048,576 B, total: 30% used)

gcc-arm-cortex-m4-rsa-only

  • FLASH: .text -64 B (-0.0%, 343,888 B / 1,048,576 B, total: 33% used)

gcc-arm-cortex-m4-tls12

  • FLASH: .text -64 B (-0.0%, 132,945 B / 262,144 B, total: 51% used)

gcc-arm-cortex-m4-tls13

  • FLASH: .text -64 B (-0.0%, 250,082 B / 262,144 B, total: 95% used)

gcc-arm-cortex-m7-pq

  • FLASH: .text -64 B (-0.0%, 314,192 B / 1,048,576 B, total: 30% used)

gcc-arm-cortex-m7-tls13

  • FLASH: .text -64 B (-0.0%, 250,082 B / 262,144 B, total: 95% used)

stm32-sim-stm32h753

  • FLASH: .text -64 B (-0.0%, 204,844 B / 2,097,152 B, total: 10% used)

zephyr-frdm_rw612

  • FLASH: datas +16 B, log_const_area -8 B, rodata +36 B, text +11,640 B (+4.1%, 294,148 B / 67,108,864 B, total: 0% used)
  • RAM: bss +49 B, datas +16 B (+0.1%, 58,423 B / 983,040 B, total: 6% used)

No memory changes detected for:


Catch memory regressions in CI with MemBrowse. Free for open source.

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.

🟡 Changes recommended

Critical timing leaks remain in ECC exceptional branches and the modular-inversion fallback, while an unconditional table assertion also fails for the timing-resistant heap-math configuration.

3 open issues
What changed in this PR

This PR hardens secret-dependent arithmetic in wolfCrypt and the OpenSSL compatibility layer against timing side channels, continuing the work from #11159.

Changes:

  • Adds blinded or Fermat-based inversion paths and timing-resistant ECC mapping and fixed-point multiplication.
  • Reworks heap-math constant-time helpers and comparison handling.
  • Adds SAKKE RNG requirements, an RNG-accepting API, and regression and fault-injection coverage.
File Description
wolfssl/​wolfcrypt/​settings.h Separates exported comparison API suppression from internal availability.
wolfssl/​wolfcrypt/​sakke.h Declares the RNG-accepting RSK API.
wolfssl/​wolfcrypt/​memory.h Updates the comparison API guard.
wolfcrypt/​src/​sp_int.c Enables modular multiplication for SAKKE.
wolfcrypt/​src/​sakke.c Adds inversion blinding, Fermat conversion, and RNG handling.
wolfcrypt/​src/​rsa.c Removes the alternate unblinded key-generation inverse.
wolfcrypt/​src/​port/​atmel/​atmel.c Uses constant-time GCM tag comparison.
wolfcrypt/​src/​misc.c Uses volatile comparison loads.
wolfcrypt/​src/​memory.c Updates the exported comparison implementation guard.
wolfcrypt/​src/​integer.c Reworks constant-time modular arithmetic helpers.
wolfcrypt/​src/​eccsi.c Blinds signing inversion and clears temporary secrets.
wolfcrypt/​src/​ecc.c Adds timing-resistant comb multiplication and mapping.
wolfcrypt/​src/​dsa.c Always uses the blinded signing path.
wolfcrypt/​benchmark/​benchmark.c Reuses the benchmark RNG for RSK generation.
tests/​unit-mcdc/​test_sakke_whitebox.c Tests rejection of a noninvertible RSK input.
tests/​unit-mcdc/​test_sakke_fault_whitebox.c Exercises blinding retries and exhaustion.
tests/​unit-mcdc/​test_integer_whitebox.c Updates source-line references in comments.
tests/​unit-mcdc/​test_integer_fault_whitebox.c Tests helper allocation failures and invalid arguments.
tests/​unit-mcdc/​test_eccsi_fault_whitebox.c Tests signing blinding retries and limits.
tests/​unit-mcdc/​test_ecc_whitebox.c Compares cached comb results with the ladder.
tests/​unit-mcdc/​test_ecc_fault_whitebox.c Adapts calls to the new multiplier signature.
tests/​api/​test_wolfmath.h Registers heap-math regression tests.
tests/​api/​test_wolfmath.c Tests arithmetic results, aliasing, and input validation.
tests/​api/​test_sakke.c Tests the RNG-accepting RSK API.
tests/​api/​test_ossl_bn.c Tests composite-modulus inversion and aliasing.
tests/​api/​test_ecc.h Registers ECC regression tests.
tests/​api/​test_ecc.c Adds boundary-scalar and cache-consistency tests.
src/​ssl_bn.c Adds best-effort inversion blinding and random-buffer clearing.
src/​pk_ec.c Documents the variable-time Shamir path.
doc/​dox_comments/​header_files/​sakke.h Adds the new SAKKE API to documentation.
doc/​dox_comments/​header_files/​doxygen_groups.h Updates RSK documentation references.
doc/​dox_comments/​header_files-ja/​sakke.h Adds the API to Japanese documentation.
doc/​dox_comments/​header_files-ja/​doxygen_groups.h Updates Japanese RSK documentation references.
configure.ac Enforces SAKKE RNG requirements and bundle selection.
CMakeLists.txt Rejects SAKKE without RNG support.
.wolfssl_known_macro_extras Updates recognized comparison and inversion macros.
.github/​configs/​os-check-linux.json Adds fixed-point ECC and SP-math SAKKE configurations.

Review effort: Balanced

Comment thread src/ssl_bn.c Resolved
Comment thread wolfcrypt/src/ecc.c Resolved
Comment thread tests/unit-mcdc/test_ecc_whitebox.c Resolved
@dgarske

dgarske commented Nov 5, 2026

Copy link
Copy Markdown
Member Author

Jenkins retest this please. Size-config test RROR: Error cloning remote repo 'origin

@dgarske dgarske assigned wolfSSL-Bot and unassigned dgarske Nov 6, 2026
@dgarske
dgarske requested a review from SparkiDev November 6, 2026 22:42
Comment thread src/ssl_bn.c Resolved
Comment thread wolfcrypt/src/ecc.c Resolved
Comment thread wolfcrypt/src/ecc.c Resolved
Comment thread wolfcrypt/src/ecc.c Resolved
Comment thread wolfcrypt/src/integer.c Resolved
Comment thread wolfcrypt/src/sakke.c Resolved
SparkiDev
SparkiDev previously approved these changes Nov 10, 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.

🟡 Changes recommended

The cached ECC path retains critical secret-dependent control flow, and modular-inverse blinding can reject valid unreduced operands with fixed-size SP math.

1 open issue
3 resolved since last review

Review effort: Balanced

Comment thread src/ssl_bn.c Resolved
@SparkiDev
SparkiDev requested a balanced review from Copilot November 12, 2026 00:51
@SparkiDev

Copy link
Copy Markdown
Contributor

@claude review

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.

🔵 Needs a closer look

The new secret-scalar comb path still uses point addition with scalar-dependent exceptional branches and extra doubling, leaving a critical timing side channel despite fixed table scans and randomized projective coordinates.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I reviewed this PR and didn't find any bugs. It's a large side-channel hardening change to core ECC, ECCSI, SAKKE and bignum code, and it changes some build and API behavior, so a human review is still worthwhile.

What was reviewed:

  • The new constant-time FP_ECC comb (fp_comb_ct/fp_lut_select) in wolfcrypt/src/ecc.c, and how wc_ecc_mulmod_ex/ex2 choose between the constant-time and variable-time paths.
  • The blinded inverses: ECCSI signing, SAKKE RSK derivation (with the new wc_MakeSakkeRsk_ex and sakke_rand_nonzero_mod_q), and wolfssl_bn_invmod_blind in src/ssl_bn.c, including its unblinded fallback and its handling of factors that share a divisor with m.
  • The mask-based mp_addmod_ct/mp_submod_ct rewrite in integer.c, the removal of WOLFSSL_MP_INVMOD_CONSTANT_TIME, and the new WC_NO_CONST_CMP_API and SAKKE-requires-RNG checks across configure.ac, CMakeLists.txt and settings.h.
Extended reasoning...

The PR is about 1750 added lines across 37 files. It hardens how secret scalars and inverses are handled in wolfCrypt ECC, ECCSI and SAKKE, in heap-math integer.c and in the OpenSSL-compat BN layer. All of that is cryptographic, timing-sensitive code, where a regression in constant-time behavior or blinding would be high severity. It also changes behavior: the FP_LUT default drops from 8 to 6, SAKKE now fails to build without an RNG, WOLFSSL_MP_INVMOD_CONSTANT_TIME is removed, and minimal builds define WC_NO_CONST_CMP_API instead of WOLFSSL_NO_CONST_CMP. Because of its size and the crypto surface it touches, it isn't a candidate for automated approval, even though the bug hunt found nothing.

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.

5 participants