Skip to content

Reduce the base point in ecc_point_to_mont() when the normalizer is 1 - #11913

Merged
philljj merged 1 commit into
wolfSSL:masterfrom
LinuxJedi:ecc-p521-unreduced-base-point
Oct 28, 2026
Merged

philljj merged 1 commit into
wolfSSL:masterfrom
LinuxJedi:ecc-p521-unreduced-base-point

Conversation

@LinuxJedi

Copy link
Copy Markdown
Member

Description

ecc_point_to_mont() converts the base point to Montgomery form for wc_ecc_mulmod_ex() and wc_ecc_mulmod_ex2(). When the Montgomery normalizer is 1, it copied the ordinates instead of multiplying them, so they were not reduced modulo the prime.

SP int uses R = 2^bits(m), so for a prime of the form 2^n - 1 the normalizer is 1. P-521's prime is 2^521 - 1, so with SP int math a P-521 base point with an ordinate at or above the prime, or a negative ordinate, went straight into the point arithmetic, whose add/sub/reduce operations require values below the modulus. Other curves, and fastmath, take the mp_mulmod() branch, which reduces.

Results for wc_ecc_mulmod() on P-521 before this change:

  • y + p: MP_VAL for every scalar (the ordinate outgrows the temporaries during doubling).
  • x + p: a wrong, unreduced point for some scalars (about 0.3% of random scalars).
  • negative x, y or z (with WOLFSSL_SP_INT_NEGATIVE): MP_VAL.

This reduces the ordinates with mp_mod() when the normalizer is 1, as the other branch effectively does. With FP_ECC, build_lut() always uses mp_mulmod(), so the cached table hid this after the first use of a point.

Found while adding a test for #11912, whose test_wc_ecc_mulmod_curves currently checks an unreduced z only because of this; once this is in, it can test unreduced x and y too.

Testing

  • New API test test_wc_ecc_mulmod_unreduced: multiplies the P-521 base point with each ordinate increased by the prime (and decreased, where negative values are supported) using a fixed scalar that showed the x failure, and compares with the result for the reduced point. It fails without the fix (x: wrong point; y and negative ordinates: MP_VAL).
  • ./tests/unit.test --api --group ecc and testwolfcrypt pass, on macOS arm64, with:
    • --disable-sp --enable-ecccustcurves=all CPPFLAGS=-DWOLFSSL_PUBLIC_MP
    • --enable-sp=ec256 --disable-sp-asm --enable-ecccustcurves=all CPPFLAGS=-DWOLFSSL_PUBLIC_MP
    • --enable-sp=ec256,ec384,ec521 --enable-sp-asm --enable-ecccustcurves=all CPPFLAGS=-DWOLFSSL_PUBLIC_MP
    • --enable-fastmath --enable-sp=ec256 --disable-sp-asm --enable-ecccustcurves=all CPPFLAGS=-DWOLFSSL_PUBLIC_MP
    • --enable-all --enable-dilithium
  • A harness doing wc_ecc_mulmod() with unreduced x, y and z on P-256/384/521, secp256k1 and the Brainpool curves (random scalars, fixed-point cache cleared each time): 0 failures in 2000 iterations each with the fix; without it, unreduced y on P-521 failed 2000/2000 and unreduced x 5/2000.

Checklist

  • added tests
  • updated/added doxygen
  • updated appropriate READMEs
  • Updated manual and documentation

ecc_point_to_mont() converts the base point to Montgomery form for
wc_ecc_mulmod_ex() and wc_ecc_mulmod_ex2(). When the Montgomery normalizer
is 1 it copied the ordinates instead of multiplying them, so they were not
reduced modulo the prime.

SP int uses R = 2^bits(m), so for a prime of the form 2^n - 1 the
normalizer is 1. P-521's prime is 2^521 - 1, so with SP int math a P-521
base point with an ordinate at or above the prime, or a negative ordinate,
went straight into the point arithmetic, which needs values below the
modulus. wc_ecc_mulmod() then returned MP_VAL for y + p for every scalar
and for negative ordinates, and a wrong, unreduced point for x + p with
some scalars. Other curves, and fastmath, take the mp_mulmod() branch,
which reduces.

Reduce the ordinates with mp_mod() when the normalizer is 1, and add
test_wc_ecc_mulmod_unreduced, which checks P-521 with each ordinate
increased by the prime and, where negative values are supported,
decreased by it.
@LinuxJedi

Copy link
Copy Markdown
Member Author

@claude review

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-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.

Fenrir Automated Review — PR #11913

Scan targets checked: wolfcrypt-src, wolfcrypt-bugs, wolfssl-bugs
Not reviewed (no scan target covers them): 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

@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. The fix is small, but it changes core ECC point arithmetic in wolfcrypt, so a maintainer familiar with the math backends should still look at it.

What was reviewed:

  • The mu == 1 branch of ecc_point_to_mont() in wolfcrypt/src/ecc.c: x, y and z are now reduced with mp_mod(), which matches what the mp_mulmod() branch already does for other curves and fastmath.
  • The new test_wc_ecc_mulmod_unreduced: its feature-macro guards, the extra negative-ordinate cases that only run when negative mp_ints are supported, and the FP_ECC cache clearing before each call.
  • A possible test failure on 64-bit builds that use SP P-521 code and support negative mp_ints was looked into and ruled out.
Extended reasoning...

The change replaces three mp_copy calls with mp_mod in the Montgomery-normalizer-equals-1 branch of ecc_point_to_mont() in wolfcrypt/src/ecc.c. It also adds one P-521 regression test and registers it in tests/api/test_ecc.h. The library change is small and follows the reduction the other branch already does. It does touch crypto: the ECC scalar multiplication path used for public-key operations. Because it changes core crypto behavior across several math backends (SP int, fastmath, SP asm), I'm deferring to a human rather than approving.

@douzzer douzzer added the For FIPS v7 Module Related to FIPS v7.0.0 module prep for submission label Oct 28, 2026
@philljj philljj self-assigned this Oct 28, 2026
@philljj

philljj commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

tests good with multi-test with gcc-c89, c89-clang-tidy, wolfssl-all, sp-asm-*-sanitizer, all-crypto, etc.

@philljj
philljj merged commit 4e4478b into wolfSSL:master Oct 28, 2026
431 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

For FIPS v7 Module Related to FIPS v7.0.0 module prep for submission

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants