code wiki / (root) / nx_p256_verify_components.nx

nx_p256_verify_components.nx source

↩ module page · 66 lines · 3082 B

1// nx_p256_verify_components.nx -- decompose the ECDSA verify budget so the next optimization targets 2// the actual biggest remaining cost (not a guess). Times: modn_inv (s^-1 mod n), generic scalar_mul 3// (u2*Q), comb scalar_mul (u1*G), point_to_affine (field inversion mod p). expect_exit: 0 4// license_tier: ORIGINAL 5import "nx_syscalls.nx" 6import "nx_csprng.nx" 7import "nx_p256_comb.nx" 8import "nx_p256_scalar_mul.nx" 9import "nx_p256_modn.nx" 10const K_MAGIC_1000000000: i64 = 1000000000 11 12func bp(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 13func bn(v: i64) -> i64 { 14 let t: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 15 let b: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } 16 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 17 var i: i64 = 0; while i < k { b[i] = t[k-1-i]; i = i + 1 } sys_write(1, b, k); return 0 18} 19func now_ns(ts: *i64) -> i64 { __syscall(SYS_CLOCK_GETTIME, 1, ts as i64, 0, 0, 0, 0); return ts[0] * K_MAGIC_1000000000 + ts[1] } 20 21const NI: i64 = 300 22 23func main() -> i64 { 24 let table: *i64 = (sys_mmap(NX_P256_COMB_BYTES)) as *i64 25 p256_comb_build(table) 26 let g: *P256Point = p256_point_alloc() 27 p256_point_load_g(g) 28 let k: *i64 = u256_alloc() 29 let a: *i64 = u256_alloc() 30 let out: *i64 = u256_alloc() 31 let r: *P256Point = p256_point_alloc() 32 let ts: *i64 = sys_mmap(32) as *i64 33 let be: *u8 = sys_mmap(32) 34 nx_csprng_fill(be, 32); be[0] = 1; u256_load_be(k, be) 35 nx_csprng_fill(be, 32); be[0] = 1; u256_load_be(a, be) 36 37 bp("=== nx_p256_verify_components (per-op, NI=" as *u8); bn(NI); bp(") ===\n" as *u8) 38 39 // modn_inv 40 var acc: i64 = 0 41 var t0: i64 = now_ns(ts) 42 var i: i64 = 0 43 while i < NI { a[0] = (a[0] ^ acc) | 1; p256_modn_inv(out, a); acc = acc ^ out[0]; i = i + 1 } 44 bp("modn_inv = " as *u8); bn((now_ns(ts) - t0) / NI); bp(" ns\n" as *u8) 45 46 // generic scalar_mul (u2*Q proxy: k*G generic) 47 acc = 0; t0 = now_ns(ts); i = 0 48 while i < NI { k[0] = (k[0] ^ acc); p256_scalar_mul(r, k, g); acc = acc ^ r.x[0]; i = i + 1 } 49 bp("scalar_generic = " as *u8); bn((now_ns(ts) - t0) / NI); bp(" ns\n" as *u8) 50 51 // comb scalar_mul (u1*G) 52 acc = 0; t0 = now_ns(ts); i = 0 53 while i < NI { k[0] = (k[0] ^ acc); p256_scalar_mul_base(r, k, table); acc = acc ^ r.x[0]; i = i + 1 } 54 bp("scalar_comb = " as *u8); bn((now_ns(ts) - t0) / NI); bp(" ns\n" as *u8) 55 56 // point_to_affine (field inversion mod p): build a Jacobian point via scalar mul, copy+affine each iter 57 let jac: *P256Point = p256_point_alloc() 58 p256_scalar_mul(jac, k, g) // a real Jacobian point (Z != 1) 59 let tmp: *P256Point = p256_point_alloc() 60 acc = 0; t0 = now_ns(ts); i = 0 61 while i < NI { p256_point_copy(tmp, jac); p256_point_to_affine(tmp); acc = acc ^ tmp.x[0]; i = i + 1 } 62 bp("to_affine(inv) = " as *u8); bn((now_ns(ts) - t0) / NI); bp(" ns\n" as *u8) 63 64 bp("checksum=" as *u8); bn(acc); bp("\n" as *u8) 65 return 0 66}