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