keccak-tiny-unrolled.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  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 <string.h>
  11. #include "crypto.h"
  12. /******** The Keccak-f[1600] permutation ********/
  13. /*** Constants. ***/
  14. static const uint8_t rho[24] = \
  15. { 1, 3, 6, 10, 15, 21,
  16. 28, 36, 45, 55, 2, 14,
  17. 27, 41, 56, 8, 25, 43,
  18. 62, 18, 39, 61, 20, 44};
  19. static const uint8_t pi[24] = \
  20. {10, 7, 11, 17, 18, 3,
  21. 5, 16, 8, 21, 24, 4,
  22. 15, 23, 19, 13, 12, 2,
  23. 20, 14, 22, 9, 6, 1};
  24. static const uint64_t RC[24] = \
  25. {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL,
  26. 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL,
  27. 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL,
  28. 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL,
  29. 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL,
  30. 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL};
  31. /*** Helper macros to unroll the permutation. ***/
  32. #define rol(x, s) (((x) << s) | ((x) >> (64 - s)))
  33. #define REPEAT6(e) e e e e e e
  34. #define REPEAT24(e) REPEAT6(e e e e)
  35. #define REPEAT5(e) e e e e e
  36. #define FOR5(v, s, e) \
  37. v = 0; \
  38. REPEAT5(e; v += s;)
  39. /*** Keccak-f[1600] ***/
  40. static inline void keccakf(void* state) {
  41. uint64_t* a = (uint64_t*)state;
  42. uint64_t b[5] = {0};
  43. uint64_t t = 0;
  44. uint8_t x, y, i = 0;
  45. REPEAT24(
  46. // Theta
  47. FOR5(x, 1,
  48. b[x] = 0;
  49. FOR5(y, 5,
  50. b[x] ^= a[x + y]; ))
  51. FOR5(x, 1,
  52. FOR5(y, 5,
  53. a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); ))
  54. // Rho and pi
  55. t = a[1];
  56. x = 0;
  57. REPEAT24(b[0] = a[pi[x]];
  58. a[pi[x]] = rol(t, rho[x]);
  59. t = b[0];
  60. x++; )
  61. // Chi
  62. FOR5(y,
  63. 5,
  64. FOR5(x, 1,
  65. b[x] = a[y + x];)
  66. FOR5(x, 1,
  67. a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); ))
  68. // Iota
  69. a[0] ^= RC[i];
  70. i++; )
  71. }
  72. /******** The FIPS202-defined functions. ********/
  73. /*** Some helper macros. ***/
  74. #define _(S) do { S } while (0)
  75. #define FOR(i, ST, L, S) \
  76. _(for (size_t i = 0; i < L; i += ST) { S; })
  77. #define mkapply_ds(NAME, S) \
  78. static inline void NAME(uint8_t* dst, \
  79. const uint8_t* src, \
  80. size_t len) { \
  81. FOR(i, 1, len, S); \
  82. }
  83. #define mkapply_sd(NAME, S) \
  84. static inline void NAME(const uint8_t* src, \
  85. uint8_t* dst, \
  86. size_t len) { \
  87. FOR(i, 1, len, S); \
  88. }
  89. mkapply_ds(xorin, dst[i] ^= src[i]) // xorin
  90. mkapply_sd(setout, dst[i] = src[i]) // setout
  91. #define P keccakf
  92. #define Plen KECCAK_MAX_RATE
  93. #define KECCAK_DELIM_DIGEST 0x06
  94. #define KECCAK_DELIM_XOF 0x1f
  95. // Fold P*F over the full blocks of an input.
  96. #define foldP(I, L, F) \
  97. while (L >= s->rate) { \
  98. F(s->a, I, s->rate); \
  99. P(s->a); \
  100. I += s->rate; \
  101. L -= s->rate; \
  102. }
  103. static inline void
  104. keccak_absorb_blocks(keccak_state *s, const uint8_t *buf, size_t nr_blocks)
  105. {
  106. size_t blen = nr_blocks * s->rate;
  107. foldP(buf, blen, xorin);
  108. }
  109. static int
  110. keccak_update(keccak_state *s, const uint8_t *buf, size_t len)
  111. {
  112. if (s->finalized)
  113. return -1;
  114. if ((buf == NULL) && len != 0)
  115. return -1;
  116. size_t remaining = len;
  117. while (remaining > 0) {
  118. if (s->offset == 0) {
  119. const size_t blocks = remaining / s->rate;
  120. size_t direct_bytes = blocks * s->rate;
  121. if (direct_bytes > 0) {
  122. keccak_absorb_blocks(s, buf, blocks);
  123. remaining -= direct_bytes;
  124. buf += direct_bytes;
  125. }
  126. }
  127. const size_t buf_avail = s->rate - s->offset;
  128. const size_t buf_bytes = (buf_avail > remaining) ? remaining : buf_avail;
  129. if (buf_bytes > 0) {
  130. memcpy(&s->block[s->offset], buf, buf_bytes);
  131. s->offset += buf_bytes;
  132. remaining -= buf_bytes;
  133. buf += buf_bytes;
  134. }
  135. if (s->offset == s->rate) {
  136. keccak_absorb_blocks(s, s->block, 1);
  137. s->offset = 0;
  138. }
  139. }
  140. return 0;
  141. }
  142. static void
  143. keccak_finalize(keccak_state *s)
  144. {
  145. // Xor in the DS and pad frame.
  146. s->a[s->offset] ^= s->delim;
  147. s->a[s->rate - 1] ^= 0x80;
  148. // Xor in the last block.
  149. xorin(s->a, s->block, s->offset);
  150. memwipe(s->block, 0, sizeof(s->block));
  151. s->finalized = 1;
  152. s->offset = s->rate;
  153. }
  154. static inline void
  155. keccak_squeeze_blocks(keccak_state *s, uint8_t *out, size_t nr_blocks)
  156. {
  157. for (size_t n = 0; n < nr_blocks; n++) {
  158. keccakf(s->a);
  159. setout(s->a, out, s->rate);
  160. out += s->rate;
  161. }
  162. }
  163. static int
  164. keccak_squeeze(keccak_state *s, uint8_t *out, size_t outlen)
  165. {
  166. if (!s->finalized)
  167. return -1;
  168. size_t remaining = outlen;
  169. while (remaining > 0) {
  170. if (s->offset == s->rate) {
  171. const size_t blocks = remaining / s->rate;
  172. const size_t direct_bytes = blocks * s->rate;
  173. if (blocks > 0) {
  174. keccak_squeeze_blocks(s, out, blocks);
  175. out += direct_bytes;
  176. remaining -= direct_bytes;
  177. }
  178. if (remaining > 0) {
  179. keccak_squeeze_blocks(s, s->block, 1);
  180. s->offset = 0;
  181. }
  182. }
  183. const size_t buf_bytes = s->rate - s->offset;
  184. const size_t indirect_bytes = (buf_bytes > remaining) ? remaining : buf_bytes;
  185. if (indirect_bytes > 0) {
  186. memcpy(out, &s->block[s->offset], indirect_bytes);
  187. out += indirect_bytes;
  188. s->offset += indirect_bytes;
  189. remaining -= indirect_bytes;
  190. }
  191. }
  192. return 0;
  193. }
  194. int
  195. keccak_digest_init(keccak_state *s, size_t bits)
  196. {
  197. if (s == NULL)
  198. return -1;
  199. if (bits != 224 && bits != 256 && bits != 384 && bits != 512)
  200. return -1;
  201. keccak_cleanse(s);
  202. s->rate = KECCAK_RATE(bits);
  203. s->delim = KECCAK_DELIM_DIGEST;
  204. return 0;
  205. }
  206. int
  207. keccak_digest_update(keccak_state *s, const uint8_t *buf, size_t len)
  208. {
  209. if (s == NULL)
  210. return -1;
  211. if (s->delim != KECCAK_DELIM_DIGEST)
  212. return -1;
  213. return keccak_update(s, buf, len);
  214. }
  215. int
  216. keccak_digest_sum(const keccak_state *s, uint8_t *out, size_t outlen)
  217. {
  218. if (s == NULL)
  219. return -1;
  220. if (s->delim != KECCAK_DELIM_DIGEST)
  221. return -1;
  222. if (out == NULL || outlen > 4 * (KECCAK_MAX_RATE - s->rate) / 8)
  223. return -1;
  224. // Work in a copy so that incremental/rolling hashes are easy.
  225. keccak_state s_tmp;
  226. keccak_clone(&s_tmp, s);
  227. keccak_finalize(&s_tmp);
  228. int ret = keccak_squeeze(&s_tmp, out, outlen);
  229. keccak_cleanse(&s_tmp);
  230. return ret;
  231. }
  232. int
  233. keccak_xof_init(keccak_state *s, size_t bits)
  234. {
  235. if (s == NULL)
  236. return -1;
  237. if (bits != 128 && bits != 256)
  238. return -1;
  239. keccak_cleanse(s);
  240. s->rate = KECCAK_RATE(bits);
  241. s->delim = KECCAK_DELIM_XOF;
  242. return 0;
  243. }
  244. int
  245. keccak_xof_absorb(keccak_state *s, const uint8_t *buf, size_t len)
  246. {
  247. if (s == NULL)
  248. return -1;
  249. if (s->delim != KECCAK_DELIM_XOF)
  250. return -1;
  251. return keccak_update(s, buf, len);
  252. }
  253. int
  254. keccak_xof_squeeze(keccak_state *s, uint8_t *out, size_t outlen)
  255. {
  256. if (s == NULL)
  257. return -1;
  258. if (s->delim != KECCAK_DELIM_XOF)
  259. return -1;
  260. if (!s->finalized)
  261. keccak_finalize(s);
  262. return keccak_squeeze(s, out, outlen);
  263. }
  264. void
  265. keccak_clone(keccak_state *out, const keccak_state *in)
  266. {
  267. memcpy(out, in, sizeof(keccak_state));
  268. }
  269. void
  270. keccak_cleanse(keccak_state *s)
  271. {
  272. memwipe(s, 0, sizeof(keccak_state));
  273. }
  274. /** The sponge-based hash construction. **/
  275. static inline int hash(uint8_t* out, size_t outlen,
  276. const uint8_t* in, size_t inlen,
  277. size_t bits, uint8_t delim) {
  278. if ((out == NULL) || ((in == NULL) && inlen != 0)) {
  279. return -1;
  280. }
  281. int ret = 0;
  282. keccak_state s;
  283. switch (delim) {
  284. case KECCAK_DELIM_DIGEST:
  285. ret |= keccak_digest_init(&s, bits);
  286. ret |= keccak_digest_update(&s, in, inlen);
  287. // Use the internal API instead of sum to avoid the memcpy.
  288. keccak_finalize(&s);
  289. ret |= keccak_squeeze(&s, out, outlen);
  290. break;
  291. case KECCAK_DELIM_XOF:
  292. ret |= keccak_xof_init(&s, bits);
  293. ret |= keccak_xof_absorb(&s, in, inlen);
  294. ret |= keccak_xof_squeeze(&s, out, outlen);
  295. break;
  296. default:
  297. return -1;
  298. }
  299. keccak_cleanse(&s);
  300. return ret;
  301. }
  302. /*** Helper macros to define SHA3 and SHAKE instances. ***/
  303. #define defshake(bits) \
  304. int shake##bits(uint8_t* out, size_t outlen, \
  305. const uint8_t* in, size_t inlen) { \
  306. return hash(out, outlen, in, inlen, bits, KECCAK_DELIM_XOF); \
  307. }
  308. #define defsha3(bits) \
  309. int sha3_##bits(uint8_t* out, size_t outlen, \
  310. const uint8_t* in, size_t inlen) { \
  311. if (outlen > (bits/8)) { \
  312. return -1; \
  313. } \
  314. return hash(out, outlen, in, inlen, bits, KECCAK_DELIM_DIGEST); \
  315. }
  316. /*** FIPS202 SHAKE VOFs ***/
  317. defshake(128)
  318. defshake(256)
  319. /*** FIPS202 SHA3 FOFs ***/
  320. defsha3(224)
  321. defsha3(256)
  322. defsha3(384)
  323. defsha3(512)