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