| ... | @@ -316,72 +316,6 @@ fn addLanesAll( | ... | @@ -316,72 +316,6 @@ fn addLanesAll( |
| 316 | } | 316 | } |
| 317 | } | 317 | } |
| 318 | | 318 | |
| 319 | /// Apply Keccak-p[1600,12] to a single state (byte representation) | | |
| 320 | fn keccakP(state: *[200]u8) void { | | |
| 321 | @setEvalBranchQuota(10000); | | |
| 322 | var lanes: [5][5]u64 = undefined; | | |
| 323 | | | |
| 324 | // Load state into lanes | | |
| 325 | inline for (0..5) |x| { | | |
| 326 | inline for (0..5) |y| { | | |
| 327 | lanes[x][y] = load64(state[8 * (x + 5 * y) ..]); | | |
| 328 | } | | |
| 329 | } | | |
| 330 | | | |
| 331 | // Apply 12 rounds | | |
| 332 | var round: usize = 0; | | |
| 333 | while (round < 12) : (round += 2) { | | |
| 334 | inline for (0..2) |i| { | | |
| 335 | // θ | | |
| 336 | var C: [5]u64 = undefined; | | |
| 337 | inline for (0..5) |x| { | | |
| 338 | C[x] = lanes[x][0] ^ lanes[x][1] ^ lanes[x][2] ^ lanes[x][3] ^ lanes[x][4]; | | |
| 339 | } | | |
| 340 | var D: [5]u64 = undefined; | | |
| 341 | inline for (0..5) |x| { | | |
| 342 | D[x] = C[(x + 4) % 5] ^ std.math.rotl(u64, C[(x + 1) % 5], 1); | | |
| 343 | } | | |
| 344 | inline for (0..5) |x| { | | |
| 345 | inline for (0..5) |y| { | | |
| 346 | lanes[x][y] ^= D[x]; | | |
| 347 | } | | |
| 348 | } | | |
| 349 | | | |
| 350 | // ρ and π | | |
| 351 | var current = lanes[1][0]; | | |
| 352 | var px: usize = 1; | | |
| 353 | var py: usize = 0; | | |
| 354 | inline for (0..24) |t| { | | |
| 355 | const temp = lanes[py][(2 * px + 3 * py) % 5]; | | |
| 356 | const rot_amount = ((t + 1) * (t + 2) / 2) % 64; | | |
| 357 | lanes[py][(2 * px + 3 * py) % 5] = std.math.rotl(u64, current, @as(u6, @intCast(rot_amount))); | | |
| 358 | current = temp; | | |
| 359 | const temp_x = py; | | |
| 360 | py = (2 * px + 3 * py) % 5; | | |
| 361 | px = temp_x; | | |
| 362 | } | | |
| 363 | | | |
| 364 | // χ | | |
| 365 | inline for (0..5) |y| { | | |
| 366 | const T = [5]u64{ lanes[0][y], lanes[1][y], lanes[2][y], lanes[3][y], lanes[4][y] }; | | |
| 367 | inline for (0..5) |x| { | | |
| 368 | lanes[x][y] = T[x] ^ (~T[(x + 1) % 5] & T[(x + 2) % 5]); | | |
| 369 | } | | |
| 370 | } | | |
| 371 | | | |
| 372 | // ι | | |
| 373 | lanes[0][0] ^= RC[round + i]; | | |
| 374 | } | | |
| 375 | } | | |
| 376 | | | |
| 377 | // Store lanes back to state | | |
| 378 | inline for (0..5) |x| { | | |
| 379 | inline for (0..5) |y| { | | |
| 380 | store64(lanes[x][y], state[8 * (x + 5 * y) ..]); | | |
| 381 | } | | |
| 382 | } | | |
| 383 | } | | |
| 384 | | | |
| 385 | /// Apply Keccak-p[1600,12] to a single state (u64 lane representation) | 319 | /// Apply Keccak-p[1600,12] to a single state (u64 lane representation) |
| 386 | fn keccakPLanes(lanes: *[25]u64) void { | 320 | fn keccakPLanes(lanes: *[25]u64) void { |
| 387 | @setEvalBranchQuota(10000); | 321 | @setEvalBranchQuota(10000); |
| ... | @@ -439,38 +373,12 @@ fn turboShakeMultiSliceToBuffer( | ... | @@ -439,38 +373,12 @@ fn turboShakeMultiSliceToBuffer( |
| 439 | separation_byte: u8, | 373 | separation_byte: u8, |
| 440 | output: []u8, | 374 | output: []u8, |
| 441 | ) void { | 375 | ) void { |
| 442 | var state: [200]u8 = @splat(0); | 376 | const StateType = if (rate == TurboSHAKE128State.block_length) TurboSHAKE128State else TurboSHAKE256State; |
| 443 | var state_pos: usize = 0; | 377 | comptime assert(StateType.block_length == rate); |
| 444 | | | |
| 445 | // Absorb all bytes from the multi-slice view | | |
| 446 | const total = view.totalLen(); | | |
| 447 | var pos: usize = 0; | | |
| 448 | while (pos < total) { | | |
| 449 | state[state_pos] ^= view.getByte(pos); | | |
| 450 | state_pos += 1; | | |
| 451 | pos += 1; | | |
| 452 | | | |
| 453 | if (state_pos == rate) { | | |
| 454 | keccakP(&state); | | |
| 455 | state_pos = 0; | | |
| 456 | } | | |
| 457 | } | | |
| 458 | | 378 | |
| 459 | // Add separation byte and padding | 379 | var state = StateType.init(.{ .delim = separation_byte }); |
| 460 | state[state_pos] ^= separation_byte; | 380 | for (view.slices) |slice| state.update(slice); |
| 461 | state[rate - 1] ^= 0x80; | 381 | state.final(output); |
| 462 | keccakP(&state); | | |
| 463 | | | |
| 464 | // Squeeze | | |
| 465 | var out_offset: usize = 0; | | |
| 466 | while (out_offset < output.len) { | | |
| 467 | const chunk = @min(rate, output.len - out_offset); | | |
| 468 | @memcpy(output[out_offset..][0..chunk], state[0..chunk]); | | |
| 469 | out_offset += chunk; | | |
| 470 | if (out_offset < output.len) { | | |
| 471 | keccakP(&state); | | |
| 472 | } | | |
| 473 | } | | |
| 474 | } | 382 | } |
| 475 | | 383 | |
| 476 | /// Generic allocating TurboSHAKE | 384 | /// Generic allocating TurboSHAKE |