nx_p256_point.nx
buildroot/runtime/nx_p256_point.nx
about
nx_p256_point.nx -- NIST P-256 elliptic-curve point operations.
Phase 0b §I.3 piece 2 of the ECDSA-P256 arc:
✓ 0. u256 big-int (6ff89dd8)
✓ 1. p256_field add/sub/neg (133f16a1)
✓ 1b. u256 wide multiplication (ddb0994a)
✓ 1c. p256_field mul + sq (d295c0a3)
✓ 1d. p256_field inverse (48e8e69d)
✓ 2. p256_point: struct + zero + set_affine + on_curve +
to_affine + double (THIS commit)
- 2b. p256_point_add (queued -- own commit, complex)
- 2c. p256_scalar_mul (queued)
- 3. p256_scalar mod n (queued)
- 4. ecdsa_p256 verify (queued)
Curve (FIPS 186-5 §D.2.4):
y^2 = x^3 + a*x + b (mod p)
a = -3
b = 0x5AC635D8 AA3A93E7 B3EBBD55 769886BC
651D06B0 CC53B0F6 3BCE3C3E 27D2604B
G = (Gx, Gy) -- base point of order n
p = NIST P-256 prime (see nx_p256_field)
Internal representation: Jacobian projective coordinates.
Affine (x, y) <-> Jacobian (X, Y, Z) where x = X/Z^2, y = Y/Z^3
Point at infinity O: Z = 0 (canonical: X = Y = 1, Z = 0)
Why Jacobian:
- point_double: 4 mults + 4 squares + ~10 add/sub
(vs affine: 2 mults + 2 squares + 1 INVERT which is ~30 mults
via Fermat; Jacobian skips the invert per doubling)
- point_add: 12 mults + 4 squares (still no invert)
- Invert deferred to once at the end via point_to_affine
Public API (this commit):
P256Point struct {x: *i64, y: *i64, z: *i64}
p256_point_alloc() -- zero/infinity
p256_point_zero(p) -- set to infinity
p256_point_copy(dst, src)
p256_point_is_infinity(p) -> 0|1
dependencies 5 imports · 26 importers
diagram shows first 10 each side; +0 more imports, +16 more importers in the complete lists below.
imports: nx_syscalls.nxnx_u256.nxnx_p256_field.nxnx_p256_field_mul.nxnx_p256_field_inv.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_h2c_p256.nxnx_jose_es256.nxnx_opaque_core.nxnx_opaque_pake.nxnx_p256_comb.nxnx_p256_ecdh.nxnx_p256_keyshare_test.nxnx_p256_point_add.nxnx_p256_point_add_test.nxnx_p256_point_test.nxnx_p256_pointloop_bench.nxnx_p256_scalar_mul.nxnx_p256_scalar_mul_test.nxnx_p256_scalar_mul_wnaf.nxnx_p256_verify_bench.nxnx_voprf.nxnx_x509_build.nx
structs
| 76 | struct P256Point |
consts
| 82 | const NX_P256_POINT_OK: i64 = 1 |
| 83 | const NX_P256_POINT_BAD: i64 = 2 |
| 84 | const NX_P256_POINT_VERDICT_N: i64 = 3 |
functions
| 86 | func nx_p256_point_verdict_is_valid(v: i64) -> i64 called by 1: main |
| 93 | func p256_point_alloc() -> *P256Point called by 41: mainmainmainmainnx_cg_ecdsa_p256_keygenmain+35 calls 4: nx_scratchu256_allocp256_field_onep256_field_zero |
| 106 | func p256_point_zero(p: *P256Point) -> i64 |
| 114 | func p256_point_is_infinity(p: *P256Point) -> i64 |
| 119 | func p256_point_copy(dst: *P256Point, src: *P256Point) -> i64 called by 10: p256_comb_buildp256_point_eqp256_point_addmainmainp256_scalar_mul+4 calls 1: u256_copy |
| 127 | func p256_point_set_affine(p: *P256Point, x: *i64, y: *i64) -> i64 |
| 146 | func p256_point_load_b(out: *i64) -> i64 |
| 163 | func p256_point_load_g(out_g: *P256Point) -> i64 |
| 193 | func p256_point_on_curve(p: *P256Point) -> i64 |
| 236 | func p256_point_to_affine(p: *P256Point) -> i64 |
| 261 | func p256_point_eq(a: *P256Point, b: *P256Point) -> i64 |
| 307 | func p256_point_double(out: *P256Point, in_pt: *P256Point) -> i64 |
| 380 | func main() -> i64 |