/** * Function that computes the Keccak-f[1600] permutation on the given state. */ void KeccakF1600_StatePermute(void *state) { unsigned int round, x, y, j, t; UINT8 LFSRstate = 0x01; for(round=0; round<24; round++) { { /* === θ step (see [Keccak Reference, Section 2.3.2]) === */ tKeccakLane C[5], D; /* Compute the parity of the columns */ for(x=0; x<5; x++) C[x] = readLane(x, 0) ^ readLane(x, 1) ^ readLane(x, 2) ^ readLane(x, 3) ^ readLane(x, 4); for(x=0; x<5; x++) { /* Compute the θ effect for a given column */ D = C[(x+4)%5] ^ ROL64(C[(x+1)%5], 1); /* Add the θ effect to the whole column */ for (y=0; y<5; y++) XORLane(x, y, D); } } { /* === ρ and π steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4]) === */ tKeccakLane current, temp; /* Start at coordinates (1 0) */ x = 1; y = 0; current = readLane(x, y); /* Iterate over ((0 1)(2 3))^t * (1 0) for 0 ≤ t ≤ 23 */ for(t=0; t<24; t++) { /* Compute the rotation constant r = (t+1)(t+2)/2 */ unsigned int r = ((t+1)*(t+2)/2)%64; /* Compute ((0 1)(2 3)) * (x y) */ unsigned int Y = (2*x+3*y)%5; x = y; y = Y; /* Swap current and state(x,y), and rotate */ temp = readLane(x, y); writeLane(x, y, ROL64(current, r)); current = temp; } } { /* === χ step (see [Keccak Reference, Section 2.3.1]) === */ tKeccakLane temp[5]; for(y=0; y<5; y++) { /* Take a copy of the plane */ for(x=0; x<5; x++) temp[x] = readLane(x, y); /* Compute χ on the plane */ for(x=0; x<5; x++) writeLane(x, y, temp[x] ^((~temp[(x+1)%5]) & temp[(x+2)%5])); } } { /* === ι step (see [Keccak Reference, Section 2.3.5]) === */ for(j=0; j<7; j++) { unsigned int bitPosition = (1<<j)-1; /* 2^j-1 */ if (LFSR86540(&LFSRstate)) XORLane(0, 0, (tKeccakLane)1<<bitPosition); } } } }
static void permute(KeccakContext* ctx) { uint8_t LFSRstate = 0x01; for (uint8_t round = 0; round < 24; ++round) { { // Theta step (see [Keccak Reference, Section 2.3.2]) uint64_t C[5], D; for (uint8_t x = 0; x < 5; ++x) { C[x] = readLane(x, 0) ^ readLane(x, 1) ^ readLane(x, 2) ^ readLane(x, 3) ^ readLane(x, 4); } for (uint8_t x = 0; x < 5; ++x) { D = C[(x+4)%5] ^ rol64(C[(x+1)%5], 1); for (uint8_t y = 0; y < 5; ++y) { XORLane(x, y, D); } } } { // p and Pi steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4]) uint8_t x = 1, y = 0; uint64_t current = readLane(x, y); for (uint8_t t = 0; t < 24; ++t) { uint8_t r = ((t + 1) * (t + 2) / 2) % 64; uint8_t Y = (2*x + 3*y) % 5; x = y; y = Y; uint64_t temp = readLane(x, y); writeLane(x, y, rol64(current, r)); current = temp; } } { // X step (see [Keccak Reference, Section 2.3.1]) for (uint8_t y = 0; y < 5; ++y) { uint64_t temp[5]; for (uint8_t x = 0; x < 5; ++x) { temp[x] = readLane(x, y); } for (uint8_t x = 0; x < 5; ++x) { writeLane(x, y, temp[x] ^((~temp[(x+1)%5]) & temp[(x+2)%5])); } } } { // i step (see [Keccak Reference, Section 2.3.5]) for (uint8_t j = 0; j < 7; ++j) { if (LFSR86540(LFSRstate)) { uint64_t bitPos = (1<<j) - 1; XORLane(0, 0, (uint64_t)1 << bitPos); } } } } }