Skip to content

Retire ar65 member surgery in the nistcurves wrappers (SPEC §6.1) #119

Description

@JC-000

What

tools/integration/build_nistcurves_p256.sh builds our P-256 archives by editing upstream's member set:

:274 rm -f "$STAGING/mul_8x8.o" "$STAGING/data_shared.o" "$STAGING/reu_mul_init.o"
:278 # onchip-comb: rm -f fp384_onchip.o mod384.o curve384.o points384_core.o
# points384_comb.o data_p384.o data_p384_limlee.o ecdsa384*.o
# sha384*.o data_sha.o inv256.o data_p256_invref.o
:337 rm -f "$STAGING/mul_8x8_onchip.o"

c64-lib-contract SPEC §6.1 now names this as forbidden:

Consumers fetch build/lib/<shortname>[-<variant>].a and link directly. No mid-build sed, no copying intermediates around, and no ar65 member surgery — an archive whose member set a consumer has edited is outside every §5/§8.0 manifest claim it ships. §6.2 and §6.3 exist so surgery is never the only route to a configuration.

This is the root cause of two gaps we already document as deferred:

  • src/contract_footprint_asserts.s excludes the comb profile from the §6.6 assert, because the surviving manifest describes the pre-surgery archive (27,000 B declared against a 16,384 B region).
  • src/lib_contract_asserts.s records the §8.0 disjointness/coverage asserts as "not writable today" for the same reason — the shipped mask describes upstream's archive, not the one we link.

What is now solvable, measured against the v0.10.2 pin

Upstream gained CONTRACT_DEFINES and APP_OWNED_DEFINES in the wave. The variant × APP_OWNED combination is reachable today — verified by building it:

make lib-p256-verify CONTRACT_DEFINES='-D SHARED_SQTAB_INIT -D SHARED_REU_MUL_INIT \
-D SHARED_REU_MUL_FETCH -D SHARED_CT_MUL_8X8'

exit 0, and od65 --dump-exports on the resulting members shows the switches do most of our surgery for us:

memberexports under the switchesour current surgery
reu_mul_init.onothing at allrm -f — unnecessary, the object is inert
mul_8x8.opoly_prod_lo/hi, sqtab_lo/hi only (no sqtab_init, no ct_mul_8x8, no mul_8x8)rm -f — nearly unnecessary
data_shared.omul_dma_lo/hi, mul_cached_a, mul_src2_buf (+ prefixed)rm -fstill collides

So items 1 and 2 are close to free. Item 3 is not.

What is hard, and why I am not doing it under release pressure

Dropping the data_shared.o surgery means c64-https stops definingmul_dma_lo/hi, mul_cached_a, mul_src2_buf in src/data.s and imports the library's instead — which is what upstream's own lib-app-owned assumes, since it keeps data_shared.o in the member list. Those buffers are gated only by LIB_NO_BARE_EXPORTS (a naming switch), so there is no way to have the library ship the archive and not the buffers.

That is a re-pointing of the REU multiply row table, and it is the single worst place in this codebase to be wrong: CLAUDE.md's "VICE harness gotcha" records that when mul_dma_lo/hi holds the wrong contents, every fp_mul returns a*255*b mod p, the handshake fails minutes later at the first encrypted record, and there is no link error and no diagnostic. The same note records the near-miss where reu_mul_init would have bound to the wrong provider's table with no diagnostic either.

It is worth doing. It is not worth doing in the same change as a release.

What is blocked upstream regardless

There is no P-256 comb archive target. Upstream's full list is lib, lib-p256-verify, lib-p384-verify, lib-p384-sha384, lib-p384-curve, lib-app-owned, lib-onchip, lib-p256-verify-onchip, lib-p384-verify-onchip, lib-p384-curve-onchip. The comb objects exist only inside the full lib-onchip archive, which is why we narrow it by hand.

So even a perfect fix to items 1-3 leaves the comb profile non-conformant, and §6.3 ("every documented variant/profile axis MUST be reachable through §6.1 targets plus §6.2 defines, with no library edits") is not satisfiable for it from our side. Filed upstream as c64-nist-curves#TBD — link to follow.

Sequencing

  1. Upstream: a lib-p256-verify-onchip-comb (or equivalent) target. Blocks the comb arm entirely.
  2. Here: switch the REU and onchip arms to CONTRACT_DEFINES + APP_OWNED switches, flipping poly_prod_lo/hi and the data_shared buffer ownership to imports. Wants its own change, its own KAT run on both profiles, and an e2e handshake — a link that succeeds proves nothing about this failure mode.
  3. Then: delete the .ifdef USE_NISTCURVES_COMB exclusion in src/contract_footprint_asserts.s and write the §8.0 disjointness/coverage asserts that the surgery currently makes meaningless.

Related: #70 (the other open consumer-side alignment item, §13 net ABI).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions