code wiki / (root) / nx_ecdsa_p384.nx

nx_ecdsa_p384.nx source

↩ module page · 121 lines · 4297 B

1// nx_ecdsa_p384.nx -- ECDSA-P384 signature verification orchestrator. 2// 3// Mirror of nx_ecdsa_p256.nx adapted to the 12-limb / 384-bit path. 4// Same verify algorithm (SEC 1 v2.0 §4.1.4): 5// Inputs: Q = (pub_x, pub_y), e (hash), (r, s) 6// 1. Range-check r, s ∈ [1, n-1] 7// 2. Verify Q on curve + not infinity 8// 3. e_n = e mod n 9// 4. s_inv = s^(-1) mod n 10// 5. u1 = (e_n * s_inv) mod n 11// 6. u2 = (r * s_inv) mod n 12// 7. R = u1*G + u2*Q 13// 8. Reject if R == infinity 14// 9. v = x_R mod n 15// 10. Accept iff v == r 16// 17// Per Cardinal 22 (composition of shipped primitives). 18// 19// license_tier: INDEPENDENT_REDERIVE 20// genealogy_id: international-research-sources/nist/sec1_v2_4.1.4 + fips_186_5 21// lineage_id: nishi_ecdsa_p384_q10 22 23// nx_safety_envelope: 24// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 25// sil_target: SIL1 26// evidence: [bulk_applied_2026-05-20, ecdsa-p384-verify-orchestrator] 27// verdict: NOT_YET_EVALUATED 28 29import "nx_syscalls.nx" 30import "nx_u384.nx" 31import "nx_p384_modn.nx" 32import "nx_p384_point.nx" 33import "nx_p384_point_add.nx" 34import "nx_p384_scalar_mul.nx" 35 36const NX_ECDSA_P384_OK: i64 = 1 37const NX_ECDSA_P384_BAD_R_RANGE: i64 = 2 38const NX_ECDSA_P384_BAD_S_RANGE: i64 = 3 39const NX_ECDSA_P384_PUBKEY_NOT_ON_CURVE: i64 = 4 40const NX_ECDSA_P384_PUBKEY_INFINITY: i64 = 5 41const NX_ECDSA_P384_INFINITY_RESULT: i64 = 6 42const NX_ECDSA_P384_BAD_SIG: i64 = 7 43const NX_ECDSA_P384_VERDICT_N: i64 = 8 44 45func nx_ecdsa_p384_verdict_is_valid(v: i64) -> i64 { 46 if v < NX_ECDSA_P384_OK { return 0 } 47 if v >= NX_ECDSA_P384_VERDICT_N { return 0 } 48 return 1 49} 50 51// Verify ECDSA-P384 signature. 52// Returns NX_ECDSA_P384_OK on valid, non-OK verdict on any failure. 53// certloop leak fix: a thin LIFO-frame wrapper -> every u384/point the verify + its scalar-muls allocate is 54// reclaimed in O(1) at return (the inner keeps its 9 early-returns untouched; the wrapper guarantees one restore). 55func nx_ecdsa_p384_verify(pub_x: *i64, pub_y: *i64, 56 hash_e: *i64, 57 sig_r: *i64, sig_s: *i64) -> i64 { 58 let _sav: i64 = nx_u384_scratch_save() 59 let v: i64 = _nx_ecdsa_p384_verify_inner(pub_x, pub_y, hash_e, sig_r, sig_s) 60 nx_u384_scratch_restore(_sav) 61 return v 62} 63func _nx_ecdsa_p384_verify_inner(pub_x: *i64, pub_y: *i64, 64 hash_e: *i64, 65 sig_r: *i64, sig_s: *i64) -> i64 { 66 let n: *i64 = u384_alloc() 67 p384_modn_load_n(n) 68 69 // ---- Range-check r, s ---- 70 if u384_is_zero(sig_r) == 1 { return NX_ECDSA_P384_BAD_R_RANGE } 71 if u384_cmp(sig_r, n) >= 0 { return NX_ECDSA_P384_BAD_R_RANGE } 72 if u384_is_zero(sig_s) == 1 { return NX_ECDSA_P384_BAD_S_RANGE } 73 if u384_cmp(sig_s, n) >= 0 { return NX_ECDSA_P384_BAD_S_RANGE } 74 75 // ---- Pubkey on curve + not infinity ---- 76 let Q: *P384Point = p384_point_alloc() 77 p384_point_set_affine(Q, pub_x, pub_y) 78 if p384_point_is_infinity(Q) == 1 { return NX_ECDSA_P384_PUBKEY_INFINITY } 79 if p384_point_on_curve(Q) != 1 { return NX_ECDSA_P384_PUBKEY_NOT_ON_CURVE } 80 81 // ---- e_n = e mod n ---- 82 let e_n: *i64 = u384_alloc() 83 p384_modn_reduce(e_n, hash_e) 84 85 // ---- s_inv = s^(-1) mod n ---- 86 let s_inv: *i64 = u384_alloc() 87 p384_modn_inv(s_inv, sig_s) 88 89 // ---- u1 = e_n * s_inv mod n, u2 = r * s_inv mod n ---- 90 let u1: *i64 = u384_alloc() 91 let u2: *i64 = u384_alloc() 92 p384_modn_mul(u1, e_n, s_inv) 93 p384_modn_mul(u2, sig_r, s_inv) 94 95 // ---- R = u1*G + u2*Q ---- 96 let G: *P384Point = p384_point_alloc() 97 p384_point_load_g(G) 98 99 let u1G: *P384Point = p384_point_alloc() 100 let u2Q: *P384Point = p384_point_alloc() 101 p384_scalar_mul(u1G, u1, G) 102 p384_scalar_mul(u2Q, u2, Q) 103 104 let R: *P384Point = p384_point_alloc() 105 p384_point_add(R, u1G, u2Q) 106 107 if p384_point_is_infinity(R) == 1 { return NX_ECDSA_P384_INFINITY_RESULT } 108 109 // ---- v = x_R mod n ---- 110 p384_point_to_affine(R) 111 let v: *i64 = u384_alloc() 112 p384_modn_reduce(v, R.x) 113 114 // ---- Accept iff v == r ---- 115 if p384_modn_eq(v, sig_r) == 1 { return NX_ECDSA_P384_OK } 116 return NX_ECDSA_P384_BAD_SIG 117} 118 119func main() -> i64 { 120 return 0 121}