nx_p256_modn.nx
buildroot/runtime/nx_p256_modn.nx
about
nx_p256_modn.nx -- arithmetic in Z/nZ where n is the NIST P-256
group order (the order of the base point G).
Phase 0b §I.3 piece 3 of the ECDSA-P256 arc:
✓ 2c. p256_scalar_mul (k * P) (THIS commit's predecessor)
✓ 3. p256_modn arithmetic (THIS commit)
- 4. ecdsa_p256 verify (queued, FINAL)
Naming distinction from existing shipped primitives:
- p256_field_* = arithmetic in F_p (the COORDINATE field)
- p256_scalar_mul = scalar-times-point operation (k * P)
- p256_modn_* = arithmetic in Z/nZ (the SCALAR field)
ECDSA verify uses Z/nZ arithmetic for:
- reducing the message hash e mod n
- computing s^(-1) mod n (Fermat: s^(n-2))
- u1 = e * s_inv mod n
- u2 = r * s_inv mod n
- final equality check x_R mod n == r
n (FIPS 186-5 §D.2.4):
n = 0xFFFFFFFF 00000000 FFFFFFFF FFFFFFFF
BCE6FAAD A7179E84 F3B9CAC2 FC632551
LE limb layout:
limb[0] = 0xFC632551 limb[4] = 0xFFFFFFFF
limb[1] = 0xF3B9CAC2 limb[5] = 0xFFFFFFFF
limb[2] = 0xA7179E84 limb[6] = 0x00000000
limb[3] = 0xBCE6FAAD limb[7] = 0xFFFFFFFF
Public API:
p256_modn_load_n(out)
p256_modn_load_n_minus_2(out)
p256_modn_zero / one / copy / eq
p256_modn_add(r, a, b) -- (a + b) mod n
p256_modn_sub(r, a, b) -- (a - b) mod n
p256_modn_neg(r, a)
p256_modn_mul(r, a, b) -- (a * b) mod n
p256_modn_sq(r, a)
p256_modn_inv(out, a) -- Fermat a^(n-2) mod n
p256_modn_reduce(r, a) -- a in [0, 2^256) -> a mod n
dependencies 3 imports · 16 importers
diagram shows first 10 each side; +0 more imports, +6 more importers in the complete lists below.
imports: nx_syscalls.nxnx_u256.nxnx_u256_mul.nx
imported by: nx_bench_sign.nxnx_bench_verify.nxnx_crypto_bench_full.nxnx_ecdsa_p256.nxnx_ecdsa_p256_sign.nxnx_ecdsa_p256_sign_test.nxnx_ecdsa_p256_test.nxnx_opaque_core.nxnx_p256_ecdh.nxnx_p256_keyshare_test.nxnx_p256_modn_mont_test.nxnx_p256_modn_test.nxnx_p256_verify_bench.nxnx_p256_verify_components.nxnx_p256_verify_timing.nxnx_voprf.nx
structs
| none |
consts
| 96 | const NX_P256_MODN_NPRIME0: i64 = 0xEE00BC4F |
functions
| 67 | func p256_modn_load_n(out: *i64) -> i64 |
| 80 | func p256_modn_load_n_minus_2(out: *i64) -> i64 |
| 98 | func p256_modn_load_R2(out: *i64) -> i64 called by 1: p256_modn_inv |
| 110 | func p256_modn_zero(out: *i64) -> i64 { return u256_zero(out) } |
| 111 | func p256_modn_one(out: *i64) -> i64 { return u256_one(out) } called by 7: _nx_ecdsa_p256_verify_implp256_modn_inv_slowp256_modn_invrand_scalarcheck_onemain+1 calls 1: u256_one |
| 112 | func p256_modn_copy(out: *i64, src: *i64) -> i64 { return u256_copy(out, src) } calls 1: u256_copy |
| 113 | func p256_modn_eq(a: *i64, b: *i64) -> i64 { return u256_eq(a, b) } |
| 116 | func p256_modn_add(r: *i64, a: *i64, b: *i64) -> i64 |
| 135 | func p256_modn_sub(r: *i64, a: *i64, b: *i64) -> i64 |
| 148 | func p256_modn_neg(r: *i64, a: *i64) -> i64 called by 1: main calls 7: u256_is_zerou256_zeronx_scratch_saveu256_allocp256_modn_load_nu256_sub_with_borrow+1 |
| 172 | func p256_modn_reduce(r: *i64, a: *i64) -> i64 |
| 187 | func u256_wide_shr_1_inplace(buf: *i64) -> i64 called by 1: p256_modn_mul |
| 200 | func u256_wide_sub_inplace(a: *i64, b: *i64) -> i64 called by 1: p256_modn_mul |
| 221 | func p256_modn_mul(out_8: *i64, a: *i64, b: *i64) -> i64 |
| 256 | func p256_modn_sq(out: *i64, a: *i64) -> i64 |
| 261 | func p256_modn_bit_at(limbs: *i64, bit_pos: i64) -> i64 |
| 274 | func p256_modn_mul_mont(out: *i64, a: *i64, b: *i64) -> i64 called by 1: p256_modn_inv calls 10: nx_scratch_saveu256_allocp256_modn_load_nu256_wide_allocu256_mul_widenx_scratch+4 |
| 324 | func p256_modn_inv_slow(out: *i64, a: *i64) -> i64 called by 1: check_one calls 9: nx_scratch_saveu256_allocp256_modn_load_n_minus_2u256_copyp256_modn_onep256_modn_sq+3 |
| 353 | func p256_modn_inv(out: *i64, a: *i64) -> i64 |
| 383 | func main() -> i64 |