Skip to content

fix(macos): BSD-sed portability + cryptography dep + ECDSA-verify note - #33

Merged
JC-000 merged 3 commits into
masterfrom
fix/macos-build-portability-and-deps
May 7, 2026
Merged

fix(macos): BSD-sed portability + cryptography dep + ECDSA-verify note#33
JC-000 merged 3 commits into
masterfrom
fix/macos-build-portability-and-deps

Conversation

@JC-000

Copy link
Copy Markdown
Owner

Summary

  • Makefile and tools/integration/build_nistcurves_p256.sh now use the portable sed -i '' form so the build works under BSD sed on macOS as well as GNU sed on Linux.
  • New requirements.txt declares cryptography (used by 7 Python scripts under tools/); c64_test_harness continues to be installed separately per the build instructions.
  • CLAUDE.md Known issues gains an entry for an ecdsa_verify (P-256) regression: a known-good signature is rejected (C=1) after ~60 s; tampered-signature path still rejects correctly; inputs are staged correctly. Affects TLS CertificateVerify only — ECDHE/X25519 handshake is unaffected. Not fixed in this PR; documented for the next investigation.

Test plan

  • make clean && make builds cleanly on macOS with BSD sed (no more "extra characters at end of l command" / "1 not defined in label" errors).
  • python3 tools/run_all_tests.py — 10/11 suites pass, 245/247 individual checks. The single failure is tools/test_x509.py group 3 subtest 3c (the ECDSA-verify regression now documented in CLAUDE.md); subtest 3d (tampered-signature rejection) still passes.
  • Linux re-verification: sed -i '' is the BSD-style invocation but is also accepted by GNU sed, so this should be a no-op for Linux builds. Worth a CI confirmation when available.

🤖 Generated with Claude Code

JC-000and others added 3 commits May 6, 2026 19:46
GNU sed accepts `sed -i '...'`; BSD sed (macOS default) treats the
pattern as the backup-suffix and consumes the next argument as the
filename, which breaks the build. Switching to `sed -i ''` is portable
across both. Affects the ld65 label rewrite in the Makefile and 12
inline edits in build_nistcurves_p256.sh.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Python test scripts under tools/ use the `cryptography` package
for cert generation, ECDSA test vectors, and AEAD reference checks,
but no project manifest declared it. Add a minimal requirements.txt
listing it; c64_test_harness is installed separately per the build
instructions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ecdsa_verify (P-256) rejects a known-good signature from the RFC test
vector — surfaced 2026-05-06 by tools/test_x509.py group 3 subtest 3c
once the BSD-sed portability fixes unblocked the macOS build. Tampered
signatures (3d) are still correctly rejected and inputs are staged
correctly, so the bug is in the verify path itself. Affects TLS
CertificateVerify; ECDHE/X25519 handshake is unaffected.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@JC-000
JC-000 merged commit 046c791 into masterMay 7, 2026
JC-000 added a commit that referenced this pull request May 12, 2026
…bump (#40)
* fix(tests): add -reu to test_x509 VICE harness; ECDSA-verify "false rejection"
The "ecdsa_verify (P-256) rejects a known-good signature" known issue
in CLAUDE.md was never a crypto bug. tools/test_x509.py launched VICE
with `ViceConfig(prg_path=PRG_PATH, warp=True, ntsc=True, sound=False)`
— no REU. The sibling c64-nist-curves fp_mul fetches 8x8 multiply rows
from REU banks 0/1 (populated by src/boot.s::reu_mul_init). Without
-reu the row fetch silently no-ops and mul_dma_lo/hi at $BA00/$BB00
stays stuck at reu_mul_init's final-iteration residue (a=255), so
every fp_mul returns a*255*b mod p instead of a*b mod p. Cascade:
wrong w=s^-1 mod n, wrong u1/u2, wrong computed R, R.x != r, verify
returns C=1. Tampered (3d) also rejects but for a different downstream
reason — outside view is identical.
Pattern verified by primitive-level KAT bisection: under default cfg,
fp_mod_mul + fp_mod_mul_n produce the unmistakable a*255*b signature
on 5/5 random inputs. With extra_args=["-reu","-reusize","512"] both
primitives pass 5/5. test_x509 group 3 then passes 4/4 — including
[3c] valid signature C=0 in ~60 s wall-clock.
The same pattern is already correct in tools/test_x25519.py:722,
tools/bench_x25519.py:138, tools/test_p384_symbols.py:370 — converge
test_x509 on it. The UCI/U64E path is unaffected (hardware REU is
always enabled); the symptom was VICE-only. Verified on U64E @ 48 MHz:
test_https_local PASS 86.7 s (full handshake + HTTP 200 + body OK).
CLAUDE.md "Known issues" entry replaced with a "VICE harness gotcha"
documenting the cause + the four ViceConfig sites that need the flag.
The ECDSA wall-clock paragraph gets a tail note redirecting readers
from the now-stale earlier entry.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(crypto): bump libs/nistcurves to v0.2.0 + extend resident-archive build
Pull in the upstream-recommended baseline (released 2026-05-12). v0.2.0
ships a defensive REU register-residue guard (issue #33-class fix
ported from c64-x25519 commit 817f525) that re-establishes $DF04=0 and
$DF0A=0 at 10 public REU-DMA entry points before touching DMA. Of
those, the ones that land in c64-https's retained carve-out are
fp_mul, fp_sqr, ec_scalar_mul_var, ecdsa_verify_256, and the modular
inverse paths in fp256/ecdsa256. The fifth (ec_scalar_mul) is inside
our stripped Lim-Lee block. Static audit (researcher pass) confirmed
no live REU polluter in c64-https today, so the defence is a cheap
insurance belt against future composed-system regressions, not a fix
for an observed bug.
Build-script changes to support the bump:
- Strip line range 762,1458d -> 762,1467d. v0.2.0 inserts +9 lines
of new defensive REU-init code inside the ec_scalar_mul Lim-Lee
body we strip (which still falls entirely inside the new range).
- Two `.import` lines for `reu_reu_lo`/`reu_addr_ctrl` now need to
survive the strip because the v0.2.0 defensive init block at the
top of ec_scalar_mul_var references them. Converted the relevant
sed `d` deletions to `c` rewrites that preserve only those two
symbols out of the original 8-symbol import lists.
- New `reu_equates_raw.s` staging file supplies the two symbol
equates (reu_reu_lo = $df04, reu_addr_ctrl = $df0a). Pulled out
of sibling's constants.s minimally to avoid colliding with our
in-tree VIC/CIA/KERNAL equates. Wired into the ca65 build loop
and ar65 archive list.
Verified VICE: tools/test_x509.py 11/11 (Group 3 ECDSA verify 4/4
incl. [3c] valid sig C=0 in ~60 s warp). Verified hardware: U64E @
48 MHz tools/uci/test_https_local PASS, full handshake 86.7 s vs the
81.9 s v0.1.0-10-gdfdfb59 baseline — the +4.8 s is the +6 cy/call
defence overhead compounded across the field-mul/sqr workload (release
notes "Security/correctness defences"). Within margin; trade is a
clear net win.
CLAUDE.md ECDSA wall-clock section gets a paragraph noting the new
86.7 s measurement vs the recorded 81.9 s baseline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(crypto): add CAVP SigVer KAT oracle for P-256 ECDSA verify
Standalone VICE harness that drives the resident `ecdsa_verify` entry
with NIST CAVP P-256/SHA-256 SigVer Result=P vectors (sourced from
libs/nistcurves/tools/vectors/nist_p256_sigver.rsp). Three valid
signatures are run end-to-end and asserted to return C=0 in addition
to the single test_x509.py group 3 [3c] vector — gives us independent
regression coverage against silent breakage of the integration path
(staging buffers, the ec_scalar_mul shim, the BE-struct pack, the
boot-time REU mul-table state) that would still let test_x509's
single vector pass.
This script is what definitively localized the recent "false-rejection"
investigation: the 3 CAVP vectors all failed identically alongside
[3c] under the missing-`-reu` VICE config, ruling out vector-specific
edge cases (high-bit on r/s, leading-zero patterns, etc.) and pointing
at a systemic integration issue. With the -reu flag now correct in
both this and test_x509, all 4 vectors pass.
Run: C64_SKIP_BUILD=1 PYTHON tools/test_ecdsa_kat_oracle.py
Output: per-vector PASS/FAIL with wall-clock + r/s/h/Qx/Qy hex
prefixes for any failure.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for freeto 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.

1 participant

@JC-000