code wiki / (root) / nx_crc32c.nx

nx_crc32c.nx source

↩ module page · 78 lines · 2907 B

1// nx_crc32c.nx -- fast TABLE-driven CRC-32C (Castagnoli) for per-PDU 2// integrity: critical-grade table-stakes (BPv7 Type-2 CRC, RIST/SRT 3// integrity, FEC-block validation). Generalizes the shipped bit-by-bit 4// nx_crc32_v1.nx (CLAUDE.md 15 / review-existing-functionality) to the 5// 256-entry byte-table lookup it flagged as future work -- the table is 6// BUILT AT RUNTIME from the polynomial (sidesteps the const-array-literal 7// gap), so it stays pure NishiLang, integer-only, zero deps. 8// 9// CRC-32C: reflected polynomial 0x82F63B78, init/xorout 0xFFFFFFFF, 10// refin/refout true. Canonical check: crc32c("123456789") = 0xE3069283. 11// 12// license_tier: ORIGINAL 13 14import "nx_syscalls.nx" 15 16const CRC32C_POLY: i64 = 0x82F63B78 17const CRC_U32: i64 = 0xFFFFFFFF 18 19// Build the 256-entry lookup table from the polynomial (call once). 20func crc32c_build_table() -> *i64 { 21 let t: *i64 = sys_mmap(256 * 8) as *i64 22 var b: i64 = 0 23 while b < 256 { 24 var c: i64 = b 25 var k: i64 = 0 26 while k < 8 { 27 if (c & 1) != 0 { c = (c >> 1) ^ CRC32C_POLY } else { c = c >> 1 } 28 k = k + 1 29 } 30 t[b] = c & CRC_U32 31 b = b + 1 32 } 33 return t 34} 35 36// One-shot CRC-32C over `n` bytes using table `t`. Includes the standard 37// init (0xFFFFFFFF) and final xor (0xFFFFFFFF). 38func crc32c_table(t: *i64, bytes: *u8, n: i64) -> i64 { 39 var crc: i64 = CRC_U32 40 var i: i64 = 0 41 while i < n { 42 let idx: i64 = (crc ^ ((bytes[i] as i64) & 0xff)) & 0xff 43 crc = ((crc >> 8) ^ t[idx]) & CRC_U32 44 i = i + 1 45 } 46 return crc ^ CRC_U32 47} 48 49// Streaming: feed chunks. `state` is the RAW running value (NOT final- 50// xored). Start with crc32c_begin(); feed with crc32c_update(); finish 51// with crc32c_final(). Lets a PDU be CRC'd across scattered buffers. 52func crc32c_begin() -> i64 { return CRC_U32 } 53func crc32c_update(t: *i64, state: i64, bytes: *u8, n: i64) -> i64 { 54 var crc: i64 = state 55 var i: i64 = 0 56 while i < n { 57 let idx: i64 = (crc ^ ((bytes[i] as i64) & 0xff)) & 0xff 58 crc = ((crc >> 8) ^ t[idx]) & CRC_U32 59 i = i + 1 60 } 61 return crc 62} 63func crc32c_final(state: i64) -> i64 { return state ^ CRC_U32 } 64 65// Verify a PDU: append the 4-byte CRC (BE) after the payload, then 66// crc32c over (payload+crc) yields the well-known residue 0 when intact. 67// Returns 1 if intact, 0 if corrupted. 68func crc32c_pdu_check(t: *i64, pdu: *u8, total_len: i64) -> i64 { 69 // crc over payload, compare to the trailing 4 bytes (BE). 70 if total_len < 4 { return 0 } 71 let plen: i64 = total_len - 4 72 let want: i64 = crc32c_table(t, pdu, plen) 73 let base: i64 = pdu as i64 74 let got: i64 = (((pdu[plen] as i64) & 0xff) << 24) | (((pdu[plen+1] as i64) & 0xff) << 16) 75 | (((pdu[plen+2] as i64) & 0xff) << 8) | ((pdu[plen+3] as i64) & 0xff) 76 if got == want { return 1 } 77 return 0 78}