nx_p384_field_mul_fast.nx
buildroot/runtime/nx_p384_field_mul_fast.nx
about
nx_p384_field_mul_fast.nx -- fast P-384 field multiply (mod p) via the prime's
own complement, replacing the 385-iteration bit-by-bit reduction in
nx_p384_field_mul.nx (the measured ~640ms-per-ECDSA-verify bottleneck).
P-384 prime: p = 2^384 - 2^128 - 2^96 + 2^32 - 1, so
2^384 == 2^128 + 2^96 - 2^32 + 1 (mod p).
For a 768-bit product C = Hi*2^384 + Lo,
C == Lo + Hi*(2^128 + 2^96 - 2^32 + 1) (mod p).
All multipliers are word-aligned (128/96/32 are multiples of the 32-bit limb),
so the fold is just shifted adds/subs (offsets 4/3/1/0). Two folds bring a
768-bit product below ~2p; a short final reduce finishes it. Normal domain
in/out -> true drop-in for p384_field_mul (no Montgomery conversions).
Correctness is pinned by KAT equality vs the bit-by-bit p384_field_mul in
nx_p384_field_mul_fast_gate.nx (same a*b mod p for random a,b).
license_tier: INDEPENDENT_REDERIVE
genealogy_id: international-research-sources/nist/fips_186_5 (P-384 generalized-Mersenne)
lineage_id: nishi_p384_field_mul_fast_q10
dependencies 4 imports · 5 importers
imports: nx_syscalls.nxnx_u384.nxnx_u384_mul.nxnx_p384_field.nx
imported by: nx_p384_field_inv.nxnx_p384_field_mul.nxnx_p384_field_mul_fast_gate.nxnx_p384_point.nxnx_p384_point_add.nx
structs
| none |
consts
| none |
functions
| 27 | func p384_acc_add_shifted(acc: *i64, hi: *i64, off: i64) -> i64 called by 1: p384_fold_once |
| 52 | func p384_acc_sub_shifted(acc: *i64, hi: *i64, off: i64) -> i64 called by 1: p384_fold_once |
| 78 | func p384_fold_once(c: *i64) -> i64 |
| 95 | func p384_fast_reduce_final(c: *i64, p: *i64) -> i64 |
| 109 | func p384_field_mul_fast(out: *i64, a: *i64, b: *i64) -> i64 |
| 121 | func p384_field_sq_fast(out: *i64, a: *i64) -> i64 |
| 125 | func main() -> i64 |