1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3
4 /* based on https://github.com/brainhub/SHA3IUF (public domain) */
5
6 #include "tomcrypt_private.h"
7
8 #ifdef LTC_SHA3
9
10 const struct ltc_hash_descriptor sha3_224_desc =
11 {
12 "sha3-224", /* name of hash */
13 17, /* internal ID */
14 28, /* Size of digest in octets */
15 144, /* Input block size in octets */
16 { 2,16,840,1,101,3,4,2,7 }, /* ASN.1 OID */
17 9, /* Length OID */
18 &sha3_224_init,
19 &sha3_process,
20 &sha3_done,
21 &sha3_224_test,
22 NULL
23 };
24
25 const struct ltc_hash_descriptor sha3_256_desc =
26 {
27 "sha3-256", /* name of hash */
28 18, /* internal ID */
29 32, /* Size of digest in octets */
30 136, /* Input block size in octets */
31 { 2,16,840,1,101,3,4,2,8 }, /* ASN.1 OID */
32 9, /* Length OID */
33 &sha3_256_init,
34 &sha3_process,
35 &sha3_done,
36 &sha3_256_test,
37 NULL
38 };
39
40 const struct ltc_hash_descriptor sha3_384_desc =
41 {
42 "sha3-384", /* name of hash */
43 19, /* internal ID */
44 48, /* Size of digest in octets */
45 104, /* Input block size in octets */
46 { 2,16,840,1,101,3,4,2,9 }, /* ASN.1 OID */
47 9, /* Length OID */
48 &sha3_384_init,
49 &sha3_process,
50 &sha3_done,
51 &sha3_384_test,
52 NULL
53 };
54
55 const struct ltc_hash_descriptor sha3_512_desc =
56 {
57 "sha3-512", /* name of hash */
58 20, /* internal ID */
59 64, /* Size of digest in octets */
60 72, /* Input block size in octets */
61 { 2,16,840,1,101,3,4,2,10 }, /* ASN.1 OID */
62 9, /* Length OID */
63 &sha3_512_init,
64 &sha3_process,
65 &sha3_done,
66 &sha3_512_test,
67 NULL
68 };
69 #endif
70
71 #ifdef LTC_KECCAK
72 const struct ltc_hash_descriptor keccak_224_desc =
73 {
74 "keccak224", /* name of hash */
75 29, /* internal ID */
76 28, /* Size of digest in octets */
77 144, /* Input block size in octets */
78 { 0 }, 0, /* no ASN.1 OID */
79 &sha3_224_init,
80 &sha3_process,
81 &keccak_done,
82 &keccak_224_test,
83 NULL
84 };
85
86 const struct ltc_hash_descriptor keccak_256_desc =
87 {
88 "keccak256", /* name of hash */
89 30, /* internal ID */
90 32, /* Size of digest in octets */
91 136, /* Input block size in octets */
92 { 0 }, 0, /* no ASN.1 OID */
93 &sha3_256_init,
94 &sha3_process,
95 &keccak_done,
96 &keccak_256_test,
97 NULL
98 };
99
100 const struct ltc_hash_descriptor keccak_384_desc =
101 {
102 "keccak384", /* name of hash */
103 31, /* internal ID */
104 48, /* Size of digest in octets */
105 104, /* Input block size in octets */
106 { 0 }, 0, /* no ASN.1 OID */
107 &sha3_384_init,
108 &sha3_process,
109 &keccak_done,
110 &keccak_384_test,
111 NULL
112 };
113
114 const struct ltc_hash_descriptor keccak_512_desc =
115 {
116 "keccak512", /* name of hash */
117 32, /* internal ID */
118 64, /* Size of digest in octets */
119 72, /* Input block size in octets */
120 { 0 }, 0, /* no ASN.1 OID */
121 &sha3_512_init,
122 &sha3_process,
123 &keccak_done,
124 &keccak_512_test,
125 NULL
126 };
127 #endif
128
129 #if defined(LTC_SHA3) || defined(LTC_KECCAK)
130
131 #define SHA3_KECCAK_SPONGE_WORDS 25 /* 1600 bits > 200 bytes > 25 x ulong64 */
132 #define SHA3_KECCAK_ROUNDS 24
133
134 static const ulong64 s_keccakf_rndc[24] = {
135 CONST64(0x0000000000000001), CONST64(0x0000000000008082),
136 CONST64(0x800000000000808a), CONST64(0x8000000080008000),
137 CONST64(0x000000000000808b), CONST64(0x0000000080000001),
138 CONST64(0x8000000080008081), CONST64(0x8000000000008009),
139 CONST64(0x000000000000008a), CONST64(0x0000000000000088),
140 CONST64(0x0000000080008009), CONST64(0x000000008000000a),
141 CONST64(0x000000008000808b), CONST64(0x800000000000008b),
142 CONST64(0x8000000000008089), CONST64(0x8000000000008003),
143 CONST64(0x8000000000008002), CONST64(0x8000000000000080),
144 CONST64(0x000000000000800a), CONST64(0x800000008000000a),
145 CONST64(0x8000000080008081), CONST64(0x8000000000008080),
146 CONST64(0x0000000080000001), CONST64(0x8000000080008008)
147 };
148
149 static const unsigned s_keccakf_rotc[24] = {
150 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
151 };
152
153 static const unsigned s_keccakf_piln[24] = {
154 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
155 };
156
s_keccakf(ulong64 s[25])157 static void s_keccakf(ulong64 s[25])
158 {
159 int i, j, round;
160 ulong64 t, bc[5];
161
162 for(round = 0; round < SHA3_KECCAK_ROUNDS; round++) {
163 /* Theta */
164 for(i = 0; i < 5; i++) {
165 bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
166 }
167 for(i = 0; i < 5; i++) {
168 t = bc[(i + 4) % 5] ^ ROL64(bc[(i + 1) % 5], 1);
169 for(j = 0; j < 25; j += 5) {
170 s[j + i] ^= t;
171 }
172 }
173 /* Rho Pi */
174 t = s[1];
175 for(i = 0; i < 24; i++) {
176 j = s_keccakf_piln[i];
177 bc[0] = s[j];
178 s[j] = ROL64(t, s_keccakf_rotc[i]);
179 t = bc[0];
180 }
181 /* Chi */
182 for(j = 0; j < 25; j += 5) {
183 for(i = 0; i < 5; i++) {
184 bc[i] = s[j + i];
185 }
186 for(i = 0; i < 5; i++) {
187 s[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
188 }
189 }
190 /* Iota */
191 s[0] ^= s_keccakf_rndc[round];
192 }
193 }
194
ss_done(hash_state * md,unsigned char * hash,ulong64 pad)195 static LTC_INLINE int ss_done(hash_state *md, unsigned char *hash, ulong64 pad)
196 {
197 unsigned i;
198
199 LTC_ARGCHK(md != NULL);
200 LTC_ARGCHK(hash != NULL);
201
202 md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (pad << (md->sha3.byte_index * 8)));
203 md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000);
204 s_keccakf(md->sha3.s);
205
206 /* store sha3.s[] as little-endian bytes into sha3.sb */
207 for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
208 STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
209 }
210
211 XMEMCPY(hash, md->sha3.sb, md->sha3.capacity_words * 4);
212 return CRYPT_OK;
213 }
214
215 /* Public Inteface */
216
sha3_224_init(hash_state * md)217 int sha3_224_init(hash_state *md)
218 {
219 LTC_ARGCHK(md != NULL);
220 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
221 md->sha3.capacity_words = 2 * 224 / (8 * sizeof(ulong64));
222 return CRYPT_OK;
223 }
224
sha3_256_init(hash_state * md)225 int sha3_256_init(hash_state *md)
226 {
227 LTC_ARGCHK(md != NULL);
228 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
229 md->sha3.capacity_words = 2 * 256 / (8 * sizeof(ulong64));
230 return CRYPT_OK;
231 }
232
sha3_384_init(hash_state * md)233 int sha3_384_init(hash_state *md)
234 {
235 LTC_ARGCHK(md != NULL);
236 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
237 md->sha3.capacity_words = 2 * 384 / (8 * sizeof(ulong64));
238 return CRYPT_OK;
239 }
240
sha3_512_init(hash_state * md)241 int sha3_512_init(hash_state *md)
242 {
243 LTC_ARGCHK(md != NULL);
244 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
245 md->sha3.capacity_words = 2 * 512 / (8 * sizeof(ulong64));
246 return CRYPT_OK;
247 }
248
249 #ifdef LTC_SHA3
sha3_shake_init(hash_state * md,int num)250 int sha3_shake_init(hash_state *md, int num)
251 {
252 LTC_ARGCHK(md != NULL);
253 if (num != 128 && num != 256) return CRYPT_INVALID_ARG;
254 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
255 md->sha3.capacity_words = (unsigned short)(2 * num / (8 * sizeof(ulong64)));
256 return CRYPT_OK;
257 }
258 #endif
259
sha3_process(hash_state * md,const unsigned char * in,unsigned long inlen)260 int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen)
261 {
262 /* 0...7 -- how much is needed to have a word */
263 unsigned old_tail = (8 - md->sha3.byte_index) & 7;
264
265 unsigned long words;
266 unsigned tail;
267 unsigned long i;
268
269 if (inlen == 0) return CRYPT_OK; /* nothing to do */
270 LTC_ARGCHK(md != NULL);
271 LTC_ARGCHK(in != NULL);
272
273 if(inlen < old_tail) { /* have no complete word or haven't started the word yet */
274 while (inlen--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
275 return CRYPT_OK;
276 }
277
278 if(old_tail) { /* will have one word to process */
279 inlen -= old_tail;
280 while (old_tail--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
281 /* now ready to add saved to the sponge */
282 md->sha3.s[md->sha3.word_index] ^= md->sha3.saved;
283 md->sha3.byte_index = 0;
284 md->sha3.saved = 0;
285 if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) {
286 s_keccakf(md->sha3.s);
287 md->sha3.word_index = 0;
288 }
289 }
290
291 /* now work in full words directly from input */
292 words = inlen / sizeof(ulong64);
293 tail = inlen - words * sizeof(ulong64);
294
295 for(i = 0; i < words; i++, in += sizeof(ulong64)) {
296 ulong64 t;
297 LOAD64L(t, in);
298 md->sha3.s[md->sha3.word_index] ^= t;
299 if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) {
300 s_keccakf(md->sha3.s);
301 md->sha3.word_index = 0;
302 }
303 }
304
305 /* finally, save the partial word */
306 while (tail--) {
307 md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
308 }
309 return CRYPT_OK;
310 }
311
312 #ifdef LTC_SHA3
sha3_done(hash_state * md,unsigned char * out)313 int sha3_done(hash_state *md, unsigned char *out)
314 {
315 return ss_done(md, out, CONST64(0x06));
316 }
317 #endif
318
319 #ifdef LTC_KECCAK
keccak_done(hash_state * md,unsigned char * out)320 int keccak_done(hash_state *md, unsigned char *out)
321 {
322 return ss_done(md, out, CONST64(0x01));
323 }
324 #endif
325
326 #ifdef LTC_SHA3
sha3_shake_done(hash_state * md,unsigned char * out,unsigned long outlen)327 int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen)
328 {
329 /* IMPORTANT NOTE: sha3_shake_done can be called many times */
330 unsigned long idx;
331 unsigned i;
332
333 if (outlen == 0) return CRYPT_OK; /* nothing to do */
334 LTC_ARGCHK(md != NULL);
335 LTC_ARGCHK(out != NULL);
336
337 if (!md->sha3.xof_flag) {
338 /* shake_xof operation must be done only once */
339 md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (CONST64(0x1F) << (md->sha3.byte_index * 8)));
340 md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000);
341 s_keccakf(md->sha3.s);
342 /* store sha3.s[] as little-endian bytes into sha3.sb */
343 for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
344 STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
345 }
346 md->sha3.byte_index = 0;
347 md->sha3.xof_flag = 1;
348 }
349
350 for (idx = 0; idx < outlen; idx++) {
351 if(md->sha3.byte_index >= (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words) * 8) {
352 s_keccakf(md->sha3.s);
353 /* store sha3.s[] as little-endian bytes into sha3.sb */
354 for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
355 STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
356 }
357 md->sha3.byte_index = 0;
358 }
359 out[idx] = md->sha3.sb[md->sha3.byte_index++];
360 }
361 return CRYPT_OK;
362 }
363
sha3_shake_memory(int num,const unsigned char * in,unsigned long inlen,unsigned char * out,const unsigned long * outlen)364 int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen)
365 {
366 hash_state md;
367 int err;
368 LTC_ARGCHK(in != NULL);
369 LTC_ARGCHK(out != NULL);
370 LTC_ARGCHK(outlen != NULL);
371 if ((err = sha3_shake_init(&md, num)) != CRYPT_OK) return err;
372 if ((err = sha3_shake_process(&md, in, inlen)) != CRYPT_OK) return err;
373 if ((err = sha3_shake_done(&md, out, *outlen)) != CRYPT_OK) return err;
374 return CRYPT_OK;
375 }
376 #endif
377
378 #endif
379