Phase 3 WIP: layout fix + TLS receive-path fixes (hits architectural limits) - #13
Merged
Conversation
…erged The harness wait_for_text() now calls transport.resume() between polls internally, so the inline polling loops are no longer needed. This replaces 13 copies of the same ~10-line loop with single wait_for_text() calls, reducing total code by 120 lines. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…r reuse The parallel runner had two bugs: (1) as_completed() didn't see futures added mid-iteration, so only the first N suites were collected, and (2) reusing VICE instances across suites caused state contamination (HKDF 0/12 on reused workers). Fix: allocate a fresh VICE instance per suite via run_suite_in_own_instance(). Add all 10 suites (was 5). Add --skip-slow and --seed flags. 193/193 pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix parallel test runner: all 10 suites, instance-per-suite.
… tests net_dns_resolve and net_set_tcp_dest both passed A/X parameters through net_save_zp, which uses X as a loop counter and clobbers both registers. This caused DNS resolution and TCP destination setup to receive garbage pointers instead of the caller's intended addresses. Fixed by pushing A/X to the stack before the ZP save and restoring after. Added test_dns.py (4 tests) exercising net_dns_resolve over TAP with dnsmasq, and test_http_integration.py (5 tests) for end-to-end plain HTTP GET (DNS → TCP → request → response). Both use ViceInstanceManager with ethernet_mode="rrnet" and run unprivileged (only dnsmasq via sudo). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ion-tests Fix A/X register clobbering in net.asm, add DNS + HTTP integration tests
Replace baseline fe25519/x25519 with optimized versions from the c64-x25519 performance tuning project, achieving ~30% speedup (12,782 jiffies / 3.6 min per key generation vs 18,005 baseline). Optimizations imported: - REU DMA multiplication tables (128KB REU, 4 cyc/product vs mul_8x8) - mult66 indirect-indexed quarter-square multiply for fe_sqr - Self-modifying accumulation addresses in fe_mul/fe_sqr inner loops - 4x unrolled constant-time fe_cswap (38 cyc/byte vs 49) - Shift-before-accumulate for fe_sqr cross terms - mul_by_38 lookup tables for fe_reduce_wide Key integration fixes: - Optimization tables (mul_dma, sqtab2, mul38) placed early in data.asm to stay below $A000 and avoid BASIC ROM shadow region - BASIC ROM banked out at boot and kept off during runtime (data buffers at $A000+ need direct RAM access) - VICE launched with -reu -reusize 512 for all test suites - Zero page lmul0/lmul1 pointers time-shared with ChaCha20 vars New files: - tools/test_x25519.py: 71 unit tests (fe25519 field ops + x25519_clamp + optional --slow RFC 7748 scalarmult vectors) - tools/bench_x25519.py: key generation benchmark with jiffy clock timing and Python X25519 verification Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Import optimized X25519 (~30% faster key generation)
Introduces tools/net_test_env.py with NetworkTestEnv context manager that handles TAP interface, dnsmasq, and optional HTTPS server lifecycle. Replaces duplicated inline setup/teardown code across network test files and guarantees cleanup via __exit__, signal handlers, and atexit. Migrates test_dns.py as proof-of-concept. Includes 14 unit tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add consolidated network test environment
Vendor the c64-test-harness bridge networking scripts (setup + cleanup) and extend them with dnsmasq (DHCP + DNS overrides). Build a reusable tools/https_e2e/ library with BridgeEnv context manager, single-VICE launcher, boot menu helpers, and HTTP listener. Two passing e2e tests drive the real c64-https binary in VICE over RR-Net at normal speed: Phase 1 verifies DHCP, Phase 2 verifies plain HTTP GET to a local listener. HTTPS (Phase 3) to follow. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The original CPU JAM at $4DE0 was caused by ip65 writing DHCP packets on top of sha256_rotr8 code: c64-https crypto code streamed from $3B28 right through ip65's BSS window at $4000-$5FFF. Fix the layout by inserting `* = $6000` before word32.asm so all of word32/chacha/poly/aead/sha256/ hmac_drbg/fe25519/x25519/ecdsa + ecdsa_verify/der/tls_cert/tls_ecdh land above the BSS. Requires three adjacent compromises to fit in the space below $7C00: - Relocate sqtab from the hardcoded $7800/$7A00 equates to labels inside data.asm BSS, freeing the $7800-$7BFF region - Stub P-384 ECDSA (src/crypto/ecdsa_verify.asm) to return an error instead of dispatching. P-384 isn't needed for the self-signed P-256 cert used in tests but MUST be restored before real CA chains. Tech debt tracked in project_p384_stubbed memory - Remove the `* = $7C00` barrier now that sqtab is gone With the layout fix, the CPU JAM is gone entirely and the TLS receive path progresses far enough to expose several follow-on bugs that a clean walkthrough diagnosed and fixed in sequence: - tls_record_io.asm: plaintext/encrypted dispatch was comparing against TLS_STATE_SERVER_HELLO ($02) but tls_state is already $02 when the ServerHello arrives, causing the code to try to AEAD-decrypt a plaintext record. Change to TLS_STATE_ENCRYPTED_EXT ($03) - net.asm: TCP recv callback had an 8-bit X register wrap when ip65 delivered packets >255 bytes, causing re-reads of source bytes. Clamp cb_remaining to 255 per invocation - tls_keyschedule.asm: tls_derive_handshake_keys fell off the end of its final loop without a clc, leaving the carry flag set from the last hmac_sha256 call. Caller's `bcs @error` then fired on success. Add clc before rts - tls13.asm: tls_ecdh_compute_shared was defined in tls_ecdh.asm but never called anywhere in the codebase, so tls_shared_secret stayed zeros. HKDF then derived handshake keys from zeros. Add the jsr call in tls_recv_server_hello right after tls_parse_server_hello succeeds - tls_record_io.asm: RFC 8446 §5 says TLS 1.3 clients MUST ignore CCS records during handshake. Add a retry that skips CCS content type Rename the demo URL from www.apple.com to www.foo.bar throughout boot.asm, dnsmasq DNS overrides, HTTPS listener cert subject/SAN, and test screen text expectations, to avoid any risk of real-world impact if the test environment escapes the bridge. Bridge setup/cleanup scripts hardened: no blanket pkill, specific PID tracking, idempotent re-entry, handling of stale vice_eth rc files and legacy tap-c64 interfaces from older test harness setups. New test tests/test_phase3_https.py drives the full Phase 3 e2e flow: BridgeEnv + HTTPS listener + VICE + DHCP + HTTPS GET. Captures granular post-mortem diagnostics (tls_state, tls_last_state, tls_recv_progress, tls_recv_sub_progress, tls_rec_header, tls_rec_buf, tls_hs_buf, tcp_recv_buf, tls_recv_state/count) via dynamic label lookup from build/labels.txt so diagnostic addresses track the current build. Instrumentation added to src/data.asm (tls_last_state, tls_recv_progress, tls_recv_sub_progress, tls_recv_poll_count) and to tls_recv_server_hello, tls_record_recv_and_decrypt, tls_recv_record for precise failure-site identification. These are permanent diagnostic helpers. Current status: handshake reaches tls_state=$03 (ENCRYPTED_EXT) and dies trying to receive the first encrypted handshake record (EncryptedExtensions). Two remaining architectural bugs require multi-file refactoring and are tracked as follow-on work: 1. tcp_recv_buf is 256 bytes with 8-bit indices. TLS 1.3 Certificate records (~374 bytes) don't fit. Needs 2KB ring with 16-bit indices and producer overflow check in net_tcp_recv_cb 2. aead_data_len is 1 byte. Caps AEAD decrypt at 255 bytes, so the ~353-byte Certificate ciphertext body is truncated and tag always fails. Needs widening to 16-bit with updated ChaCha20/Poly1305 loops Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two coordinated architectural changes to unblock TLS 1.3 handshake past the ServerHello state: **tcp_recv_buf at \$C000, 4096 bytes, 16-bit indices** The previous 256-byte ring with 8-bit head/tail silently overwrote unread data whenever ip65 delivered a TCP segment larger than the empty space — the TLS 1.3 post-ServerHello flight (CCS + Encrypted- Extensions + Certificate + CertVerify + Finished, ~600-800 bytes) always overflowed. Move the buffer to the 4KB free-RAM region at \$C000-\$CFFF (always RAM on a C64, never ROM-shadowed) via an equate in constants.asm — zero impact on data.asm BSS footprint. Convert head/tail to 16-bit words. Add a tcp_recv_overflow sticky flag set by the producer when it would lap the consumer. Update all consumer and producer paths in net.asm to use 16-bit indexing with mask-on-access (\$0FFF = 4095). http.asm feed loop also updated. Add producer overflow check in net_tcp_recv_cb so ip65's callback cannot silently corrupt the ring. **aead_data_len widened to 16-bit** Was a single byte, which capped AEAD encrypt/decrypt at 255 bytes. TLS 1.3 Certificate records carry ~350+ bytes of ciphertext, so decrypt was always truncated and the Poly1305 tag always failed. Change aead_data_len to !word in data.asm. Update the aead_encrypt / aead_decrypt / aead_compute_tag paths in crypto/aead.asm to 16-bit counter semantics (compare-with-ora for zero, decrement with borrow, length block stored in both bytes of the 64-bit field). Update chacha20_encrypt block loop to a 16-bit counter over cc20_remain:cc20_remain_hi. Update tls_record.asm where tls_enc_aead_len is copied into aead_data_len — both bytes are stored now. poly1305_update in poly1305.asm is unchanged because AEAD exclusively drives Poly1305 via aead_process_padded now; the standalone poly1305_update path is dead code and doesn't need widening for this fix. **Verification** After this change, Phase 3 test reaches tls_state=\$03 (ENCRYPTED_EXT), confirms the full post-ServerHello server flight is visible and intact in the ring at \$C000 (ServerHello, CCS, EncryptedExtensions record 50B, Certificate record 369B), tcp_recv_head/tail 16-bit values working. No regression on DHCP, DNS, TCP connect, or ServerHello parse. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds on-screen progress markers at each TLS handshake state transition in tls_connect plus entry/exit counters on net_poll to definitively localize the Phase 3 HTTPS stall. **Markers** (src/tls13.asm + src/boot.asm): CH/SH/HK1/KEYS/ENC1/RX/GOT2/DEC/PROC/EE/CERT/CV/FIN/CFIN printed on screen as each step of tls_connect completes. The branch-target trampoline pattern (`bcc @okn / jmp @error / @okn:`) is used because the inserted print calls push @error out of bcs range. **Counters** (src/data.asm + src/net.asm): net_poll_entry_count and net_poll_return_count 16-bit counters increment at entry and exit of net_poll. Gap between them = number of active ip65_process calls currently on the stack. **Test diagnostics** (tests/test_phase3_https.py): - Dynamic label lookup via _label_addr() against build/labels.txt so diagnostic reads always hit the current build regardless of BSS layout shifts - File-logged post-mortem at /tmp/c64-https-phase3-diag.log with explicit flush(), survives hard-kill - Per-heartbeat sampling of tcp_recv_head, tcp_recv_tail, net_poll_entry/return_count, printed inline - CPU register read (PC, SP, A, X, Y) via transport.read_registers() - Top-of-stack return-address chain with label resolution - Full dumps of tls_rec_buf, tls_hs_buf, tcp_recv_buf in hex+ASCII **Conclusion from this instrumentation**: Phase 3 handshake progresses successfully through CH, SH, HK1, KEYS, ENC1, RX markers — i.e., all of X25519 keygen, X25519 shared secret, HKDF handshake-key derivation, and transition into tls_recv_encrypted. It then stalls permanently while net_poll_entry - net_poll_return = 1 (exactly one ip65_process call on the stack, never returning) and tcp_recv_tail frozen at 0x0198 (408 bytes) across 1800 seconds / 55+ heartbeats. The stall is inside ip65 — likely the CS8900a driver or IP/TCP receive path — triggered by the second TCP segment carrying Certificate record bytes arriving after the multi-minute X25519 silence. None of the c64-https TLS code has a bug at this point; the TLS layer never gets a CPU quantum because net_poll doesn't return. This commit preserves the instrumentation for future sessions to investigate the ip65 stall with PC sampling and ip65 code inspection. Co-Authored-By: Claude Opus 4.6 (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
c64-httpsrunning in VICE over RR-Net (Phase 1 DHCP and Phase 2 plain HTTP GET pass on this branch).sha256_rotr8code.clc, never-called ECDH shared-secret, CCS filter).aead_data_lenwidened to 16-bit so TLS 1.3 Certificate records no longer overflow or truncate.net_pollentry/return counters, dynamic label lookup in the test harness) preserved for the next session.What's included
5feb0ce— Add end-to-end bridge tests for DHCP and HTTP GETVendors the
c64-test-harnessbridge networking scripts (setup + cleanup) and extends them with dnsmasq (DHCP + DNS overrides). Builds a reusabletools/https_e2e/library with aBridgeEnvcontext manager, single-VICE launcher, boot-menu helpers, and HTTP listener. Two passing e2e tests drive the realc64-httpsbinary inside VICE over RR-Net at normal speed: Phase 1 verifies DHCP, Phase 2 verifies a plain HTTP GET to a local listener. This is the scaffolding every later phase rides on.d973531— Relocate crypto above ip65 BSS + multiple TLS receive-path fixesThe original CPU JAM at
$4DE0was caused byc64-httpscrypto code streaming from$3B28straight through ip65's BSS window at$4000-$5FFF: when DHCP ran, it overwrotesha256_rotr8with packet bytes. Inserting* = $6000beforecrypto/word32.asminsrc/main.asmmoves every crypto unit (word32/chacha/poly1305/aead/sha256/hmac_drbg/fe25519/x25519/ecdsa/ecdsa_verify/der/tls_cert/tls_ecdh) above the BSS. To fit in the space below$7C00three compromises were required:sqtab_lo/sqtab_himoved from hardcoded$7800/$7A00equates to labels insidedata.asmBSS; P-384 ECDSA was stubbed incrypto/ecdsa_verify.asm(tech debt tracked inproject_p384_stubbed, must be restored before real CA chains); and the old* = $7C00barrier was removed. With the JAM gone, a chain of follow-on TLS receive-path bugs became diagnosable and were fixed in the same commit (see "TLS receive-path fixes" below). Also renames the demo URL fromwww.apple.comtowww.foo.barthroughoutboot.asm, dnsmasq overrides, HTTPS listener cert subject/SAN, and test screen text, so a stray packet can never escape the bridge to a real host. The bridge setup/cleanup scripts are hardened (no blanketpkill, specific PID tracking, idempotent re-entry, stale-rc-file handling). Addstests/test_phase3_https.pywith granular post-mortem diagnostics via dynamic label lookup frombuild/labels.txt.c8ca348— Grow tcp_recv_buf to 4KB + widen aead_data_len to 16-bitTwo coordinated architectural changes that unblock the TLS 1.3 handshake past ServerHello. The previous 256-byte ring buffer with 8-bit head/tail silently overwrote unread data whenever ip65 delivered a TCP segment larger than the remaining space — the post-ServerHello flight (CCS + EncryptedExtensions + Certificate + CertVerify + Finished, 600–800 bytes) always overflowed.
tcp_recv_bufis now a 4096-byte buffer pinned to$C000-$CFFF(always-RAM region on the C64 with BASIC ROM banked out) declared as an equate inconstants.asm, so it consumes zero BSS. Head/tail are 16-bit with mask-on-access ($0FFF), and atcp_recv_overflowsticky flag is set by the producer innet_tcp_recv_cbif it would lap the consumer.net.asmconsumer/producer paths andhttp.asm's feed loop are updated to 16-bit indexing. Separately,aead_data_lenindata.asmis widened from 1 byte to 16-bit because the previous 8-bit cap truncated any AEAD record larger than 255 bytes — TLS 1.3 Certificate ciphertext is ~353 bytes, so every Poly1305 tag check failed.crypto/aead.asmnow uses 16-bit counter semantics throughoutaead_encrypt/aead_decrypt/aead_compute_tag, the length block stores both bytes,chacha20_encrypt's block loop runs on a 16-bitcc20_remain:cc20_remain_hi, andtls_record.asmcopies both bytes oftls_enc_aead_lenintoaead_data_len.7eb8b8a— Phase 3 screen markers + net_poll counters + diagnostic instrumentationAdds on-screen progress markers (
CH,SH,HK1,KEYS,ENC1,RX,GOT2,DEC,PROC,EE,CERT,CV,FIN,CFIN) at each TLS handshake state transition intls_connect, plus 16-bit entry/exit counters onnet_pollso the gapnet_poll_entry_count - net_poll_return_countdirectly exposes how manyip65_processframes are parked on the stack. The branch-target trampoline pattern (bcc @okN / jmp @error / @okN:) is used where the inserted print calls would push@errorout ofbcsrange.tests/test_phase3_https.pyis extended with dynamic label lookup via_label_addr()againstbuild/labels.txt(so diagnostic reads always hit the current build regardless ofdata.asmlayout shifts), a file-logged post-mortem at/tmp/c64-https-phase3-diag.logwith explicit flush that survives hard-kill, per-heartbeat sampling oftcp_recv_head/tcp_recv_tail/net_poll_*, CPU-register reads viatransport.read_registers(), and a top-of-stack return-address chain with label resolution. This instrumentation is what localized the remaining stall to ip65, not c64-https (see "What still doesn't work").Memory-layout fixes (the load-bearing part)
The
* = $6000directive inserted beforecrypto/word32.asminsrc/main.asmis the single most important change in this PR. Before it, thec64-httpsbinary had crypto code mapped linearly from$3B28upward, which meanssha256_rotr8and its neighbors sat inside ip65's BSS region at$4000-$5FFF. ip65 allocates DHCP/ARP/IP/TCP packet buffers in that window, so the first DHCP request issued from the boot menu wrote packet payload bytes directly on top ofsha256_rotr8, which then took a$02opcode on next entry and CPU-JAMed at$4DE0. Relocating the crypto blob above the BSS ends that. The three adjustments that come with it —sqtab_lo/sqtab_himoved from hardcoded$7800/$7A00equates intodata.asmBSS labels, P-384 ECDSA stubbed incrypto/ecdsa_verify.asm, and the* = $7C00barrier removed — are all necessary to fit everything below$7C00and are tracked inproject_p384_stubbedas known tech debt that must be restored before the client can validate real CA chains.tcp_recv_bufis separately pinned to$C000as an equate inconstants.asm. That region ($C000-$CFFF) is always RAM when the$01processor port is set to$36(BASIC ROM out, KERNAL in) asboot.asmdoes, so it's 4 KB of completely free buffer space that costs zero BSS. The buffer's 16-bit head/tail live indata.asmBSS (tcp_recv_head,tcp_recv_tail,tcp_recv_overflow), so nodata.asmlabel shifts affect the ring's backing store. Wideningaead_data_lento a!wordindata.asmis the matching fix on the crypto side: without it, the 8-bit counter truncated AEAD decrypt at 255 bytes and the ~353-byte Certificate ciphertext body always failed Poly1305.TLS receive-path fixes
All landed in
d973531:src/net.asm—net_tcp_recv_cbhad an 8-bit X register wrap when ip65 delivered packets >255 bytes.cb_remainingis now clamped to 255 per invocation so the callback re-enters cleanly on the next slice.src/tls_record_io.asm— plaintext/encrypted dispatch was comparing againstTLS_STATE_SERVER_HELLO($02), buttls_stateis already$02when the ServerHello is being received, so the code was trying to AEAD-decrypt a plaintext record. Changed toTLS_STATE_ENCRYPTED_EXT($03). Also adds a CCS filter: RFC 8446 §5 requires TLS 1.3 clients to ignore ChangeCipherSpec records during handshake, and the record receive loop now retries past them.src/tls_keyschedule.asm—tls_derive_handshake_keysfell off its final loop without aclc, leaving carry set from the lasthmac_sha256. The caller'sbcs @errorthen fired on success. Addedclcbeforerts.src/tls13.asm(tls_recv_server_hello) —tls_ecdh_compute_sharedwas defined intls_ecdh.asmbut never called anywhere in the codebase, sotls_shared_secretstayed all zeros and HKDF derived handshake keys from zeros. Added the missingjsr tls_ecdh_compute_sharedright aftertls_parse_server_hellosucceeds.What still doesn't work
The Phase 3 HTTPS end-to-end test (
tests/test_phase3_https.py) still fails at runtime, but the failure is inside ip65, not c64-https. The on-screen markers reachCH → SH → HK1 → KEYS → ENC1 → RXcleanly (ClientHello sent, ServerHello parsed, X25519 shared secret computed, HKDF handshake keys derived, enteredtls_recv_encrypted, firstnet_pollcall inside the encrypted-wait loop) and then hang. Thenet_poll_entry_count/net_poll_return_count16-bit counters show a gap of exactly 1 — oneip65_processcall on the stack, never returning — andtcp_recv_tailsits frozen at$0198(408 bytes delivered) across 55+ heartbeats / 1800 seconds. PC samples during the hang hit different addresses inside ip65 code ($20BE,$9E8D), so ip65 is executing, just caught in an inner loop that doesn't yield — most likely the CS8900a driver or TCP reassembly path choking on a burst of retransmits that arrive after ~3.6 minutes of CPU silence during the X25519 shared-secret computation.This is tracked separately. Four candidate mitigations are written up in the
project_phase3_handoffsession memory (ip65 upstream patch, c64-https-side close/reopen workaround, server-side pacing, or warp mode during X25519 to eliminate the long silence). None of them require reverting anything in this PR.Phase 1 (DHCP) and Phase 2 (HTTP GET) end-to-end tests pass on this branch. The memory-layout fix, the TLS receive-path fixes, and the buffer-widening changes are all independently load-bearing for future progress, and nothing in them depends on the ip65 stall being resolved first.
Testing
sudo PYTHONPATH=tools python3 tests/test_phase1_dhcp.py(DHCP end-to-end over bridge + RR-Net)sudo PYTHONPATH=tools python3 tests/test_phase2_http.py(HTTP GET to local listener)sudo PYTHONPATH=tools python3 tests/test_phase3_https.pyhangs after theRXmarker insideip65_process; see "What still doesn't work" above. The failure is preserved at the ip65 boundary by design — all c64-https markers light up cleanly first.tools/test_crypto.py,tools/test_sha256.py,tools/test_x25519.py,tools/test_hkdf.py,tools/test_keyschedule_steps.py,tools/test_tls_handshake.py,tools/test_tls_record.py,tools/test_net.py,tools/test_http.py,tools/test_dns.py,tools/test_x509.py,tools/test_entropy.py,tools/test_chained_hmac.py.Review notes for merger
tools/https_e2e/(the bridge test library) is checked in on this branch:__init__.py,env.py,c64_menu.py,http_listener.py,https_listener.py,vice_on_bridge.py. The only other tracked diagnostic scaffold istools/_diag_carry.py(a small carry-flag probe from thetls_derive_handshake_keysbug hunt).tools/diag_4de0_*.py/tools/diag_read_live.pyscripts that appeared during the CPU-JAM post-mortem are not tracked anywhere — they live only in working trees and are not part of this PR.project_phase3_handoff.mdin the session memory is the primary session-handoff document for whoever picks up the ip65 investigation next. It has the full list of addresses, the four mitigation options, and the gotchas (X25519 timing,$01processor port and BASIC ROM shadowing, label shifts indata.asm, buffered-stdout pitfalls withtee).* = $6000insrc/main.asmis load-bearing. Do not move it.crypto/ecdsa_verify.asmreturns error). Tracked inproject_p384_stubbed; must be restored before the client can validate any real CA chain.🤖 Generated with Claude Code
Originally posted by @JC-000 on 2026-04-14