code wiki / (root) / nx_p256_fieldmul_mulx.nx

nx_p256_fieldmul_mulx.nx source

↩ module page · 46 lines · 2212 B

1// nx_p256_fieldmul_mulx.nx -- P-256 field multiply using the FUSED __mul256_wide intrinsic 2// (ADX/BMI2 mulx+adcx+adox) for the 256x256->512 product, then the EXISTING NIST Solinas reducer. 3// This is the drop-in fast path for p256_field_mul: identical reduction, only the multiply changes. 4// Kept in a SEPARATE file (imports nx_p256_field_mul.nx for _p256_solinas_reduce) so the live 5// crypto source stays clean -- a file that USES __mul256_wide only builds with a compiler that has 6// the intrinsic (the candidate), never breaking the live-compiler build of the P-256 stack. 7// Correctness: nx_p256_fieldmul_mulx_difftest proves p256_field_mul_mulx == p256_field_mul bit-exact. 8// license_tier: ORIGINAL 9import "nx_p256_field_mul.nx" // _p256_solinas_reduce + p256_field_mul (reference) + u256 constants 10 11// 8x32 field element (a[0..7]) -> 4x64 (packed little-endian). 12func fmx_pack64(dst64: *i64, src32: *i64) -> i64 { 13 var k: i64 = 0 14 while k < 4 { dst64[k] = (src32[2*k] & 0xffffffff) | ((src32[2*k+1] & 0xffffffff) << 32); k = k + 1 } 15 return 0 16} 17// 8x64 product -> 16x32 product words c0..c15 (what _p256_solinas_reduce consumes). 18func fmx_split32(c16: *i64, prod64: *i64) -> i64 { 19 var k: i64 = 0 20 while k < 8 { c16[2*k] = prod64[k] & 0xffffffff; c16[2*k+1] = (prod64[k] >> 32) & 0xffffffff; k = k + 1 } 21 return 0 22} 23 24// (a*b) mod p, canonical. Same contract as p256_field_mul (out_8/a/b are 8x32). Self-contained. 25func p256_field_mul_mulx(out_8: *i64, a: *i64, b: *i64) -> i64 { 26 let a64: *i64 = sys_mmap(4 * 8) as *i64 27 let b64: *i64 = sys_mmap(4 * 8) as *i64 28 let prod: *i64 = sys_mmap(8 * 8) as *i64 29 let c16: *i64 = sys_mmap(16 * 8) as *i64 30 fmx_pack64(a64, a) 31 fmx_pack64(b64, b) 32 __mul256_wide(prod, a64, b64) 33 fmx_split32(c16, prod) 34 _p256_solinas_reduce(out_8, c16) 35 return 0 36} 37 38// scratch-passed variant (NO per-call mmap) -- for honest benchmarking of the arithmetic. 39func p256_field_mul_mulx_s(out_8: *i64, a: *i64, b: *i64, a64: *i64, b64: *i64, prod: *i64, c16: *i64) -> i64 { 40 fmx_pack64(a64, a) 41 fmx_pack64(b64, b) 42 __mul256_wide(prod, a64, b64) 43 fmx_split32(c16, prod) 44 _p256_solinas_reduce(out_8, c16) 45 return 0 46}