Skip to content

chore(libs): bump x25519 pin to v0.13.0, and keep the wrapper linkable - #189

Merged
JC-000 merged 1 commit into
masterfrom
chore/x25519-pin-v0.13.0-rebase
Sep 6, 2026
Merged

chore(libs): bump x25519 pin to v0.13.0, and keep the wrapper linkable#189
JC-000 merged 1 commit into
masterfrom
chore/x25519-pin-v0.13.0-rebase

Conversation

@JC-000

@JC-000 JC-000 commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Closes #166.

Bumps libs/x25519 from v0.11.2 to v0.13.0
(3ea64210ce4c7c4fcebdded49c3ca663ce0fd8d3, tag dereferenced via the GitHub
API, not read off git submodule status), and restates three BSS bytes in the
integration wrapper so the sibling lane keeps failing on the one failure it
already had.

This is a rebase onto dc06095 of a commit prepared in an earlier session that
was code-reviewed but never built, never tested and never pushed. Everything
below was measured here.

Read this first: the sibling is dormant, so this is hygiene, not a fix

#166 is an advisory, and it is careful to bound itself. Bounding it further:
libs/x25519 contributes zero bytes to every PRG we ship.

  • USE_X25519_SIBLING ?= 0 (Makefile:44); no PACKAGE_VARIANTS row in
    tools/package/_common.sh sets it.
  • CLAUDE.md already records that it links under neither backend, and that is
    still true at the new pin (verified below).
  • Vendored c64-x25519 is v0.11.2, which predates the §8.2 REU post-execute settle — affects the REU-on target at turbo #166 asks specifically whether uci-comb "drives x25519's REU multiply
    path". It does not. reu_fetch_mul_row is APP_OWNED here (our
    SHARED_REU_MUL_FETCH define suppresses the library's copy), and in all
    three shipped maps the symbol does not exist at all: boot.s:52-54 gates
    the .export off under USE_NISTCURVES_ONCHIP, leaving the body at
    boot.s:945 as unreferenced code. Its single caller
    src/crypto/fe25519.s:439 sits in the .else of the same guard and is
    compiled out — fe25519.s deliberately does not even .import the symbol on
    that profile. All three shipped variants set the flag (comb promotes it at
    Makefile:221-222).

So the §8.2 REU settle this bump brings in is not reachable from anything we
release. Do not read this PR as closing a live defect. It gets the vendored
tree onto a maintained tag so the dormant lane is not the thing that surprises
us later.

The exposure that is real is in libs/nistcurves, which is in every shipped
PRG and still pinned below its own §8.2 release — filed separately, see below.

Both backends link

Standing rule for any pin bump. Submodules initialised in a fresh worktree,
make ip65-libs run once, blob rebuilt in-worktree.

ip65-onchip  ba2be10824e376842690a3d07f61854898c22f4c937eca261212a47ff96ef947  47,105 B
uci-onchip   5f9e9fb9e70edd2a15ab2249120f161d1826262140fa6ce6f3e01410a876b474  62,977 B
uci-comb     c423476011e1928f5955e4773c3cf28c4876dcf76e70be9de40c2f4522f8bf72  62,977 B
ip65 blob    cf1a5ff7809af4e4655e385b378b936054f41046ff2b7604828af3240c2d90dd   6,951 B

The blob matches the documented cf1a5ff7… / 6,951 B, so the worktree built
its own and did not reach into the parent checkout.

All three PRGs are byte-identical to dc06095. I built the same three at
origin/master in the same worktree and compared — same hashes, both sides.
That is the measurement that supports the "zero bytes in the shipped PRG"
claim above; it is not a mixed-build artefact, it is the point.

KATs

Both in VICE via tools/_vice_helpers.py::default_vice_config()
(-reu -reusize 512 applied, per the harness gotcha).

suite build result
tools/test_x25519.py ip65, REU profile (its default) 73/73, incl. RFC 7748 vectors 1 and 2
tools/test_ecdsa_kat_oracle.py ip65, REU profile (its default) 6/6 — 3 valid accepted, 3 invalid rejected
tools/test_ecdsa_kat_oracle.py ip65-onchip, C64_SKIP_BUILD=1 6/6

The onchip run is the poly_prod_lo/hi rendezvous guard CLAUDE.md asks for —
this PR does not touch that ownership, but the run is cheap evidence that it is
still intact. No hardware was used.

Red-green

Most of this diff is a submodule gitlink, for which no behavioural test is
possible: the changed bytes are not in any PRG we build, so there is
nothing to assert about runtime behaviour and I am not claiming coverage I do
not have.

The one hunk with an effect is the wrapper change, and that one does
red-green cleanly. The sibling gained three bytes in its src/data.s
(x25519_reu_fault plus the REU_SETTLE slow path's two internal bytes;
the sibling annotates them §8.2 at v0.13.0x25519.inc:414,
fe25519.s:40 — the commit message's "v0.12.0" is off by a release).
build_x25519.sh replaces that file wholesale, so the staged BSS has to
restate them.

Red — new pin, wrapper hunk reverted to dc06095,
make BACKEND=uci USE_X25519_SIBLING=1:

Unresolved external 'x25519_reu_fault' referenced in:
Unresolved external 'x25519_reu_settle_cnt' referenced in:
Unresolved external 'x25519_reu_settle_smp' referenced in:
ld65: Error: 3 unresolved external(s) found - cannot create output file
ld65: Warning: ... Segment 'X25519_BSS' overflows memory area 'CRYPTO_OVERLAY' by 1536 bytes

Green — with the hunk, same command:

ld65: Warning: ... Segment 'X25519_BSS' overflows memory area 'CRYPTO_OVERLAY' by 1536 bytes
ld65: Error: Cannot generate most of the files due to memory area overflow

The three unresolved externals are gone and only the pre-existing structural
overflow remains — the lane still does not link, which is unchanged and out of
scope here.

One note for the record: CLAUDE.md states this overflow as 1,280 B, not
1,536 B. The measurement above is what ld65 reports today at both pins; the
CLAUDE.md figure is stale. Added to #193 (CLAUDE.md margin staleness) rather
than fixed here — other lanes are in that file.

Reviewer notes

  • The commit message carries the same PRG hash for uci-comb (c423476…) that
    I measured at dc06095, even though it was written against 0b55c30. I did
    not take that on trust; both sides were rebuilt and compared here.
  • Nothing about the pinned tree's REU settle is exercised by any test in this
    repo, because nothing links it.

Related, not in this PR

🤖 Generated with Claude Code

Issue #166 is an advisory that the vendored libs/x25519 v0.11.2 predates
the c64-lib-contract §8.2 REU post-execute settle. It is correct about
the tree and wrong about the blast radius: USE_X25519_SIBLING defaults
to 0 (Makefile:44), does not link under either backend, and no shipped
product passes it, so libs/x25519 contributes zero bytes to every PRG we
release. This bump is hygiene, not a fix.

Proof of PRG-neutrality, per the repo rule that only the PRG sha256
counts: `make clean && make BACKEND=uci USE_NISTCURVES_ONCHIP_COMB=1`
before and after the bump both produce
c423476011e1928f5955e4773c3cf28c4876dcf76e70be9de40c2f4522f8bf72.
The sibling archive is never even staged (build/lib/ holds only
nistcurves-p256-onchip-comb.a).

The bump is not free for the dead sibling lane. v0.12.0 added three
bytes to the sibling's src/data.s (x25519_reu_fault plus the REU_SETTLE
slow path's two internal bytes), and this wrapper replaces that file
wholesale, so at the new pin `make BACKEND=uci USE_X25519_SIBLING=1`
gained three unresolved externals on top of the pre-existing structural
overflow. Restating the three bytes in the staged BSS restores parity:
the link now fails on exactly the one failure it failed on at v0.11.2,
`X25519_BSS overflows CRYPTO_OVERLAY by 1536 bytes`, and nothing else.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

Vendored c64-x25519 is v0.11.2, which predates the §8.2 REU post-execute settle — affects the REU-on target at turbo

1 participant