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