| ... | @@ -22,19 +22,15 @@ fn Rp(a: usize, b: usize, c: usize, d: usize) QuarterRound { | ... | @@ -22,19 +22,15 @@ fn Rp(a: usize, b: usize, c: usize, d: usize) QuarterRound { |
| 22 | }; | 22 | }; |
| 23 | } | 23 | } |
| 24 | | 24 | |
| 25 | fn rotate(a: u32, b: u5) u32 { | | |
| 26 | return ((a << b) | | | |
| 27 | (a >> @intCast(u5, (32 - @intCast(u6, b)))) | | |
| 28 | ); | | |
| 29 | } | | |
| 30 | | | |
| 31 | // The chacha family of ciphers are based on the salsa family. | 25 | // The chacha family of ciphers are based on the salsa family. |
| 32 | fn salsa20_wordtobyte(input: [16]u32) [64]u8 { | 26 | fn salsa20_wordtobyte(out: []u8, input: [16]u32) void { |
| | 27 | assert(out.len >= 64); |
| | 28 | |
| 33 | var x: [16]u32 = undefined; | 29 | var x: [16]u32 = undefined; |
| 34 | var out: [64]u8 = undefined; | | |
| 35 | | 30 | |
| 36 | for (x) |_, i| | 31 | for (x) |_, i| |
| 37 | x[i] = input[i]; | 32 | x[i] = input[i]; |
| | 33 | |
| 38 | const rounds = comptime []QuarterRound{ | 34 | const rounds = comptime []QuarterRound{ |
| 39 | Rp( 0, 4, 8,12), | 35 | Rp( 0, 4, 8,12), |
| 40 | Rp( 1, 5, 9,13), | 36 | Rp( 1, 5, 9,13), |
| ... | @@ -45,20 +41,21 @@ fn salsa20_wordtobyte(input: [16]u32) [64]u8 { | ... | @@ -45,20 +41,21 @@ fn salsa20_wordtobyte(input: [16]u32) [64]u8 { |
| 45 | Rp( 2, 7, 8,13), | 41 | Rp( 2, 7, 8,13), |
| 46 | Rp( 3, 4, 9,14), | 42 | Rp( 3, 4, 9,14), |
| 47 | }; | 43 | }; |
| 48 | comptime var j: usize = 20; | 44 | |
| 49 | inline while (j > 0) : (j -=2) { | 45 | comptime var j: usize = 0; |
| 50 | for (rounds) |r| { | 46 | inline while (j < 20) : (j += 2) { |
| 51 | x[r.a] +%= x[r.b]; x[r.d] = rotate(x[r.d] ^ x[r.a], 16); | 47 | // two-round cycles |
| 52 | x[r.c] +%= x[r.d]; x[r.b] = rotate(x[r.b] ^ x[r.c], 12); | 48 | inline for (rounds) |r| { |
| 53 | x[r.a] +%= x[r.b]; x[r.d] = rotate(x[r.d] ^ x[r.a], 8); | 49 | x[r.a] +%= x[r.b]; x[r.d] = std.math.rotl(u32, x[r.d] ^ x[r.a], u32(16)); |
| 54 | x[r.c] +%= x[r.d]; x[r.b] = rotate(x[r.b] ^ x[r.c], 7); | 50 | x[r.c] +%= x[r.d]; x[r.b] = std.math.rotl(u32, x[r.b] ^ x[r.c], u32(12)); |
| | 51 | x[r.a] +%= x[r.b]; x[r.d] = std.math.rotl(u32, x[r.d] ^ x[r.a], u32(8)); |
| | 52 | x[r.c] +%= x[r.d]; x[r.b] = std.math.rotl(u32, x[r.b] ^ x[r.c], u32(7)); |
| 55 | } | 53 | } |
| 56 | } | 54 | } |
| 57 | for (x) |_, i| | 55 | |
| 58 | x[i] +%= input[i]; | 56 | for (x) |_, i| { |
| 59 | for (x) |_, i| | 57 | mem.writeInt(out[4 * i .. 4 * i + 4], x[i] +% input[i], builtin.Endian.Little); |
| 60 | mem.writeInt(out[4 * i .. 4 * i + 4], x[i], builtin.Endian.Little); | 58 | } |
| 61 | return out; | | |
| 62 | } | 59 | } |
| 63 | | 60 | |
| 64 | fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) void { | 61 | fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) void { |
| ... | @@ -73,13 +70,14 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo | ... | @@ -73,13 +70,14 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo |
| 73 | mem.readIntLE(u32, c[8..12]), | 70 | mem.readIntLE(u32, c[8..12]), |
| 74 | mem.readIntLE(u32, c[12..16]), | 71 | mem.readIntLE(u32, c[12..16]), |
| 75 | }; | 72 | }; |
| 76 | | 73 | |
| 77 | mem.copy(u32, ctx[0..], constant_le[0..4]); | 74 | mem.copy(u32, ctx[0..], constant_le[0..4]); |
| 78 | mem.copy(u32, ctx[4..12], key[0..8]); | 75 | mem.copy(u32, ctx[4..12], key[0..8]); |
| 79 | mem.copy(u32, ctx[12..16], counter[0..4]); | 76 | mem.copy(u32, ctx[12..16], counter[0..4]); |
| 80 | | 77 | |
| 81 | while (true) { | 78 | while (true) { |
| 82 | var buf = salsa20_wordtobyte(ctx); | 79 | var buf: [64]u8 = undefined; |
| | 80 | salsa20_wordtobyte(buf[0..], ctx); |
| 83 | | 81 | |
| 84 | if (remaining < 64) { | 82 | if (remaining < 64) { |
| 85 | var i: usize = 0; | 83 | var i: usize = 0; |
| ... | @@ -88,8 +86,8 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo | ... | @@ -88,8 +86,8 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo |
| 88 | return; | 86 | return; |
| 89 | } | 87 | } |
| 90 | | 88 | |
| 91 | comptime var i: usize = 0; | 89 | var i: usize = 0; |
| 92 | inline while (i < 64) : (i += 1) | 90 | while (i < 64) : (i += 1) |
| 93 | out[cursor + i] = in[cursor + i] ^ buf[i]; | 91 | out[cursor + i] = in[cursor + i] ^ buf[i]; |
| 94 | | 92 | |
| 95 | cursor += 64; | 93 | cursor += 64; |