fix(macos): BSD-sed portability + cryptography dep + ECDSA-verify note - #33
Merged
Conversation
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 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makefileandtools/integration/build_nistcurves_p256.shnow use the portablesed -i ''form so the build works under BSD sed on macOS as well as GNU sed on Linux.requirements.txtdeclarescryptography(used by 7 Python scripts undertools/);c64_test_harnesscontinues to be installed separately per the build instructions.CLAUDE.mdKnown issues gains an entry for anecdsa_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 && makebuilds 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 istools/test_x509.pygroup 3 subtest 3c (the ECDSA-verify regression now documented inCLAUDE.md); subtest 3d (tampered-signature rejection) still passes.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