9#include "keccak-tiny.h"
18loadu64le(
const unsigned char *x) {
20 memcpy(&r, x,
sizeof(r));
25storeu64le(uint8_t *x, uint64_t u) {
26 uint64_t val = _le64toh(u);
27 memcpy(x, &val,
sizeof(u));
33static const uint8_t rho[24] = \
34 { 1, 3, 6, 10, 15, 21,
35 28, 36, 45, 55, 2, 14,
36 27, 41, 56, 8, 25, 43,
37 62, 18, 39, 61, 20, 44};
38static const uint8_t pi[24] = \
39 {10, 7, 11, 17, 18, 3,
41 15, 23, 19, 13, 12, 2,
43static const uint64_t RC[24] = \
44 {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL,
45 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL,
46 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL,
47 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL,
48 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL,
49 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL};
52#define rol(x, s) (((x) << s) | ((x) >> (64 - s)))
53#define REPEAT6(e) e e e e e e
54#define REPEAT24(e) REPEAT6(e e e e)
55#define REPEAT5(e) e e e e e
56#define FOR5(v, s, e) \
61static inline void keccakf(
void* state) {
62 uint64_t* a = (uint64_t*)state;
75 a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); ))
79 REPEAT24(b[0] = a[pi[x]];
80 a[pi[x]] = rol(t, rho[x]);
89 a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); ))
103xorin8(uint8_t *dst, const uint8_t *src,
size_t len) {
104 uint64_t* a = (uint64_t*)dst;
105 for (
size_t i = 0; i < len; i += 8) {
106 a[i/8] ^= loadu64le(src + i);
113setout8(
const uint8_t *src, uint8_t *dst,
size_t len) {
114 const uint64_t *si = (
const uint64_t*)src;
115 for (
size_t i = 0; i < len; i+= 8) {
116 storeu64le(dst+i, si[i/8]);
121#define Plen KECCAK_MAX_RATE
123#define KECCAK_DELIM_DIGEST 0x06
124#define KECCAK_DELIM_XOF 0x1f
127#define foldP(I, L, F) \
128 while (L >= s->rate) { \
129 F(s->a, I, s->rate); \
136keccak_absorb_blocks(
keccak_state *s,
const uint8_t *buf,
size_t nr_blocks)
138 size_t blen = nr_blocks * s->rate;
139 foldP(buf, blen, xorin8);
143keccak_update(
keccak_state *s,
const uint8_t *buf,
size_t len)
147 if ((buf == NULL) && len != 0)
150 size_t remaining = len;
151 while (remaining > 0) {
152 if (s->offset == 0) {
153 const size_t blocks = remaining / s->rate;
154 size_t direct_bytes = blocks * s->rate;
155 if (direct_bytes > 0) {
156 keccak_absorb_blocks(s, buf, blocks);
157 remaining -= direct_bytes;
162 const size_t buf_avail = s->rate - s->offset;
163 const size_t buf_bytes = (buf_avail > remaining) ? remaining : buf_avail;
165 memcpy(&s->block[s->offset], buf, buf_bytes);
166 s->offset += buf_bytes;
167 remaining -= buf_bytes;
170 if (s->offset == s->rate) {
171 keccak_absorb_blocks(s, s->block, 1);
182 s->block[s->offset++] = s->delim;
183 for (
size_t i = s->offset; i < s->rate; i++) {
186 s->block[s->rate - 1] |= 0x80;
189 xorin8(s->a, s->block, s->rate);
191 memwipe(s->block, 0,
sizeof(s->block));
197keccak_squeeze_blocks(
keccak_state *s, uint8_t *out,
size_t nr_blocks)
199 for (
size_t n = 0; n < nr_blocks; n++) {
201 setout8(s->a, out, s->rate);
207keccak_squeeze(
keccak_state *s, uint8_t *out,
size_t outlen)
212 size_t remaining = outlen;
213 while (remaining > 0) {
214 if (s->offset == s->rate) {
215 const size_t blocks = remaining / s->rate;
216 const size_t direct_bytes = blocks * s->rate;
218 keccak_squeeze_blocks(s, out, blocks);
220 remaining -= direct_bytes;
224 keccak_squeeze_blocks(s, s->block, 1);
229 const size_t buf_bytes = s->rate - s->offset;
230 const size_t indirect_bytes = (buf_bytes > remaining) ? remaining : buf_bytes;
231 if (indirect_bytes > 0) {
232 memcpy(out, &s->block[s->offset], indirect_bytes);
233 out += indirect_bytes;
234 s->offset += indirect_bytes;
235 remaining -= indirect_bytes;
246 if (bits != 224 && bits != 256 && bits != 384 && bits != 512)
250 s->rate = KECCAK_RATE(bits);
251 s->delim = KECCAK_DELIM_DIGEST;
256keccak_digest_update(
keccak_state *s,
const uint8_t *buf,
size_t len)
260 if (s->delim != KECCAK_DELIM_DIGEST)
263 return keccak_update(s, buf, len);
267keccak_digest_sum(
const keccak_state *s, uint8_t *out,
size_t outlen)
271 if (s->delim != KECCAK_DELIM_DIGEST)
273 if (out == NULL || outlen > 4 * (KECCAK_MAX_RATE - s->rate) / 8)
278 keccak_clone(&s_tmp, s);
279 keccak_finalize(&s_tmp);
280 int ret = keccak_squeeze(&s_tmp, out, outlen);
281 keccak_cleanse(&s_tmp);
290 if (bits != 128 && bits != 256)
294 s->rate = KECCAK_RATE(bits);
295 s->delim = KECCAK_DELIM_XOF;
300keccak_xof_absorb(
keccak_state *s,
const uint8_t *buf,
size_t len)
304 if (s->delim != KECCAK_DELIM_XOF)
307 return keccak_update(s, buf, len);
311keccak_xof_squeeze(
keccak_state *s, uint8_t *out,
size_t outlen)
315 if (s->delim != KECCAK_DELIM_XOF)
321 return keccak_squeeze(s, out, outlen);
337static inline int hash(uint8_t* out,
size_t outlen,
338 const uint8_t* in,
size_t inlen,
339 size_t bits, uint8_t delim) {
340 if ((out == NULL) || ((in == NULL) && inlen != 0)) {
349 case KECCAK_DELIM_DIGEST:
350 ret |= keccak_digest_init(&s, bits);
351 ret |= keccak_digest_update(&s, in, inlen);
354 ret |= keccak_squeeze(&s, out, outlen);
356 case KECCAK_DELIM_XOF:
357 ret |= keccak_xof_init(&s, bits);
358 ret |= keccak_xof_absorb(&s, in, inlen);
359 ret |= keccak_xof_squeeze(&s, out, outlen);
369#define defshake(bits) \
370 int shake##bits(uint8_t* out, size_t outlen, \
371 const uint8_t* in, size_t inlen) { \
372 return hash(out, outlen, in, inlen, bits, KECCAK_DELIM_XOF); \
374#define defsha3(bits) \
375 int sha3_##bits(uint8_t* out, size_t outlen, \
376 const uint8_t* in, size_t inlen) { \
377 if (outlen > (bits/8)) { \
380 return hash(out, outlen, in, inlen, bits, KECCAK_DELIM_DIGEST); \
void memwipe(void *mem, uint8_t byte, size_t sz)
Common functions for cryptographic routines.