xref: /optee_os/core/lib/libtomcrypt/src/hashes/blake2b.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_BLAKE2B
235a913ee7SJerome Forissier 
245a913ee7SJerome Forissier enum blake2b_constant {
255a913ee7SJerome Forissier    BLAKE2B_BLOCKBYTES = 128,
265a913ee7SJerome Forissier    BLAKE2B_OUTBYTES = 64,
275a913ee7SJerome Forissier    BLAKE2B_KEYBYTES = 64,
285a913ee7SJerome Forissier    BLAKE2B_SALTBYTES = 16,
295a913ee7SJerome Forissier    BLAKE2B_PERSONALBYTES = 16,
305a913ee7SJerome Forissier    BLAKE2B_PARAM_SIZE = 64
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 = 16,
435a913ee7SJerome Forissier    O_INNER_LENGTH = 17,
445a913ee7SJerome Forissier    O_RESERVED = 18,
455a913ee7SJerome Forissier    O_SALT = 32,
465a913ee7SJerome Forissier    O_PERSONAL = 48
475a913ee7SJerome Forissier };
485a913ee7SJerome Forissier 
495a913ee7SJerome Forissier /*
505a913ee7SJerome Forissier struct blake2b_param {
515a913ee7SJerome Forissier    unsigned char digest_length;
525a913ee7SJerome Forissier    unsigned char key_length;
535a913ee7SJerome Forissier    unsigned char fanout;
545a913ee7SJerome Forissier    unsigned char depth;
555a913ee7SJerome Forissier    ulong32 leaf_length;
565a913ee7SJerome Forissier    ulong32 node_offset;
575a913ee7SJerome Forissier    ulong32 xof_length;
585a913ee7SJerome Forissier    unsigned char node_depth;
595a913ee7SJerome Forissier    unsigned char inner_length;
605a913ee7SJerome Forissier    unsigned char reserved[14];
615a913ee7SJerome Forissier    unsigned char salt[BLAKE2B_SALTBYTES];
625a913ee7SJerome Forissier    unsigned char personal[BLAKE2B_PERSONALBYTES];
635a913ee7SJerome Forissier };
645a913ee7SJerome Forissier */
655a913ee7SJerome Forissier 
665a913ee7SJerome Forissier const struct ltc_hash_descriptor blake2b_160_desc =
675a913ee7SJerome Forissier {
685a913ee7SJerome Forissier     "blake2b-160",
695a913ee7SJerome Forissier     25,
705a913ee7SJerome Forissier     20,
715a913ee7SJerome Forissier     128,
725a913ee7SJerome Forissier     { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 5 },
735a913ee7SJerome Forissier     11,
745a913ee7SJerome Forissier     &blake2b_160_init,
755a913ee7SJerome Forissier     &blake2b_process,
765a913ee7SJerome Forissier     &blake2b_done,
775a913ee7SJerome Forissier     &blake2b_160_test,
785a913ee7SJerome Forissier     NULL
795a913ee7SJerome Forissier };
805a913ee7SJerome Forissier 
815a913ee7SJerome Forissier const struct ltc_hash_descriptor blake2b_256_desc =
825a913ee7SJerome Forissier {
835a913ee7SJerome Forissier     "blake2b-256",
845a913ee7SJerome Forissier     26,
855a913ee7SJerome Forissier     32,
865a913ee7SJerome Forissier     128,
875a913ee7SJerome Forissier     { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 8 },
885a913ee7SJerome Forissier     11,
895a913ee7SJerome Forissier     &blake2b_256_init,
905a913ee7SJerome Forissier     &blake2b_process,
915a913ee7SJerome Forissier     &blake2b_done,
925a913ee7SJerome Forissier     &blake2b_256_test,
935a913ee7SJerome Forissier     NULL
945a913ee7SJerome Forissier };
955a913ee7SJerome Forissier 
965a913ee7SJerome Forissier const struct ltc_hash_descriptor blake2b_384_desc =
975a913ee7SJerome Forissier {
985a913ee7SJerome Forissier     "blake2b-384",
995a913ee7SJerome Forissier     27,
1005a913ee7SJerome Forissier     48,
1015a913ee7SJerome Forissier     128,
1025a913ee7SJerome Forissier     { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 12 },
1035a913ee7SJerome Forissier     11,
1045a913ee7SJerome Forissier     &blake2b_384_init,
1055a913ee7SJerome Forissier     &blake2b_process,
1065a913ee7SJerome Forissier     &blake2b_done,
1075a913ee7SJerome Forissier     &blake2b_384_test,
1085a913ee7SJerome Forissier     NULL
1095a913ee7SJerome Forissier };
1105a913ee7SJerome Forissier 
1115a913ee7SJerome Forissier const struct ltc_hash_descriptor blake2b_512_desc =
1125a913ee7SJerome Forissier {
1135a913ee7SJerome Forissier     "blake2b-512",
1145a913ee7SJerome Forissier     28,
1155a913ee7SJerome Forissier     64,
1165a913ee7SJerome Forissier     128,
1175a913ee7SJerome Forissier     { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 16 },
1185a913ee7SJerome Forissier     11,
1195a913ee7SJerome Forissier     &blake2b_512_init,
1205a913ee7SJerome Forissier     &blake2b_process,
1215a913ee7SJerome Forissier     &blake2b_done,
1225a913ee7SJerome Forissier     &blake2b_512_test,
1235a913ee7SJerome Forissier     NULL
1245a913ee7SJerome Forissier };
1255a913ee7SJerome Forissier 
1265a913ee7SJerome Forissier static const ulong64 blake2b_IV[8] =
1275a913ee7SJerome Forissier {
1285a913ee7SJerome Forissier   CONST64(0x6a09e667f3bcc908), CONST64(0xbb67ae8584caa73b),
1295a913ee7SJerome Forissier   CONST64(0x3c6ef372fe94f82b), CONST64(0xa54ff53a5f1d36f1),
1305a913ee7SJerome Forissier   CONST64(0x510e527fade682d1), CONST64(0x9b05688c2b3e6c1f),
1315a913ee7SJerome Forissier   CONST64(0x1f83d9abfb41bd6b), CONST64(0x5be0cd19137e2179)
1325a913ee7SJerome Forissier };
1335a913ee7SJerome Forissier 
1345a913ee7SJerome Forissier static const unsigned char blake2b_sigma[12][16] =
1355a913ee7SJerome Forissier {
1365a913ee7SJerome Forissier   {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,
1375a913ee7SJerome Forissier   { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 } ,
1385a913ee7SJerome Forissier   { 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4 } ,
1395a913ee7SJerome Forissier   {  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8 } ,
1405a913ee7SJerome Forissier   {  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13 } ,
1415a913ee7SJerome Forissier   {  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9 } ,
1425a913ee7SJerome Forissier   { 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11 } ,
1435a913ee7SJerome Forissier   { 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10 } ,
1445a913ee7SJerome Forissier   {  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 } ,
1455a913ee7SJerome Forissier   { 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0 } ,
1465a913ee7SJerome Forissier   {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,
1475a913ee7SJerome Forissier   { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 }
1485a913ee7SJerome Forissier };
1495a913ee7SJerome Forissier 
s_blake2b_set_lastnode(hash_state * md)150*8411e6adSJerome Forissier static void s_blake2b_set_lastnode(hash_state *md) { md->blake2b.f[1] = CONST64(0xffffffffffffffff); }
1515a913ee7SJerome Forissier 
1525a913ee7SJerome Forissier /* Some helper functions, not necessarily useful */
s_blake2b_is_lastblock(const hash_state * md)153*8411e6adSJerome Forissier static int s_blake2b_is_lastblock(const hash_state *md) { return md->blake2b.f[0] != 0; }
1545a913ee7SJerome Forissier 
s_blake2b_set_lastblock(hash_state * md)155*8411e6adSJerome Forissier static void s_blake2b_set_lastblock(hash_state *md)
1565a913ee7SJerome Forissier {
1575a913ee7SJerome Forissier    if (md->blake2b.last_node) {
158*8411e6adSJerome Forissier       s_blake2b_set_lastnode(md);
1595a913ee7SJerome Forissier    }
1605a913ee7SJerome Forissier    md->blake2b.f[0] = CONST64(0xffffffffffffffff);
1615a913ee7SJerome Forissier }
1625a913ee7SJerome Forissier 
s_blake2b_increment_counter(hash_state * md,ulong64 inc)163*8411e6adSJerome Forissier static void s_blake2b_increment_counter(hash_state *md, ulong64 inc)
1645a913ee7SJerome Forissier {
1655a913ee7SJerome Forissier    md->blake2b.t[0] += inc;
1665a913ee7SJerome Forissier    if (md->blake2b.t[0] < inc) md->blake2b.t[1]++;
1675a913ee7SJerome Forissier }
1685a913ee7SJerome Forissier 
s_blake2b_init0(hash_state * md)169*8411e6adSJerome Forissier static void s_blake2b_init0(hash_state *md)
1705a913ee7SJerome Forissier {
1715a913ee7SJerome Forissier    unsigned long i;
1725a913ee7SJerome Forissier    XMEMSET(&md->blake2b, 0, sizeof(md->blake2b));
1735a913ee7SJerome Forissier 
1745a913ee7SJerome Forissier    for (i = 0; i < 8; ++i) {
1755a913ee7SJerome Forissier       md->blake2b.h[i] = blake2b_IV[i];
1765a913ee7SJerome Forissier    }
1775a913ee7SJerome Forissier }
1785a913ee7SJerome Forissier 
1795a913ee7SJerome Forissier /* init xors IV with input parameter block */
s_blake2b_init_param(hash_state * md,const unsigned char * P)180*8411e6adSJerome Forissier static int s_blake2b_init_param(hash_state *md, const unsigned char *P)
1815a913ee7SJerome Forissier {
1825a913ee7SJerome Forissier    unsigned long i;
1835a913ee7SJerome Forissier 
184*8411e6adSJerome Forissier    s_blake2b_init0(md);
1855a913ee7SJerome Forissier 
1865a913ee7SJerome Forissier    /* IV XOR ParamBlock */
1875a913ee7SJerome Forissier    for (i = 0; i < 8; ++i) {
1885a913ee7SJerome Forissier       ulong64 tmp;
1895a913ee7SJerome Forissier       LOAD64L(tmp, P + i * 8);
1905a913ee7SJerome Forissier       md->blake2b.h[i] ^= tmp;
1915a913ee7SJerome Forissier    }
1925a913ee7SJerome Forissier 
1935a913ee7SJerome Forissier    md->blake2b.outlen = P[O_DIGEST_LENGTH];
1945a913ee7SJerome Forissier    return CRYPT_OK;
1955a913ee7SJerome Forissier }
1965a913ee7SJerome Forissier 
1975a913ee7SJerome Forissier /**
1985a913ee7SJerome Forissier    Initialize the hash/MAC state
1995a913ee7SJerome Forissier 
2005a913ee7SJerome Forissier       Use this function to init for arbitrary sizes.
2015a913ee7SJerome Forissier 
2025a913ee7SJerome Forissier       Give a key and keylen to init for MAC mode.
2035a913ee7SJerome Forissier 
2045a913ee7SJerome Forissier    @param md      The hash state you wish to initialize
2055a913ee7SJerome Forissier    @param outlen  The desired output-length
2065a913ee7SJerome Forissier    @param key     The key of the MAC
2075a913ee7SJerome Forissier    @param keylen  The length of the key
2085a913ee7SJerome Forissier    @return CRYPT_OK if successful
2095a913ee7SJerome Forissier */
blake2b_init(hash_state * md,unsigned long outlen,const unsigned char * key,unsigned long keylen)2105a913ee7SJerome Forissier int blake2b_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen)
2115a913ee7SJerome Forissier {
2125a913ee7SJerome Forissier    unsigned char P[BLAKE2B_PARAM_SIZE];
2135a913ee7SJerome Forissier    int err;
2145a913ee7SJerome Forissier 
2155a913ee7SJerome Forissier    LTC_ARGCHK(md != NULL);
2165a913ee7SJerome Forissier 
2175a913ee7SJerome Forissier    if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) {
2185a913ee7SJerome Forissier       return CRYPT_INVALID_ARG;
2195a913ee7SJerome Forissier    }
2205a913ee7SJerome Forissier    if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2B_KEYBYTES)) {
2215a913ee7SJerome Forissier       return CRYPT_INVALID_ARG;
2225a913ee7SJerome Forissier    }
2235a913ee7SJerome Forissier 
2245a913ee7SJerome Forissier    XMEMSET(P, 0, sizeof(P));
2255a913ee7SJerome Forissier 
2265a913ee7SJerome Forissier    P[O_DIGEST_LENGTH] = (unsigned char)outlen;
2275a913ee7SJerome Forissier    P[O_KEY_LENGTH] = (unsigned char)keylen;
2285a913ee7SJerome Forissier    P[O_FANOUT] = 1;
2295a913ee7SJerome Forissier    P[O_DEPTH] = 1;
2305a913ee7SJerome Forissier 
231*8411e6adSJerome Forissier    err = s_blake2b_init_param(md, P);
2325a913ee7SJerome Forissier    if (err != CRYPT_OK) return err;
2335a913ee7SJerome Forissier 
2345a913ee7SJerome Forissier    if (key) {
2355a913ee7SJerome Forissier       unsigned char block[BLAKE2B_BLOCKBYTES];
2365a913ee7SJerome Forissier 
2375a913ee7SJerome Forissier       XMEMSET(block, 0, BLAKE2B_BLOCKBYTES);
2385a913ee7SJerome Forissier       XMEMCPY(block, key, keylen);
2395a913ee7SJerome Forissier       blake2b_process(md, block, BLAKE2B_BLOCKBYTES);
2405a913ee7SJerome Forissier 
2415a913ee7SJerome Forissier #ifdef LTC_CLEAN_STACK
2425a913ee7SJerome Forissier       zeromem(block, sizeof(block));
2435a913ee7SJerome Forissier #endif
2445a913ee7SJerome Forissier    }
2455a913ee7SJerome Forissier 
2465a913ee7SJerome Forissier    return CRYPT_OK;
2475a913ee7SJerome Forissier }
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 */
blake2b_160_init(hash_state * md)2545a913ee7SJerome Forissier int blake2b_160_init(hash_state *md) { return blake2b_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 */
blake2b_256_init(hash_state * md)2615a913ee7SJerome Forissier int blake2b_256_init(hash_state *md) { return blake2b_init(md, 32, 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 */
blake2b_384_init(hash_state * md)2685a913ee7SJerome Forissier int blake2b_384_init(hash_state *md) { return blake2b_init(md, 48, NULL, 0); }
2695a913ee7SJerome Forissier 
2705a913ee7SJerome Forissier /**
2715a913ee7SJerome Forissier    Initialize the hash state
2725a913ee7SJerome Forissier    @param md   The hash state you wish to initialize
2735a913ee7SJerome Forissier    @return CRYPT_OK if successful
2745a913ee7SJerome Forissier */
blake2b_512_init(hash_state * md)2755a913ee7SJerome Forissier int blake2b_512_init(hash_state *md) { return blake2b_init(md, 64, NULL, 0); }
2765a913ee7SJerome Forissier 
2775a913ee7SJerome Forissier #define G(r, i, a, b, c, d)                                                                                            \
2785a913ee7SJerome Forissier    do {                                                                                                                \
2795a913ee7SJerome Forissier       a = a + b + m[blake2b_sigma[r][2 * i + 0]];                                                                      \
2805a913ee7SJerome Forissier       d = ROR64(d ^ a, 32);                                                                                            \
2815a913ee7SJerome Forissier       c = c + d;                                                                                                       \
2825a913ee7SJerome Forissier       b = ROR64(b ^ c, 24);                                                                                            \
2835a913ee7SJerome Forissier       a = a + b + m[blake2b_sigma[r][2 * i + 1]];                                                                      \
2845a913ee7SJerome Forissier       d = ROR64(d ^ a, 16);                                                                                            \
2855a913ee7SJerome Forissier       c = c + d;                                                                                                       \
2865a913ee7SJerome Forissier       b = ROR64(b ^ c, 63);                                                                                            \
2875a913ee7SJerome Forissier    } while (0)
2885a913ee7SJerome Forissier 
2895a913ee7SJerome Forissier #define ROUND(r)                                                                                                       \
2905a913ee7SJerome Forissier    do {                                                                                                                \
2915a913ee7SJerome Forissier       G(r, 0, v[0], v[4], v[8], v[12]);                                                                                \
2925a913ee7SJerome Forissier       G(r, 1, v[1], v[5], v[9], v[13]);                                                                                \
2935a913ee7SJerome Forissier       G(r, 2, v[2], v[6], v[10], v[14]);                                                                               \
2945a913ee7SJerome Forissier       G(r, 3, v[3], v[7], v[11], v[15]);                                                                               \
2955a913ee7SJerome Forissier       G(r, 4, v[0], v[5], v[10], v[15]);                                                                               \
2965a913ee7SJerome Forissier       G(r, 5, v[1], v[6], v[11], v[12]);                                                                               \
2975a913ee7SJerome Forissier       G(r, 6, v[2], v[7], v[8], v[13]);                                                                                \
2985a913ee7SJerome Forissier       G(r, 7, v[3], v[4], v[9], v[14]);                                                                                \
2995a913ee7SJerome Forissier    } while (0)
3005a913ee7SJerome Forissier 
3015a913ee7SJerome Forissier #ifdef LTC_CLEAN_STACK
ss_blake2b_compress(hash_state * md,const unsigned char * buf)302*8411e6adSJerome Forissier static int ss_blake2b_compress(hash_state *md, const unsigned char *buf)
3035a913ee7SJerome Forissier #else
304*8411e6adSJerome Forissier static int s_blake2b_compress(hash_state *md, const unsigned char *buf)
3055a913ee7SJerome Forissier #endif
3065a913ee7SJerome Forissier {
3075a913ee7SJerome Forissier    ulong64 m[16];
3085a913ee7SJerome Forissier    ulong64 v[16];
3095a913ee7SJerome Forissier    unsigned long i;
3105a913ee7SJerome Forissier 
3115a913ee7SJerome Forissier    for (i = 0; i < 16; ++i) {
3125a913ee7SJerome Forissier       LOAD64L(m[i], buf + i * sizeof(m[i]));
3135a913ee7SJerome Forissier    }
3145a913ee7SJerome Forissier 
3155a913ee7SJerome Forissier    for (i = 0; i < 8; ++i) {
3165a913ee7SJerome Forissier       v[i] = md->blake2b.h[i];
3175a913ee7SJerome Forissier    }
3185a913ee7SJerome Forissier 
3195a913ee7SJerome Forissier    v[8] = blake2b_IV[0];
3205a913ee7SJerome Forissier    v[9] = blake2b_IV[1];
3215a913ee7SJerome Forissier    v[10] = blake2b_IV[2];
3225a913ee7SJerome Forissier    v[11] = blake2b_IV[3];
3235a913ee7SJerome Forissier    v[12] = blake2b_IV[4] ^ md->blake2b.t[0];
3245a913ee7SJerome Forissier    v[13] = blake2b_IV[5] ^ md->blake2b.t[1];
3255a913ee7SJerome Forissier    v[14] = blake2b_IV[6] ^ md->blake2b.f[0];
3265a913ee7SJerome Forissier    v[15] = blake2b_IV[7] ^ md->blake2b.f[1];
3275a913ee7SJerome Forissier 
3285a913ee7SJerome Forissier    ROUND(0);
3295a913ee7SJerome Forissier    ROUND(1);
3305a913ee7SJerome Forissier    ROUND(2);
3315a913ee7SJerome Forissier    ROUND(3);
3325a913ee7SJerome Forissier    ROUND(4);
3335a913ee7SJerome Forissier    ROUND(5);
3345a913ee7SJerome Forissier    ROUND(6);
3355a913ee7SJerome Forissier    ROUND(7);
3365a913ee7SJerome Forissier    ROUND(8);
3375a913ee7SJerome Forissier    ROUND(9);
3385a913ee7SJerome Forissier    ROUND(10);
3395a913ee7SJerome Forissier    ROUND(11);
3405a913ee7SJerome Forissier 
3415a913ee7SJerome Forissier    for (i = 0; i < 8; ++i) {
3425a913ee7SJerome Forissier       md->blake2b.h[i] = md->blake2b.h[i] ^ v[i] ^ v[i + 8];
3435a913ee7SJerome Forissier    }
3445a913ee7SJerome Forissier    return CRYPT_OK;
3455a913ee7SJerome Forissier }
3465a913ee7SJerome Forissier 
3475a913ee7SJerome Forissier #undef G
3485a913ee7SJerome Forissier #undef ROUND
3495a913ee7SJerome Forissier 
3505a913ee7SJerome Forissier #ifdef LTC_CLEAN_STACK
s_blake2b_compress(hash_state * md,const unsigned char * buf)351*8411e6adSJerome Forissier static int s_blake2b_compress(hash_state *md, const unsigned char *buf)
3525a913ee7SJerome Forissier {
3535a913ee7SJerome Forissier    int err;
354*8411e6adSJerome Forissier    err = ss_blake2b_compress(md, buf);
3555a913ee7SJerome Forissier    burn_stack(sizeof(ulong64) * 32 + sizeof(unsigned long));
3565a913ee7SJerome Forissier    return err;
3575a913ee7SJerome Forissier }
3585a913ee7SJerome Forissier #endif
3595a913ee7SJerome Forissier 
3605a913ee7SJerome Forissier /**
3615a913ee7SJerome Forissier    Process a block of memory through the hash
3625a913ee7SJerome Forissier    @param md     The hash state
3635a913ee7SJerome Forissier    @param in     The data to hash
3645a913ee7SJerome Forissier    @param inlen  The length of the data (octets)
3655a913ee7SJerome Forissier    @return CRYPT_OK if successful
3665a913ee7SJerome Forissier */
blake2b_process(hash_state * md,const unsigned char * in,unsigned long inlen)3675a913ee7SJerome Forissier int blake2b_process(hash_state *md, const unsigned char *in, unsigned long inlen)
3685a913ee7SJerome Forissier {
3695a913ee7SJerome Forissier    LTC_ARGCHK(md != NULL);
3705a913ee7SJerome Forissier    LTC_ARGCHK(in != NULL);
3715a913ee7SJerome Forissier 
3725a913ee7SJerome Forissier    if (md->blake2b.curlen > sizeof(md->blake2b.buf)) {
3735a913ee7SJerome Forissier       return CRYPT_INVALID_ARG;
3745a913ee7SJerome Forissier    }
3755a913ee7SJerome Forissier 
3765a913ee7SJerome Forissier    if (inlen > 0) {
3775a913ee7SJerome Forissier       unsigned long left = md->blake2b.curlen;
3785a913ee7SJerome Forissier       unsigned long fill = BLAKE2B_BLOCKBYTES - left;
3795a913ee7SJerome Forissier       if (inlen > fill) {
3805a913ee7SJerome Forissier          md->blake2b.curlen = 0;
3815a913ee7SJerome Forissier          XMEMCPY(md->blake2b.buf + (left % sizeof(md->blake2b.buf)), in, fill); /* Fill buffer */
382*8411e6adSJerome Forissier          s_blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES);
383*8411e6adSJerome Forissier          s_blake2b_compress(md, md->blake2b.buf); /* Compress */
3845a913ee7SJerome Forissier          in += fill;
3855a913ee7SJerome Forissier          inlen -= fill;
3865a913ee7SJerome Forissier          while (inlen > BLAKE2B_BLOCKBYTES) {
387*8411e6adSJerome Forissier             s_blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES);
388*8411e6adSJerome Forissier             s_blake2b_compress(md, in);
3895a913ee7SJerome Forissier             in += BLAKE2B_BLOCKBYTES;
3905a913ee7SJerome Forissier             inlen -= BLAKE2B_BLOCKBYTES;
3915a913ee7SJerome Forissier          }
3925a913ee7SJerome Forissier       }
3935a913ee7SJerome Forissier       XMEMCPY(md->blake2b.buf + md->blake2b.curlen, in, inlen);
3945a913ee7SJerome Forissier       md->blake2b.curlen += inlen;
3955a913ee7SJerome Forissier    }
3965a913ee7SJerome Forissier    return CRYPT_OK;
3975a913ee7SJerome Forissier }
3985a913ee7SJerome Forissier 
3995a913ee7SJerome Forissier /**
4005a913ee7SJerome Forissier    Terminate the hash to get the digest
4015a913ee7SJerome Forissier    @param md  The hash state
4025a913ee7SJerome Forissier    @param out [out] The destination of the hash (size depending on the length used on init)
4035a913ee7SJerome Forissier    @return CRYPT_OK if successful
4045a913ee7SJerome Forissier */
blake2b_done(hash_state * md,unsigned char * out)4055a913ee7SJerome Forissier int blake2b_done(hash_state *md, unsigned char *out)
4065a913ee7SJerome Forissier {
4075a913ee7SJerome Forissier    unsigned char buffer[BLAKE2B_OUTBYTES] = { 0 };
4085a913ee7SJerome Forissier    unsigned long i;
4095a913ee7SJerome Forissier 
4105a913ee7SJerome Forissier    LTC_ARGCHK(md != NULL);
4115a913ee7SJerome Forissier    LTC_ARGCHK(out != NULL);
4125a913ee7SJerome Forissier 
4135a913ee7SJerome Forissier    /* if(md->blakebs.outlen != outlen) return CRYPT_INVALID_ARG; */
4145a913ee7SJerome Forissier 
415*8411e6adSJerome Forissier    if (s_blake2b_is_lastblock(md)) {
4165a913ee7SJerome Forissier       return CRYPT_ERROR;
4175a913ee7SJerome Forissier    }
4185a913ee7SJerome Forissier 
419*8411e6adSJerome Forissier    s_blake2b_increment_counter(md, md->blake2b.curlen);
420*8411e6adSJerome Forissier    s_blake2b_set_lastblock(md);
4215a913ee7SJerome Forissier    XMEMSET(md->blake2b.buf + md->blake2b.curlen, 0, BLAKE2B_BLOCKBYTES - md->blake2b.curlen); /* Padding */
422*8411e6adSJerome Forissier    s_blake2b_compress(md, md->blake2b.buf);
4235a913ee7SJerome Forissier 
4245a913ee7SJerome Forissier    for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
4255a913ee7SJerome Forissier       STORE64L(md->blake2b.h[i], buffer + i * 8);
4265a913ee7SJerome Forissier    }
4275a913ee7SJerome Forissier 
4285a913ee7SJerome Forissier    XMEMCPY(out, buffer, md->blake2b.outlen);
4295a913ee7SJerome Forissier    zeromem(md, sizeof(hash_state));
4305a913ee7SJerome Forissier #ifdef LTC_CLEAN_STACK
4315a913ee7SJerome Forissier    zeromem(buffer, sizeof(buffer));
4325a913ee7SJerome Forissier #endif
4335a913ee7SJerome Forissier    return CRYPT_OK;
4345a913ee7SJerome Forissier }
4355a913ee7SJerome Forissier 
4365a913ee7SJerome Forissier /**
4375a913ee7SJerome Forissier   Self-test the hash
4385a913ee7SJerome Forissier   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
4395a913ee7SJerome Forissier */
blake2b_512_test(void)4405a913ee7SJerome Forissier int blake2b_512_test(void)
4415a913ee7SJerome Forissier {
4425a913ee7SJerome Forissier #ifndef LTC_TEST
4435a913ee7SJerome Forissier    return CRYPT_NOP;
4445a913ee7SJerome Forissier #else
4455a913ee7SJerome Forissier    static const struct {
4465a913ee7SJerome Forissier       const char *msg;
4475a913ee7SJerome Forissier       unsigned char hash[64];
4485a913ee7SJerome Forissier   } tests[] = {
4495a913ee7SJerome Forissier     { "",
4505a913ee7SJerome Forissier       { 0x78, 0x6a, 0x02, 0xf7, 0x42, 0x01, 0x59, 0x03,
4515a913ee7SJerome Forissier         0xc6, 0xc6, 0xfd, 0x85, 0x25, 0x52, 0xd2, 0x72,
4525a913ee7SJerome Forissier         0x91, 0x2f, 0x47, 0x40, 0xe1, 0x58, 0x47, 0x61,
4535a913ee7SJerome Forissier         0x8a, 0x86, 0xe2, 0x17, 0xf7, 0x1f, 0x54, 0x19,
4545a913ee7SJerome Forissier         0xd2, 0x5e, 0x10, 0x31, 0xaf, 0xee, 0x58, 0x53,
4555a913ee7SJerome Forissier         0x13, 0x89, 0x64, 0x44, 0x93, 0x4e, 0xb0, 0x4b,
4565a913ee7SJerome Forissier         0x90, 0x3a, 0x68, 0x5b, 0x14, 0x48, 0xb7, 0x55,
4575a913ee7SJerome Forissier         0xd5, 0x6f, 0x70, 0x1a, 0xfe, 0x9b, 0xe2, 0xce } },
4585a913ee7SJerome Forissier     { "abc",
4595a913ee7SJerome Forissier       { 0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d,
4605a913ee7SJerome Forissier         0x6a, 0x27, 0x97, 0xb6, 0x9f, 0x12, 0xf6, 0xe9,
4615a913ee7SJerome Forissier         0x4c, 0x21, 0x2f, 0x14, 0x68, 0x5a, 0xc4, 0xb7,
4625a913ee7SJerome Forissier         0x4b, 0x12, 0xbb, 0x6f, 0xdb, 0xff, 0xa2, 0xd1,
4635a913ee7SJerome Forissier         0x7d, 0x87, 0xc5, 0x39, 0x2a, 0xab, 0x79, 0x2d,
4645a913ee7SJerome Forissier         0xc2, 0x52, 0xd5, 0xde, 0x45, 0x33, 0xcc, 0x95,
4655a913ee7SJerome Forissier         0x18, 0xd3, 0x8a, 0xa8, 0xdb, 0xf1, 0x92, 0x5a,
4665a913ee7SJerome Forissier         0xb9, 0x23, 0x86, 0xed, 0xd4, 0x00, 0x99, 0x23 } },
4675a913ee7SJerome Forissier 
4685a913ee7SJerome Forissier     { NULL, { 0 } }
4695a913ee7SJerome Forissier   };
4705a913ee7SJerome Forissier 
4715a913ee7SJerome Forissier    int i;
4725a913ee7SJerome Forissier    unsigned char tmp[64];
4735a913ee7SJerome Forissier    hash_state md;
4745a913ee7SJerome Forissier 
4755a913ee7SJerome Forissier    for (i = 0; tests[i].msg != NULL; i++) {
4765a913ee7SJerome Forissier       blake2b_512_init(&md);
477*8411e6adSJerome Forissier       blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
4785a913ee7SJerome Forissier       blake2b_done(&md, tmp);
4795a913ee7SJerome Forissier       if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_512", i)) {
4805a913ee7SJerome Forissier          return CRYPT_FAIL_TESTVECTOR;
4815a913ee7SJerome Forissier       }
4825a913ee7SJerome Forissier    }
4835a913ee7SJerome Forissier    return CRYPT_OK;
4845a913ee7SJerome Forissier #endif
4855a913ee7SJerome Forissier }
4865a913ee7SJerome Forissier 
4875a913ee7SJerome Forissier /**
4885a913ee7SJerome Forissier   Self-test the hash
4895a913ee7SJerome Forissier   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
4905a913ee7SJerome Forissier */
blake2b_384_test(void)4915a913ee7SJerome Forissier int blake2b_384_test(void)
4925a913ee7SJerome Forissier {
4935a913ee7SJerome Forissier #ifndef LTC_TEST
4945a913ee7SJerome Forissier    return CRYPT_NOP;
4955a913ee7SJerome Forissier #else
4965a913ee7SJerome Forissier    static const struct {
4975a913ee7SJerome Forissier       const char *msg;
4985a913ee7SJerome Forissier       unsigned char hash[48];
4995a913ee7SJerome Forissier   } tests[] = {
5005a913ee7SJerome Forissier     { "",
5015a913ee7SJerome Forissier       { 0xb3, 0x28, 0x11, 0x42, 0x33, 0x77, 0xf5, 0x2d,
5025a913ee7SJerome Forissier         0x78, 0x62, 0x28, 0x6e, 0xe1, 0xa7, 0x2e, 0xe5,
5035a913ee7SJerome Forissier         0x40, 0x52, 0x43, 0x80, 0xfd, 0xa1, 0x72, 0x4a,
5045a913ee7SJerome Forissier         0x6f, 0x25, 0xd7, 0x97, 0x8c, 0x6f, 0xd3, 0x24,
5055a913ee7SJerome Forissier         0x4a, 0x6c, 0xaf, 0x04, 0x98, 0x81, 0x26, 0x73,
5065a913ee7SJerome Forissier         0xc5, 0xe0, 0x5e, 0xf5, 0x83, 0x82, 0x51, 0x00 } },
5075a913ee7SJerome Forissier     { "abc",
5085a913ee7SJerome Forissier       { 0x6f, 0x56, 0xa8, 0x2c, 0x8e, 0x7e, 0xf5, 0x26,
5095a913ee7SJerome Forissier         0xdf, 0xe1, 0x82, 0xeb, 0x52, 0x12, 0xf7, 0xdb,
5105a913ee7SJerome Forissier         0x9d, 0xf1, 0x31, 0x7e, 0x57, 0x81, 0x5d, 0xbd,
5115a913ee7SJerome Forissier         0xa4, 0x60, 0x83, 0xfc, 0x30, 0xf5, 0x4e, 0xe6,
5125a913ee7SJerome Forissier         0xc6, 0x6b, 0xa8, 0x3b, 0xe6, 0x4b, 0x30, 0x2d,
5135a913ee7SJerome Forissier         0x7c, 0xba, 0x6c, 0xe1, 0x5b, 0xb5, 0x56, 0xf4 } },
5145a913ee7SJerome Forissier 
5155a913ee7SJerome Forissier     { NULL, { 0 } }
5165a913ee7SJerome Forissier   };
5175a913ee7SJerome Forissier 
5185a913ee7SJerome Forissier    int i;
5195a913ee7SJerome Forissier    unsigned char tmp[48];
5205a913ee7SJerome Forissier    hash_state md;
5215a913ee7SJerome Forissier 
5225a913ee7SJerome Forissier    for (i = 0; tests[i].msg != NULL; i++) {
5235a913ee7SJerome Forissier       blake2b_384_init(&md);
524*8411e6adSJerome Forissier       blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
5255a913ee7SJerome Forissier       blake2b_done(&md, tmp);
5265a913ee7SJerome Forissier       if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_384", i)) {
5275a913ee7SJerome Forissier          return CRYPT_FAIL_TESTVECTOR;
5285a913ee7SJerome Forissier       }
5295a913ee7SJerome Forissier    }
5305a913ee7SJerome Forissier    return CRYPT_OK;
5315a913ee7SJerome Forissier #endif
5325a913ee7SJerome Forissier }
5335a913ee7SJerome Forissier 
5345a913ee7SJerome Forissier /**
5355a913ee7SJerome Forissier   Self-test the hash
5365a913ee7SJerome Forissier   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
5375a913ee7SJerome Forissier */
blake2b_256_test(void)5385a913ee7SJerome Forissier int blake2b_256_test(void)
5395a913ee7SJerome Forissier {
5405a913ee7SJerome Forissier #ifndef LTC_TEST
5415a913ee7SJerome Forissier    return CRYPT_NOP;
5425a913ee7SJerome Forissier #else
5435a913ee7SJerome Forissier    static const struct {
5445a913ee7SJerome Forissier       const char *msg;
5455a913ee7SJerome Forissier       unsigned char hash[32];
5465a913ee7SJerome Forissier   } tests[] = {
5475a913ee7SJerome Forissier     { "",
5485a913ee7SJerome Forissier       { 0x0e, 0x57, 0x51, 0xc0, 0x26, 0xe5, 0x43, 0xb2,
5495a913ee7SJerome Forissier         0xe8, 0xab, 0x2e, 0xb0, 0x60, 0x99, 0xda, 0xa1,
5505a913ee7SJerome Forissier         0xd1, 0xe5, 0xdf, 0x47, 0x77, 0x8f, 0x77, 0x87,
5515a913ee7SJerome Forissier         0xfa, 0xab, 0x45, 0xcd, 0xf1, 0x2f, 0xe3, 0xa8 } },
5525a913ee7SJerome Forissier     { "abc",
5535a913ee7SJerome Forissier       { 0xbd, 0xdd, 0x81, 0x3c, 0x63, 0x42, 0x39, 0x72,
5545a913ee7SJerome Forissier         0x31, 0x71, 0xef, 0x3f, 0xee, 0x98, 0x57, 0x9b,
5555a913ee7SJerome Forissier         0x94, 0x96, 0x4e, 0x3b, 0xb1, 0xcb, 0x3e, 0x42,
5565a913ee7SJerome Forissier         0x72, 0x62, 0xc8, 0xc0, 0x68, 0xd5, 0x23, 0x19 } },
5575a913ee7SJerome Forissier     { "12345678901234567890123456789012345678901234567890"
5585a913ee7SJerome Forissier       "12345678901234567890123456789012345678901234567890"
5595a913ee7SJerome Forissier       "12345678901234567890123456789012345678901234567890"
5605a913ee7SJerome Forissier       "12345678901234567890123456789012345678901234567890"
5615a913ee7SJerome Forissier       "12345678901234567890123456789012345678901234567890"
5625a913ee7SJerome Forissier       "12345678901234567890123456789012345678901234567890",
5635a913ee7SJerome Forissier       { 0x0f, 0x6e, 0x01, 0x8d, 0x38, 0xd6, 0x3f, 0x08,
5645a913ee7SJerome Forissier         0x4d, 0x58, 0xe3, 0x0c, 0x90, 0xfb, 0xa2, 0x41,
5655a913ee7SJerome Forissier         0x5f, 0xca, 0x17, 0xfa, 0x66, 0x26, 0x49, 0xf3,
5665a913ee7SJerome Forissier         0x8a, 0x30, 0x41, 0x7c, 0x57, 0xcd, 0xa8, 0x14 } },
5675a913ee7SJerome Forissier 
5685a913ee7SJerome Forissier     { NULL, { 0 } }
5695a913ee7SJerome Forissier   };
5705a913ee7SJerome Forissier 
5715a913ee7SJerome Forissier    int i;
5725a913ee7SJerome Forissier    unsigned char tmp[32];
5735a913ee7SJerome Forissier    hash_state md;
5745a913ee7SJerome Forissier 
5755a913ee7SJerome Forissier    for (i = 0; tests[i].msg != NULL; i++) {
5765a913ee7SJerome Forissier       blake2b_256_init(&md);
577*8411e6adSJerome Forissier       blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
5785a913ee7SJerome Forissier       blake2b_done(&md, tmp);
5795a913ee7SJerome Forissier       if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_256", i)) {
5805a913ee7SJerome Forissier          return CRYPT_FAIL_TESTVECTOR;
5815a913ee7SJerome Forissier       }
5825a913ee7SJerome Forissier    }
5835a913ee7SJerome Forissier    return CRYPT_OK;
5845a913ee7SJerome Forissier #endif
5855a913ee7SJerome Forissier }
5865a913ee7SJerome Forissier 
5875a913ee7SJerome Forissier /**
5885a913ee7SJerome Forissier   Self-test the hash
5895a913ee7SJerome Forissier   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
5905a913ee7SJerome Forissier */
blake2b_160_test(void)5915a913ee7SJerome Forissier int blake2b_160_test(void)
5925a913ee7SJerome Forissier {
5935a913ee7SJerome Forissier #ifndef LTC_TEST
5945a913ee7SJerome Forissier    return CRYPT_NOP;
5955a913ee7SJerome Forissier #else
5965a913ee7SJerome Forissier    static const struct {
5975a913ee7SJerome Forissier       const char *msg;
5985a913ee7SJerome Forissier       unsigned char hash[20];
5995a913ee7SJerome Forissier   } tests[] = {
6005a913ee7SJerome Forissier     { "",
6015a913ee7SJerome Forissier       { 0x33, 0x45, 0x52, 0x4a, 0xbf, 0x6b, 0xbe, 0x18,
6025a913ee7SJerome Forissier         0x09, 0x44, 0x92, 0x24, 0xb5, 0x97, 0x2c, 0x41,
6035a913ee7SJerome Forissier         0x79, 0x0b, 0x6c, 0xf2 } },
6045a913ee7SJerome Forissier     { "abc",
6055a913ee7SJerome Forissier       { 0x38, 0x42, 0x64, 0xf6, 0x76, 0xf3, 0x95, 0x36,
6065a913ee7SJerome Forissier         0x84, 0x05, 0x23, 0xf2, 0x84, 0x92, 0x1c, 0xdc,
6075a913ee7SJerome Forissier         0x68, 0xb6, 0x84, 0x6b } },
6085a913ee7SJerome Forissier 
6095a913ee7SJerome Forissier     { NULL, { 0 } }
6105a913ee7SJerome Forissier   };
6115a913ee7SJerome Forissier 
6125a913ee7SJerome Forissier    int i;
6135a913ee7SJerome Forissier    unsigned char tmp[20];
6145a913ee7SJerome Forissier    hash_state md;
6155a913ee7SJerome Forissier 
6165a913ee7SJerome Forissier    for (i = 0; tests[i].msg != NULL; i++) {
6175a913ee7SJerome Forissier       blake2b_160_init(&md);
618*8411e6adSJerome Forissier       blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
6195a913ee7SJerome Forissier       blake2b_done(&md, tmp);
6205a913ee7SJerome Forissier       if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_160", i)) {
6215a913ee7SJerome Forissier          return CRYPT_FAIL_TESTVECTOR;
6225a913ee7SJerome Forissier       }
6235a913ee7SJerome Forissier    }
6245a913ee7SJerome Forissier    return CRYPT_OK;
6255a913ee7SJerome Forissier #endif
6265a913ee7SJerome Forissier }
6275a913ee7SJerome Forissier 
6285a913ee7SJerome Forissier #endif
629