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...@@ -168,7 +168,7 @@ pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64
168 const start = timer.lap();168 const start = timer.lap();
169 while (offset < bytes) : (offset += in.len) {169 while (offset < bytes) : (offset += in.len) {
170 Aead.encrypt(in[0..], tag[0..], in[0..], &[_]u8{}, nonce, key);170 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);
172 }172 }
173 mem.doNotOptimizeAway(&in);173 mem.doNotOptimizeAway(&in);
174 const end = timer.read();174 const end = timer.read();
lib/std/crypto/gimli.zig+44-12
...@@ -38,7 +38,35 @@ pub const State = struct {...@@ -38,7 +38,35 @@ pub const State = struct {
38 return mem.sliceAsBytes(self.data[0..]);38 return mem.sliceAsBytes(self.data[0..]);
39 }39 }
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 {
42 const state = &self.data;70 const state = &self.data;
43 var round = @as(u32, 24);71 var round = @as(u32, 24);
44 while (round > 0) : (round -= 1) {72 while (round > 0) : (round -= 1) {
...@@ -66,6 +94,8 @@ pub const State = struct {...@@ -66,6 +94,8 @@ pub const State = struct {
66 }94 }
67 }95 }
6896
97 pub const permute = if (std.builtin.mode == .ReleaseSmall) permute_small else permute_unrolled;
98
69 pub fn squeeze(self: *Self, out: []u8) void {99 pub fn squeeze(self: *Self, out: []u8) void {
70 var i = @as(usize, 0);100 var i = @as(usize, 0);
71 while (i + RATE <= out.len) : (i += RATE) {101 while (i + RATE <= out.len) : (i += RATE) {
...@@ -249,15 +279,15 @@ pub const Aead = struct {...@@ -249,15 +279,15 @@ pub const Aead = struct {
249 in = in[State.RATE..];279 in = in[State.RATE..];
250 out = out[State.RATE..];280 out = out[State.RATE..];
251 }) {281 }) {
252 for (buf[0..State.RATE]) |*p, i| {282 for (in[0..State.RATE]) |v, i| {
253 p.* ^= in[i];283 buf[i] ^= v;
254 out[i] = p.*;
255 }284 }
285 mem.copy(u8, out[0..State.RATE], buf[0..State.RATE]);
256 state.permute();286 state.permute();
257 }287 }
258 for (buf[0..in.len]) |*p, i| {288 for (in[0..]) |v, i| {
259 p.* ^= in[i];289 buf[i] ^= v;
260 out[i] = p.*;290 out[i] = buf[i];
261 }291 }
262292
263 // XOR 1 into the next byte of the state293 // XOR 1 into the next byte of the state
...@@ -291,15 +321,17 @@ pub const Aead = struct {...@@ -291,15 +321,17 @@ pub const Aead = struct {
291 in = in[State.RATE..];321 in = in[State.RATE..];
292 out = out[State.RATE..];322 out = out[State.RATE..];
293 }) {323 }) {
294 for (buf[0..State.RATE]) |*p, i| {324 const d = in[0..State.RATE].*;
295 out[i] = p.* ^ in[i];325 for (d) |v, i| {
296 p.* = in[i];326 out[i] = buf[i] ^ v;
297 }327 }
328 mem.copy(u8, buf[0..State.RATE], d[0..State.RATE]);
298 state.permute();329 state.permute();
299 }330 }
300 for (buf[0..in.len]) |*p, i| {331 for (buf[0..in.len]) |*p, i| {
301 out[i] = p.* ^ in[i];332 const d = in[i];
302 p.* = in[i];333 out[i] = p.* ^ d;
334 p.* = d;
303 }335 }
304336
305 // XOR 1 into the next byte of the state337 // XOR 1 into the next byte of the state