Repository navigation
ecc: return infinity for a scalar that is 0 modulo the order - #11932
yosuke-wolfssl wants to merge 1 commit into
Conversation
|
@claude review |
|
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #11932
Scan targets checked: wolfcrypt-src, wolfcrypt-bugs, wolfssl-bugs
Not reviewed (no scan target covers them): .github/configs/os-check-linux.json, tests/api/test_ecc.h
Coverage: 2 of 2 in-scope changed file(s) opened by the reviewer
Fenrir result: Approved ✅
No new issues found in the changed files.
Advisory only — this automated result does not count as a GitHub approval.
Review tier: Lite
There was a problem hiding this comment.
I reviewed this PR and didn't find any bugs. It changes core ECC scalar multiplication in both the FP_ECC and non-FP_ECC builds, so a human look from someone who owns ecc.c is still worthwhile.
What was reviewed:
- The zero-k early return in the non-FP
wc_ecc_mulmod_ex: it jumps toexitbefore anything is allocated, and the cleanup code there handles NULLtG, NULLM[]and NULLkey. - The new
first == 1handling after the loops inecc_mul2add,accel_fp_mulandaccel_fp_mul2add. In theaccel_fp_mul2addzB branch, copying LUT[zB] with z = mu matches the existing zA copy. ecc_set_point_infinityis defined in a block guarded the same way as its new callers. The zero-scalar early return branches on a public-zero condition rather than on secret bits, but whether that is acceptable in hardened builds is a maintainer call.
Extended reasoning...
The change touches wolfcrypt/src/ecc.c, which handles ECC scalar multiplication and point addition: early returns for k == 0, setting the result to infinity after the loop, and a fix to how accel_fp_mul2add tracks first. It also adds a P-256 regression test and turns on WOLFSSL_PUBLIC_ECC_ADD_DBL in one CI config. This is security-sensitive crypto code, and the change could affect correctness and constant-time behaviour across several build variants (FP_ECC, SMALL_STACK_CACHE, NO_MALLOC). That is why I deferred instead of approving, even though the bug hunt ran until it stopped finding anything and reported no bugs.
- wc_ecc_mulmod_ex() and wc_ecc_mulmod_ex2(), with and without FP_ECC, set R to (0, 0, 1) and return when k is zero. - accel_fp_mul(), accel_fp_mul2add() and normal_ecc_mul2add() set the result to infinity when first is still set after the loop. - accel_fp_mul2add() copies LUT[zB] into R and clears first when the add of LUT[zA] in the same column set first. - tests: add test_wc_ecc_mulmod_zero for k == 0, k == 2n, and ecc_mul2add() with both scalars 0 or 2n and with (n - 2, 3). - os-check: all-public-mp adds -DWOLFSSL_PUBLIC_ECC_ADD_DBL. Issue: F-16895, F-16896, F-16904
d1db16d to
01275dd
Compare
Problem
Only the public
wc_ecc_mulmod()returns infinity for k == 0. Direct callers ofwc_ecc_mulmod_ex()/wc_ecc_mulmod_ex2()(exported withWOLFSSL_PUBLIC_ECC_ADD_DBL) andecc_mul2add()reach scalar multiplications that never produce a zero result.accel_fp_mul2add()also lost a correct result. When thezAadd reached infinity, thezBadd in the same column made R a real point again but leftfirstset. Later columns then skipped doublings, and in the last columnecc_map()read the copied table entry's z = 0 as infinity.ecc_mul2add(G, n - 2, G, 3)returned infinity instead of G.Fix (
wolfcrypt/src/ecc.c)wc_ecc_mulmod_ex()andwc_ecc_mulmod_ex2(), FP and non-FP, set R to (0, 0, 1) and return when k is zero.accel_fp_mul(),accel_fp_mul2add()andnormal_ecc_mul2add()set the result to infinity whenfirstis still set, which covers scalars that reduce to 0.accel_fp_mul2add(): when thezAadd setsfirst,LUT[zB]is copied in with z =muandfirstcleared, as the loop's other branch already does.Closes f-16895, f-16896, f-16904.
Tests
test_wc_ecc_mulmod_zero(P-256) checks for exactly (0, 0, 1) on k == 0 through_ex/_ex2, with R pre-filled and with R aliasing G, and on k == 2n. It also checksecc_mul2add()with both scalars 0 or 2n, and thatecc_mul2add(G, n - 2, G, 3)is G. TheFP_ECCcache is reset before each loop so the cached-table paths run. It needsWOLFSSL_PUBLIC_MPandWOLFSSL_PUBLIC_ECC_ADD_DBL, so theall-public-mpjob inos-check-linux.jsonnow also defines the latter.Verification
--disable-harden,--enable-fpecc, fpecc +--disable-harden,--enable-heapmath,WC_PROTECT_ENCRYPTED_MEM): pass under GCC-Werror, ASan + UBSan clean. Each fails or crashes with its fix reverted.all-public-mpthroughparallel-make-check.pywith the CI flags:make check24 suites, 0 failures. The new test runs and passes.