Skip to content

Reject negative scalars in ECC point multiplication - #12036

Open
Frauschi wants to merge 1 commit into
wolfSSL:masterfrom
Frauschi:ecc-negative-scalar
Open

Frauschi wants to merge 1 commit into
wolfSSL:masterfrom
Frauschi:ecc-negative-scalar

Conversation

@Frauschi

@Frauschi Frauschi commented Nov 6, 2026

Copy link
Copy Markdown
Member

Description

ECC scalar multiplication computed |k|·G for a negative scalar and returned success, reachable from every OPENSSL_EXTRA build. Every entry point now rejects it, and EC_POINT_mul() reduces such scalars as OpenSSL does.

Fixes F-16901.

  • wc_ecc_mulmod_ex(), wc_ecc_mulmod_ex2() and ecc_mul2add() return ECC_OUT_OF_RANGE_E for a negative scalar, in the generic, SP and fixed-point code
  • The SP-only paths also reject a scalar longer than the curve, which they silently truncated
  • The NXP LTC and STM32 PKA ports get the same checks; LTC also bounds k and the point coordinates it copies into fixed stack buffers
  • The ports set the result's y positive instead of copying the sign of k
  • EC_POINT_mul() reduces a negative or over-wide scalar modulo order × cofactor
  • The fixed-point ecc_mul2add() checks its arguments before allocating

Limitations

  • A negative EC_KEY private key still reaches the SP ECDH and sign paths as |k|; that is a separate follow-up

Testing

  • New test_wc_ecc_mulmod_negative: negative and oversized scalars for wc_ecc_mulmod(), _ex, _ex2 and ecc_mul2add()
  • New test_wolfSSL_EC_POINT_mul_negative: -5, -order and order·2^64+5 give the same points as their reduced values

Copilot AI balanced review requested due to automatic review settings November 6, 2026 10:00
@github-actions

github-actions Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

MemBrowse Memory Report · Explore what changed →

gcc-arm-cortex-m0plus

  • FLASH: .text +24 B (+0.0%, 70,743 B / 262,144 B, total: 27% used)

gcc-arm-cortex-m3

  • FLASH: .text +20 B (+0.0%, 131,697 B / 262,144 B, total: 50% used)

gcc-arm-cortex-m4-min-ecc

  • FLASH: .text +64 B (+0.1%, 68,057 B / 262,144 B, total: 26% used)

gcc-arm-cortex-m4-openssl-compat

  • FLASH: .text +320 B (+0.0%, 800,996 B / 1,048,576 B, total: 76% used)

gcc-arm-cortex-m4-sp-math

  • FLASH: .text +64 B (+0.1%, 68,057 B / 262,144 B, total: 26% used)

gcc-arm-cortex-m4-tls12

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

zephyr-frdm_rw612

  • FLASH: log_const_area -8 B, rodata -8 B, text +1,592 B (+0.6%, 284,040 B / 67,108,864 B, total: 0% 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

The LTC path permits a stack-buffer overflow with oversized moduli, and scalar-handling regressions and P-256 test-configuration failures remain unresolved.

5 open issues
What changed in this PR

This PR hardens ECC scalar multiplication for F-16901 by rejecting negative scalars in wolfCrypt and adding scalar reduction in the OpenSSL compatibility layer.

Changes:

  • Adds scalar validation across software and hardware implementations, plus coordinate bounds checks for NXP LTC.
  • Reduces negative and oversized EC_POINT_mul() scalars modulo order × cofactor.
  • Adds regression tests and documents the range error.
File Description
wolfcrypt/​src/​port/​st/​stm32.c Validates scalars and sets the result’s y sign positive.
wolfcrypt/​src/​port/​nxp/​ksdk_port.c Adds scalar and coordinate checks; sets y positive.
wolfcrypt/​src/​ecc.c Rejects negative scalars and validates fixed-point arguments before allocation.
tests/​api/​test_ossl_ec.h Registers the compatibility-layer regression test.
tests/​api/​test_ossl_ec.c Tests negative and oversized scalar reduction.
tests/​api/​test_ecc.h Registers the wolfCrypt scalar-validation test.
tests/​api/​test_ecc.c Tests scalar rejection and positive-scalar acceptance.
src/​pk_ec.c Adds scalar reduction before ECC multiplication.
doc/​dox_comments/​header_files/​ecc.h Documents ECC_OUT_OF_RANGE_E for invalid scalars.

Review effort: Balanced

Comment thread wolfcrypt/src/port/nxp/ksdk_port.c Resolved
Comment thread src/pk_ec.c Resolved
Comment thread src/pk_ec.c Resolved
Comment thread tests/api/test_ecc.c Resolved
Comment thread tests/api/test_ossl_ec.c Resolved
@Frauschi

Frauschi commented Nov 6, 2026

Copy link
Copy Markdown
Member Author

@claude review

@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.

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Comment thread src/pk_ec.c Resolved

@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 #12036

Scan targets checked: wolfcrypt-src, wolfcrypt-bugs, wolfcrypt-port-bugs, wolfssl-src, wolfssl-bugs
Not reviewed (no scan target covers them): doc/dox_comments/header_files/ecc.h, tests/api/test_ecc.h, tests/api/test_ossl_ec.h
Coverage: 6 of 6 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: Max

@Frauschi
Frauschi force-pushed the ecc-negative-scalar branch 2 times, most recently from 1cf7741 to b49acb7 Compare November 6, 2026 11:27
wc_ecc_mulmod_ex(), wc_ecc_mulmod_ex2() and ecc_mul2add() checked the
scalar only by bit length and then read its magnitude, so a negative k
computed |k|*G and returned success. That is the negation of the right
result. Negative values reach these functions with fastmath, heap math
and sp_int with WOLFSSL_SP_INT_NEGATIVE, which every OPENSSL_EXTRA build
defines. Return ECC_OUT_OF_RANGE_E for a negative scalar at every entry
point, as ecc_make_pub_sw() and the signature range checks already do,
including the NXP LTC and STM32 PKA ports, which have their own. Those
ports set the sign of the result's y from k; they now set it positive,
since reading the coordinates leaves the sign of a reused point
unchanged. The fixed-point ecc_mul2add() also gains the argument checks
the other implementation has, done before it allocates.

The SP-only wc_ecc_mulmod_ex2() and the fixed-point SP-only
wc_ecc_mulmod_ex() and wc_ecc_mulmod_ex2() also check the scalar's
length, as the SP-only wc_ecc_mulmod_ex() does. The SP code drops the
high digits of a longer scalar and returned a wrong point. The LTC port
checks the length as the generic code does, rejects point coordinates
wider than the prime with IS_POINT_E, and refuses a prime wider than its
coordinate buffers, since it copied all of them into fixed stack
buffers. The STM32 PKA port checks the length too, so it returns
ECC_OUT_OF_RANGE_E rather than BUFFER_E.

EC_POINT_mul() passed the BIGNUM's mp_int straight through. OpenSSL
reduces a negative or over-wide scalar modulo the number of points on
the curve, the order times the cofactor. Reduce n and m the same way
when they are negative or wider than the prime, which some backends
reject, so they give the same result. Some math libraries leave the
remainder with the sign of the dividend, so a negative remainder gets
the modulus added. Reducing by the order alone would be wrong for a
point outside the prime-order subgroup on a curve with a cofactor. The
bound comes from the curve's degree, so scalars in range cost nothing
extra, and the modulus is computed once.

Fixes F-16901.
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.

4 participants