aboutsummaryrefslogtreecommitdiff
path: root/C/Sha3.c
diff options
context:
space:
mode:
Diffstat (limited to 'C/Sha3.c')
-rw-r--r--C/Sha3.c359
1 files changed, 359 insertions, 0 deletions
diff --git a/C/Sha3.c b/C/Sha3.c
new file mode 100644
index 0000000..be972d6
--- /dev/null
+++ b/C/Sha3.c
@@ -0,0 +1,359 @@
1/* Sha3.c -- SHA-3 Hash
2: Igor Pavlov : Public domain
3This code is based on public domain code from Wei Dai's Crypto++ library. */
4
5#include "Precomp.h"
6
7#include <string.h>
8
9#include "Sha3.h"
10#include "RotateDefs.h"
11#include "CpuArch.h"
12
13#define U64C(x) UINT64_CONST(x)
14
15static
16MY_ALIGN(64)
17const UInt64 SHA3_K_ARRAY[24] =
18{
19 U64C(0x0000000000000001), U64C(0x0000000000008082),
20 U64C(0x800000000000808a), U64C(0x8000000080008000),
21 U64C(0x000000000000808b), U64C(0x0000000080000001),
22 U64C(0x8000000080008081), U64C(0x8000000000008009),
23 U64C(0x000000000000008a), U64C(0x0000000000000088),
24 U64C(0x0000000080008009), U64C(0x000000008000000a),
25 U64C(0x000000008000808b), U64C(0x800000000000008b),
26 U64C(0x8000000000008089), U64C(0x8000000000008003),
27 U64C(0x8000000000008002), U64C(0x8000000000000080),
28 U64C(0x000000000000800a), U64C(0x800000008000000a),
29 U64C(0x8000000080008081), U64C(0x8000000000008080),
30 U64C(0x0000000080000001), U64C(0x8000000080008008)
31};
32
33void Sha3_Init(CSha3 *p)
34{
35 p->count = 0;
36 memset(p->state, 0, sizeof(p->state));
37}
38
39#define GET_state(i, a) UInt64 a = state[i];
40#define SET_state(i, a) state[i] = a;
41
42#define LS_5(M, i, a0,a1,a2,a3,a4) \
43 M ((i) * 5 , a0) \
44 M ((i) * 5 + 1, a1) \
45 M ((i) * 5 + 2, a2) \
46 M ((i) * 5 + 3, a3) \
47 M ((i) * 5 + 4, a4) \
48
49#define LS_25(M) \
50 LS_5 (M, 0, a50, a51, a52, a53, a54) \
51 LS_5 (M, 1, a60, a61, a62, a63, a64) \
52 LS_5 (M, 2, a70, a71, a72, a73, a74) \
53 LS_5 (M, 3, a80, a81, a82, a83, a84) \
54 LS_5 (M, 4, a90, a91, a92, a93, a94) \
55
56
57#define XOR_1(i, a0) \
58 a0 ^= GetUi64(data + (i) * 8); \
59
60#define XOR_4(i, a0,a1,a2,a3) \
61 XOR_1 ((i) , a0); \
62 XOR_1 ((i) + 1, a1); \
63 XOR_1 ((i) + 2, a2); \
64 XOR_1 ((i) + 3, a3); \
65
66#define D(d,b1,b2) \
67 d = b1 ^ Z7_ROTL64(b2, 1);
68
69#define D5 \
70 D (d0, c4, c1) \
71 D (d1, c0, c2) \
72 D (d2, c1, c3) \
73 D (d3, c2, c4) \
74 D (d4, c3, c0) \
75
76#define C0(c,a,d) \
77 c = a ^ d; \
78
79#define C(c,a,d,k) \
80 c = a ^ d; \
81 c = Z7_ROTL64(c, k); \
82
83#define E4(e1,e2,e3,e4) \
84 e1 = c1 ^ (~c2 & c3); \
85 e2 = c2 ^ (~c3 & c4); \
86 e3 = c3 ^ (~c4 & c0); \
87 e4 = c4 ^ (~c0 & c1); \
88
89#define CK( v0,w0, \
90 v1,w1,k1, \
91 v2,w2,k2, \
92 v3,w3,k3, \
93 v4,w4,k4, e0,e1,e2,e3,e4, keccak_c) \
94 C0(c0,v0,w0) \
95 C (c1,v1,w1,k1) \
96 C (c2,v2,w2,k2) \
97 C (c3,v3,w3,k3) \
98 C (c4,v4,w4,k4) \
99 e0 = c0 ^ (~c1 & c2) ^ keccak_c; \
100 E4(e1,e2,e3,e4) \
101
102#define CE( v0,w0,k0, \
103 v1,w1,k1, \
104 v2,w2,k2, \
105 v3,w3,k3, \
106 v4,w4,k4, e0,e1,e2,e3,e4) \
107 C (c0,v0,w0,k0) \
108 C (c1,v1,w1,k1) \
109 C (c2,v2,w2,k2) \
110 C (c3,v3,w3,k3) \
111 C (c4,v4,w4,k4) \
112 e0 = c0 ^ (~c1 & c2); \
113 E4(e1,e2,e3,e4) \
114
115// numBlocks != 0
116static
117Z7_NO_INLINE
118void Z7_FASTCALL Sha3_UpdateBlocks(UInt64 state[SHA3_NUM_STATE_WORDS],
119 const Byte *data, size_t numBlocks, size_t blockSize)
120{
121 LS_25 (GET_state)
122
123 do
124 {
125 unsigned round;
126 XOR_4 ( 0, a50, a51, a52, a53)
127 XOR_4 ( 4, a54, a60, a61, a62)
128 XOR_1 ( 8, a63)
129 if (blockSize > 8 * 9) { XOR_4 ( 9, a64, a70, a71, a72) // sha3-384
130 if (blockSize > 8 * 13) { XOR_4 (13, a73, a74, a80, a81) // sha3-256
131 if (blockSize > 8 * 17) { XOR_1 (17, a82) // sha3-224
132 if (blockSize > 8 * 18) { XOR_1 (18, a83) // shake128
133 XOR_1 (19, a84)
134 XOR_1 (20, a90) }}}}
135 data += blockSize;
136
137 for (round = 0; round < 24; round += 2)
138 {
139 UInt64 c0, c1, c2, c3, c4;
140 UInt64 d0, d1, d2, d3, d4;
141 UInt64 e50, e51, e52, e53, e54;
142 UInt64 e60, e61, e62, e63, e64;
143 UInt64 e70, e71, e72, e73, e74;
144 UInt64 e80, e81, e82, e83, e84;
145 UInt64 e90, e91, e92, e93, e94;
146
147 c0 = a50^a60^a70^a80^a90;
148 c1 = a51^a61^a71^a81^a91;
149 c2 = a52^a62^a72^a82^a92;
150 c3 = a53^a63^a73^a83^a93;
151 c4 = a54^a64^a74^a84^a94;
152 D5
153 CK( a50, d0,
154 a61, d1, 44,
155 a72, d2, 43,
156 a83, d3, 21,
157 a94, d4, 14, e50, e51, e52, e53, e54, SHA3_K_ARRAY[round])
158 CE( a53, d3, 28,
159 a64, d4, 20,
160 a70, d0, 3,
161 a81, d1, 45,
162 a92, d2, 61, e60, e61, e62, e63, e64)
163 CE( a51, d1, 1,
164 a62, d2, 6,
165 a73, d3, 25,
166 a84, d4, 8,
167 a90, d0, 18, e70, e71, e72, e73, e74)
168 CE( a54, d4, 27,
169 a60, d0, 36,
170 a71, d1, 10,
171 a82, d2, 15,
172 a93, d3, 56, e80, e81, e82, e83, e84)
173 CE( a52, d2, 62,
174 a63, d3, 55,
175 a74, d4, 39,
176 a80, d0, 41,
177 a91, d1, 2, e90, e91, e92, e93, e94)
178
179 // ---------- ROUND + 1 ----------
180
181 c0 = e50^e60^e70^e80^e90;
182 c1 = e51^e61^e71^e81^e91;
183 c2 = e52^e62^e72^e82^e92;
184 c3 = e53^e63^e73^e83^e93;
185 c4 = e54^e64^e74^e84^e94;
186 D5
187 CK( e50, d0,
188 e61, d1, 44,
189 e72, d2, 43,
190 e83, d3, 21,
191 e94, d4, 14, a50, a51, a52, a53, a54, SHA3_K_ARRAY[(size_t)round + 1])
192 CE( e53, d3, 28,
193 e64, d4, 20,
194 e70, d0, 3,
195 e81, d1, 45,
196 e92, d2, 61, a60, a61, a62, a63, a64)
197 CE( e51, d1, 1,
198 e62, d2, 6,
199 e73, d3, 25,
200 e84, d4, 8,
201 e90, d0, 18, a70, a71, a72, a73, a74)
202 CE (e54, d4, 27,
203 e60, d0, 36,
204 e71, d1, 10,
205 e82, d2, 15,
206 e93, d3, 56, a80, a81, a82, a83, a84)
207 CE (e52, d2, 62,
208 e63, d3, 55,
209 e74, d4, 39,
210 e80, d0, 41,
211 e91, d1, 2, a90, a91, a92, a93, a94)
212 }
213 }
214 while (--numBlocks);
215
216 LS_25 (SET_state)
217}
218
219
220#define Sha3_UpdateBlock(p) \
221 Sha3_UpdateBlocks(p->state, p->buffer, 1, p->blockSize)
222
223void Sha3_Update(CSha3 *p, const Byte *data, size_t size)
224{
225/*
226 for (;;)
227 {
228 if (size == 0)
229 return;
230 unsigned cur = p->blockSize - p->count;
231 if (cur > size)
232 cur = (unsigned)size;
233 size -= cur;
234 unsigned pos = p->count;
235 p->count = pos + cur;
236 while (pos & 7)
237 {
238 if (cur == 0)
239 return;
240 Byte *pb = &(((Byte *)p->state)[pos]);
241 *pb = (Byte)(*pb ^ *data++);
242 cur--;
243 pos++;
244 }
245 if (cur >= 8)
246 {
247 do
248 {
249 *(UInt64 *)(void *)&(((Byte *)p->state)[pos]) ^= GetUi64(data);
250 data += 8;
251 pos += 8;
252 cur -= 8;
253 }
254 while (cur >= 8);
255 }
256 if (pos != p->blockSize)
257 {
258 if (cur)
259 {
260 Byte *pb = &(((Byte *)p->state)[pos]);
261 do
262 {
263 *pb = (Byte)(*pb ^ *data++);
264 pb++;
265 }
266 while (--cur);
267 }
268 return;
269 }
270 Sha3_UpdateBlock(p->state);
271 p->count = 0;
272 }
273*/
274 if (size == 0)
275 return;
276 {
277 const unsigned pos = p->count;
278 const unsigned num = p->blockSize - pos;
279 if (num > size)
280 {
281 p->count = pos + (unsigned)size;
282 memcpy(p->buffer + pos, data, size);
283 return;
284 }
285 if (pos != 0)
286 {
287 size -= num;
288 memcpy(p->buffer + pos, data, num);
289 data += num;
290 Sha3_UpdateBlock(p);
291 }
292 }
293 if (size >= p->blockSize)
294 {
295 const size_t numBlocks = size / p->blockSize;
296 const Byte *dataOld = data;
297 data += numBlocks * p->blockSize;
298 size = (size_t)(dataOld + size - data);
299 Sha3_UpdateBlocks(p->state, dataOld, numBlocks, p->blockSize);
300 }
301 p->count = (unsigned)size;
302 if (size)
303 memcpy(p->buffer, data, size);
304}
305
306
307// we support only (digestSize % 4 == 0) cases
308void Sha3_Final(CSha3 *p, Byte *digest, unsigned digestSize, unsigned shake)
309{
310 memset(p->buffer + p->count, 0, p->blockSize - p->count);
311 // we write bits markers from low to higher in current byte:
312 // - if sha-3 : 2 bits : 0,1
313 // - if shake : 4 bits : 1111
314 // then we write bit 1 to same byte.
315 // And we write bit 1 to highest bit of last byte of block.
316 p->buffer[p->count] = (Byte)(shake ? 0x1f : 0x06);
317 // we need xor operation (^= 0x80) here because we must write 0x80 bit
318 // to same byte as (0x1f : 0x06), if (p->count == p->blockSize - 1) !!!
319 p->buffer[p->blockSize - 1] ^= 0x80;
320/*
321 ((Byte *)p->state)[p->count] ^= (Byte)(shake ? 0x1f : 0x06);
322 ((Byte *)p->state)[p->blockSize - 1] ^= 0x80;
323*/
324 Sha3_UpdateBlock(p);
325#if 1 && defined(MY_CPU_LE)
326 memcpy(digest, p->state, digestSize);
327#else
328 {
329 const unsigned numWords = digestSize >> 3;
330 unsigned i;
331 for (i = 0; i < numWords; i++)
332 {
333 const UInt64 v = p->state[i];
334 SetUi64(digest, v)
335 digest += 8;
336 }
337 if (digestSize & 4) // for SHA3-224
338 {
339 const UInt32 v = (UInt32)p->state[numWords];
340 SetUi32(digest, v)
341 }
342 }
343#endif
344 Sha3_Init(p);
345}
346
347#undef GET_state
348#undef SET_state
349#undef LS_5
350#undef LS_25
351#undef XOR_1
352#undef XOR_4
353#undef D
354#undef D5
355#undef C0
356#undef C
357#undef E4
358#undef CK
359#undef CE