code wiki / _hdl_build / nx_poly1305_bench.nx

nx_poly1305_bench.nx source

↩ module page · 91 lines · 4030 B

1// nx_poly1305_bench.nx -- throughput bench for the SCALAR Poly1305 (same verified 5x26-bit-limb code 2// as nx_poly1305_gate). MACs a 16384-byte buffer 65536 times = 1 GiB; wall-time -> MB/s. Tells us 3// whether the AEAD is Poly1305-bound (need SIMD) or ChaCha-bound (scalar suffices, ChaCha already 4// exceeds). Time it: compile->nxasm->elf, then `time ./elf`. license_tier: ORIGINAL 5import "nx_syscalls.nx" 6const K_MAGIC_16384: i64 = 16384 7const K_MAGIC_65536: i64 = 65536 8 9func u8to32(p: *u8, o: i64) -> i64 { 10 return (p[o] as i64) | ((p[o + 1] as i64) << 8) | ((p[o + 2] as i64) << 16) | ((p[o + 3] as i64) << 24) 11} 12 13func poly_block(m: *u8, off: i64, hibit: i64, h: *i64, r: *i64, s: *i64) -> i64 { 14 let t0: i64 = u8to32(m, off + 0) 15 let t1: i64 = u8to32(m, off + 4) 16 let t2: i64 = u8to32(m, off + 8) 17 let t3: i64 = u8to32(m, off + 12) 18 let a0: i64 = h[0] + (t0 & 0x3ffffff) 19 let a1: i64 = h[1] + (((t0 >> 26) | (t1 << 6)) & 0x3ffffff) 20 let a2: i64 = h[2] + (((t1 >> 20) | (t2 << 12)) & 0x3ffffff) 21 let a3: i64 = h[3] + (((t2 >> 14) | (t3 << 18)) & 0x3ffffff) 22 let a4: i64 = h[4] + ((t3 >> 8) | hibit) 23 var d0: i64 = a0 * r[0] + a1 * s[4] + a2 * s[3] + a3 * s[2] + a4 * s[1] 24 var d1: i64 = a0 * r[1] + a1 * r[0] + a2 * s[4] + a3 * s[3] + a4 * s[2] 25 var d2: i64 = a0 * r[2] + a1 * r[1] + a2 * r[0] + a3 * s[4] + a4 * s[3] 26 var d3: i64 = a0 * r[3] + a1 * r[2] + a2 * r[1] + a3 * r[0] + a4 * s[4] 27 var d4: i64 = a0 * r[4] + a1 * r[3] + a2 * r[2] + a3 * r[1] + a4 * r[0] 28 var c: i64 = d0 >> 26 29 h[0] = d0 & 0x3ffffff 30 d1 = d1 + c; c = d1 >> 26; h[1] = d1 & 0x3ffffff 31 d2 = d2 + c; c = d2 >> 26; h[2] = d2 & 0x3ffffff 32 d3 = d3 + c; c = d3 >> 26; h[3] = d3 & 0x3ffffff 33 d4 = d4 + c; c = d4 >> 26; h[4] = d4 & 0x3ffffff 34 h[0] = h[0] + c * 5; c = h[0] >> 26; h[0] = h[0] & 0x3ffffff 35 h[1] = h[1] + c 36 return 0 37} 38 39func poly1305(key: *u8, msg: *u8, mlen: i64, tag: *u8) -> i64 { 40 let r: *i64 = (sys_mmap(48)) as *i64 41 let s: *i64 = (sys_mmap(48)) as *i64 42 let h: *i64 = (sys_mmap(48)) as *i64 43 let k0: i64 = u8to32(key, 0) 44 let k1: i64 = u8to32(key, 4) 45 let k2: i64 = u8to32(key, 8) 46 let k3: i64 = u8to32(key, 12) 47 r[0] = k0 & 0x3ffffff 48 r[1] = ((k0 >> 26) | (k1 << 6)) & 0x3ffff03 49 r[2] = ((k1 >> 20) | (k2 << 12)) & 0x3ffc0ff 50 r[3] = ((k2 >> 14) | (k3 << 18)) & 0x3f03fff 51 r[4] = (k3 >> 8) & 0x00fffff 52 s[1] = r[1] * 5; s[2] = r[2] * 5; s[3] = r[3] * 5; s[4] = r[4] * 5 53 h[0] = 0; h[1] = 0; h[2] = 0; h[3] = 0; h[4] = 0 54 var off: i64 = 0 55 while off + 16 <= mlen { poly_block(msg, off, 0x1000000, h, r, s); off = off + 16 } 56 var c: i64 = h[1] >> 26; h[1] = h[1] & 0x3ffffff; h[2] = h[2] + c 57 c = h[2] >> 26; h[2] = h[2] & 0x3ffffff; h[3] = h[3] + c 58 c = h[3] >> 26; h[3] = h[3] & 0x3ffffff; h[4] = h[4] + c 59 c = h[4] >> 26; h[4] = h[4] & 0x3ffffff; h[0] = h[0] + c * 5 60 c = h[0] >> 26; h[0] = h[0] & 0x3ffffff; h[1] = h[1] + c 61 var p0: i64 = (h[0] | (h[1] << 26)) & 0xffffffff 62 var p1: i64 = ((h[1] >> 6) | (h[2] << 20)) & 0xffffffff 63 var p2: i64 = ((h[2] >> 12) | (h[3] << 14)) & 0xffffffff 64 var p3: i64 = ((h[3] >> 18) | (h[4] << 8)) & 0xffffffff 65 var f: i64 = p0 + u8to32(key, 16); p0 = f & 0xffffffff 66 f = p1 + u8to32(key, 20) + (f >> 32); p1 = f & 0xffffffff 67 f = p2 + u8to32(key, 24) + (f >> 32); p2 = f & 0xffffffff 68 f = p3 + u8to32(key, 28) + (f >> 32); p3 = f & 0xffffffff 69 tag[0] = (p0 & 0xff) as u8 70 tag[1] = (p1 & 0xff) as u8 71 tag[2] = (p2 & 0xff) as u8 72 tag[3] = (p3 & 0xff) as u8 73 return 0 74} 75 76func main() -> i64 { 77 let key: *u8 = sys_mmap(32) 78 var i: i64 = 0 79 while i < 32 { key[i] = ((i * 7 + 3) & 0xff) as u8; i = i + 1 } 80 let buf: *u8 = sys_mmap(K_MAGIC_16384) 81 i = 0 82 while i < K_MAGIC_16384 { buf[i] = (i & 0xff) as u8; i = i + 1 } 83 let tag: *u8 = sys_mmap(16) 84 var n: i64 = 0 85 while n < K_MAGIC_65536 { 86 poly1305(key, buf, K_MAGIC_16384, tag) 87 n = n + 1 88 } 89 sys_write(1, tag, 1) 90 return 0 91}