xref: /optee_os/core/lib/libtomcrypt/src/hashes/sha3.c (revision 8411e6ad673d20c4742ed30c785e3f5cdea54dfa)
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