code wiki / (root) / nx_p256_scalar_mul.nx

nx_p256_scalar_mul.nx

buildroot/runtime/nx_p256_scalar_mul.nx

3738 B104 linesdepth 8pulls 9 transitivereach 732 importersview sourcekind tooltopic p256
docsdependenciesstructsconstsfunctions

about

nx_p256_scalar_mul.nx -- P-256 scalar multiplication k * P. Phase 0b §I.3 piece 2c of the ECDSA-P256 arc: ✓ 2b. p256_point_add (190acf1f) ✓ 2c. p256_scalar_mul (THIS commit) - 3. p256_scalar mod n (queued) - 4. ecdsa_p256 verify (queued) Algorithm: binary double-and-add, left-to-right (MSB-first): result := O (infinity) for bit_pos = 255 down to 0: result := double(result) if bit_pos-th bit of k is set: result := add(result, P) return result Cost: 256 doublings + up to 256 adds. For a typical 256-bit scalar (~128 set bits), roughly 256 doubles + 128 adds = 384 point ops. Each point op composes ~10-15 field ops; with our slow field_mul at ~4100 limb-ops, one scalar-mult is roughly ~20-25M limb-ops, or ~2-3s on qemu-riscv64-static. ECDSA verify needs TWO scalar mults (u1*G + u2*Q). Shamir's trick (compute both via one shared doubling chain by walking the bits of u1 and u2 in lockstep against a 4-element precomputed point table {O, G, Q, G+Q}) is an optimization queued for a follow-up. For first-cut correctness this commit ships the simpler standalone scalar_mul. Public API: p256_scalar_mul(out, k_8, p) -- k_8: 8-limb 256-bit scalar (LE limb order, MUST be < n in practice but no defensive check here -- caller's ECDSA verify already reduces u1, u2 mod n) -- p: input point (Jacobian) -- out: result point (Jacobian); MAY alias p Edge cases handled: - k == 0: returns O (infinity)

dependencies 5 imports · 23 importers

nx_syscalls.nx nx_u256.nx nx_p256_field.nx nx_p256_point.nx nx_p256_point_add.nx nx_p256_scalar_mul.nx nx_bench_comb.nx nx_bench_kg.nx nx_bench_sign.nx nx_bench_verify.nx nx_cert_gen.nx nx_crypto_bench_full.nx nx_ecdsa_p256.nx nx_ecdsa_p256_sign.nx nx_ecdsa_p256_sign_test.nx nx_jose_es256.nx

diagram shows first 10 each side; +0 more imports, +13 more importers in the complete lists below.

imports: nx_syscalls.nxnx_u256.nxnx_p256_field.nxnx_p256_point.nxnx_p256_point_add.nx

imported by: nx_bench_comb.nxnx_bench_kg.nxnx_bench_sign.nxnx_bench_verify.nxnx_cert_gen.nxnx_crypto_bench_full.nxnx_ecdsa_p256.nxnx_ecdsa_p256_sign.nxnx_ecdsa_p256_sign_test.nxnx_jose_es256.nxnx_opaque_core.nxnx_opaque_pake.nxnx_p256_comb_bench.nxnx_p256_comb_test.nxnx_p256_ecdh.nxnx_p256_ecverify_core_bench.nxnx_p256_keyshare_test.nxnx_p256_scalar_mul_test.nxnx_p256_verify_bench.nxnx_p256_verify_components.nxnx_p256_wnaf_bench.nxnx_p256_wnaf_difftest.nxnx_voprf.nx

structs

none

consts

none

functions

70func p256_scalar_mul(out: *P256Point, k_8: *i64, p: *P256Point) -> i64
102func main() -> i64