Skip to content

PPC64LE brainpoolP512r1 ECDH: [d]P by three-bit windows - #4779

Merged
alex merged 2 commits into
mainfrom
claude/ppc64le-brainpool512-ecdh-main
Nov 9, 2026
Merged

alex merged 2 commits into
mainfrom
claude/ppc64le-brainpool512-ecdh-main

Conversation

@alex

@alex alex commented Nov 8, 2026

Copy link
Copy Markdown
Member

Part of #4141 (the PPC64LE audit, finding 1). Now that #4722 has merged, this restacks #4769 onto main and replaces it. The two commits are #4769's, cherry-picked unchanged.

vg_ecdh_brainpoolp512r1 on PPC64LE computed [d]P with the Montgomery ladder. It now uses three-bit windows with the formulas for any a.

Why three bits, and why start from the top two bits

  • Four-bit windows don't fit. brainpoolP512r1's coordinates are 8 words, so an entry is 192 bytes. Sixteen entries from the end of the tables of bits (5632) would end at 8704, past the 8192-byte working space. Eight entries end at 7168, as for P-521 (PPC64LE P-521 ECDH: [d]P by three-bit windows #4722).
  • The top window would read past the table of bits. The scalar's 512 bits are 3 · 170 + 2. So PPC64LE P-521 ECDH: [d]P by three-bit windows #4722's loop of 171 windows from R = O would read bit 512 in its top window. That is one byte past the table of bits, the first entry of the next table (p − 2's bits, which MulPowOk provides), which is 1. Instead, R starts at the table's entry for the top two bits (top2, then the usual masked scan, then R = D), and the 170 windows below follow.

What changes

No TCB, Spec or Rust change. The only crate change is ecdh_brainpoolp512r1.rs and its assembly.

Testing

Benchmark

Benchmarks run 42529524175, the same windows. It ran before the addition chain and #4774's multiplication reached either side, with arches=powerpc64, modules=ecdh_brainpoolp512r1, and base bd7184fc (main with the ladder):

Benchmark Base Head Change
ecdh_brainpoolp512r1/64 3.84 ms 2.11 ms 45.0% faster

Generated by Claude Code

brainpoolP512r1's sixteen entries of four-bit windows (192 bytes each) do not
fit the working space past the tables of bits, so its windows take three
bits, as P-521's do (Window3.lean), with the complete addition and the
Jacobian doubling for any a (rcb, dblJa), as brainpoolP384r1's four-bit
windows do (WindowA.lean): Impl/Ecdsa/PPC64LE/Window3A.lean.

The scalar's 512 bits are 170 windows and two bits above them: a 171st
window from R = O would read a bit past the table of bits (the first bit of
the table of p - 2's). So R starts at the entry of the top two bits
(mul3top), and the 170 windows below them follow. The proof is P-521's on
brainpoolP512r1's field and eight-word layout, with the doublings and the
addition for any a.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TKUFHFbSpgWBYWAsEnfUks
Regenerated with the full emitter on #4722.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TKUFHFbSpgWBYWAsEnfUks
@alex
alex added this pull request to the merge queue Nov 9, 2026
Merged via the queue into main with commit e907322 Nov 9, 2026
21 checks passed
@alex
alex deleted the claude/ppc64le-brainpool512-ecdh-main branch November 9, 2026 00:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants