xref: /optee_os/core/lib/libtomcrypt/src/hashes/blake2s.c (revision 8411e6ad673d20c4742ed30c785e3f5cdea54dfa)
1*8411e6adSJerome Forissier /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2*8411e6adSJerome Forissier /* SPDX-License-Identifier: Unlicense */
35a913ee7SJerome Forissier 
45a913ee7SJerome Forissier /*
55a913ee7SJerome Forissier    BLAKE2 reference source code package - reference C implementations
65a913ee7SJerome Forissier 
75a913ee7SJerome Forissier    Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
85a913ee7SJerome Forissier    terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
95a913ee7SJerome Forissier    your option.  The terms of these licenses can be found at:
105a913ee7SJerome Forissier 
115a913ee7SJerome Forissier    - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
125a913ee7SJerome Forissier    - OpenSSL license   : https://www.openssl.org/source/license.html
135a913ee7SJerome Forissier    - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
145a913ee7SJerome Forissier 
155a913ee7SJerome Forissier    More information about the BLAKE2 hash function can be found at
165a913ee7SJerome Forissier    https://blake2.net.
175a913ee7SJerome Forissier */
185a913ee7SJerome Forissier /* see also https://www.ietf.org/rfc/rfc7693.txt */
195a913ee7SJerome Forissier 
205a913ee7SJerome Forissier #include "tomcrypt_private.h"
215a913ee7SJerome Forissier 
225a913ee7SJerome Forissier #ifdef LTC_BLAKE2S
235a913ee7SJerome Forissier 
245a913ee7SJerome Forissier enum blake2s_constant {
255a913ee7SJerome Forissier    BLAKE2S_BLOCKBYTES = 64,
265a913ee7SJerome Forissier    BLAKE2S_OUTBYTES = 32,
275a913ee7SJerome Forissier    BLAKE2S_KEYBYTES = 32,
285a913ee7SJerome Forissier    BLAKE2S_SALTBYTES = 8,
295a913ee7SJerome Forissier    BLAKE2S_PERSONALBYTES = 8,
305a913ee7SJerome Forissier    BLAKE2S_PARAM_SIZE = 32
315a913ee7SJerome Forissier };
325a913ee7SJerome Forissier 
335a913ee7SJerome Forissier /* param offsets */
345a913ee7SJerome Forissier enum {
355a913ee7SJerome Forissier    O_DIGEST_LENGTH = 0,
365a913ee7SJerome Forissier    O_KEY_LENGTH = 1,
375a913ee7SJerome Forissier    O_FANOUT = 2,
385a913ee7SJerome Forissier    O_DEPTH = 3,
395a913ee7SJerome Forissier    O_LEAF_LENGTH = 4,
405a913ee7SJerome Forissier    O_NODE_OFFSET = 8,
415a913ee7SJerome Forissier    O_XOF_LENGTH = 12,
425a913ee7SJerome Forissier    O_NODE_DEPTH = 14,
435a913ee7SJerome Forissier    O_INNER_LENGTH = 15,
445a913ee7SJerome Forissier    O_SALT = 16,
455a913ee7SJerome Forissier    O_PERSONAL = 24
465a913ee7SJerome Forissier };
475a913ee7SJerome Forissier 
485a913ee7SJerome Forissier /*
495a913ee7SJerome Forissier struct blake2s_param {
505a913ee7SJerome Forissier    unsigned char digest_length;
515a913ee7SJerome Forissier    unsigned char key_length;
525a913ee7SJerome Forissier    unsigned char fanout;
535a913ee7SJerome Forissier    unsigned char depth;
545a913ee7SJerome Forissier    ulong32 leaf_length;
555a913ee7SJerome Forissier    ulong32 node_offset;
565a913ee7SJerome Forissier    ushort16 xof_length;
575a913ee7SJerome Forissier    unsigned char node_depth;
585a913ee7SJerome Forissier    unsigned char inner_length;
595a913ee7SJerome Forissier    unsigned char salt[BLAKE2S_SALTBYTES];
605a913ee7SJerome Forissier    unsigned char personal[BLAKE2S_PERSONALBYTES];
615a913ee7SJerome Forissier };
625a913ee7SJerome Forissier */
635a913ee7SJerome Forissier 
645a913ee7SJerome Forissier const struct ltc_hash_descriptor blake2s_128_desc =
655a913ee7SJerome Forissier {
665a913ee7SJerome Forissier     "blake2s-128",
675a913ee7SJerome Forissier     21,
685a913ee7SJerome Forissier     16,
695a913ee7SJerome Forissier     64,
705a913ee7SJerome Forissier     { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 4 },
715a913ee7SJerome Forissier     11,
725a913ee7SJerome Forissier     &blake2s_128_init,
735a913ee7SJerome Forissier     &blake2s_process,
745a913ee7SJerome Forissier     &blake2s_done,
755a913ee7SJerome Forissier     &blake2s_128_test,
765a913ee7SJerome Forissier     NULL
775a913ee7SJerome Forissier };
785a913ee7SJerome Forissier 
795a913ee7SJerome Forissier const struct ltc_hash_descriptor blake2s_160_desc =
805a913ee7SJerome Forissier {
815a913ee7SJerome Forissier     "blake2s-160",
825a913ee7SJerome Forissier     22,
835a913ee7SJerome Forissier     20,
845a913ee7SJerome Forissier     64,
855a913ee7SJerome Forissier     { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 5 },
865a913ee7SJerome Forissier     11,
875a913ee7SJerome Forissier     &blake2s_160_init,
885a913ee7SJerome Forissier     &blake2s_process,
895a913ee7SJerome Forissier     &blake2s_done,
905a913ee7SJerome Forissier     &blake2s_160_test,
915a913ee7SJerome Forissier     NULL
925a913ee7SJerome Forissier };
935a913ee7SJerome Forissier 
945a913ee7SJerome Forissier const struct ltc_hash_descriptor blake2s_224_desc =
955a913ee7SJerome Forissier {
965a913ee7SJerome Forissier     "blake2s-224",
975a913ee7SJerome Forissier     23,
985a913ee7SJerome Forissier     28,
995a913ee7SJerome Forissier     64,
1005a913ee7SJerome Forissier     { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 7 },
1015a913ee7SJerome Forissier     11,
1025a913ee7SJerome Forissier     &blake2s_224_init,
1035a913ee7SJerome Forissier     &blake2s_process,
1045a913ee7SJerome Forissier     &blake2s_done,
1055a913ee7SJerome Forissier     &blake2s_224_test,
1065a913ee7SJerome Forissier     NULL
1075a913ee7SJerome Forissier };
1085a913ee7SJerome Forissier 
1095a913ee7SJerome Forissier const struct ltc_hash_descriptor blake2s_256_desc =
1105a913ee7SJerome Forissier {
1115a913ee7SJerome Forissier     "blake2s-256",
1125a913ee7SJerome Forissier     24,
1135a913ee7SJerome Forissier     32,
1145a913ee7SJerome Forissier     64,
1155a913ee7SJerome Forissier     { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 8 },
1165a913ee7SJerome Forissier     11,
1175a913ee7SJerome Forissier     &blake2s_256_init,
1185a913ee7SJerome Forissier     &blake2s_process,
1195a913ee7SJerome Forissier     &blake2s_done,
1205a913ee7SJerome Forissier     &blake2s_256_test,
1215a913ee7SJerome Forissier     NULL
1225a913ee7SJerome Forissier };
1235a913ee7SJerome Forissier 
1245a913ee7SJerome Forissier static const ulong32 blake2s_IV[8] = {
1255a913ee7SJerome Forissier     0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
1265a913ee7SJerome Forissier     0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
1275a913ee7SJerome Forissier };
1285a913ee7SJerome Forissier 
1295a913ee7SJerome Forissier static const unsigned char blake2s_sigma[10][16] = {
1305a913ee7SJerome Forissier     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
1315a913ee7SJerome Forissier     { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
1325a913ee7SJerome Forissier     { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
1335a913ee7SJerome Forissier     { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
1345a913ee7SJerome Forissier     { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
1355a913ee7SJerome Forissier     { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
1365a913ee7SJerome Forissier     { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
1375a913ee7SJerome Forissier     { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
1385a913ee7SJerome Forissier     { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
1395a913ee7SJerome Forissier     { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
1405a913ee7SJerome Forissier };
1415a913ee7SJerome Forissier 
s_blake2s_set_lastnode(hash_state * md)142*8411e6adSJerome Forissier static void s_blake2s_set_lastnode(hash_state *md) { md->blake2s.f[1] = 0xffffffffUL; }
1435a913ee7SJerome Forissier 
1445a913ee7SJerome Forissier /* Some helper functions, not necessarily useful */
s_blake2s_is_lastblock(const hash_state * md)145*8411e6adSJerome Forissier static int s_blake2s_is_lastblock(const hash_state *md) { return md->blake2s.f[0] != 0; }
1465a913ee7SJerome Forissier 
s_blake2s_set_lastblock(hash_state * md)147*8411e6adSJerome Forissier static void s_blake2s_set_lastblock(hash_state *md)
1485a913ee7SJerome Forissier {
1495a913ee7SJerome Forissier    if (md->blake2s.last_node) {
150*8411e6adSJerome Forissier       s_blake2s_set_lastnode(md);
1515a913ee7SJerome Forissier    }
1525a913ee7SJerome Forissier    md->blake2s.f[0] = 0xffffffffUL;
1535a913ee7SJerome Forissier }
1545a913ee7SJerome Forissier 
s_blake2s_increment_counter(hash_state * md,const ulong32 inc)155*8411e6adSJerome Forissier static void s_blake2s_increment_counter(hash_state *md, const ulong32 inc)
1565a913ee7SJerome Forissier {
1575a913ee7SJerome Forissier    md->blake2s.t[0] += inc;
1585a913ee7SJerome Forissier    if (md->blake2s.t[0] < inc) md->blake2s.t[1]++;
1595a913ee7SJerome Forissier }
1605a913ee7SJerome Forissier 
s_blake2s_init0(hash_state * md)161*8411e6adSJerome Forissier static int s_blake2s_init0(hash_state *md)
1625a913ee7SJerome Forissier {
1635a913ee7SJerome Forissier    int i;
1645a913ee7SJerome Forissier    XMEMSET(&md->blake2s, 0, sizeof(struct blake2s_state));
1655a913ee7SJerome Forissier 
1665a913ee7SJerome Forissier    for (i = 0; i < 8; ++i) {
1675a913ee7SJerome Forissier       md->blake2s.h[i] = blake2s_IV[i];
1685a913ee7SJerome Forissier    }
1695a913ee7SJerome Forissier 
1705a913ee7SJerome Forissier    return CRYPT_OK;
1715a913ee7SJerome Forissier }
1725a913ee7SJerome Forissier 
1735a913ee7SJerome Forissier /* init2 xors IV with input parameter block */
s_blake2s_init_param(hash_state * md,const unsigned char * P)174*8411e6adSJerome Forissier static int s_blake2s_init_param(hash_state *md, const unsigned char *P)
1755a913ee7SJerome Forissier {
1765a913ee7SJerome Forissier    unsigned long i;
1775a913ee7SJerome Forissier 
178*8411e6adSJerome Forissier    s_blake2s_init0(md);
1795a913ee7SJerome Forissier 
1805a913ee7SJerome Forissier    /* IV XOR ParamBlock */
1815a913ee7SJerome Forissier    for (i = 0; i < 8; ++i) {
1825a913ee7SJerome Forissier       ulong32 tmp;
1835a913ee7SJerome Forissier       LOAD32L(tmp, P + i * 4);
1845a913ee7SJerome Forissier       md->blake2s.h[i] ^= tmp;
1855a913ee7SJerome Forissier    }
1865a913ee7SJerome Forissier 
1875a913ee7SJerome Forissier    md->blake2s.outlen = P[O_DIGEST_LENGTH];
1885a913ee7SJerome Forissier    return CRYPT_OK;
1895a913ee7SJerome Forissier }
1905a913ee7SJerome Forissier 
1915a913ee7SJerome Forissier /**
1925a913ee7SJerome Forissier    Initialize the hash/MAC state
1935a913ee7SJerome Forissier 
1945a913ee7SJerome Forissier       Use this function to init for arbitrary sizes.
1955a913ee7SJerome Forissier 
1965a913ee7SJerome Forissier       Give a key and keylen to init for MAC mode.
1975a913ee7SJerome Forissier 
1985a913ee7SJerome Forissier    @param md      The hash state you wish to initialize
1995a913ee7SJerome Forissier    @param outlen  The desired output-length
2005a913ee7SJerome Forissier    @param key     The key of the MAC
2015a913ee7SJerome Forissier    @param keylen  The length of the key
2025a913ee7SJerome Forissier    @return CRYPT_OK if successful
2035a913ee7SJerome Forissier */
blake2s_init(hash_state * md,unsigned long outlen,const unsigned char * key,unsigned long keylen)2045a913ee7SJerome Forissier int blake2s_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen)
2055a913ee7SJerome Forissier {
2065a913ee7SJerome Forissier    unsigned char P[BLAKE2S_PARAM_SIZE];
2075a913ee7SJerome Forissier    int err;
2085a913ee7SJerome Forissier 
2095a913ee7SJerome Forissier    LTC_ARGCHK(md != NULL);
2105a913ee7SJerome Forissier 
2115a913ee7SJerome Forissier    if ((!outlen) || (outlen > BLAKE2S_OUTBYTES)) {
2125a913ee7SJerome Forissier       return CRYPT_INVALID_ARG;
2135a913ee7SJerome Forissier    }
2145a913ee7SJerome Forissier    if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2S_KEYBYTES)) {
2155a913ee7SJerome Forissier       return CRYPT_INVALID_ARG;
2165a913ee7SJerome Forissier    }
2175a913ee7SJerome Forissier 
2185a913ee7SJerome Forissier    XMEMSET(P, 0, sizeof(P));
2195a913ee7SJerome Forissier 
2205a913ee7SJerome Forissier    P[O_DIGEST_LENGTH] = (unsigned char)outlen;
2215a913ee7SJerome Forissier    P[O_KEY_LENGTH] = (unsigned char)keylen;
2225a913ee7SJerome Forissier    P[O_FANOUT] = 1;
2235a913ee7SJerome Forissier    P[O_DEPTH] = 1;
2245a913ee7SJerome Forissier 
225*8411e6adSJerome Forissier    err = s_blake2s_init_param(md, P);
2265a913ee7SJerome Forissier    if (err != CRYPT_OK) return err;
2275a913ee7SJerome Forissier 
2285a913ee7SJerome Forissier    if (key) {
2295a913ee7SJerome Forissier       unsigned char block[BLAKE2S_BLOCKBYTES];
2305a913ee7SJerome Forissier 
2315a913ee7SJerome Forissier       XMEMSET(block, 0, BLAKE2S_BLOCKBYTES);
2325a913ee7SJerome Forissier       XMEMCPY(block, key, keylen);
2335a913ee7SJerome Forissier       blake2s_process(md, block, BLAKE2S_BLOCKBYTES);
2345a913ee7SJerome Forissier 
2355a913ee7SJerome Forissier #ifdef LTC_CLEAN_STACK
2365a913ee7SJerome Forissier       zeromem(block, sizeof(block));
2375a913ee7SJerome Forissier #endif
2385a913ee7SJerome Forissier    }
2395a913ee7SJerome Forissier    return CRYPT_OK;
2405a913ee7SJerome Forissier }
2415a913ee7SJerome Forissier 
2425a913ee7SJerome Forissier /**
2435a913ee7SJerome Forissier    Initialize the hash state
2445a913ee7SJerome Forissier    @param md   The hash state you wish to initialize
2455a913ee7SJerome Forissier    @return CRYPT_OK if successful
2465a913ee7SJerome Forissier */
blake2s_128_init(hash_state * md)2475a913ee7SJerome Forissier int blake2s_128_init(hash_state *md) { return blake2s_init(md, 16, NULL, 0); }
2485a913ee7SJerome Forissier 
2495a913ee7SJerome Forissier /**
2505a913ee7SJerome Forissier    Initialize the hash state
2515a913ee7SJerome Forissier    @param md   The hash state you wish to initialize
2525a913ee7SJerome Forissier    @return CRYPT_OK if successful
2535a913ee7SJerome Forissier */
blake2s_160_init(hash_state * md)2545a913ee7SJerome Forissier int blake2s_160_init(hash_state *md) { return blake2s_init(md, 20, NULL, 0); }
2555a913ee7SJerome Forissier 
2565a913ee7SJerome Forissier /**
2575a913ee7SJerome Forissier    Initialize the hash state
2585a913ee7SJerome Forissier    @param md   The hash state you wish to initialize
2595a913ee7SJerome Forissier    @return CRYPT_OK if successful
2605a913ee7SJerome Forissier */
blake2s_224_init(hash_state * md)2615a913ee7SJerome Forissier int blake2s_224_init(hash_state *md) { return blake2s_init(md, 28, NULL, 0); }
2625a913ee7SJerome Forissier 
2635a913ee7SJerome Forissier /**
2645a913ee7SJerome Forissier    Initialize the hash state
2655a913ee7SJerome Forissier    @param md   The hash state you wish to initialize
2665a913ee7SJerome Forissier    @return CRYPT_OK if successful
2675a913ee7SJerome Forissier */
blake2s_256_init(hash_state * md)2685a913ee7SJerome Forissier int blake2s_256_init(hash_state *md) { return blake2s_init(md, 32, NULL, 0); }
2695a913ee7SJerome Forissier 
2705a913ee7SJerome Forissier #define G(r, i, a, b, c, d)                                                                                            \
2715a913ee7SJerome Forissier    do {                                                                                                                \
2725a913ee7SJerome Forissier       a = a + b + m[blake2s_sigma[r][2 * i + 0]];                                                                      \
2735a913ee7SJerome Forissier       d = ROR(d ^ a, 16);                                                                                              \
2745a913ee7SJerome Forissier       c = c + d;                                                                                                       \
2755a913ee7SJerome Forissier       b = ROR(b ^ c, 12);                                                                                              \
2765a913ee7SJerome Forissier       a = a + b + m[blake2s_sigma[r][2 * i + 1]];                                                                      \
2775a913ee7SJerome Forissier       d = ROR(d ^ a, 8);                                                                                               \
2785a913ee7SJerome Forissier       c = c + d;                                                                                                       \
2795a913ee7SJerome Forissier       b = ROR(b ^ c, 7);                                                                                               \
2805a913ee7SJerome Forissier    } while (0)
2815a913ee7SJerome Forissier #define ROUND(r)                                                                                                       \
2825a913ee7SJerome Forissier    do {                                                                                                                \
2835a913ee7SJerome Forissier       G(r, 0, v[0], v[4], v[8], v[12]);                                                                                \
2845a913ee7SJerome Forissier       G(r, 1, v[1], v[5], v[9], v[13]);                                                                                \
2855a913ee7SJerome Forissier       G(r, 2, v[2], v[6], v[10], v[14]);                                                                               \
2865a913ee7SJerome Forissier       G(r, 3, v[3], v[7], v[11], v[15]);                                                                               \
2875a913ee7SJerome Forissier       G(r, 4, v[0], v[5], v[10], v[15]);                                                                               \
2885a913ee7SJerome Forissier       G(r, 5, v[1], v[6], v[11], v[12]);                                                                               \
2895a913ee7SJerome Forissier       G(r, 6, v[2], v[7], v[8], v[13]);                                                                                \
2905a913ee7SJerome Forissier       G(r, 7, v[3], v[4], v[9], v[14]);                                                                                \
2915a913ee7SJerome Forissier    } while (0)
2925a913ee7SJerome Forissier 
2935a913ee7SJerome Forissier #ifdef LTC_CLEAN_STACK
ss_blake2s_compress(hash_state * md,const unsigned char * buf)294*8411e6adSJerome Forissier static int ss_blake2s_compress(hash_state *md, const unsigned char *buf)
2955a913ee7SJerome Forissier #else
296*8411e6adSJerome Forissier static int s_blake2s_compress(hash_state *md, const unsigned char *buf)
2975a913ee7SJerome Forissier #endif
2985a913ee7SJerome Forissier {
2995a913ee7SJerome Forissier    unsigned long i;
3005a913ee7SJerome Forissier    ulong32 m[16];
3015a913ee7SJerome Forissier    ulong32 v[16];
3025a913ee7SJerome Forissier 
3035a913ee7SJerome Forissier    for (i = 0; i < 16; ++i) {
3045a913ee7SJerome Forissier       LOAD32L(m[i], buf + i * sizeof(m[i]));
3055a913ee7SJerome Forissier    }
3065a913ee7SJerome Forissier 
3075a913ee7SJerome Forissier    for (i = 0; i < 8; ++i) {
3085a913ee7SJerome Forissier       v[i] = md->blake2s.h[i];
3095a913ee7SJerome Forissier    }
3105a913ee7SJerome Forissier 
3115a913ee7SJerome Forissier    v[8] = blake2s_IV[0];
3125a913ee7SJerome Forissier    v[9] = blake2s_IV[1];
3135a913ee7SJerome Forissier    v[10] = blake2s_IV[2];
3145a913ee7SJerome Forissier    v[11] = blake2s_IV[3];
3155a913ee7SJerome Forissier    v[12] = md->blake2s.t[0] ^ blake2s_IV[4];
3165a913ee7SJerome Forissier    v[13] = md->blake2s.t[1] ^ blake2s_IV[5];
3175a913ee7SJerome Forissier    v[14] = md->blake2s.f[0] ^ blake2s_IV[6];
3185a913ee7SJerome Forissier    v[15] = md->blake2s.f[1] ^ blake2s_IV[7];
3195a913ee7SJerome Forissier 
3205a913ee7SJerome Forissier    ROUND(0);
3215a913ee7SJerome Forissier    ROUND(1);
3225a913ee7SJerome Forissier    ROUND(2);
3235a913ee7SJerome Forissier    ROUND(3);
3245a913ee7SJerome Forissier    ROUND(4);
3255a913ee7SJerome Forissier    ROUND(5);
3265a913ee7SJerome Forissier    ROUND(6);
3275a913ee7SJerome Forissier    ROUND(7);
3285a913ee7SJerome Forissier    ROUND(8);
3295a913ee7SJerome Forissier    ROUND(9);
3305a913ee7SJerome Forissier 
3315a913ee7SJerome Forissier    for (i = 0; i < 8; ++i) {
3325a913ee7SJerome Forissier       md->blake2s.h[i] = md->blake2s.h[i] ^ v[i] ^ v[i + 8];
3335a913ee7SJerome Forissier    }
3345a913ee7SJerome Forissier    return CRYPT_OK;
3355a913ee7SJerome Forissier }
3365a913ee7SJerome Forissier #undef G
3375a913ee7SJerome Forissier #undef ROUND
3385a913ee7SJerome Forissier 
3395a913ee7SJerome Forissier #ifdef LTC_CLEAN_STACK
s_blake2s_compress(hash_state * md,const unsigned char * buf)340*8411e6adSJerome Forissier static int s_blake2s_compress(hash_state *md, const unsigned char *buf)
3415a913ee7SJerome Forissier {
3425a913ee7SJerome Forissier    int err;
343*8411e6adSJerome Forissier    err = ss_blake2s_compress(md, buf);
3445a913ee7SJerome Forissier    burn_stack(sizeof(ulong32) * (32) + sizeof(unsigned long));
3455a913ee7SJerome Forissier    return err;
3465a913ee7SJerome Forissier }
3475a913ee7SJerome Forissier #endif
3485a913ee7SJerome Forissier 
3495a913ee7SJerome Forissier /**
3505a913ee7SJerome Forissier    Process a block of memory through the hash
3515a913ee7SJerome Forissier    @param md     The hash state
3525a913ee7SJerome Forissier    @param in     The data to hash
3535a913ee7SJerome Forissier    @param inlen  The length of the data (octets)
3545a913ee7SJerome Forissier    @return CRYPT_OK if successful
3555a913ee7SJerome Forissier */
blake2s_process(hash_state * md,const unsigned char * in,unsigned long inlen)3565a913ee7SJerome Forissier int blake2s_process(hash_state *md, const unsigned char *in, unsigned long inlen)
3575a913ee7SJerome Forissier {
3585a913ee7SJerome Forissier    LTC_ARGCHK(md != NULL);
3595a913ee7SJerome Forissier    LTC_ARGCHK(in != NULL);
3605a913ee7SJerome Forissier 
3615a913ee7SJerome Forissier    if (md->blake2s.curlen > sizeof(md->blake2s.buf)) {
3625a913ee7SJerome Forissier       return CRYPT_INVALID_ARG;
3635a913ee7SJerome Forissier    }
3645a913ee7SJerome Forissier 
3655a913ee7SJerome Forissier    if (inlen > 0) {
3665a913ee7SJerome Forissier       unsigned long left = md->blake2s.curlen;
3675a913ee7SJerome Forissier       unsigned long fill = BLAKE2S_BLOCKBYTES - left;
3685a913ee7SJerome Forissier       if (inlen > fill) {
3695a913ee7SJerome Forissier          md->blake2s.curlen = 0;
3705a913ee7SJerome Forissier          XMEMCPY(md->blake2s.buf + (left % sizeof(md->blake2s.buf)), in, fill); /* Fill buffer */
371*8411e6adSJerome Forissier          s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES);
372*8411e6adSJerome Forissier          s_blake2s_compress(md, md->blake2s.buf); /* Compress */
3735a913ee7SJerome Forissier          in += fill;
3745a913ee7SJerome Forissier          inlen -= fill;
3755a913ee7SJerome Forissier          while (inlen > BLAKE2S_BLOCKBYTES) {
376*8411e6adSJerome Forissier             s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES);
377*8411e6adSJerome Forissier             s_blake2s_compress(md, in);
3785a913ee7SJerome Forissier             in += BLAKE2S_BLOCKBYTES;
3795a913ee7SJerome Forissier             inlen -= BLAKE2S_BLOCKBYTES;
3805a913ee7SJerome Forissier          }
3815a913ee7SJerome Forissier       }
3825a913ee7SJerome Forissier       XMEMCPY(md->blake2s.buf + md->blake2s.curlen, in, inlen);
3835a913ee7SJerome Forissier       md->blake2s.curlen += inlen;
3845a913ee7SJerome Forissier    }
3855a913ee7SJerome Forissier    return CRYPT_OK;
3865a913ee7SJerome Forissier }
3875a913ee7SJerome Forissier 
3885a913ee7SJerome Forissier /**
3895a913ee7SJerome Forissier    Terminate the hash to get the digest
3905a913ee7SJerome Forissier    @param md  The hash state
3915a913ee7SJerome Forissier    @param out [out] The destination of the hash (size depending on the length used on init)
3925a913ee7SJerome Forissier    @return CRYPT_OK if successful
3935a913ee7SJerome Forissier */
blake2s_done(hash_state * md,unsigned char * out)3945a913ee7SJerome Forissier int blake2s_done(hash_state *md, unsigned char *out)
3955a913ee7SJerome Forissier {
3965a913ee7SJerome Forissier    unsigned char buffer[BLAKE2S_OUTBYTES] = { 0 };
3975a913ee7SJerome Forissier    unsigned long i;
3985a913ee7SJerome Forissier 
3995a913ee7SJerome Forissier    LTC_ARGCHK(md != NULL);
4005a913ee7SJerome Forissier    LTC_ARGCHK(out != NULL);
4015a913ee7SJerome Forissier 
4025a913ee7SJerome Forissier    /* if(md->blake2s.outlen != outlen) return CRYPT_INVALID_ARG; */
4035a913ee7SJerome Forissier 
404*8411e6adSJerome Forissier    if (s_blake2s_is_lastblock(md)) {
4055a913ee7SJerome Forissier       return CRYPT_ERROR;
4065a913ee7SJerome Forissier    }
407*8411e6adSJerome Forissier    s_blake2s_increment_counter(md, md->blake2s.curlen);
408*8411e6adSJerome Forissier    s_blake2s_set_lastblock(md);
4095a913ee7SJerome Forissier    XMEMSET(md->blake2s.buf + md->blake2s.curlen, 0, BLAKE2S_BLOCKBYTES - md->blake2s.curlen); /* Padding */
410*8411e6adSJerome Forissier    s_blake2s_compress(md, md->blake2s.buf);
4115a913ee7SJerome Forissier 
4125a913ee7SJerome Forissier    for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
4135a913ee7SJerome Forissier       STORE32L(md->blake2s.h[i], buffer + i * 4);
4145a913ee7SJerome Forissier    }
4155a913ee7SJerome Forissier 
4165a913ee7SJerome Forissier    XMEMCPY(out, buffer, md->blake2s.outlen);
4175a913ee7SJerome Forissier    zeromem(md, sizeof(hash_state));
4185a913ee7SJerome Forissier #ifdef LTC_CLEAN_STACK
4195a913ee7SJerome Forissier    zeromem(buffer, sizeof(buffer));
4205a913ee7SJerome Forissier #endif
4215a913ee7SJerome Forissier    return CRYPT_OK;
4225a913ee7SJerome Forissier }
4235a913ee7SJerome Forissier 
4245a913ee7SJerome Forissier /**
4255a913ee7SJerome Forissier   Self-test the hash
4265a913ee7SJerome Forissier   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
4275a913ee7SJerome Forissier */
blake2s_256_test(void)4285a913ee7SJerome Forissier int blake2s_256_test(void)
4295a913ee7SJerome Forissier {
4305a913ee7SJerome Forissier #ifndef LTC_TEST
4315a913ee7SJerome Forissier    return CRYPT_NOP;
4325a913ee7SJerome Forissier #else
4335a913ee7SJerome Forissier    static const struct {
4345a913ee7SJerome Forissier       const char *msg;
4355a913ee7SJerome Forissier       unsigned char hash[32];
4365a913ee7SJerome Forissier   } tests[] = {
4375a913ee7SJerome Forissier     { "",
4385a913ee7SJerome Forissier       { 0x69, 0x21, 0x7a, 0x30, 0x79, 0x90, 0x80, 0x94,
4395a913ee7SJerome Forissier         0xe1, 0x11, 0x21, 0xd0, 0x42, 0x35, 0x4a, 0x7c,
4405a913ee7SJerome Forissier         0x1f, 0x55, 0xb6, 0x48, 0x2c, 0xa1, 0xa5, 0x1e,
4415a913ee7SJerome Forissier         0x1b, 0x25, 0x0d, 0xfd, 0x1e, 0xd0, 0xee, 0xf9 } },
4425a913ee7SJerome Forissier     { "abc",
4435a913ee7SJerome Forissier       { 0x50, 0x8c, 0x5e, 0x8c, 0x32, 0x7c, 0x14, 0xe2,
4445a913ee7SJerome Forissier         0xe1, 0xa7, 0x2b, 0xa3, 0x4e, 0xeb, 0x45, 0x2f,
4455a913ee7SJerome Forissier         0x37, 0x45, 0x8b, 0x20, 0x9e, 0xd6, 0x3a, 0x29,
4465a913ee7SJerome Forissier         0x4d, 0x99, 0x9b, 0x4c, 0x86, 0x67, 0x59, 0x82 } },
4475a913ee7SJerome Forissier     { "12345678901234567890123456789012345678901234567890"
4485a913ee7SJerome Forissier       "12345678901234567890123456789012345678901234567890"
4495a913ee7SJerome Forissier       "12345678901234567890123456789012345678901234567890"
4505a913ee7SJerome Forissier       "12345678901234567890123456789012345678901234567890"
4515a913ee7SJerome Forissier       "12345678901234567890123456789012345678901234567890"
4525a913ee7SJerome Forissier       "12345678901234567890123456789012345678901234567890",
4535a913ee7SJerome Forissier       { 0xa3, 0x78, 0x8b, 0x5b, 0x59, 0xee, 0xe4, 0x41,
4545a913ee7SJerome Forissier         0x95, 0x23, 0x58, 0x00, 0xa4, 0xf9, 0xfa, 0x41,
4555a913ee7SJerome Forissier         0x86, 0x0c, 0x7b, 0x1c, 0x35, 0xa2, 0x42, 0x70,
4565a913ee7SJerome Forissier         0x50, 0x80, 0x79, 0x56, 0xe3, 0xbe, 0x31, 0x74 } },
4575a913ee7SJerome Forissier 
4585a913ee7SJerome Forissier     { NULL, { 0 } }
4595a913ee7SJerome Forissier   };
4605a913ee7SJerome Forissier 
4615a913ee7SJerome Forissier    int i;
4625a913ee7SJerome Forissier    unsigned char tmp[32];
4635a913ee7SJerome Forissier    hash_state md;
4645a913ee7SJerome Forissier 
4655a913ee7SJerome Forissier    for (i = 0; tests[i].msg != NULL; i++) {
4665a913ee7SJerome Forissier       blake2s_256_init(&md);
467*8411e6adSJerome Forissier       blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
4685a913ee7SJerome Forissier       blake2s_done(&md, tmp);
4695a913ee7SJerome Forissier       if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_256", i)) {
4705a913ee7SJerome Forissier          return CRYPT_FAIL_TESTVECTOR;
4715a913ee7SJerome Forissier       }
4725a913ee7SJerome Forissier 
4735a913ee7SJerome Forissier    }
4745a913ee7SJerome Forissier    return CRYPT_OK;
4755a913ee7SJerome Forissier #endif
4765a913ee7SJerome Forissier }
4775a913ee7SJerome Forissier 
4785a913ee7SJerome Forissier /**
4795a913ee7SJerome Forissier   Self-test the hash
4805a913ee7SJerome Forissier   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
4815a913ee7SJerome Forissier */
blake2s_224_test(void)4825a913ee7SJerome Forissier int blake2s_224_test(void)
4835a913ee7SJerome Forissier {
4845a913ee7SJerome Forissier #ifndef LTC_TEST
4855a913ee7SJerome Forissier    return CRYPT_NOP;
4865a913ee7SJerome Forissier #else
4875a913ee7SJerome Forissier    static const struct {
4885a913ee7SJerome Forissier       const char *msg;
4895a913ee7SJerome Forissier       unsigned char hash[28];
4905a913ee7SJerome Forissier   } tests[] = {
4915a913ee7SJerome Forissier     { "",
4925a913ee7SJerome Forissier       { 0x1f, 0xa1, 0x29, 0x1e, 0x65, 0x24, 0x8b, 0x37,
4935a913ee7SJerome Forissier         0xb3, 0x43, 0x34, 0x75, 0xb2, 0xa0, 0xdd, 0x63,
4945a913ee7SJerome Forissier         0xd5, 0x4a, 0x11, 0xec, 0xc4, 0xe3, 0xe0, 0x34,
4955a913ee7SJerome Forissier         0xe7, 0xbc, 0x1e, 0xf4 } },
4965a913ee7SJerome Forissier     { "abc",
4975a913ee7SJerome Forissier       { 0x0b, 0x03, 0x3f, 0xc2, 0x26, 0xdf, 0x7a, 0xbd,
4985a913ee7SJerome Forissier         0xe2, 0x9f, 0x67, 0xa0, 0x5d, 0x3d, 0xc6, 0x2c,
4995a913ee7SJerome Forissier         0xf2, 0x71, 0xef, 0x3d, 0xfe, 0xa4, 0xd3, 0x87,
5005a913ee7SJerome Forissier         0x40, 0x7f, 0xbd, 0x55 } },
5015a913ee7SJerome Forissier 
5025a913ee7SJerome Forissier     { NULL, { 0 } }
5035a913ee7SJerome Forissier   };
5045a913ee7SJerome Forissier 
5055a913ee7SJerome Forissier    int i;
5065a913ee7SJerome Forissier    unsigned char tmp[28];
5075a913ee7SJerome Forissier    hash_state md;
5085a913ee7SJerome Forissier 
5095a913ee7SJerome Forissier    for (i = 0; tests[i].msg != NULL; i++) {
5105a913ee7SJerome Forissier       blake2s_224_init(&md);
511*8411e6adSJerome Forissier       blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
5125a913ee7SJerome Forissier       blake2s_done(&md, tmp);
5135a913ee7SJerome Forissier       if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_224", i)) {
5145a913ee7SJerome Forissier          return CRYPT_FAIL_TESTVECTOR;
5155a913ee7SJerome Forissier       }
5165a913ee7SJerome Forissier 
5175a913ee7SJerome Forissier    }
5185a913ee7SJerome Forissier    return CRYPT_OK;
5195a913ee7SJerome Forissier #endif
5205a913ee7SJerome Forissier }
5215a913ee7SJerome Forissier 
5225a913ee7SJerome Forissier /**
5235a913ee7SJerome Forissier   Self-test the hash
5245a913ee7SJerome Forissier   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
5255a913ee7SJerome Forissier */
blake2s_160_test(void)5265a913ee7SJerome Forissier int blake2s_160_test(void)
5275a913ee7SJerome Forissier {
5285a913ee7SJerome Forissier #ifndef LTC_TEST
5295a913ee7SJerome Forissier    return CRYPT_NOP;
5305a913ee7SJerome Forissier #else
5315a913ee7SJerome Forissier    static const struct {
5325a913ee7SJerome Forissier       const char *msg;
5335a913ee7SJerome Forissier       unsigned char hash[20];
5345a913ee7SJerome Forissier   } tests[] = {
5355a913ee7SJerome Forissier     { "",
5365a913ee7SJerome Forissier       { 0x35, 0x4c, 0x9c, 0x33, 0xf7, 0x35, 0x96, 0x24,
5375a913ee7SJerome Forissier         0x18, 0xbd, 0xac, 0xb9, 0x47, 0x98, 0x73, 0x42,
5385a913ee7SJerome Forissier         0x9c, 0x34, 0x91, 0x6f} },
5395a913ee7SJerome Forissier     { "abc",
5405a913ee7SJerome Forissier       { 0x5a, 0xe3, 0xb9, 0x9b, 0xe2, 0x9b, 0x01, 0x83,
5415a913ee7SJerome Forissier         0x4c, 0x3b, 0x50, 0x85, 0x21, 0xed, 0xe6, 0x04,
5425a913ee7SJerome Forissier         0x38, 0xf8, 0xde, 0x17 } },
5435a913ee7SJerome Forissier 
5445a913ee7SJerome Forissier     { NULL, { 0 } }
5455a913ee7SJerome Forissier   };
5465a913ee7SJerome Forissier 
5475a913ee7SJerome Forissier    int i;
5485a913ee7SJerome Forissier    unsigned char tmp[20];
5495a913ee7SJerome Forissier    hash_state md;
5505a913ee7SJerome Forissier 
5515a913ee7SJerome Forissier    for (i = 0; tests[i].msg != NULL; i++) {
5525a913ee7SJerome Forissier       blake2s_160_init(&md);
553*8411e6adSJerome Forissier       blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
5545a913ee7SJerome Forissier       blake2s_done(&md, tmp);
5555a913ee7SJerome Forissier       if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_160", i)) {
5565a913ee7SJerome Forissier          return CRYPT_FAIL_TESTVECTOR;
5575a913ee7SJerome Forissier       }
5585a913ee7SJerome Forissier 
5595a913ee7SJerome Forissier    }
5605a913ee7SJerome Forissier    return CRYPT_OK;
5615a913ee7SJerome Forissier #endif
5625a913ee7SJerome Forissier }
5635a913ee7SJerome Forissier 
5645a913ee7SJerome Forissier /**
5655a913ee7SJerome Forissier   Self-test the hash
5665a913ee7SJerome Forissier   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
5675a913ee7SJerome Forissier */
blake2s_128_test(void)5685a913ee7SJerome Forissier int blake2s_128_test(void)
5695a913ee7SJerome Forissier {
5705a913ee7SJerome Forissier #ifndef LTC_TEST
5715a913ee7SJerome Forissier    return CRYPT_NOP;
5725a913ee7SJerome Forissier #else
5735a913ee7SJerome Forissier    static const struct {
5745a913ee7SJerome Forissier       const char *msg;
5755a913ee7SJerome Forissier       unsigned char hash[16];
5765a913ee7SJerome Forissier   } tests[] = {
5775a913ee7SJerome Forissier     { "",
5785a913ee7SJerome Forissier       { 0x64, 0x55, 0x0d, 0x6f, 0xfe, 0x2c, 0x0a, 0x01,
5795a913ee7SJerome Forissier         0xa1, 0x4a, 0xba, 0x1e, 0xad, 0xe0, 0x20, 0x0c } },
5805a913ee7SJerome Forissier     { "abc",
5815a913ee7SJerome Forissier       { 0xaa, 0x49, 0x38, 0x11, 0x9b, 0x1d, 0xc7, 0xb8,
5825a913ee7SJerome Forissier         0x7c, 0xba, 0xd0, 0xff, 0xd2, 0x00, 0xd0, 0xae } },
5835a913ee7SJerome Forissier 
5845a913ee7SJerome Forissier     { NULL, { 0 } }
5855a913ee7SJerome Forissier   };
5865a913ee7SJerome Forissier 
5875a913ee7SJerome Forissier    int i;
5885a913ee7SJerome Forissier    unsigned char tmp[16];
5895a913ee7SJerome Forissier    hash_state md;
5905a913ee7SJerome Forissier 
5915a913ee7SJerome Forissier    for (i = 0; tests[i].msg != NULL; i++) {
5925a913ee7SJerome Forissier       blake2s_128_init(&md);
593*8411e6adSJerome Forissier       blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
5945a913ee7SJerome Forissier       blake2s_done(&md, tmp);
5955a913ee7SJerome Forissier       if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_128", i)) {
5965a913ee7SJerome Forissier          return CRYPT_FAIL_TESTVECTOR;
5975a913ee7SJerome Forissier       }
5985a913ee7SJerome Forissier    }
5995a913ee7SJerome Forissier    return CRYPT_OK;
6005a913ee7SJerome Forissier #endif
6015a913ee7SJerome Forissier }
6025a913ee7SJerome Forissier 
6035a913ee7SJerome Forissier #endif
604