From db5aa6cff7f497dbb2ba7422260eea343bd5b248 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Wed, 7 Oct 2026 12:38:15 +0200 Subject: [PATCH 1/3] crypto.keccak_p: allow arbitrary round numbers (still <= 24) Round numbers that were not a multiple of 3 caused an OOB. Nothing in the standard library uses a number of round that is not 12 or 24, and these are the only values used in current specifications. But we should be future proof and we already provide an API that's expected to work with any number of rounds, so honor that. --- lib/std/crypto/keccak_p.zig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/std/crypto/keccak_p.zig b/lib/std/crypto/keccak_p.zig index b707833e2d7a5a56cc8c38cd989ff6bee5a9b0a1..9164ba48bab7b6776ac8a4ab7f79d28b492c8120 100644 --- a/lib/std/crypto/keccak_p.zig +++ b/lib/std/crypto/keccak_p.zig @@ -177,8 +177,9 @@ pub fn KeccakF(comptime f: u11) type { /// Apply a (possibly) reduced-round permutation to the state. pub fn permuteR(self: *Self, comptime rounds: u5) void { + comptime assert(rounds <= max_rounds); // Keccak only supports up to 24 rounds var i = RC.len - rounds; - while (i < RC.len - RC.len % 3) : (i += 3) { + while (i < RC.len - rounds % 3) : (i += 3) { self.round(RC[i]); self.round(RC[i + 1]); self.round(RC[i + 2]); -- 2.54.0 From b1ccf7eb1e6a3d499220d25cff300358669ad3db Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Wed, 7 Oct 2026 13:03:32 +0200 Subject: [PATCH 2/3] Add core.keccak to the crypto.zig tests The Keccak tests only ran indirectly via the sha3 functions, but having that in the crypto.zig tests is convenient for individual testing. --- lib/std/crypto.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/std/crypto.zig b/lib/std/crypto.zig index 0c50efba4c7ae48379828c87280a1e3eac41d677..38a825654d006f920c9e11581fbd6e12b3d7d354 100644 --- a/lib/std/crypto.zig +++ b/lib/std/crypto.zig @@ -300,6 +300,7 @@ test { _ = auth.siphash; _ = core.aes; + _ = core.keccak; _ = core.Ascon; _ = core.modes; -- 2.54.0 From bb5ba74ab1d9e10fc4657ef68800192bab538341 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Wed, 7 Oct 2026 13:07:32 +0200 Subject: [PATCH 3/3] Remove dead code in kangarootwelve KeccakPlanes is not used any more in the current implementation. --- lib/std/crypto/kangarootwelve.zig | 50 ------------------------------- 1 file changed, 50 deletions(-) diff --git a/lib/std/crypto/kangarootwelve.zig b/lib/std/crypto/kangarootwelve.zig index befcdac6ef472cf68001a3089c2ae34ab8c4a421..2f2a9dd7774faf36958444c92019bf3323e9bb09 100644 --- a/lib/std/crypto/kangarootwelve.zig +++ b/lib/std/crypto/kangarootwelve.zig @@ -316,56 +316,6 @@ fn addLanesAll( } } -/// Apply Keccak-p[1600,12] to a single state (u64 lane representation) -fn keccakPLanes(lanes: *[25]u64) void { - @setEvalBranchQuota(10000); - - // Apply 12 rounds - inline for (RC) |rc| { - // θ - var C: [5]u64 = undefined; - inline for (0..5) |x| { - C[x] = lanes[x] ^ lanes[x + 5] ^ lanes[x + 10] ^ lanes[x + 15] ^ lanes[x + 20]; - } - var D: [5]u64 = undefined; - inline for (0..5) |x| { - D[x] = C[(x + 4) % 5] ^ std.math.rotl(u64, C[(x + 1) % 5], 1); - } - inline for (0..5) |x| { - inline for (0..5) |y| { - lanes[x + 5 * y] ^= D[x]; - } - } - - // ρ and π - var current = lanes[1]; - var px: usize = 1; - var py: usize = 0; - inline for (0..24) |t| { - const next_y = (2 * px + 3 * py) % 5; - const next_idx = py + 5 * next_y; - const temp = lanes[next_idx]; - const rot_amount = ((t + 1) * (t + 2) / 2) % 64; - lanes[next_idx] = std.math.rotl(u64, current, @as(u6, @intCast(rot_amount))); - current = temp; - px = py; - py = next_y; - } - - // χ - inline for (0..5) |y| { - const idx = 5 * y; - const T = [5]u64{ lanes[idx], lanes[idx + 1], lanes[idx + 2], lanes[idx + 3], lanes[idx + 4] }; - inline for (0..5) |x| { - lanes[idx + x] = T[x] ^ (~T[(x + 1) % 5] & T[(x + 2) % 5]); - } - } - - // ι - lanes[0] ^= rc; - } -} - /// Generic non-allocating TurboSHAKE: write output to provided buffer fn turboShakeMultiSliceToBuffer( comptime rate: usize, -- 2.54.0