code wiki / (root) / nx_handshake_crypto_bench.nx

nx_handshake_crypto_bench.nx source

↩ module page · 83 lines · 3274 B

1// nx_handshake_crypto_bench.nx -- 1:1 cost of the per-handshake public-key 2// crypto (the suspected ~150ms TLS bottleneck). A TLS 1.3 server handshake 3// does: 1 X25519 ephemeral keygen + 1 X25519 ECDH (shared secret) + 1 4// Ed25519 signature over the transcript. Measured here with sys_now_us 5// (ms) + __rdtsc (cycles). If keygen+ecdh+sign ~= 150ms, the crypto IS the 6// bottleneck (-> comb-tables). If it's a few ms, the daemon has a 7// per-connection inefficiency elsewhere (-> profile the daemon path). 8// 9// license_tier: ORIGINAL 10 11import "nx_syscalls.nx" 12import "nx_x25519.nx" 13import "nx_ed25519_signature.nx" 14 15func bdec(n: i64) -> i64 { 16 if n == 0 { sys_write(1, "0" as *u8, 1); return 0 } 17 var m: i64 = n 18 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 19 let d: *u8 = sys_mmap(24) 20 var k: i64 = 0 21 while m > 0 { d[k] = (0x30 + (m % 10)) as u8; m = m / 10; k = k + 1 } 22 var i: i64 = k - 1 23 while i >= 0 { let one: *u8 = sys_mmap(1); one[0] = d[i]; sys_write(1, one, 1); i = i - 1 } 24 return 0 25} 26// print micros as D.DDD ms 27func msfix(us: i64) -> i64 { 28 bdec(us / 1000); sys_write(1, ".", 1) 29 let f: i64 = us % 1000 30 if f < 100 { sys_write(1, "0", 1) } 31 if f < 10 { sys_write(1, "0", 1) } 32 bdec(f); return 0 33} 34func fill(p: *u8, n: i64, v: i64) -> i64 { 35 var i: i64 = 0 36 while i < n { p[i] = (v & 0xff) as u8; i = i + 1 } 37 return 0 38} 39func report(label: *u8, llen: i64, n: i64, us: i64, cyc: i64) -> i64 { 40 sys_write(1, label, llen) 41 sys_write(1, " ", 2); msfix(us / n); sys_write(1, " ms/op ", 9) 42 bdec(cyc / n); sys_write(1, " cyc/op\n", 8) 43 return 0 44} 45 46func main() -> i64 { 47 let priv: *u8 = sys_mmap(32); fill(priv, 32, 0x42) 48 let pub: *u8 = sys_mmap(32) 49 let peer: *u8 = sys_mmap(32); fill(peer, 32, 0x37) 50 let shared: *u8 = sys_mmap(32) 51 let msg: *u8 = sys_mmap(64); fill(msg, 64, 0x5a) // transcript-hash stand-in 52 let sig: *u8 = sys_mmap(64) 53 let N: i64 = 50 54 55 // warmup 56 x25519(priv, peer, shared); ed25519_sign_full(priv, msg, 64, sig) 57 58 sys_write(1, "TLS-HANDSHAKE CRYPTO COST (1:1, __rdtsc + us, N=50)\n", 51) 59 sys_write(1, "--------------------------------------------------\n", 51) 60 61 // X25519 scalar mult: the handshake does this TWICE (ephemeral keygen + 62 // ECDH shared secret) -- both are one ladder, identical cost. 63 var u0: i64 = sys_now_us(); var c0: i64 = __rdtsc() 64 var i: i64 = 0 65 while i < N { x25519(priv, peer, shared); i = i + 1 } 66 var c1: i64 = __rdtsc(); var u1: i64 = sys_now_us() 67 report("X25519 scalarmul:", 17, N, u1 - u0, c1 - c0) 68 let x_us: i64 = (u1 - u0) / N 69 70 // Ed25519 sign (transcript signature, once per handshake) 71 u0 = sys_now_us(); c0 = __rdtsc() 72 i = 0 73 while i < N { ed25519_sign_full(priv, msg, 64, sig); i = i + 1 } 74 c1 = __rdtsc(); u1 = sys_now_us() 75 report("Ed25519 sign :", 17, N, u1 - u0, c1 - c0) 76 let s_us: i64 = (u1 - u0) / N 77 78 sys_write(1, "\n Per-handshake PK crypto ~= 2*X25519 + 1*sign = ", 49) 79 msfix(2 * x_us + s_us); sys_write(1, " ms\n", 4) 80 sys_write(1, " (measured handshake ~150ms; if this sum << 150ms, the daemon has\n", 66) 81 sys_write(1, " per-connection overhead elsewhere -> profile the daemon path)\n", 64) 82 return 0 83}