1*8411e6adSJerome Forissier /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2*8411e6adSJerome Forissier /* SPDX-License-Identifier: Unlicense */
35a913ee7SJerome Forissier
45a913ee7SJerome Forissier /* based on https://github.com/brainhub/SHA3IUF (public domain) */
55a913ee7SJerome Forissier
65a913ee7SJerome Forissier #include "tomcrypt_private.h"
75a913ee7SJerome Forissier
85a913ee7SJerome Forissier #ifdef LTC_SHA3
95a913ee7SJerome Forissier
105a913ee7SJerome Forissier const struct ltc_hash_descriptor sha3_224_desc =
115a913ee7SJerome Forissier {
125a913ee7SJerome Forissier "sha3-224", /* name of hash */
135a913ee7SJerome Forissier 17, /* internal ID */
145a913ee7SJerome Forissier 28, /* Size of digest in octets */
155a913ee7SJerome Forissier 144, /* Input block size in octets */
165a913ee7SJerome Forissier { 2,16,840,1,101,3,4,2,7 }, /* ASN.1 OID */
175a913ee7SJerome Forissier 9, /* Length OID */
185a913ee7SJerome Forissier &sha3_224_init,
195a913ee7SJerome Forissier &sha3_process,
205a913ee7SJerome Forissier &sha3_done,
215a913ee7SJerome Forissier &sha3_224_test,
225a913ee7SJerome Forissier NULL
235a913ee7SJerome Forissier };
245a913ee7SJerome Forissier
255a913ee7SJerome Forissier const struct ltc_hash_descriptor sha3_256_desc =
265a913ee7SJerome Forissier {
275a913ee7SJerome Forissier "sha3-256", /* name of hash */
285a913ee7SJerome Forissier 18, /* internal ID */
295a913ee7SJerome Forissier 32, /* Size of digest in octets */
305a913ee7SJerome Forissier 136, /* Input block size in octets */
315a913ee7SJerome Forissier { 2,16,840,1,101,3,4,2,8 }, /* ASN.1 OID */
325a913ee7SJerome Forissier 9, /* Length OID */
335a913ee7SJerome Forissier &sha3_256_init,
345a913ee7SJerome Forissier &sha3_process,
355a913ee7SJerome Forissier &sha3_done,
365a913ee7SJerome Forissier &sha3_256_test,
375a913ee7SJerome Forissier NULL
385a913ee7SJerome Forissier };
395a913ee7SJerome Forissier
405a913ee7SJerome Forissier const struct ltc_hash_descriptor sha3_384_desc =
415a913ee7SJerome Forissier {
425a913ee7SJerome Forissier "sha3-384", /* name of hash */
435a913ee7SJerome Forissier 19, /* internal ID */
445a913ee7SJerome Forissier 48, /* Size of digest in octets */
455a913ee7SJerome Forissier 104, /* Input block size in octets */
465a913ee7SJerome Forissier { 2,16,840,1,101,3,4,2,9 }, /* ASN.1 OID */
475a913ee7SJerome Forissier 9, /* Length OID */
485a913ee7SJerome Forissier &sha3_384_init,
495a913ee7SJerome Forissier &sha3_process,
505a913ee7SJerome Forissier &sha3_done,
515a913ee7SJerome Forissier &sha3_384_test,
525a913ee7SJerome Forissier NULL
535a913ee7SJerome Forissier };
545a913ee7SJerome Forissier
555a913ee7SJerome Forissier const struct ltc_hash_descriptor sha3_512_desc =
565a913ee7SJerome Forissier {
575a913ee7SJerome Forissier "sha3-512", /* name of hash */
585a913ee7SJerome Forissier 20, /* internal ID */
595a913ee7SJerome Forissier 64, /* Size of digest in octets */
605a913ee7SJerome Forissier 72, /* Input block size in octets */
615a913ee7SJerome Forissier { 2,16,840,1,101,3,4,2,10 }, /* ASN.1 OID */
625a913ee7SJerome Forissier 9, /* Length OID */
635a913ee7SJerome Forissier &sha3_512_init,
645a913ee7SJerome Forissier &sha3_process,
655a913ee7SJerome Forissier &sha3_done,
665a913ee7SJerome Forissier &sha3_512_test,
675a913ee7SJerome Forissier NULL
685a913ee7SJerome Forissier };
695a913ee7SJerome Forissier #endif
705a913ee7SJerome Forissier
715a913ee7SJerome Forissier #ifdef LTC_KECCAK
725a913ee7SJerome Forissier const struct ltc_hash_descriptor keccak_224_desc =
735a913ee7SJerome Forissier {
745a913ee7SJerome Forissier "keccak224", /* name of hash */
755a913ee7SJerome Forissier 29, /* internal ID */
765a913ee7SJerome Forissier 28, /* Size of digest in octets */
775a913ee7SJerome Forissier 144, /* Input block size in octets */
785a913ee7SJerome Forissier { 0 }, 0, /* no ASN.1 OID */
795a913ee7SJerome Forissier &sha3_224_init,
805a913ee7SJerome Forissier &sha3_process,
815a913ee7SJerome Forissier &keccak_done,
825a913ee7SJerome Forissier &keccak_224_test,
835a913ee7SJerome Forissier NULL
845a913ee7SJerome Forissier };
855a913ee7SJerome Forissier
865a913ee7SJerome Forissier const struct ltc_hash_descriptor keccak_256_desc =
875a913ee7SJerome Forissier {
885a913ee7SJerome Forissier "keccak256", /* name of hash */
895a913ee7SJerome Forissier 30, /* internal ID */
905a913ee7SJerome Forissier 32, /* Size of digest in octets */
915a913ee7SJerome Forissier 136, /* Input block size in octets */
925a913ee7SJerome Forissier { 0 }, 0, /* no ASN.1 OID */
935a913ee7SJerome Forissier &sha3_256_init,
945a913ee7SJerome Forissier &sha3_process,
955a913ee7SJerome Forissier &keccak_done,
965a913ee7SJerome Forissier &keccak_256_test,
975a913ee7SJerome Forissier NULL
985a913ee7SJerome Forissier };
995a913ee7SJerome Forissier
1005a913ee7SJerome Forissier const struct ltc_hash_descriptor keccak_384_desc =
1015a913ee7SJerome Forissier {
1025a913ee7SJerome Forissier "keccak384", /* name of hash */
1035a913ee7SJerome Forissier 31, /* internal ID */
1045a913ee7SJerome Forissier 48, /* Size of digest in octets */
1055a913ee7SJerome Forissier 104, /* Input block size in octets */
1065a913ee7SJerome Forissier { 0 }, 0, /* no ASN.1 OID */
1075a913ee7SJerome Forissier &sha3_384_init,
1085a913ee7SJerome Forissier &sha3_process,
1095a913ee7SJerome Forissier &keccak_done,
1105a913ee7SJerome Forissier &keccak_384_test,
1115a913ee7SJerome Forissier NULL
1125a913ee7SJerome Forissier };
1135a913ee7SJerome Forissier
1145a913ee7SJerome Forissier const struct ltc_hash_descriptor keccak_512_desc =
1155a913ee7SJerome Forissier {
1165a913ee7SJerome Forissier "keccak512", /* name of hash */
1175a913ee7SJerome Forissier 32, /* internal ID */
1185a913ee7SJerome Forissier 64, /* Size of digest in octets */
1195a913ee7SJerome Forissier 72, /* Input block size in octets */
1205a913ee7SJerome Forissier { 0 }, 0, /* no ASN.1 OID */
1215a913ee7SJerome Forissier &sha3_512_init,
1225a913ee7SJerome Forissier &sha3_process,
1235a913ee7SJerome Forissier &keccak_done,
1245a913ee7SJerome Forissier &keccak_512_test,
1255a913ee7SJerome Forissier NULL
1265a913ee7SJerome Forissier };
1275a913ee7SJerome Forissier #endif
1285a913ee7SJerome Forissier
1295a913ee7SJerome Forissier #if defined(LTC_SHA3) || defined(LTC_KECCAK)
1305a913ee7SJerome Forissier
1315a913ee7SJerome Forissier #define SHA3_KECCAK_SPONGE_WORDS 25 /* 1600 bits > 200 bytes > 25 x ulong64 */
1325a913ee7SJerome Forissier #define SHA3_KECCAK_ROUNDS 24
1335a913ee7SJerome Forissier
134*8411e6adSJerome Forissier static const ulong64 s_keccakf_rndc[24] = {
1355a913ee7SJerome Forissier CONST64(0x0000000000000001), CONST64(0x0000000000008082),
1365a913ee7SJerome Forissier CONST64(0x800000000000808a), CONST64(0x8000000080008000),
1375a913ee7SJerome Forissier CONST64(0x000000000000808b), CONST64(0x0000000080000001),
1385a913ee7SJerome Forissier CONST64(0x8000000080008081), CONST64(0x8000000000008009),
1395a913ee7SJerome Forissier CONST64(0x000000000000008a), CONST64(0x0000000000000088),
1405a913ee7SJerome Forissier CONST64(0x0000000080008009), CONST64(0x000000008000000a),
1415a913ee7SJerome Forissier CONST64(0x000000008000808b), CONST64(0x800000000000008b),
1425a913ee7SJerome Forissier CONST64(0x8000000000008089), CONST64(0x8000000000008003),
1435a913ee7SJerome Forissier CONST64(0x8000000000008002), CONST64(0x8000000000000080),
1445a913ee7SJerome Forissier CONST64(0x000000000000800a), CONST64(0x800000008000000a),
1455a913ee7SJerome Forissier CONST64(0x8000000080008081), CONST64(0x8000000000008080),
1465a913ee7SJerome Forissier CONST64(0x0000000080000001), CONST64(0x8000000080008008)
1475a913ee7SJerome Forissier };
1485a913ee7SJerome Forissier
149*8411e6adSJerome Forissier static const unsigned s_keccakf_rotc[24] = {
1505a913ee7SJerome Forissier 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
1515a913ee7SJerome Forissier };
1525a913ee7SJerome Forissier
153*8411e6adSJerome Forissier static const unsigned s_keccakf_piln[24] = {
1545a913ee7SJerome Forissier 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
1555a913ee7SJerome Forissier };
1565a913ee7SJerome Forissier
s_keccakf(ulong64 s[25])157*8411e6adSJerome Forissier static void s_keccakf(ulong64 s[25])
1585a913ee7SJerome Forissier {
1595a913ee7SJerome Forissier int i, j, round;
1605a913ee7SJerome Forissier ulong64 t, bc[5];
1615a913ee7SJerome Forissier
1625a913ee7SJerome Forissier for(round = 0; round < SHA3_KECCAK_ROUNDS; round++) {
1635a913ee7SJerome Forissier /* Theta */
1645a913ee7SJerome Forissier for(i = 0; i < 5; i++) {
1655a913ee7SJerome Forissier bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
1665a913ee7SJerome Forissier }
1675a913ee7SJerome Forissier for(i = 0; i < 5; i++) {
1685a913ee7SJerome Forissier t = bc[(i + 4) % 5] ^ ROL64(bc[(i + 1) % 5], 1);
1695a913ee7SJerome Forissier for(j = 0; j < 25; j += 5) {
1705a913ee7SJerome Forissier s[j + i] ^= t;
1715a913ee7SJerome Forissier }
1725a913ee7SJerome Forissier }
1735a913ee7SJerome Forissier /* Rho Pi */
1745a913ee7SJerome Forissier t = s[1];
1755a913ee7SJerome Forissier for(i = 0; i < 24; i++) {
176*8411e6adSJerome Forissier j = s_keccakf_piln[i];
1775a913ee7SJerome Forissier bc[0] = s[j];
178*8411e6adSJerome Forissier s[j] = ROL64(t, s_keccakf_rotc[i]);
1795a913ee7SJerome Forissier t = bc[0];
1805a913ee7SJerome Forissier }
1815a913ee7SJerome Forissier /* Chi */
1825a913ee7SJerome Forissier for(j = 0; j < 25; j += 5) {
1835a913ee7SJerome Forissier for(i = 0; i < 5; i++) {
1845a913ee7SJerome Forissier bc[i] = s[j + i];
1855a913ee7SJerome Forissier }
1865a913ee7SJerome Forissier for(i = 0; i < 5; i++) {
1875a913ee7SJerome Forissier s[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
1885a913ee7SJerome Forissier }
1895a913ee7SJerome Forissier }
1905a913ee7SJerome Forissier /* Iota */
191*8411e6adSJerome Forissier s[0] ^= s_keccakf_rndc[round];
1925a913ee7SJerome Forissier }
1935a913ee7SJerome Forissier }
1945a913ee7SJerome Forissier
ss_done(hash_state * md,unsigned char * hash,ulong64 pad)195*8411e6adSJerome Forissier static LTC_INLINE int ss_done(hash_state *md, unsigned char *hash, ulong64 pad)
1965a913ee7SJerome Forissier {
1975a913ee7SJerome Forissier unsigned i;
1985a913ee7SJerome Forissier
1995a913ee7SJerome Forissier LTC_ARGCHK(md != NULL);
2005a913ee7SJerome Forissier LTC_ARGCHK(hash != NULL);
2015a913ee7SJerome Forissier
2025a913ee7SJerome Forissier md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (pad << (md->sha3.byte_index * 8)));
2035a913ee7SJerome Forissier md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000);
204*8411e6adSJerome Forissier s_keccakf(md->sha3.s);
2055a913ee7SJerome Forissier
2065a913ee7SJerome Forissier /* store sha3.s[] as little-endian bytes into sha3.sb */
2075a913ee7SJerome Forissier for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
2085a913ee7SJerome Forissier STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
2095a913ee7SJerome Forissier }
2105a913ee7SJerome Forissier
2115a913ee7SJerome Forissier XMEMCPY(hash, md->sha3.sb, md->sha3.capacity_words * 4);
2125a913ee7SJerome Forissier return CRYPT_OK;
2135a913ee7SJerome Forissier }
2145a913ee7SJerome Forissier
2155a913ee7SJerome Forissier /* Public Inteface */
2165a913ee7SJerome Forissier
sha3_224_init(hash_state * md)2175a913ee7SJerome Forissier int sha3_224_init(hash_state *md)
2185a913ee7SJerome Forissier {
2195a913ee7SJerome Forissier LTC_ARGCHK(md != NULL);
2205a913ee7SJerome Forissier XMEMSET(&md->sha3, 0, sizeof(md->sha3));
2215a913ee7SJerome Forissier md->sha3.capacity_words = 2 * 224 / (8 * sizeof(ulong64));
2225a913ee7SJerome Forissier return CRYPT_OK;
2235a913ee7SJerome Forissier }
2245a913ee7SJerome Forissier
sha3_256_init(hash_state * md)2255a913ee7SJerome Forissier int sha3_256_init(hash_state *md)
2265a913ee7SJerome Forissier {
2275a913ee7SJerome Forissier LTC_ARGCHK(md != NULL);
2285a913ee7SJerome Forissier XMEMSET(&md->sha3, 0, sizeof(md->sha3));
2295a913ee7SJerome Forissier md->sha3.capacity_words = 2 * 256 / (8 * sizeof(ulong64));
2305a913ee7SJerome Forissier return CRYPT_OK;
2315a913ee7SJerome Forissier }
2325a913ee7SJerome Forissier
sha3_384_init(hash_state * md)2335a913ee7SJerome Forissier int sha3_384_init(hash_state *md)
2345a913ee7SJerome Forissier {
2355a913ee7SJerome Forissier LTC_ARGCHK(md != NULL);
2365a913ee7SJerome Forissier XMEMSET(&md->sha3, 0, sizeof(md->sha3));
2375a913ee7SJerome Forissier md->sha3.capacity_words = 2 * 384 / (8 * sizeof(ulong64));
2385a913ee7SJerome Forissier return CRYPT_OK;
2395a913ee7SJerome Forissier }
2405a913ee7SJerome Forissier
sha3_512_init(hash_state * md)2415a913ee7SJerome Forissier int sha3_512_init(hash_state *md)
2425a913ee7SJerome Forissier {
2435a913ee7SJerome Forissier LTC_ARGCHK(md != NULL);
2445a913ee7SJerome Forissier XMEMSET(&md->sha3, 0, sizeof(md->sha3));
2455a913ee7SJerome Forissier md->sha3.capacity_words = 2 * 512 / (8 * sizeof(ulong64));
2465a913ee7SJerome Forissier return CRYPT_OK;
2475a913ee7SJerome Forissier }
2485a913ee7SJerome Forissier
2495a913ee7SJerome Forissier #ifdef LTC_SHA3
sha3_shake_init(hash_state * md,int num)2505a913ee7SJerome Forissier int sha3_shake_init(hash_state *md, int num)
2515a913ee7SJerome Forissier {
2525a913ee7SJerome Forissier LTC_ARGCHK(md != NULL);
2535a913ee7SJerome Forissier if (num != 128 && num != 256) return CRYPT_INVALID_ARG;
2545a913ee7SJerome Forissier XMEMSET(&md->sha3, 0, sizeof(md->sha3));
2555a913ee7SJerome Forissier md->sha3.capacity_words = (unsigned short)(2 * num / (8 * sizeof(ulong64)));
2565a913ee7SJerome Forissier return CRYPT_OK;
2575a913ee7SJerome Forissier }
2585a913ee7SJerome Forissier #endif
2595a913ee7SJerome Forissier
sha3_process(hash_state * md,const unsigned char * in,unsigned long inlen)2605a913ee7SJerome Forissier int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen)
2615a913ee7SJerome Forissier {
2625a913ee7SJerome Forissier /* 0...7 -- how much is needed to have a word */
2635a913ee7SJerome Forissier unsigned old_tail = (8 - md->sha3.byte_index) & 7;
2645a913ee7SJerome Forissier
2655a913ee7SJerome Forissier unsigned long words;
2665a913ee7SJerome Forissier unsigned tail;
2675a913ee7SJerome Forissier unsigned long i;
2685a913ee7SJerome Forissier
2695a913ee7SJerome Forissier if (inlen == 0) return CRYPT_OK; /* nothing to do */
2705a913ee7SJerome Forissier LTC_ARGCHK(md != NULL);
2715a913ee7SJerome Forissier LTC_ARGCHK(in != NULL);
2725a913ee7SJerome Forissier
2735a913ee7SJerome Forissier if(inlen < old_tail) { /* have no complete word or haven't started the word yet */
2745a913ee7SJerome Forissier while (inlen--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
2755a913ee7SJerome Forissier return CRYPT_OK;
2765a913ee7SJerome Forissier }
2775a913ee7SJerome Forissier
2785a913ee7SJerome Forissier if(old_tail) { /* will have one word to process */
2795a913ee7SJerome Forissier inlen -= old_tail;
2805a913ee7SJerome Forissier while (old_tail--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
2815a913ee7SJerome Forissier /* now ready to add saved to the sponge */
2825a913ee7SJerome Forissier md->sha3.s[md->sha3.word_index] ^= md->sha3.saved;
2835a913ee7SJerome Forissier md->sha3.byte_index = 0;
2845a913ee7SJerome Forissier md->sha3.saved = 0;
2855a913ee7SJerome Forissier if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) {
286*8411e6adSJerome Forissier s_keccakf(md->sha3.s);
2875a913ee7SJerome Forissier md->sha3.word_index = 0;
2885a913ee7SJerome Forissier }
2895a913ee7SJerome Forissier }
2905a913ee7SJerome Forissier
2915a913ee7SJerome Forissier /* now work in full words directly from input */
2925a913ee7SJerome Forissier words = inlen / sizeof(ulong64);
2935a913ee7SJerome Forissier tail = inlen - words * sizeof(ulong64);
2945a913ee7SJerome Forissier
2955a913ee7SJerome Forissier for(i = 0; i < words; i++, in += sizeof(ulong64)) {
2965a913ee7SJerome Forissier ulong64 t;
2975a913ee7SJerome Forissier LOAD64L(t, in);
2985a913ee7SJerome Forissier md->sha3.s[md->sha3.word_index] ^= t;
2995a913ee7SJerome Forissier if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) {
300*8411e6adSJerome Forissier s_keccakf(md->sha3.s);
3015a913ee7SJerome Forissier md->sha3.word_index = 0;
3025a913ee7SJerome Forissier }
3035a913ee7SJerome Forissier }
3045a913ee7SJerome Forissier
3055a913ee7SJerome Forissier /* finally, save the partial word */
3065a913ee7SJerome Forissier while (tail--) {
3075a913ee7SJerome Forissier md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
3085a913ee7SJerome Forissier }
3095a913ee7SJerome Forissier return CRYPT_OK;
3105a913ee7SJerome Forissier }
3115a913ee7SJerome Forissier
3125a913ee7SJerome Forissier #ifdef LTC_SHA3
sha3_done(hash_state * md,unsigned char * out)3135a913ee7SJerome Forissier int sha3_done(hash_state *md, unsigned char *out)
3145a913ee7SJerome Forissier {
315*8411e6adSJerome Forissier return ss_done(md, out, CONST64(0x06));
3165a913ee7SJerome Forissier }
3175a913ee7SJerome Forissier #endif
3185a913ee7SJerome Forissier
3195a913ee7SJerome Forissier #ifdef LTC_KECCAK
keccak_done(hash_state * md,unsigned char * out)3205a913ee7SJerome Forissier int keccak_done(hash_state *md, unsigned char *out)
3215a913ee7SJerome Forissier {
322*8411e6adSJerome Forissier return ss_done(md, out, CONST64(0x01));
3235a913ee7SJerome Forissier }
3245a913ee7SJerome Forissier #endif
3255a913ee7SJerome Forissier
3265a913ee7SJerome Forissier #ifdef LTC_SHA3
sha3_shake_done(hash_state * md,unsigned char * out,unsigned long outlen)3275a913ee7SJerome Forissier int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen)
3285a913ee7SJerome Forissier {
3295a913ee7SJerome Forissier /* IMPORTANT NOTE: sha3_shake_done can be called many times */
3305a913ee7SJerome Forissier unsigned long idx;
3315a913ee7SJerome Forissier unsigned i;
3325a913ee7SJerome Forissier
3335a913ee7SJerome Forissier if (outlen == 0) return CRYPT_OK; /* nothing to do */
3345a913ee7SJerome Forissier LTC_ARGCHK(md != NULL);
3355a913ee7SJerome Forissier LTC_ARGCHK(out != NULL);
3365a913ee7SJerome Forissier
3375a913ee7SJerome Forissier if (!md->sha3.xof_flag) {
3385a913ee7SJerome Forissier /* shake_xof operation must be done only once */
3395a913ee7SJerome Forissier md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (CONST64(0x1F) << (md->sha3.byte_index * 8)));
3405a913ee7SJerome Forissier md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000);
341*8411e6adSJerome Forissier s_keccakf(md->sha3.s);
3425a913ee7SJerome Forissier /* store sha3.s[] as little-endian bytes into sha3.sb */
3435a913ee7SJerome Forissier for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
3445a913ee7SJerome Forissier STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
3455a913ee7SJerome Forissier }
3465a913ee7SJerome Forissier md->sha3.byte_index = 0;
3475a913ee7SJerome Forissier md->sha3.xof_flag = 1;
3485a913ee7SJerome Forissier }
3495a913ee7SJerome Forissier
3505a913ee7SJerome Forissier for (idx = 0; idx < outlen; idx++) {
3515a913ee7SJerome Forissier if(md->sha3.byte_index >= (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words) * 8) {
352*8411e6adSJerome Forissier s_keccakf(md->sha3.s);
3535a913ee7SJerome Forissier /* store sha3.s[] as little-endian bytes into sha3.sb */
3545a913ee7SJerome Forissier for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
3555a913ee7SJerome Forissier STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
3565a913ee7SJerome Forissier }
3575a913ee7SJerome Forissier md->sha3.byte_index = 0;
3585a913ee7SJerome Forissier }
3595a913ee7SJerome Forissier out[idx] = md->sha3.sb[md->sha3.byte_index++];
3605a913ee7SJerome Forissier }
3615a913ee7SJerome Forissier return CRYPT_OK;
3625a913ee7SJerome Forissier }
3635a913ee7SJerome Forissier
sha3_shake_memory(int num,const unsigned char * in,unsigned long inlen,unsigned char * out,const unsigned long * outlen)3645a913ee7SJerome Forissier int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen)
3655a913ee7SJerome Forissier {
3665a913ee7SJerome Forissier hash_state md;
3675a913ee7SJerome Forissier int err;
3685a913ee7SJerome Forissier LTC_ARGCHK(in != NULL);
3695a913ee7SJerome Forissier LTC_ARGCHK(out != NULL);
3705a913ee7SJerome Forissier LTC_ARGCHK(outlen != NULL);
3715a913ee7SJerome Forissier if ((err = sha3_shake_init(&md, num)) != CRYPT_OK) return err;
3725a913ee7SJerome Forissier if ((err = sha3_shake_process(&md, in, inlen)) != CRYPT_OK) return err;
3735a913ee7SJerome Forissier if ((err = sha3_shake_done(&md, out, *outlen)) != CRYPT_OK) return err;
3745a913ee7SJerome Forissier return CRYPT_OK;
3755a913ee7SJerome Forissier }
3765a913ee7SJerome Forissier #endif
3775a913ee7SJerome Forissier
3785a913ee7SJerome Forissier #endif
379