Version 3 tables.
[osl.git] / sha3.c
1 /*
2 Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
3 Joan Daemen, Michaƫl Peeters, Gilles Van Assche and Ronny Van Keer, hereby
4 denoted as "the implementer".
5
6 For more information, feedback or questions, please refer to our websites:
7 http://keccak.noekeon.org/
8 http://keyak.noekeon.org/
9 http://ketje.noekeon.org/
10
11 To the extent possible under law, the implementer has waived all copyright
12 and related or neighboring rights to the source code in this file.
13 http://creativecommons.org/publicdomain/zero/1.0/
14 */
15
16 #define FOR(i,n) for(i=0; i<n; ++i)
17 typedef unsigned char u8;
18 typedef unsigned long long int u64;
19 typedef unsigned int ui;
20
21 static int LFSR86540(u8 *R)
22 {
23 *R = ((*R) << 1) ^ (((*R) & 0x80)? 0x71 : 0);
24 return ((*R) & 2 ) >> 1;
25 }
26
27 static u64 load64(const u8 *x)
28 {
29 ui i;
30 u64 u = 0;
31
32 FOR(i, 8) {
33 u <<= 8;
34 u |= x[7 - i];
35 }
36 return u;
37 }
38
39 static void store64(u8 *x, u64 u)
40 {
41 ui i;
42
43 FOR(i, 8) {
44 x[i] = u;
45 u >>= 8;
46 }
47 }
48
49 static void xor64(u8 *x, u64 u)
50 {
51 ui i;
52 FOR(i, 8) {
53 x[i] ^= u;
54 u >>= 8;
55 }
56 }
57
58 #define rL(x, y) load64((u8*)s + 8 * (x + 5 * y))
59 #define wL(x, y, l) store64((u8*)s + 8 * (x + 5 * y), l)
60 #define XL(x, y, l) xor64((u8*)s + 8 * (x + 5 * y), l)
61 #define ROL(a, o) ((((u64)a) << o) ^ (((u64)a) >> (64 - o)))
62
63 static void KeccakF1600(void *s)
64 {
65 ui r, x, y, i, j, Y;
66 u8 R = 0x01;
67 u64 C[5], D;
68
69 for (i = 0; i < 24; i++) {
70 FOR(x, 5)
71 C[x] = rL(x, 0) ^ rL(x, 1) ^ rL(x, 2) ^ rL(x, 3) ^ rL(x, 4);
72 FOR(x, 5) {
73 D = C[(x + 4) % 5] ^ ROL(C[(x + 1) % 5], 1);
74 FOR(y, 5)
75 XL(x, y, D);
76 }
77 x = 1;
78 y = r = 0;
79 D = rL(x, y);
80 FOR(j, 24) {
81 r += j + 1;
82 Y = (2 * x + 3 * y) % 5;
83 x = y;
84 y = Y;
85 C[0] = rL(x, y);
86 wL(x, y, ROL(D, r % 64));
87 D = C[0];
88 }
89 FOR(y, 5) {
90 FOR(x, 5)
91 C[x] = rL(x, y);
92 FOR(x, 5)
93 wL(x, y, C[x] ^ ((~C[(x + 1) % 5]) & C[(x + 2) % 5]));
94 }
95 FOR(j, 7)
96 if (LFSR86540(&R))
97 XL(0, 0, (u64)1 << ((1 << j) - 1));
98 }
99 }
100
101 static void Keccak(ui r, const u8 *in, u64 inLen, u8 sfx, u8 *out, u64 outLen)
102 {
103 u8 s[200];
104 ui R = r / 8;
105 ui i, b = 0;
106
107 FOR(i, 200)
108 s[i] = 0;
109 /* absorb */
110 while (inLen > 0) {
111 b = (inLen < R)? inLen : R;
112 FOR(i, b)
113 s[i] ^= in[i];
114 in += b;
115 inLen -= b;
116 if (b == R) {
117 KeccakF1600(s);
118 b = 0;
119 }
120 }
121 /* pad */
122 s[b] ^= sfx;
123 if ((sfx & 0x80) && (b == (R - 1)))
124 KeccakF1600(s);
125 s[R - 1] ^= 0x80;
126 KeccakF1600(s);
127 /* squeeze */
128 while (outLen > 0) {
129 b = (outLen < R)? outLen : R;
130 FOR(i, b)
131 out[i] = s[i];
132 out += b;
133 outLen -= b;
134 if (outLen > 0)
135 KeccakF1600(s);
136 }
137 }
138
139 /**
140 * Compute the hash value for osl version 2 tables.
141 *
142 * \param data Pointer to the data to compute the hash value from.
143 * \param len The length of \a data in bytes.
144 * \param result must point to an area at least 20 bytes large.
145 */
146 void sha3_hash(const char *data, unsigned long len, unsigned char *result)
147 {
148 Keccak(1152, (const u8*)data, len, 0x06, result, 20);
149 }