import C keccak implementation taken from NIST reference
[mobile-com.git] / DH-Keccak / assets / KremKeccak / KeccakF-1600-reference.c
1 /*
2 The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
3 Michaƫl Peeters and Gilles Van Assche. For more information, feedback or
4 questions, please refer to our website: http://keccak.noekeon.org/
5
6 Implementation by the designers,
7 hereby denoted as "the implementer".
8
9 To the extent possible under law, the implementer has waived all copyright
10 and related or neighboring rights to the source code in this file.
11 http://creativecommons.org/publicdomain/zero/1.0/
12 */
13
14 #include <stdio.h>
15 #include <string.h>
16 #include "brg_endian.h"
17 #include "displayIntermediateValues.h"
18 #include "KeccakNISTInterface.h"
19 #include "KeccakF-1600-interface.h"
20
21 typedef unsigned char UINT8;
22 typedef unsigned long long int UINT64;
23
24 #define nrRounds 24
25 UINT64 KeccakRoundConstants[nrRounds];
26 #define nrLanes 25
27 unsigned int KeccakRhoOffsets[nrLanes];
28
29 void KeccakPermutationOnWords(UINT64 *state);
30 void theta(UINT64 *A);
31 void rho(UINT64 *A);
32 void pi(UINT64 *A);
33 void chi(UINT64 *A);
34 void iota(UINT64 *A, unsigned int indexRound);
35
36 void fromBytesToWords(UINT64 *stateAsWords, const unsigned char *state)
37 {
38 unsigned int i, j;
39
40 for(i=0; i<(KeccakPermutationSize/64); i++) {
41 stateAsWords[i] = 0;
42 for(j=0; j<(64/8); j++)
43 stateAsWords[i] |= (UINT64)(state[i*(64/8)+j]) << (8*j);
44 }
45 }
46
47 void fromWordsToBytes(unsigned char *state, const UINT64 *stateAsWords)
48 {
49 unsigned int i, j;
50
51 for(i=0; i<(KeccakPermutationSize/64); i++)
52 for(j=0; j<(64/8); j++)
53 state[i*(64/8)+j] = (stateAsWords[i] >> (8*j)) & 0xFF;
54 }
55
56 void KeccakPermutation(unsigned char *state)
57 {
58 #if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
59 UINT64 stateAsWords[KeccakPermutationSize/64];
60 #endif
61
62 displayStateAsBytes(1, "Input of permutation", state);
63 #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
64 KeccakPermutationOnWords((UINT64*)state);
65 #else
66 fromBytesToWords(stateAsWords, state);
67 KeccakPermutationOnWords(stateAsWords);
68 fromWordsToBytes(state, stateAsWords);
69 #endif
70 displayStateAsBytes(1, "State after permutation", state);
71 }
72
73 void KeccakPermutationAfterXor(unsigned char *state, const unsigned char *data, unsigned int dataLengthInBytes)
74 {
75 unsigned int i;
76
77 for(i=0; i<dataLengthInBytes; i++)
78 state[i] ^= data[i];
79 KeccakPermutation(state);
80 }
81
82 void KeccakPermutationOnWords(UINT64 *state)
83 {
84 unsigned int i;
85
86 displayStateAs64bitWords(3, "Same, with lanes as 64-bit words", state);
87
88 for(i=0; i<nrRounds; i++) {
89 displayRoundNumber(3, i);
90
91 theta(state);
92 displayStateAs64bitWords(3, "After theta", state);
93
94 rho(state);
95 displayStateAs64bitWords(3, "After rho", state);
96
97 pi(state);
98 displayStateAs64bitWords(3, "After pi", state);
99
100 chi(state);
101 displayStateAs64bitWords(3, "After chi", state);
102
103 iota(state, i);
104 displayStateAs64bitWords(3, "After iota", state);
105 }
106 }
107
108 #define index(x, y) (((x)%5)+5*((y)%5))
109 #define ROL64(a, offset) ((offset != 0) ? ((((UINT64)a) << offset) ^ (((UINT64)a) >> (64-offset))) : a)
110
111 void theta(UINT64 *A)
112 {
113 unsigned int x, y;
114 UINT64 C[5], D[5];
115
116 for(x=0; x<5; x++) {
117 C[x] = 0;
118 for(y=0; y<5; y++)
119 C[x] ^= A[index(x, y)];
120 }
121 for(x=0; x<5; x++)
122 D[x] = ROL64(C[(x+1)%5], 1) ^ C[(x+4)%5];
123 for(x=0; x<5; x++)
124 for(y=0; y<5; y++)
125 A[index(x, y)] ^= D[x];
126 }
127
128 void rho(UINT64 *A)
129 {
130 unsigned int x, y;
131
132 for(x=0; x<5; x++) for(y=0; y<5; y++)
133 A[index(x, y)] = ROL64(A[index(x, y)], KeccakRhoOffsets[index(x, y)]);
134 }
135
136 void pi(UINT64 *A)
137 {
138 unsigned int x, y;
139 UINT64 tempA[25];
140
141 for(x=0; x<5; x++) for(y=0; y<5; y++)
142 tempA[index(x, y)] = A[index(x, y)];
143 for(x=0; x<5; x++) for(y=0; y<5; y++)
144 A[index(0*x+1*y, 2*x+3*y)] = tempA[index(x, y)];
145 }
146
147 void chi(UINT64 *A)
148 {
149 unsigned int x, y;
150 UINT64 C[5];
151
152 for(y=0; y<5; y++) {
153 for(x=0; x<5; x++)
154 C[x] = A[index(x, y)] ^ ((~A[index(x+1, y)]) & A[index(x+2, y)]);
155 for(x=0; x<5; x++)
156 A[index(x, y)] = C[x];
157 }
158 }
159
160 void iota(UINT64 *A, unsigned int indexRound)
161 {
162 A[index(0, 0)] ^= KeccakRoundConstants[indexRound];
163 }
164
165 int LFSR86540(UINT8 *LFSR)
166 {
167 int result = ((*LFSR) & 0x01) != 0;
168 if (((*LFSR) & 0x80) != 0)
169 // Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1
170 (*LFSR) = ((*LFSR) << 1) ^ 0x71;
171 else
172 (*LFSR) <<= 1;
173 return result;
174 }
175
176 void KeccakInitializeRoundConstants()
177 {
178 UINT8 LFSRstate = 0x01;
179 unsigned int i, j, bitPosition;
180
181 for(i=0; i<nrRounds; i++) {
182 KeccakRoundConstants[i] = 0;
183 for(j=0; j<7; j++) {
184 bitPosition = (1<<j)-1; //2^j-1
185 if (LFSR86540(&LFSRstate))
186 KeccakRoundConstants[i] ^= (UINT64)1<<bitPosition;
187 }
188 }
189 }
190
191 void KeccakInitializeRhoOffsets()
192 {
193 unsigned int x, y, t, newX, newY;
194
195 KeccakRhoOffsets[index(0, 0)] = 0;
196 x = 1;
197 y = 0;
198 for(t=0; t<24; t++) {
199 KeccakRhoOffsets[index(x, y)] = ((t+1)*(t+2)/2) % 64;
200 newX = (0*x+1*y) % 5;
201 newY = (2*x+3*y) % 5;
202 x = newX;
203 y = newY;
204 }
205 }
206
207 void KeccakInitialize()
208 {
209 KeccakInitializeRoundConstants();
210 KeccakInitializeRhoOffsets();
211 }
212
213 void displayRoundConstants(FILE *f)
214 {
215 unsigned int i;
216
217 for(i=0; i<nrRounds; i++) {
218 fprintf(f, "RC[%02i][0][0] = ", i);
219 fprintf(f, "%08X", (unsigned int)(KeccakRoundConstants[i] >> 32));
220 fprintf(f, "%08X", (unsigned int)(KeccakRoundConstants[i] & 0xFFFFFFFFULL));
221 fprintf(f, "\n");
222 }
223 fprintf(f, "\n");
224 }
225
226 void displayRhoOffsets(FILE *f)
227 {
228 unsigned int x, y;
229
230 for(y=0; y<5; y++) for(x=0; x<5; x++) {
231 fprintf(f, "RhoOffset[%i][%i] = ", x, y);
232 fprintf(f, "%2i", KeccakRhoOffsets[index(x, y)]);
233 fprintf(f, "\n");
234 }
235 fprintf(f, "\n");
236 }
237
238 void KeccakInitializeState(unsigned char *state)
239 {
240 memset(state, 0, KeccakPermutationSizeInBytes);
241 }
242
243 #ifdef ProvideFast576
244 void KeccakAbsorb576bits(unsigned char *state, const unsigned char *data)
245 {
246 KeccakPermutationAfterXor(state, data, 72);
247 }
248 #endif
249
250 #ifdef ProvideFast832
251 void KeccakAbsorb832bits(unsigned char *state, const unsigned char *data)
252 {
253 KeccakPermutationAfterXor(state, data, 104);
254 }
255 #endif
256
257 #ifdef ProvideFast1024
258 void KeccakAbsorb1024bits(unsigned char *state, const unsigned char *data)
259 {
260 KeccakPermutationAfterXor(state, data, 128);
261 }
262 #endif
263
264 #ifdef ProvideFast1088
265 void KeccakAbsorb1088bits(unsigned char *state, const unsigned char *data)
266 {
267 KeccakPermutationAfterXor(state, data, 136);
268 }
269 #endif
270
271 #ifdef ProvideFast1152
272 void KeccakAbsorb1152bits(unsigned char *state, const unsigned char *data)
273 {
274 KeccakPermutationAfterXor(state, data, 144);
275 }
276 #endif
277
278 #ifdef ProvideFast1344
279 void KeccakAbsorb1344bits(unsigned char *state, const unsigned char *data)
280 {
281 KeccakPermutationAfterXor(state, data, 168);
282 }
283 #endif
284
285 void KeccakAbsorb(unsigned char *state, const unsigned char *data, unsigned int laneCount)
286 {
287 KeccakPermutationAfterXor(state, data, laneCount*8);
288 }
289
290 #ifdef ProvideFast1024
291 void KeccakExtract1024bits(const unsigned char *state, unsigned char *data)
292 {
293 memcpy(data, state, 128);
294 }
295 #endif
296
297 void KeccakExtract(const unsigned char *state, unsigned char *data, unsigned int laneCount)
298 {
299 memcpy(data, state, laneCount*8);
300 }