keccak-tiny.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /** libkeccak-tiny
  2. *
  3. * A single-file implementation of SHA-3 and SHAKE.
  4. *
  5. * Implementor: David Leon Gil
  6. * License: CC0, attribution kindly requested. Blame taken too,
  7. * but not liability.
  8. */
  9. #include "keccak-tiny.h"
  10. #include <stdint.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. /******** The Keccak-f[1600] permutation ********/
  15. /*** Constants. ***/
  16. static const uint8_t rho[24] = \
  17. { 1, 3, 6, 10, 15, 21,
  18. 28, 36, 45, 55, 2, 14,
  19. 27, 41, 56, 8, 25, 43,
  20. 62, 18, 39, 61, 20, 44};
  21. static const uint8_t pi[24] = \
  22. {10, 7, 11, 17, 18, 3,
  23. 5, 16, 8, 21, 24, 4,
  24. 15, 23, 19, 13, 12, 2,
  25. 20, 14, 22, 9, 6, 1};
  26. static const uint64_t RC[24] = \
  27. {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL,
  28. 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL,
  29. 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL,
  30. 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL,
  31. 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL,
  32. 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL};
  33. /*** Helper macros to unroll the permutation. ***/
  34. #define rol(x, s) (((x) << s) | ((x) >> (64 - s)))
  35. #define REPEAT6(e) e e e e e e
  36. #define REPEAT24(e) REPEAT6(e e e e)
  37. #define REPEAT5(e) e e e e e
  38. #define FOR5(v, s, e) \
  39. v = 0; \
  40. REPEAT5(e; v += s;)
  41. /*** Keccak-f[1600] ***/
  42. static inline void keccakf(void* state) {
  43. uint64_t* a = (uint64_t*)state;
  44. uint64_t b[5] = {0};
  45. uint64_t t = 0;
  46. uint8_t x, y;
  47. for (int i = 0; i < 24; i++) {
  48. // Theta
  49. FOR5(x, 1,
  50. b[x] = 0;
  51. FOR5(y, 5,
  52. b[x] ^= a[x + y]; ))
  53. FOR5(x, 1,
  54. FOR5(y, 5,
  55. a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); ))
  56. // Rho and pi
  57. t = a[1];
  58. x = 0;
  59. REPEAT24(b[0] = a[pi[x]];
  60. a[pi[x]] = rol(t, rho[x]);
  61. t = b[0];
  62. x++; )
  63. // Chi
  64. FOR5(y,
  65. 5,
  66. FOR5(x, 1,
  67. b[x] = a[y + x];)
  68. FOR5(x, 1,
  69. a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); ))
  70. // Iota
  71. a[0] ^= RC[i];
  72. }
  73. }
  74. /******** The FIPS202-defined functions. ********/
  75. /*** Some helper macros. ***/
  76. #define _(S) do { S } while (0)
  77. #define FOR(i, ST, L, S) \
  78. _(for (size_t i = 0; i < L; i += ST) { S; })
  79. #define mkapply_ds(NAME, S) \
  80. static inline void NAME(uint8_t* dst, \
  81. const uint8_t* src, \
  82. size_t len) { \
  83. FOR(i, 1, len, S); \
  84. }
  85. #define mkapply_sd(NAME, S) \
  86. static inline void NAME(const uint8_t* src, \
  87. uint8_t* dst, \
  88. size_t len) { \
  89. FOR(i, 1, len, S); \
  90. }
  91. mkapply_ds(xorin, dst[i] ^= src[i]) // xorin
  92. mkapply_sd(setout, dst[i] = src[i]) // setout
  93. #define P keccakf
  94. #define Plen 200
  95. // Fold P*F over the full blocks of an input.
  96. #define foldP(I, L, F) \
  97. while (L >= rate) { \
  98. F(a, I, rate); \
  99. P(a); \
  100. I += rate; \
  101. L -= rate; \
  102. }
  103. /** The sponge-based hash construction. **/
  104. static inline int hash(uint8_t* out, size_t outlen,
  105. const uint8_t* in, size_t inlen,
  106. size_t rate, uint8_t delim) {
  107. if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) {
  108. return -1;
  109. }
  110. uint8_t a[Plen] = {0};
  111. // Absorb input.
  112. foldP(in, inlen, xorin);
  113. // Xor in the DS and pad frame.
  114. a[inlen] ^= delim;
  115. a[rate - 1] ^= 0x80;
  116. // Xor in the last block.
  117. xorin(a, in, inlen);
  118. // Apply P
  119. P(a);
  120. // Squeeze output.
  121. foldP(out, outlen, setout);
  122. setout(a, out, outlen);
  123. memset_s(a, 200, 0, 200);
  124. return 0;
  125. }
  126. /*** Helper macros to define SHA3 and SHAKE instances. ***/
  127. #define defshake(bits) \
  128. int shake##bits(uint8_t* out, size_t outlen, \
  129. const uint8_t* in, size_t inlen) { \
  130. return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x1f); \
  131. }
  132. #define defsha3(bits) \
  133. int sha3_##bits(uint8_t* out, size_t outlen, \
  134. const uint8_t* in, size_t inlen) { \
  135. if (outlen > (bits/8)) { \
  136. return -1; \
  137. } \
  138. return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x06); \
  139. }
  140. /*** FIPS202 SHAKE VOFs ***/
  141. defshake(128)
  142. defshake(256)
  143. /*** FIPS202 SHA3 FOFs ***/
  144. defsha3(224)
  145. defsha3(256)
  146. defsha3(384)
  147. defsha3(512)