Add sha3 implementation, introduce version-2 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 /*
17  * Note for osl
18  * ~~~~~~~~~~~~
19  * This is NOT the hash function which will eventually be part of an osl
20  * release. It will be replaced by whatever git comes up as the successor of
21  * sha1. This hash function is FOR TESTING ONLY.
22  */
23
24 #define FOR(i,n) for(i=0; i<n; ++i)
25 typedef unsigned char u8;
26 typedef unsigned long long int u64;
27 typedef unsigned int ui;
28
29 static int LFSR86540(u8 *R)
30 {
31         *R = ((*R) << 1) ^ (((*R) & 0x80)? 0x71 : 0);
32         return ((*R) & 2 ) >> 1;
33 }
34
35 static u64 load64(const u8 *x)
36 {
37         ui i;
38         u64 u = 0;
39
40         FOR(i, 8) {
41                 u <<= 8;
42                 u |= x[7 - i];
43         }
44         return u;
45 }
46
47 static void store64(u8 *x, u64 u)
48 {
49         ui i;
50
51         FOR(i, 8) {
52                 x[i] = u;
53                 u >>= 8;
54         }
55 }
56
57 static void xor64(u8 *x, u64 u)
58 {
59         ui i;
60         FOR(i, 8) {
61                 x[i] ^= u;
62                 u >>= 8;
63         }
64 }
65
66 #define rL(x, y) load64((u8*)s + 8 * (x + 5 * y))
67 #define wL(x, y, l) store64((u8*)s + 8 * (x + 5 * y), l)
68 #define XL(x, y, l) xor64((u8*)s + 8 * (x + 5 * y), l)
69 #define ROL(a, o) ((((u64)a) << o) ^ (((u64)a) >> (64 - o)))
70
71 static void KeccakF1600(void *s)
72 {
73         ui r, x, y, i, j, Y;
74         u8 R = 0x01;
75         u64 C[5], D;
76
77         for (i = 0; i < 24; i++) {
78                 FOR(x, 5)
79                         C[x] = rL(x, 0) ^ rL(x, 1) ^ rL(x, 2) ^ rL(x, 3) ^ rL(x, 4);
80                 FOR(x, 5) {
81                         D = C[(x + 4) % 5] ^ ROL(C[(x + 1) % 5], 1);
82                         FOR(y, 5)
83                                 XL(x, y, D);
84                 }
85                 x = 1;
86                 y = r = 0;
87                 D = rL(x, y);
88                 FOR(j, 24) {
89                         r += j + 1;
90                         Y = (2 * x + 3 * y) % 5;
91                         x = y;
92                         y = Y;
93                         C[0] = rL(x, y);
94                         wL(x, y, ROL(D, r % 64));
95                         D = C[0];
96                 }
97                 FOR(y, 5) {
98                         FOR(x, 5)
99                                 C[x] = rL(x, y);
100                         FOR(x, 5)
101                                 wL(x, y, C[x] ^ ((~C[(x + 1) % 5]) & C[(x + 2) % 5]));
102                 }
103                 FOR(j, 7)
104                         if (LFSR86540(&R))
105                                 XL(0, 0, (u64)1 << ((1 << j) - 1));
106         }
107 }
108
109 static void Keccak(ui r, const u8 *in, u64 inLen, u8 sfx, u8 *out, u64 outLen)
110 {
111         u8 s[200];
112         ui R = r / 8;
113         ui i, b = 0;
114
115         FOR(i, 200)
116                 s[i] = 0;
117         /* absorb */
118         while (inLen > 0) {
119                 b = (inLen < R)? inLen : R;
120                 FOR(i, b)
121                         s[i] ^= in[i];
122                 in += b;
123                 inLen -= b;
124                 if (b == R) {
125                         KeccakF1600(s);
126                         b = 0;
127                 }
128         }
129         /* pad */
130         s[b] ^= sfx;
131         if ((sfx & 0x80) && (b == (R - 1)))
132                 KeccakF1600(s);
133         s[R - 1] ^= 0x80;
134         KeccakF1600(s);
135         /* squeeze */
136         while (outLen > 0) {
137                 b = (outLen < R)? outLen : R;
138                 FOR(i, b)
139                         out[i] = s[i];
140                 out += b;
141                 outLen -= b;
142                 if (outLen > 0)
143                         KeccakF1600(s);
144         }
145 }
146
147 /**
148  * Compute the hash value for osl version 2 tables.
149  *
150  * \param data Pointer to the data to compute the hash value from.
151  * \param len The length of \a data in bytes.
152  * \param result must point to an area at least 20 bytes large.
153  */
154 void sha3_hash(const char *data, unsigned long len, unsigned char *result)
155 {
156          Keccak(1152, (const u8*)data, len, 0x06, result, 20);
157 }