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}