23 #include "KeccakCore.h"
25 #include "utility/EndianUtil.h"
26 #include "utility/RotateUtil.h"
27 #include "utility/ProgMemUtil.h"
42 #if !defined(CRYPTO_LITTLE_ENDIAN)
44 #error "KeccakCore is not supported on big-endian platforms yet - todo"
57 memset(state.A, 0,
sizeof(state.A));
78 return 1600 - ((size_t)_blockSize) * 8;
116 memset(state.A, 0,
sizeof(state.A));
118 state.outputSize = 0;
136 state.outputSize = 0;
139 const uint8_t *d = (
const uint8_t *)data;
141 uint8_t len = _blockSize - state.inputSize;
144 uint8_t *Abytes = ((uint8_t *)state.A) + state.inputSize;
145 for (uint8_t posn = 0; posn < len; ++posn)
146 Abytes[posn] ^= d[posn];
147 state.inputSize += len;
150 if (state.inputSize == _blockSize) {
174 uint8_t size = state.inputSize;
175 uint64_t *Awords = &(state.A[0][0]);
176 Awords[size / 8] ^= (((uint64_t)tag) << ((size % 8) * 8));
177 Awords[(_blockSize - 1) / 8] ^= 0x8000000000000000ULL;
180 state.outputSize = 0;
200 uint8_t *d = (uint8_t *)data;
204 if (state.outputSize >= _blockSize) {
206 state.outputSize = 0;
210 tempSize = _blockSize - state.outputSize;
215 memcpy(d, ((uint8_t *)(state.A)) + state.outputSize, tempSize);
216 state.outputSize += tempSize;
245 uint8_t *Abytes = (uint8_t *)state.A;
252 memcpy(Abytes, key, len);
260 memset(Abytes + hashSize, pad, size - hashSize);
261 memset(Abytes + size, 0,
sizeof(state.A) - size);
274 void KeccakCore::keccakp()
281 for (uint8_t round = 0; round < 24; ++round) {
282 __asm__ __volatile__ (
303 "eor r8,__tmp_reg__\n"
304 "ldd __tmp_reg__,Z+1\n"
305 "eor r9,__tmp_reg__\n"
306 "ldd __tmp_reg__,Z+2\n"
307 "eor r10,__tmp_reg__\n"
308 "ldd __tmp_reg__,Z+3\n"
309 "eor r11,__tmp_reg__\n"
310 "ldd __tmp_reg__,Z+4\n"
311 "eor r12,__tmp_reg__\n"
312 "ldd __tmp_reg__,Z+5\n"
313 "eor r13,__tmp_reg__\n"
314 "ldd __tmp_reg__,Z+6\n"
315 "eor r14,__tmp_reg__\n"
316 "ldd __tmp_reg__,Z+7\n"
317 "eor r15,__tmp_reg__\n"
329 "sbc r31,__zero_reg__\n"
352 "adc r8, __zero_reg__\n"
353 "ldd __tmp_reg__,Y+32\n"
354 "eor r8,__tmp_reg__\n"
355 "ldd __tmp_reg__,Y+33\n"
356 "eor r9,__tmp_reg__\n"
357 "ldd __tmp_reg__,Y+34\n"
358 "eor r10,__tmp_reg__\n"
359 "ldd __tmp_reg__,Y+35\n"
360 "eor r11,__tmp_reg__\n"
361 "ldd __tmp_reg__,Y+36\n"
362 "eor r12,__tmp_reg__\n"
363 "ldd __tmp_reg__,Y+37\n"
364 "eor r13,__tmp_reg__\n"
365 "ldd __tmp_reg__,Y+38\n"
366 "eor r14,__tmp_reg__\n"
367 "ldd __tmp_reg__,Y+39\n"
368 "eor r15,__tmp_reg__\n"
372 "eor __tmp_reg__,r8\n"
374 "ldd __tmp_reg__,Z+1\n"
375 "eor __tmp_reg__,r9\n"
376 "std Z+1,__tmp_reg__\n"
377 "ldd __tmp_reg__,Z+2\n"
378 "eor __tmp_reg__,r10\n"
379 "std Z+2,__tmp_reg__\n"
380 "ldd __tmp_reg__,Z+3\n"
381 "eor __tmp_reg__,r11\n"
382 "std Z+3,__tmp_reg__\n"
383 "ldd __tmp_reg__,Z+4\n"
384 "eor __tmp_reg__,r12\n"
385 "std Z+4,__tmp_reg__\n"
386 "ldd __tmp_reg__,Z+5\n"
387 "eor __tmp_reg__,r13\n"
388 "std Z+5,__tmp_reg__\n"
389 "ldd __tmp_reg__,Z+6\n"
390 "eor __tmp_reg__,r14\n"
391 "std Z+6,__tmp_reg__\n"
392 "ldd __tmp_reg__,Z+7\n"
393 "eor __tmp_reg__,r15\n"
394 "std Z+7,__tmp_reg__\n"
399 "sbc r31,__zero_reg__\n"
416 "adc r8, __zero_reg__\n"
418 "eor r8,__tmp_reg__\n"
419 "ldd __tmp_reg__,Y+1\n"
420 "eor r9,__tmp_reg__\n"
421 "ldd __tmp_reg__,Y+2\n"
422 "eor r10,__tmp_reg__\n"
423 "ldd __tmp_reg__,Y+3\n"
424 "eor r11,__tmp_reg__\n"
425 "ldd __tmp_reg__,Y+4\n"
426 "eor r12,__tmp_reg__\n"
427 "ldd __tmp_reg__,Y+5\n"
428 "eor r13,__tmp_reg__\n"
429 "ldd __tmp_reg__,Y+6\n"
430 "eor r14,__tmp_reg__\n"
431 "ldd __tmp_reg__,Y+7\n"
432 "eor r15,__tmp_reg__\n"
436 "eor __tmp_reg__,r8\n"
438 "ldd __tmp_reg__,Z+1\n"
439 "eor __tmp_reg__,r9\n"
440 "std Z+1,__tmp_reg__\n"
441 "ldd __tmp_reg__,Z+2\n"
442 "eor __tmp_reg__,r10\n"
443 "std Z+2,__tmp_reg__\n"
444 "ldd __tmp_reg__,Z+3\n"
445 "eor __tmp_reg__,r11\n"
446 "std Z+3,__tmp_reg__\n"
447 "ldd __tmp_reg__,Z+4\n"
448 "eor __tmp_reg__,r12\n"
449 "std Z+4,__tmp_reg__\n"
450 "ldd __tmp_reg__,Z+5\n"
451 "eor __tmp_reg__,r13\n"
452 "std Z+5,__tmp_reg__\n"
453 "ldd __tmp_reg__,Z+6\n"
454 "eor __tmp_reg__,r14\n"
455 "std Z+6,__tmp_reg__\n"
456 "ldd __tmp_reg__,Z+7\n"
457 "eor __tmp_reg__,r15\n"
458 "std Z+7,__tmp_reg__\n"
463 "sbc r31,__zero_reg__\n"
480 "adc r8, __zero_reg__\n"
481 "ldd __tmp_reg__,Y+8\n"
482 "eor r8,__tmp_reg__\n"
483 "ldd __tmp_reg__,Y+9\n"
484 "eor r9,__tmp_reg__\n"
485 "ldd __tmp_reg__,Y+10\n"
486 "eor r10,__tmp_reg__\n"
487 "ldd __tmp_reg__,Y+11\n"
488 "eor r11,__tmp_reg__\n"
489 "ldd __tmp_reg__,Y+12\n"
490 "eor r12,__tmp_reg__\n"
491 "ldd __tmp_reg__,Y+13\n"
492 "eor r13,__tmp_reg__\n"
493 "ldd __tmp_reg__,Y+14\n"
494 "eor r14,__tmp_reg__\n"
495 "ldd __tmp_reg__,Y+15\n"
496 "eor r15,__tmp_reg__\n"
500 "eor __tmp_reg__,r8\n"
502 "ldd __tmp_reg__,Z+1\n"
503 "eor __tmp_reg__,r9\n"
504 "std Z+1,__tmp_reg__\n"
505 "ldd __tmp_reg__,Z+2\n"
506 "eor __tmp_reg__,r10\n"
507 "std Z+2,__tmp_reg__\n"
508 "ldd __tmp_reg__,Z+3\n"
509 "eor __tmp_reg__,r11\n"
510 "std Z+3,__tmp_reg__\n"
511 "ldd __tmp_reg__,Z+4\n"
512 "eor __tmp_reg__,r12\n"
513 "std Z+4,__tmp_reg__\n"
514 "ldd __tmp_reg__,Z+5\n"
515 "eor __tmp_reg__,r13\n"
516 "std Z+5,__tmp_reg__\n"
517 "ldd __tmp_reg__,Z+6\n"
518 "eor __tmp_reg__,r14\n"
519 "std Z+6,__tmp_reg__\n"
520 "ldd __tmp_reg__,Z+7\n"
521 "eor __tmp_reg__,r15\n"
522 "std Z+7,__tmp_reg__\n"
527 "sbc r31,__zero_reg__\n"
544 "adc r8, __zero_reg__\n"
545 "ldd __tmp_reg__,Y+16\n"
546 "eor r8,__tmp_reg__\n"
547 "ldd __tmp_reg__,Y+17\n"
548 "eor r9,__tmp_reg__\n"
549 "ldd __tmp_reg__,Y+18\n"
550 "eor r10,__tmp_reg__\n"
551 "ldd __tmp_reg__,Y+19\n"
552 "eor r11,__tmp_reg__\n"
553 "ldd __tmp_reg__,Y+20\n"
554 "eor r12,__tmp_reg__\n"
555 "ldd __tmp_reg__,Y+21\n"
556 "eor r13,__tmp_reg__\n"
557 "ldd __tmp_reg__,Y+22\n"
558 "eor r14,__tmp_reg__\n"
559 "ldd __tmp_reg__,Y+23\n"
560 "eor r15,__tmp_reg__\n"
564 "eor __tmp_reg__,r8\n"
566 "ldd __tmp_reg__,Z+1\n"
567 "eor __tmp_reg__,r9\n"
568 "std Z+1,__tmp_reg__\n"
569 "ldd __tmp_reg__,Z+2\n"
570 "eor __tmp_reg__,r10\n"
571 "std Z+2,__tmp_reg__\n"
572 "ldd __tmp_reg__,Z+3\n"
573 "eor __tmp_reg__,r11\n"
574 "std Z+3,__tmp_reg__\n"
575 "ldd __tmp_reg__,Z+4\n"
576 "eor __tmp_reg__,r12\n"
577 "std Z+4,__tmp_reg__\n"
578 "ldd __tmp_reg__,Z+5\n"
579 "eor __tmp_reg__,r13\n"
580 "std Z+5,__tmp_reg__\n"
581 "ldd __tmp_reg__,Z+6\n"
582 "eor __tmp_reg__,r14\n"
583 "std Z+6,__tmp_reg__\n"
584 "ldd __tmp_reg__,Z+7\n"
585 "eor __tmp_reg__,r15\n"
586 "std Z+7,__tmp_reg__\n"
591 "sbc r31,__zero_reg__\n"
608 "adc r8, __zero_reg__\n"
609 "ldd __tmp_reg__,Y+24\n"
610 "eor r8,__tmp_reg__\n"
611 "ldd __tmp_reg__,Y+25\n"
612 "eor r9,__tmp_reg__\n"
613 "ldd __tmp_reg__,Y+26\n"
614 "eor r10,__tmp_reg__\n"
615 "ldd __tmp_reg__,Y+27\n"
616 "eor r11,__tmp_reg__\n"
617 "ldd __tmp_reg__,Y+28\n"
618 "eor r12,__tmp_reg__\n"
619 "ldd __tmp_reg__,Y+29\n"
620 "eor r13,__tmp_reg__\n"
621 "ldd __tmp_reg__,Y+30\n"
622 "eor r14,__tmp_reg__\n"
623 "ldd __tmp_reg__,Y+31\n"
624 "eor r15,__tmp_reg__\n"
628 "eor __tmp_reg__,r8\n"
630 "ldd __tmp_reg__,Z+1\n"
631 "eor __tmp_reg__,r9\n"
632 "std Z+1,__tmp_reg__\n"
633 "ldd __tmp_reg__,Z+2\n"
634 "eor __tmp_reg__,r10\n"
635 "std Z+2,__tmp_reg__\n"
636 "ldd __tmp_reg__,Z+3\n"
637 "eor __tmp_reg__,r11\n"
638 "std Z+3,__tmp_reg__\n"
639 "ldd __tmp_reg__,Z+4\n"
640 "eor __tmp_reg__,r12\n"
641 "std Z+4,__tmp_reg__\n"
642 "ldd __tmp_reg__,Z+5\n"
643 "eor __tmp_reg__,r13\n"
644 "std Z+5,__tmp_reg__\n"
645 "ldd __tmp_reg__,Z+6\n"
646 "eor __tmp_reg__,r14\n"
647 "std Z+6,__tmp_reg__\n"
648 "ldd __tmp_reg__,Z+7\n"
649 "eor __tmp_reg__,r15\n"
650 "std Z+7,__tmp_reg__\n"
655 "sbc r31,__zero_reg__\n"
695 "adc r8, __zero_reg__\n"
704 "adc r8, __zero_reg__\n"
713 "adc r8, __zero_reg__\n"
722 "adc r8, __zero_reg__\n"
750 "adc r8, __zero_reg__\n"
778 "adc r8, __zero_reg__\n"
787 "adc r8, __zero_reg__\n"
796 "adc r8, __zero_reg__\n"
847 "sbc r27,__zero_reg__\n"
865 "adc r8, __zero_reg__\n"
874 "adc r8, __zero_reg__\n"
883 "adc r8, __zero_reg__\n"
892 "adc r8, __zero_reg__\n"
920 "adc r8, __zero_reg__\n"
929 "adc r8, __zero_reg__\n"
938 "adc r8, __zero_reg__\n"
947 "adc r8, __zero_reg__\n"
1014 "adc r8, __zero_reg__\n"
1023 "adc r8, __zero_reg__\n"
1032 "adc r8, __zero_reg__\n"
1041 "adc r8, __zero_reg__\n"
1082 "sbc r27,__zero_reg__\n"
1100 "adc r8, __zero_reg__\n"
1109 "adc r8, __zero_reg__\n"
1118 "adc r8, __zero_reg__\n"
1146 "adc r8, __zero_reg__\n"
1155 "adc r8, __zero_reg__\n"
1164 "adc r8, __zero_reg__\n"
1192 "adc r8, __zero_reg__\n"
1220 "adc r8, __zero_reg__\n"
1229 "adc r8, __zero_reg__\n"
1270 "sbc r27,__zero_reg__\n"
1434 "adc r8, __zero_reg__\n"
1446 "sbc r27,__zero_reg__\n"
1552 "adc r8, __zero_reg__\n"
1561 "adc r8, __zero_reg__\n"
1608 "adc r8, __zero_reg__\n"
1617 "adc r8, __zero_reg__\n"
1627 "sbc r27,__zero_reg__\n"
1629 "sbc r31,__zero_reg__\n"
1884 : :
"x"(B),
"z"(state.A)
1885 :
"r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15",
1886 "r16",
"r17",
"r18",
"r19",
"r20",
"r21",
"memory"
1889 static const uint8_t addMod5Table[9] PROGMEM = {
1890 0, 1, 2, 3, 4, 0, 1, 2, 3
1892 #define addMod5(x, y) (pgm_read_byte(&(addMod5Table[(x) + (y)])))
1894 uint8_t index, index2;
1895 for (uint8_t round = 0; round < 24; ++round) {
1899 for (index = 0; index < 5; ++index) {
1900 B[0][index] = state.A[0][index] ^ state.A[1][index] ^
1901 state.A[2][index] ^ state.A[3][index] ^
1904 for (index = 0; index < 5; ++index) {
1905 D = B[0][addMod5(index, 4)] ^
1906 leftRotate1_64(B[0][addMod5(index, 1)]);
1907 for (index2 = 0; index2 < 5; ++index2)
1908 state.A[index2][index] ^= D;
1913 B[0][0] = state.A[0][0];
1914 B[1][0] = leftRotate28_64(state.A[0][3]);
1915 B[2][0] = leftRotate1_64 (state.A[0][1]);
1916 B[3][0] = leftRotate27_64(state.A[0][4]);
1917 B[4][0] = leftRotate62_64(state.A[0][2]);
1918 B[0][1] = leftRotate44_64(state.A[1][1]);
1919 B[1][1] = leftRotate20_64(state.A[1][4]);
1920 B[2][1] = leftRotate6_64 (state.A[1][2]);
1921 B[3][1] = leftRotate36_64(state.A[1][0]);
1922 B[4][1] = leftRotate55_64(state.A[1][3]);
1923 B[0][2] = leftRotate43_64(state.A[2][2]);
1924 B[1][2] = leftRotate3_64 (state.A[2][0]);
1925 B[2][2] = leftRotate25_64(state.A[2][3]);
1926 B[3][2] = leftRotate10_64(state.A[2][1]);
1927 B[4][2] = leftRotate39_64(state.A[2][4]);
1928 B[0][3] = leftRotate21_64(state.A[3][3]);
1929 B[1][3] = leftRotate45_64(state.A[3][1]);
1930 B[2][3] = leftRotate8_64 (state.A[3][4]);
1931 B[3][3] = leftRotate15_64(state.A[3][2]);
1932 B[4][3] = leftRotate41_64(state.A[3][0]);
1933 B[0][4] = leftRotate14_64(state.A[4][4]);
1934 B[1][4] = leftRotate61_64(state.A[4][2]);
1935 B[2][4] = leftRotate18_64(state.A[4][0]);
1936 B[3][4] = leftRotate56_64(state.A[4][3]);
1937 B[4][4] = leftRotate2_64 (state.A[4][1]);
1940 for (index = 0; index < 5; ++index) {
1941 for (index2 = 0; index2 < 5; ++index2) {
1942 state.A[index2][index] =
1944 ((~B[index2][addMod5(index, 1)]) &
1945 B[index2][addMod5(index, 2)]);
1951 static uint64_t
const RC[24] PROGMEM = {
1952 0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808AULL,
1953 0x8000000080008000ULL, 0x000000000000808BULL, 0x0000000080000001ULL,
1954 0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008AULL,
1955 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000AULL,
1956 0x000000008000808BULL, 0x800000000000008BULL, 0x8000000000008089ULL,
1957 0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
1958 0x000000000000800AULL, 0x800000008000000AULL, 0x8000000080008081ULL,
1959 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
1961 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.