23 #include "KeccakCore.h"
25 #include "utility/EndianUtil.h"
26 #include "utility/RotateUtil.h"
27 #include "utility/ProgMemUtil.h"
52 memset(state.A, 0,
sizeof(state.A));
73 return 1600 - ((size_t)_blockSize) * 8;
111 memset(state.A, 0,
sizeof(state.A));
113 state.outputSize = 0;
131 state.outputSize = 0;
134 const uint8_t *d = (
const uint8_t *)data;
135 #if !defined(CRYPTO_LITTLE_ENDIAN)
136 uint64_t *Awords = &(state.A[0][0]);
137 uint8_t index, index2;
140 uint8_t len = _blockSize - state.inputSize;
143 #if defined(CRYPTO_LITTLE_ENDIAN)
144 uint8_t *Abytes = ((uint8_t *)state.A) + state.inputSize;
145 for (uint8_t posn = 0; posn < len; ++posn)
146 Abytes[posn] ^= d[posn];
148 index2 = state.inputSize;
149 for (index = 0; index < len; ++index) {
150 Awords[index2 / 8] ^= (((uint64_t)d[index]) << ((index2 % 8) * 8));
154 state.inputSize += len;
157 if (state.inputSize == _blockSize) {
181 uint8_t size = state.inputSize;
182 uint64_t *Awords = &(state.A[0][0]);
183 Awords[size / 8] ^= (((uint64_t)tag) << ((size % 8) * 8));
184 Awords[(_blockSize - 1) / 8] ^= 0x8000000000000000ULL;
187 state.outputSize = 0;
203 #if !defined(CRYPTO_LITTLE_ENDIAN)
204 uint8_t index, index2;
205 const uint64_t *Awords = &(state.A[0][0]);
212 uint8_t *d = (uint8_t *)data;
216 if (state.outputSize >= _blockSize) {
218 state.outputSize = 0;
222 tempSize = _blockSize - state.outputSize;
227 #if defined(CRYPTO_LITTLE_ENDIAN)
228 memcpy(d, ((uint8_t *)(state.A)) + state.outputSize, tempSize);
230 index2 = state.outputSize;
231 for (index = 0; index < tempSize; ++index) {
232 d[index] = (uint8_t)(Awords[index2 / 8] >> ((index2 % 8) * 8));
236 state.outputSize += tempSize;
265 uint8_t *b = (uint8_t *)state.B;
277 memset(b + len, pad, size - len);
288 void KeccakCore::keccakp()
290 static const uint8_t addMod5Table[9] PROGMEM = {
291 0, 1, 2, 3, 4, 0, 1, 2, 3
293 #define addMod5(x, y) (pgm_read_byte(&(addMod5Table[(x) + (y)])))
295 uint8_t index, index2;
296 for (uint8_t round = 0; round < 24; ++round) {
300 for (index = 0; index < 5; ++index) {
301 state.B[0][index] = state.A[0][index] ^ state.A[1][index] ^
302 state.A[2][index] ^ state.A[3][index] ^
305 for (index = 0; index < 5; ++index) {
306 D = state.B[0][addMod5(index, 4)] ^
307 leftRotate1_64(state.B[0][addMod5(index, 1)]);
308 for (index2 = 0; index2 < 5; ++index2)
309 state.A[index2][index] ^= D;
314 state.B[0][0] = state.A[0][0];
315 state.B[1][0] = leftRotate28_64(state.A[0][3]);
316 state.B[2][0] = leftRotate1_64 (state.A[0][1]);
317 state.B[3][0] = leftRotate27_64(state.A[0][4]);
318 state.B[4][0] = leftRotate62_64(state.A[0][2]);
319 state.B[0][1] = leftRotate44_64(state.A[1][1]);
320 state.B[1][1] = leftRotate20_64(state.A[1][4]);
321 state.B[2][1] = leftRotate6_64 (state.A[1][2]);
322 state.B[3][1] = leftRotate36_64(state.A[1][0]);
323 state.B[4][1] = leftRotate55_64(state.A[1][3]);
324 state.B[0][2] = leftRotate43_64(state.A[2][2]);
325 state.B[1][2] = leftRotate3_64 (state.A[2][0]);
326 state.B[2][2] = leftRotate25_64(state.A[2][3]);
327 state.B[3][2] = leftRotate10_64(state.A[2][1]);
328 state.B[4][2] = leftRotate39_64(state.A[2][4]);
329 state.B[0][3] = leftRotate21_64(state.A[3][3]);
330 state.B[1][3] = leftRotate45_64(state.A[3][1]);
331 state.B[2][3] = leftRotate8_64 (state.A[3][4]);
332 state.B[3][3] = leftRotate15_64(state.A[3][2]);
333 state.B[4][3] = leftRotate41_64(state.A[3][0]);
334 state.B[0][4] = leftRotate14_64(state.A[4][4]);
335 state.B[1][4] = leftRotate61_64(state.A[4][2]);
336 state.B[2][4] = leftRotate18_64(state.A[4][0]);
337 state.B[3][4] = leftRotate56_64(state.A[4][3]);
338 state.B[4][4] = leftRotate2_64 (state.A[4][1]);
341 for (index = 0; index < 5; ++index) {
342 for (index2 = 0; index2 < 5; ++index2) {
343 state.A[index2][index] =
344 state.B[index2][index] ^
345 ((~state.B[index2][addMod5(index, 1)]) &
346 state.B[index2][addMod5(index, 2)]);
351 static uint64_t
const RC[24] PROGMEM = {
352 0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808AULL,
353 0x8000000080008000ULL, 0x000000000000808BULL, 0x0000000080000001ULL,
354 0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008AULL,
355 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000AULL,
356 0x000000008000808BULL, 0x800000000000008BULL, 0x8000000000008089ULL,
357 0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
358 0x000000000000800AULL, 0x800000008000000AULL, 0x8000000080008081ULL,
359 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
361 state.A[0][0] ^= pgm_read_qword(RC + round);
size_t blockSize() const
Returns the input block size for the sponge function in bytes.
void setHMACKey(const void *key, size_t len, uint8_t pad, size_t hashSize)
Sets a HMAC key for a Keccak-based hash algorithm.
void setCapacity(size_t capacity)
Sets the capacity of the Keccak sponge function in bits.
~KeccakCore()
Destroys this Keccak sponge function after clearing all sensitive information.
void extract(void *data, size_t size)
Extracts data from the Keccak sponge function.
void pad(uint8_t tag)
Pads the last block of input data to blockSize().
size_t capacity() const
Returns the capacity of the sponge function in bits.
KeccakCore()
Constructs a new Keccak sponge function.
void update(const void *data, size_t size)
Updates the Keccak sponge function with more input data.
void clear()
Clears all sensitive data from this object.
void reset()
Resets the Keccak sponge function ready for a new session.