Skip to content

Constant-time handling of the ECC point at infinity - #11173

Draft
dgarske wants to merge 6 commits into
wolfSSL:masterfrom
dgarske:fenrir_ecc_ct_points
Draft

Constant-time handling of the ECC point at infinity#11173
dgarske wants to merge 6 commits into
wolfSSL:masterfrom
dgarske:fenrir_ecc_ct_points

Conversation

@dgarske

@dgarske dgarske commented Aug 13, 2026

Copy link
Copy Markdown
Member

Stacked on #11172 - do not merge until that lands.
This branch is based on fenrir_threadsafety_keys, so GitHub shows #11172's
five commits here as well. The change belonging to this PR is the single
commit "Handle the point at infinity without branching in ECC point add and
double (F-2618)" - 1 file, 159 lines. Once #11172 merges I will rebase this
onto master and the diff will shrink to that commit alone.

Constant-time handling of the ECC point at infinity

Part 4 of 4 from an internal automated source review. Builds on part 3 (fenrir_threadsafety_keys) and should merge after it. Kept separate because it is the only change in the batch with a measurable performance cost.

Report Summary
F-2618 ECC point add and double exceptional case handling

ecc_projective_add_point_safe() and ecc_projective_dbl_point_safe() branched on whether an operand was the point at infinity, collapsing to a point copy instead of doing the arithmetic. Both now run the ordinary operation regardless and select the result with mp_cond_copy(), so an exceptional operand costs the same as an ordinary one.

The addition computes into a temporary rather than into R: every call site passes the first operand as the destination, so writing R early would destroy A before the selection. The temporary is on the stack unless the build asked otherwise, and inherits the key heap and the small-stack cache back-pointer from R so it behaves like the caller's own points.

The A == B equality branch is deliberately left in place. The Montgomery ladder cannot reach it, and covering it would mean computing a doubling as well as an addition on every call.

Performance

Measured interleaved A/B with standalone binaries, four runs each, on a default ./configure build:

Operation master branch Delta
ECDH agree 5747.6 5228.0 -9.0%
ECDSA sign 5484.8 5043.8 -8.0%
ECDSA verify 8181.6 7746.1 -5.3%

This is the legacy point arithmetic only. Builds using --enable-sp - including --enable-all - route P-256/384/521 through the SP implementations and are unaffected.

Worth noting for the record: this code is not compiled out under SP math as the report claims. The guard is !WOLFSSL_SP_MATH, not !WOLFSSL_SP_MATH_ALL, and instrumentation confirms P-256 ECDH and ECDSA reach both functions in a default build.

A further caveat: mp_cmp_ct() and mp_montgomery_reduce_ct() are #defined to the non-constant-time versions on integer.c and tfm.c, so this change cannot deliver constant time on those backends regardless.

Testing

make check passes on --enable-all, --enable-all --enable-lms, --enable-fastmath, --enable-heapmath, --enable-smallstack --enable-smallstackcache and --enable-fpecc.

Copilot AI lite review requested due to automatic review settings August 13, 2026 22:42
@dgarske dgarske self-assigned this Aug 13, 2026
@dgarske
dgarske marked this pull request as draft August 13, 2026 22:43

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 aims to remove data-dependent branching when handling the ECC point at infinity in the “safe” projective add/double paths by always performing the arithmetic and selecting results afterward. Because this branch is stacked on #11172, the diff also includes thread-safety and key-handling related changes (mutex once-init helper, RSA blinding adjustment, netRandom init changes) plus test updates.

Changes:

  • Make ecc_projective_add_point_safe() / ecc_projective_dbl_point_safe() handle infinity without early-exit branches by computing unconditionally and selecting via constant-time conditional copies.
  • Add wc_local_InitMutexOnce() and migrate several lazy mutex-init sites to a single “init exactly once” pattern.
  • Update RSA blinding inversion to avoid using mp_invmod() directly on a secret-derived value, and adjust tests for the new ECC private-key range checks/import behavior.

Reviewed changes

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

Show a summary per file
File Description
wolfssl/wolfcrypt/wc_port.h Declares wc_MutexOnceFlag and wc_local_InitMutexOnce() for one-time mutex initialization.
wolfcrypt/src/wc_port.c Implements wc_local_InitMutexOnce() election/wait logic.
wolfcrypt/src/random.c Switches netRandom mutex init to wc_local_InitMutexOnce() and updates init-state tracking.
wolfcrypt/src/ecc.c Reworks infinity handling in projective add/double safe paths; adds ECC private scalar range check and converts mutex init flags to once-init.
wolfcrypt/src/cryptocb.c Adjusts crypto callback registry entry publish/retire ordering and error handling.
wolfcrypt/src/rsa.c Adds masked inversion step for RSA blinding to avoid secret-dependent inversion behavior.
wolfcrypt/src/port/nxp/se050_port.c Ensures sensitive DER buffers are wiped fully before free in SE050 RSA/ECC paths.
wolfcrypt/test/test.c Updates ECC mulmod tests to avoid using curve constants as “private key” inputs.
tests/api/test_ecc.h Registers new ECC private-key range test.
tests/api/test_ecc.c Adds coverage for ECC private-key range rejection and adjusts shared-secret infinity-case coverage accordingly.
Suppressed comments (1)

wolfcrypt/src/ecc.c:8788

  • The infinity check uses logical &&, which may short-circuit and skip the y==0 test when x!=0, creating data-dependent control flow. If the intent is constant-time/cost-independent handling of infinity, compute both mp_iszero() results unconditionally (e.g., with separate statements or bitwise '&').
    inf = (mp_iszero(P->x) == MP_YES) && (mp_iszero(P->y) == MP_YES);

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

Comment thread wolfcrypt/src/ecc.c Outdated
@dgarske
dgarske force-pushed the fenrir_ecc_ct_points branch from 2e9a449 to a867b11 Compare August 13, 2026 23:18
@dgarske
dgarske force-pushed the fenrir_ecc_ct_points branch from a867b11 to f557e75 Compare August 14, 2026 15:08
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.

2 participants