code wiki / bin / nx_crypto_bench_full.nx

nx_crypto_bench_full.nx source

↩ module page · 152 lines · 5092 B

1// nx_crypto_bench_full.nx -- 1:1 bits-up crypto bench vs OpenSSL incumbent. 2// 3// Measures (us/op, MONOTONIC clock, warmed up): 4// 1. p256_kG_generic -- generic double-and-add k*G (PRE-COMB baseline) 5// 2. p256_kG_comb -- fixed-base comb k*G (BITS-UP path) 6// 3. ecdsa_p256_sign -- full sign (generic kG path; no comb file on box) 7// 4. ecdsa_p256_verify -- full verify (u1*G + u2*Q, real signature) 8// 5. x25519_ecdh -- variable-base scalar mult (shared secret) 9// 10// The comb path here is exercised in-memory via p256_comb_build + 11// p256_scalar_mul_base (same code the deploy signer uses when the 12// /volume1/.../p256_comb.bin file is present), so we get the honest 13// comb-vs-generic SPEEDUP without needing the NAS file on disk. 14import "nx_syscalls.nx" 15import "nx_csprng.nx" 16import "nx_u256.nx" 17import "nx_p256_modn.nx" 18import "nx_p256_point.nx" 19import "nx_p256_scalar_mul.nx" 20import "nx_p256_comb.nx" 21import "nx_ecdsa_p256.nx" 22import "nx_ecdsa_p256_sign.nx" 23import "nx_x25519_ephemeral.nx" 24 25func bstrlen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != 0 { n = n + 1 } return n } 26 27// print "<label>=<value> us/op (N=<n>)" 28func bprint(label: *u8, total_us: i64, n: i64) -> i64 { 29 sys_write(1, label, bstrlen(label)) 30 sys_write(1, "=" as *u8, 1) 31 let per: i64 = total_us / n 32 let buf: *u8 = sys_mmap(24) 33 var d: i64 = 0 34 if per == 0 { buf[0] = 48; d = 1 } else { 35 var x: i64 = per 36 var c: i64 = 0 37 while x > 0 { c = c + 1; x = x / 10 } 38 d = c 39 var i: i64 = d - 1 40 x = per 41 while i >= 0 { buf[i] = (48 + (x % 10)) as u8; x = x / 10; i = i - 1 } 42 } 43 sys_write(1, buf, d) 44 sys_write(1, " us/op N=" as *u8, 10) 45 // print n 46 let buf2: *u8 = sys_mmap(24) 47 var d2: i64 = 0 48 if n == 0 { buf2[0] = 48; d2 = 1 } else { 49 var x2: i64 = n 50 var c2: i64 = 0 51 while x2 > 0 { c2 = c2 + 1; x2 = x2 / 10 } 52 d2 = c2 53 var i2: i64 = d2 - 1 54 x2 = n 55 while i2 >= 0 { buf2[i2] = (48 + (x2 % 10)) as u8; x2 = x2 / 10; i2 = i2 - 1 } 56 } 57 sys_write(1, buf2, d2) 58 sys_write(1, "\n" as *u8, 1) 59 return 0 60} 61 62func main() -> i64 { 63 // ---- shared setup ---- 64 let g: *P256Point = p256_point_alloc() 65 p256_point_load_g(g) 66 let table: *i64 = (sys_mmap(NX_P256_COMB_BYTES)) as *i64 67 p256_comb_build(table) 68 69 let k: *i64 = u256_alloc() 70 let be: *u8 = sys_mmap(32) 71 nx_csprng_fill(be, 32) 72 be[0] = 0 // keep scalar well below group order 73 u256_load_be(k, be) 74 75 let pout: *P256Point = p256_point_alloc() 76 77 var t0: i64 = 0 78 var i: i64 = 0 79 80 // ---- 1. generic k*G (pre-comb baseline) ---- 81 // warmup 82 p256_scalar_mul(pout, k, g) 83 p256_scalar_mul(pout, k, g) 84 let NG: i64 = 60 85 t0 = sys_now_us() 86 i = 0 87 while i < NG { p256_scalar_mul(pout, k, g); i = i + 1 } 88 bprint("p256_kG_generic " as *u8, sys_now_us() - t0, NG) 89 90 // ---- 2. comb k*G (bits-up path) ---- 91 p256_scalar_mul_base(pout, k, table) // warmup 92 p256_scalar_mul_base(pout, k, table) 93 let NC: i64 = 2000 94 t0 = sys_now_us() 95 i = 0 96 while i < NC { p256_scalar_mul_base(pout, k, table); i = i + 1 } 97 bprint("p256_kG_comb " as *u8, sys_now_us() - t0, NC) 98 99 // ---- 3 + 4. ECDSA sign + verify (need a real keypair/sig) ---- 100 let dkey: *i64 = u256_alloc() 101 nx_csprng_fill(be, 32); be[0] = 0 102 u256_load_be(dkey, be) 103 let hash: *i64 = u256_alloc() 104 nx_csprng_fill(be, 32) 105 u256_load_be(hash, be) 106 let rr: *i64 = u256_alloc() 107 let ss: *i64 = u256_alloc() 108 109 nx_ecdsa_p256_sign(dkey, hash, rr, ss) // warmup + produce a real sig 110 let NS: i64 = 40 111 t0 = sys_now_us() 112 i = 0 113 while i < NS { nx_ecdsa_p256_sign(dkey, hash, rr, ss); i = i + 1 } 114 bprint("ecdsa_p256_sign " as *u8, sys_now_us() - t0, NS) 115 116 // public key Q = d*G for verify 117 let q: *P256Point = p256_point_alloc() 118 p256_scalar_mul(q, dkey, g) 119 p256_point_to_affine(q) 120 121 // sanity: verify the real signature once 122 let vv: i64 = nx_ecdsa_p256_verify(q.x, q.y, hash, rr, ss) 123 if vv != 1 { 124 sys_write(1, "VERIFY_SELFTEST_FAIL\n" as *u8, 21) 125 return 7 126 } 127 nx_ecdsa_p256_verify(q.x, q.y, hash, rr, ss) // warmup 128 let NV: i64 = 40 129 t0 = sys_now_us() 130 i = 0 131 while i < NV { nx_ecdsa_p256_verify(q.x, q.y, hash, rr, ss); i = i + 1 } 132 bprint("ecdsa_p256_verfy" as *u8, sys_now_us() - t0, NV) 133 134 // ---- 5. X25519 ECDH (variable-base) ---- 135 let priv: *u8 = sys_mmap(32) 136 let pub2: *u8 = sys_mmap(32) 137 let secret: *u8 = sys_mmap(32) 138 let peerpriv: *u8 = sys_mmap(32) 139 nx_csprng_fill(priv, 32) 140 nx_csprng_fill(peerpriv, 32) 141 x25519_gen_keypair(peerpriv, pub2) 142 x25519_shared_secret(priv, pub2, secret) // warmup 143 x25519_shared_secret(priv, pub2, secret) 144 let NX: i64 = 1000 145 t0 = sys_now_us() 146 i = 0 147 while i < NX { x25519_shared_secret(priv, pub2, secret); i = i + 1 } 148 bprint("x25519_ecdh " as *u8, sys_now_us() - t0, NX) 149 150 sys_write(1, "BENCH_DONE\n" as *u8, 11) 151 return 0 152}