17db96d56Sopenharmony_ci// sha3.c
27db96d56Sopenharmony_ci// 19-Nov-11  Markku-Juhani O. Saarinen <mjos@iki.fi>
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_ci// Revised 07-Aug-15 to match with official release of FIPS PUB 202 "SHA3"
57db96d56Sopenharmony_ci// Revised 03-Sep-15 for portability + OpenSSL - style API
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ci#include "sha3.h"
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci// update the state with given number of rounds
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_cistatic void sha3_keccakf(uint64_t st[25])
127db96d56Sopenharmony_ci{
137db96d56Sopenharmony_ci    // constants
147db96d56Sopenharmony_ci    const uint64_t keccakf_rndc[24] = {
157db96d56Sopenharmony_ci        0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
167db96d56Sopenharmony_ci        0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
177db96d56Sopenharmony_ci        0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
187db96d56Sopenharmony_ci        0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
197db96d56Sopenharmony_ci        0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
207db96d56Sopenharmony_ci        0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
217db96d56Sopenharmony_ci        0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
227db96d56Sopenharmony_ci        0x8000000000008080, 0x0000000080000001, 0x8000000080008008
237db96d56Sopenharmony_ci    };
247db96d56Sopenharmony_ci    const int keccakf_rotc[24] = {
257db96d56Sopenharmony_ci        1,  3,  6,  10, 15, 21, 28, 36, 45, 55, 2,  14,
267db96d56Sopenharmony_ci        27, 41, 56, 8,  25, 43, 62, 18, 39, 61, 20, 44
277db96d56Sopenharmony_ci    };
287db96d56Sopenharmony_ci    const int keccakf_piln[24] = {
297db96d56Sopenharmony_ci        10, 7,  11, 17, 18, 3, 5,  16, 8,  21, 24, 4,
307db96d56Sopenharmony_ci        15, 23, 19, 13, 12, 2, 20, 14, 22, 9,  6,  1
317db96d56Sopenharmony_ci    };
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ci    // variables
347db96d56Sopenharmony_ci    int i, j, r;
357db96d56Sopenharmony_ci    uint64_t t, bc[5];
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
387db96d56Sopenharmony_ci    uint8_t *v;
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_ci    // endianess conversion. this is redundant on little-endian targets
417db96d56Sopenharmony_ci    for (i = 0; i < 25; i++) {
427db96d56Sopenharmony_ci        v = (uint8_t *) &st[i];
437db96d56Sopenharmony_ci        st[i] = ((uint64_t) v[0])     | (((uint64_t) v[1]) << 8) |
447db96d56Sopenharmony_ci            (((uint64_t) v[2]) << 16) | (((uint64_t) v[3]) << 24) |
457db96d56Sopenharmony_ci            (((uint64_t) v[4]) << 32) | (((uint64_t) v[5]) << 40) |
467db96d56Sopenharmony_ci            (((uint64_t) v[6]) << 48) | (((uint64_t) v[7]) << 56);
477db96d56Sopenharmony_ci    }
487db96d56Sopenharmony_ci#endif
497db96d56Sopenharmony_ci
507db96d56Sopenharmony_ci    // actual iteration
517db96d56Sopenharmony_ci    for (r = 0; r < KECCAKF_ROUNDS; r++) {
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ci        // Theta
547db96d56Sopenharmony_ci        for (i = 0; i < 5; i++)
557db96d56Sopenharmony_ci            bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20];
567db96d56Sopenharmony_ci
577db96d56Sopenharmony_ci        for (i = 0; i < 5; i++) {
587db96d56Sopenharmony_ci            t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
597db96d56Sopenharmony_ci            for (j = 0; j < 25; j += 5)
607db96d56Sopenharmony_ci                st[j + i] ^= t;
617db96d56Sopenharmony_ci        }
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_ci        // Rho Pi
647db96d56Sopenharmony_ci        t = st[1];
657db96d56Sopenharmony_ci        for (i = 0; i < 24; i++) {
667db96d56Sopenharmony_ci            j = keccakf_piln[i];
677db96d56Sopenharmony_ci            bc[0] = st[j];
687db96d56Sopenharmony_ci            st[j] = ROTL64(t, keccakf_rotc[i]);
697db96d56Sopenharmony_ci            t = bc[0];
707db96d56Sopenharmony_ci        }
717db96d56Sopenharmony_ci
727db96d56Sopenharmony_ci        //  Chi
737db96d56Sopenharmony_ci        for (j = 0; j < 25; j += 5) {
747db96d56Sopenharmony_ci            for (i = 0; i < 5; i++)
757db96d56Sopenharmony_ci                bc[i] = st[j + i];
767db96d56Sopenharmony_ci            for (i = 0; i < 5; i++)
777db96d56Sopenharmony_ci                st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
787db96d56Sopenharmony_ci        }
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_ci        //  Iota
817db96d56Sopenharmony_ci        st[0] ^= keccakf_rndc[r];
827db96d56Sopenharmony_ci    }
837db96d56Sopenharmony_ci
847db96d56Sopenharmony_ci#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
857db96d56Sopenharmony_ci    // endianess conversion. this is redundant on little-endian targets
867db96d56Sopenharmony_ci    for (i = 0; i < 25; i++) {
877db96d56Sopenharmony_ci        v = (uint8_t *) &st[i];
887db96d56Sopenharmony_ci        t = st[i];
897db96d56Sopenharmony_ci        v[0] = t & 0xFF;
907db96d56Sopenharmony_ci        v[1] = (t >> 8) & 0xFF;
917db96d56Sopenharmony_ci        v[2] = (t >> 16) & 0xFF;
927db96d56Sopenharmony_ci        v[3] = (t >> 24) & 0xFF;
937db96d56Sopenharmony_ci        v[4] = (t >> 32) & 0xFF;
947db96d56Sopenharmony_ci        v[5] = (t >> 40) & 0xFF;
957db96d56Sopenharmony_ci        v[6] = (t >> 48) & 0xFF;
967db96d56Sopenharmony_ci        v[7] = (t >> 56) & 0xFF;
977db96d56Sopenharmony_ci    }
987db96d56Sopenharmony_ci#endif
997db96d56Sopenharmony_ci}
1007db96d56Sopenharmony_ci
1017db96d56Sopenharmony_ci// Initialize the context for SHA3
1027db96d56Sopenharmony_ci
1037db96d56Sopenharmony_cistatic int sha3_init(sha3_ctx_t *c, int mdlen)
1047db96d56Sopenharmony_ci{
1057db96d56Sopenharmony_ci    int i;
1067db96d56Sopenharmony_ci
1077db96d56Sopenharmony_ci    for (i = 0; i < 25; i++)
1087db96d56Sopenharmony_ci        c->st.q[i] = 0;
1097db96d56Sopenharmony_ci    c->mdlen = mdlen;
1107db96d56Sopenharmony_ci    c->rsiz = 200 - 2 * mdlen;
1117db96d56Sopenharmony_ci    c->pt = 0;
1127db96d56Sopenharmony_ci
1137db96d56Sopenharmony_ci    return 1;
1147db96d56Sopenharmony_ci}
1157db96d56Sopenharmony_ci
1167db96d56Sopenharmony_ci// update state with more data
1177db96d56Sopenharmony_ci
1187db96d56Sopenharmony_cistatic int sha3_update(sha3_ctx_t *c, const void *data, size_t len)
1197db96d56Sopenharmony_ci{
1207db96d56Sopenharmony_ci    size_t i;
1217db96d56Sopenharmony_ci    int j;
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_ci    j = c->pt;
1247db96d56Sopenharmony_ci    for (i = 0; i < len; i++) {
1257db96d56Sopenharmony_ci        c->st.b[j++] ^= ((const uint8_t *) data)[i];
1267db96d56Sopenharmony_ci        if (j >= c->rsiz) {
1277db96d56Sopenharmony_ci            sha3_keccakf(c->st.q);
1287db96d56Sopenharmony_ci            j = 0;
1297db96d56Sopenharmony_ci        }
1307db96d56Sopenharmony_ci    }
1317db96d56Sopenharmony_ci    c->pt = j;
1327db96d56Sopenharmony_ci
1337db96d56Sopenharmony_ci    return 1;
1347db96d56Sopenharmony_ci}
1357db96d56Sopenharmony_ci
1367db96d56Sopenharmony_ci// finalize and output a hash
1377db96d56Sopenharmony_ci
1387db96d56Sopenharmony_cistatic int sha3_final(void *md, sha3_ctx_t *c)
1397db96d56Sopenharmony_ci{
1407db96d56Sopenharmony_ci    int i;
1417db96d56Sopenharmony_ci
1427db96d56Sopenharmony_ci    c->st.b[c->pt] ^= 0x06;
1437db96d56Sopenharmony_ci    c->st.b[c->rsiz - 1] ^= 0x80;
1447db96d56Sopenharmony_ci    sha3_keccakf(c->st.q);
1457db96d56Sopenharmony_ci
1467db96d56Sopenharmony_ci    for (i = 0; i < c->mdlen; i++) {
1477db96d56Sopenharmony_ci        ((uint8_t *) md)[i] = c->st.b[i];
1487db96d56Sopenharmony_ci    }
1497db96d56Sopenharmony_ci
1507db96d56Sopenharmony_ci    return 1;
1517db96d56Sopenharmony_ci}
1527db96d56Sopenharmony_ci
1537db96d56Sopenharmony_ci#if 0
1547db96d56Sopenharmony_ci// compute a SHA-3 hash (md) of given byte length from "in"
1557db96d56Sopenharmony_ci
1567db96d56Sopenharmony_civoid *sha3(const void *in, size_t inlen, void *md, int mdlen)
1577db96d56Sopenharmony_ci{
1587db96d56Sopenharmony_ci    sha3_ctx_t sha3;
1597db96d56Sopenharmony_ci
1607db96d56Sopenharmony_ci    sha3_init(&sha3, mdlen);
1617db96d56Sopenharmony_ci    sha3_update(&sha3, in, inlen);
1627db96d56Sopenharmony_ci    sha3_final(md, &sha3);
1637db96d56Sopenharmony_ci
1647db96d56Sopenharmony_ci    return md;
1657db96d56Sopenharmony_ci}
1667db96d56Sopenharmony_ci#endif
1677db96d56Sopenharmony_ci
1687db96d56Sopenharmony_ci// SHAKE128 and SHAKE256 extensible-output functionality
1697db96d56Sopenharmony_ci
1707db96d56Sopenharmony_cistatic void shake_xof(sha3_ctx_t *c)
1717db96d56Sopenharmony_ci{
1727db96d56Sopenharmony_ci    c->st.b[c->pt] ^= 0x1F;
1737db96d56Sopenharmony_ci    c->st.b[c->rsiz - 1] ^= 0x80;
1747db96d56Sopenharmony_ci    sha3_keccakf(c->st.q);
1757db96d56Sopenharmony_ci    c->pt = 0;
1767db96d56Sopenharmony_ci}
1777db96d56Sopenharmony_ci
1787db96d56Sopenharmony_cistatic void shake_out(sha3_ctx_t *c, void *out, size_t len)
1797db96d56Sopenharmony_ci{
1807db96d56Sopenharmony_ci    size_t i;
1817db96d56Sopenharmony_ci    int j;
1827db96d56Sopenharmony_ci
1837db96d56Sopenharmony_ci    j = c->pt;
1847db96d56Sopenharmony_ci    for (i = 0; i < len; i++) {
1857db96d56Sopenharmony_ci        if (j >= c->rsiz) {
1867db96d56Sopenharmony_ci            sha3_keccakf(c->st.q);
1877db96d56Sopenharmony_ci            j = 0;
1887db96d56Sopenharmony_ci        }
1897db96d56Sopenharmony_ci        ((uint8_t *) out)[i] = c->st.b[j++];
1907db96d56Sopenharmony_ci    }
1917db96d56Sopenharmony_ci    c->pt = j;
1927db96d56Sopenharmony_ci}
1937db96d56Sopenharmony_ci
194