authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-29 15:16:52-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-09-29 15:16:52-04:00
log65b03092e3414f920de8df9cac60cf973ff56b37
treee2c366ceebb8bfd5cd1e9f8e84b2b6ac4b1f5bb5
parent3b478631fb658f96227652f71dc7785d0c3324be
parent56d820087d712c3b3e93e8aeed8d556509050479
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6450 from jedisct1/gimli-opt

std/crypto: make Gimli 60% faster

2 files changed, 45 insertions(+), 13 deletions(-)

lib/std/crypto/benchmark.zig+1-1
......@@ -168,7 +168,7 @@ pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64
168168 const start = timer.lap();
169169 while (offset < bytes) : (offset += in.len) {
170170 Aead.encrypt(in[0..], tag[0..], in[0..], &[_]u8{}, nonce, key);
171 Aead.decrypt(in[0..], in[0..], tag, &[_]u8{}, nonce, key) catch unreachable;
171 try Aead.decrypt(in[0..], in[0..], tag, &[_]u8{}, nonce, key);
172172 }
173173 mem.doNotOptimizeAway(&in);
174174 const end = timer.read();
lib/std/crypto/gimli.zig+44-12
......@@ -38,7 +38,35 @@ pub const State = struct {
3838 return mem.sliceAsBytes(self.data[0..]);
3939 }
4040
41 pub fn permute(self: *Self) void {
41 fn permute_unrolled(self: *Self) void {
42 const state = &self.data;
43 comptime var round = @as(u32, 24);
44 inline while (round > 0) : (round -= 1) {
45 var column = @as(usize, 0);
46 while (column < 4) : (column += 1) {
47 const x = math.rotl(u32, state[column], 24);
48 const y = math.rotl(u32, state[4 + column], 9);
49 const z = state[8 + column];
50 state[8 + column] = ((x ^ (z << 1)) ^ ((y & z) << 2));
51 state[4 + column] = ((y ^ x) ^ ((x | z) << 1));
52 state[column] = ((z ^ y) ^ ((x & y) << 3));
53 }
54 switch (round & 3) {
55 0 => {
56 mem.swap(u32, &state[0], &state[1]);
57 mem.swap(u32, &state[2], &state[3]);
58 state[0] ^= round | 0x9e377900;
59 },
60 2 => {
61 mem.swap(u32, &state[0], &state[2]);
62 mem.swap(u32, &state[1], &state[3]);
63 },
64 else => {},
65 }
66 }
67 }
68
69 fn permute_small(self: *Self) void {
4270 const state = &self.data;
4371 var round = @as(u32, 24);
4472 while (round > 0) : (round -= 1) {
......@@ -66,6 +94,8 @@ pub const State = struct {
6694 }
6795 }
6896
97 pub const permute = if (std.builtin.mode == .ReleaseSmall) permute_small else permute_unrolled;
98
6999 pub fn squeeze(self: *Self, out: []u8) void {
70100 var i = @as(usize, 0);
71101 while (i + RATE <= out.len) : (i += RATE) {
......@@ -249,15 +279,15 @@ pub const Aead = struct {
249279 in = in[State.RATE..];
250280 out = out[State.RATE..];
251281 }) {
252 for (buf[0..State.RATE]) |*p, i| {
253 p.* ^= in[i];
254 out[i] = p.*;
282 for (in[0..State.RATE]) |v, i| {
283 buf[i] ^= v;
255284 }
285 mem.copy(u8, out[0..State.RATE], buf[0..State.RATE]);
256286 state.permute();
257287 }
258 for (buf[0..in.len]) |*p, i| {
259 p.* ^= in[i];
260 out[i] = p.*;
288 for (in[0..]) |v, i| {
289 buf[i] ^= v;
290 out[i] = buf[i];
261291 }
262292
263293 // XOR 1 into the next byte of the state
......@@ -291,15 +321,17 @@ pub const Aead = struct {
291321 in = in[State.RATE..];
292322 out = out[State.RATE..];
293323 }) {
294 for (buf[0..State.RATE]) |*p, i| {
295 out[i] = p.* ^ in[i];
296 p.* = in[i];
324 const d = in[0..State.RATE].*;
325 for (d) |v, i| {
326 out[i] = buf[i] ^ v;
297327 }
328 mem.copy(u8, buf[0..State.RATE], d[0..State.RATE]);
298329 state.permute();
299330 }
300331 for (buf[0..in.len]) |*p, i| {
301 out[i] = p.* ^ in[i];
302 p.* = in[i];
332 const d = in[i];
333 out[i] = p.* ^ d;
334 p.* = d;
303335 }
304336
305337 // XOR 1 into the next byte of the state