Skip to content

Fix Thumb-1 sp_div_word - #12121

Open
yosuke-wolfssl wants to merge 3 commits into
wolfSSL:masterfrom
yosuke-wolfssl:fix/f-thumb-sp
Open

yosuke-wolfssl wants to merge 3 commits into
wolfSSL:masterfrom
yosuke-wolfssl:fix/f-thumb-sp

Conversation

@yosuke-wolfssl

Copy link
Copy Markdown
Contributor

Problem

The Thumb-1 sp_div_word (WOLFSSL_SP_ARM_THUMB with WOLFSSL_SP_DIV_WORD_HALF, which WOLFSSL_SP_DIV_32 implies) returns wrong quotient digits in three independent ways. As a result, mp_div, mp_mod, mp_mulmod, mp_div_d, mp_mod_d and mp_gcd (e.g. the RSA key generation check gcd(p-1, e)) return wrong results.

Fix (wolfcrypt/src/sp_int.c)

One commit per finding:

  • Removes the dead movs r4, %[hi]; r4 is reloaded before use.
  • Keeps d - rem and also adds 1 when it is zero, as the ARM32 sp_div_word does.
  • Replaces the 0-or-8 pre-shift with a branch-free 16/8/4/2/1 search that shifts d until its top bit is set. This also removes the old branch on d.

Closes f-18179, f-18180, f-18181.

Tests

New mp_test_div_word in wolfcrypt/test/test.c: 6 known-answer vectors through mp_div_d and mp_mod_d, one group per finding.

Verification

  • ARMv6 Thumb-1 builds with -DWOLFSSL_SP_DIV_32 under qemu-arm 8.2.2, using GCC 13.3 and clang 18:
    • testwolfcrypt: on master it fails (GCC fails in mp_test_lcm_gcd); with this series it passes on both compilers.
    • New vectors: each group fails before its commit and passes after it.
  • Direct check of sp_div_word against 64-bit division (3M random and edge inputs): 2,354,919 wrong on master (GCC), 0 wrong after the series (GCC and clang).
  • Native 64-bit builds pass with -Werror.
  • Performance (qemu): sp_div_word is about 7% slower; RSA-2048, DH-2048 and P-256 operations change by less than 1%.

The clang Thumb build only works with workarounds for problems already on master, which are tracked separately.

- Remove the movs r4 between the subtract and subtract-with-carry
  of the first correction round in the Thumb sp_div_word.
- mp_test gains mp_test_div_word with an mp_div_d vector whose
  divisor has the top bit set.

Issue: F-18180
- The final fix-up of the Thumb sp_div_word keeps d - rem in r5,
  adds 1 to the quotient when rem > d, then subtracts 1 from r5 and
  adds the borrow, so rem == d also adds 1.
- mp_test_div_word gains two exact-division vectors.

Issue: F-18181
- The Thumb sp_div_word shifts d left until its top bit is set,
  using a branch-free 16/8/4/2/1 search written once per compiler
  in place of the 0-or-8 bit pre-shift.
- mp_test_div_word gains vectors with divisors in [2^16, 2^23)
  and [2^24, 2^31), and checks mp_mod_d for every vector.

Issue: F-18179
@yosuke-wolfssl yosuke-wolfssl self-assigned this Nov 13, 2026
Copilot AI balanced review requested due to automatic review settings November 13, 2026 04:14

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.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@yosuke-wolfssl yosuke-wolfssl changed the title Fix/f thumb sp Fix Thumb-1 sp_div_word Nov 13, 2026
@yosuke-wolfssl

Copy link
Copy Markdown
Contributor Author

@claude review

@github-actions

github-actions Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

MemBrowse Memory Report · Explore what changed →

zephyr-frdm_rw612

  • FLASH: datas +16 B, log_const_area -8 B, rodata +36 B, text +11,664 B (+4.1%, 294,172 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.

@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 found no bugs. It rewrites hand-written Thumb-1 inline assembly in a core bignum division routine, in three syntax variants (Keil, clang, GCC), so a human should still look at it.

What I checked:

  • The new 16/8/4/2/1 normalization uses sub #1 followed by sbc r6,r6. When the tested top bits are zero, this produces an all-ones mask, so d is shifted and r3 adds up the shift without branching. r5 and r6 are already in the asm clobber list.
  • The final correction step: d - r4 now feeds a borrow-based +1 into the quotient before the existing subtract-1 step. Removing the dead movs r4, %[hi] and the old lsl d, d, r3 matches the new flow.
  • I worked out 5 of the 6 new test vectors by hand and they check out; I didn't recompute the 64-bit top-bit-set vector. The new test's guard matches at the definition and the call site, and mp_test itself already requires !WOLFSSL_RSA_VERIFY_ONLY, so mp_div_d/mp_mod_d are available.
  • I didn't assemble or run the Thumb-1 builds or the qemu results described in the PR. Those claims are unverified here.
Extended reasoning...

The change rewrites the ARM Thumb-1 inline-asm sp_div_word in wolfcrypt/src/sp_int.c and adds a known-answer test in wolfcrypt/test/test.c. That routine is used by mp_div, mp_mod, mp_mulmod and gcd, which RSA/DH/ECC rely on. It is cryptographic arithmetic, and timing resistance matters there. The asm reads as correct and branch-free, but it is about 150 lines of hand-written assembly in three syntax variants that this review could not assemble or run. A human with Thumb-1 toolchain access should confirm it.

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

Scan targets checked: wolfcrypt-src, wolfcrypt-bugs
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: Max

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