166d7fb94SJason A. Donenfeld /* SPDX-License-Identifier: GPL-2.0 OR MIT */
266d7fb94SJason A. Donenfeld /*
366d7fb94SJason A. Donenfeld * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
466d7fb94SJason A. Donenfeld */
566d7fb94SJason A. Donenfeld
68786841bSEric Biggers #ifndef _CRYPTO_BLAKE2S_H
78786841bSEric Biggers #define _CRYPTO_BLAKE2S_H
866d7fb94SJason A. Donenfeld
9bbda6e0fSEric Biggers #include <linux/bug.h>
10*244d22ffSAndy Shevchenko #include <linux/kconfig.h>
1166d7fb94SJason A. Donenfeld #include <linux/types.h>
1266d7fb94SJason A. Donenfeld #include <linux/string.h>
1366d7fb94SJason A. Donenfeld
1466d7fb94SJason A. Donenfeld enum blake2s_lengths {
1566d7fb94SJason A. Donenfeld BLAKE2S_BLOCK_SIZE = 64,
1666d7fb94SJason A. Donenfeld BLAKE2S_HASH_SIZE = 32,
1766d7fb94SJason A. Donenfeld BLAKE2S_KEY_SIZE = 32,
1866d7fb94SJason A. Donenfeld
1966d7fb94SJason A. Donenfeld BLAKE2S_128_HASH_SIZE = 16,
2066d7fb94SJason A. Donenfeld BLAKE2S_160_HASH_SIZE = 20,
2166d7fb94SJason A. Donenfeld BLAKE2S_224_HASH_SIZE = 28,
2266d7fb94SJason A. Donenfeld BLAKE2S_256_HASH_SIZE = 32,
2366d7fb94SJason A. Donenfeld };
2466d7fb94SJason A. Donenfeld
2566d7fb94SJason A. Donenfeld struct blake2s_state {
267d87131fSEric Biggers /* 'h', 't', and 'f' are used in assembly code, so keep them as-is. */
2766d7fb94SJason A. Donenfeld u32 h[8];
2866d7fb94SJason A. Donenfeld u32 t[2];
2966d7fb94SJason A. Donenfeld u32 f[2];
3066d7fb94SJason A. Donenfeld u8 buf[BLAKE2S_BLOCK_SIZE];
3166d7fb94SJason A. Donenfeld unsigned int buflen;
3266d7fb94SJason A. Donenfeld unsigned int outlen;
3366d7fb94SJason A. Donenfeld };
3466d7fb94SJason A. Donenfeld
3566d7fb94SJason A. Donenfeld enum blake2s_iv {
3666d7fb94SJason A. Donenfeld BLAKE2S_IV0 = 0x6A09E667UL,
3766d7fb94SJason A. Donenfeld BLAKE2S_IV1 = 0xBB67AE85UL,
3866d7fb94SJason A. Donenfeld BLAKE2S_IV2 = 0x3C6EF372UL,
3966d7fb94SJason A. Donenfeld BLAKE2S_IV3 = 0xA54FF53AUL,
4066d7fb94SJason A. Donenfeld BLAKE2S_IV4 = 0x510E527FUL,
4166d7fb94SJason A. Donenfeld BLAKE2S_IV5 = 0x9B05688CUL,
4266d7fb94SJason A. Donenfeld BLAKE2S_IV6 = 0x1F83D9ABUL,
4366d7fb94SJason A. Donenfeld BLAKE2S_IV7 = 0x5BE0CD19UL,
4466d7fb94SJason A. Donenfeld };
4566d7fb94SJason A. Donenfeld
__blake2s_init(struct blake2s_state * state,size_t outlen,const void * key,size_t keylen)4642ad8cf8SEric Biggers static inline void __blake2s_init(struct blake2s_state *state, size_t outlen,
4742ad8cf8SEric Biggers const void *key, size_t keylen)
4866d7fb94SJason A. Donenfeld {
4942ad8cf8SEric Biggers state->h[0] = BLAKE2S_IV0 ^ (0x01010000 | keylen << 8 | outlen);
5042ad8cf8SEric Biggers state->h[1] = BLAKE2S_IV1;
5142ad8cf8SEric Biggers state->h[2] = BLAKE2S_IV2;
5242ad8cf8SEric Biggers state->h[3] = BLAKE2S_IV3;
5342ad8cf8SEric Biggers state->h[4] = BLAKE2S_IV4;
5442ad8cf8SEric Biggers state->h[5] = BLAKE2S_IV5;
5542ad8cf8SEric Biggers state->h[6] = BLAKE2S_IV6;
5642ad8cf8SEric Biggers state->h[7] = BLAKE2S_IV7;
5742ad8cf8SEric Biggers state->t[0] = 0;
5842ad8cf8SEric Biggers state->t[1] = 0;
5942ad8cf8SEric Biggers state->f[0] = 0;
6042ad8cf8SEric Biggers state->f[1] = 0;
6142ad8cf8SEric Biggers state->buflen = 0;
6242ad8cf8SEric Biggers state->outlen = outlen;
6342ad8cf8SEric Biggers if (keylen) {
6442ad8cf8SEric Biggers memcpy(state->buf, key, keylen);
6542ad8cf8SEric Biggers memset(&state->buf[keylen], 0, BLAKE2S_BLOCK_SIZE - keylen);
6642ad8cf8SEric Biggers state->buflen = BLAKE2S_BLOCK_SIZE;
6742ad8cf8SEric Biggers }
6866d7fb94SJason A. Donenfeld }
6966d7fb94SJason A. Donenfeld
blake2s_init(struct blake2s_state * state,const size_t outlen)7066d7fb94SJason A. Donenfeld static inline void blake2s_init(struct blake2s_state *state,
7166d7fb94SJason A. Donenfeld const size_t outlen)
7266d7fb94SJason A. Donenfeld {
7342ad8cf8SEric Biggers __blake2s_init(state, outlen, NULL, 0);
7466d7fb94SJason A. Donenfeld }
7566d7fb94SJason A. Donenfeld
blake2s_init_key(struct blake2s_state * state,const size_t outlen,const void * key,const size_t keylen)7666d7fb94SJason A. Donenfeld static inline void blake2s_init_key(struct blake2s_state *state,
7766d7fb94SJason A. Donenfeld const size_t outlen, const void *key,
7866d7fb94SJason A. Donenfeld const size_t keylen)
7966d7fb94SJason A. Donenfeld {
8066d7fb94SJason A. Donenfeld WARN_ON(IS_ENABLED(DEBUG) && (!outlen || outlen > BLAKE2S_HASH_SIZE ||
8166d7fb94SJason A. Donenfeld !key || !keylen || keylen > BLAKE2S_KEY_SIZE));
8266d7fb94SJason A. Donenfeld
8342ad8cf8SEric Biggers __blake2s_init(state, outlen, key, keylen);
8466d7fb94SJason A. Donenfeld }
8566d7fb94SJason A. Donenfeld
8642ad8cf8SEric Biggers void blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen);
8742ad8cf8SEric Biggers void blake2s_final(struct blake2s_state *state, u8 *out);
8842ad8cf8SEric Biggers
blake2s(u8 * out,const u8 * in,const u8 * key,const size_t outlen,const size_t inlen,const size_t keylen)8966d7fb94SJason A. Donenfeld static inline void blake2s(u8 *out, const u8 *in, const u8 *key,
9066d7fb94SJason A. Donenfeld const size_t outlen, const size_t inlen,
9166d7fb94SJason A. Donenfeld const size_t keylen)
9266d7fb94SJason A. Donenfeld {
9366d7fb94SJason A. Donenfeld struct blake2s_state state;
9466d7fb94SJason A. Donenfeld
9566d7fb94SJason A. Donenfeld WARN_ON(IS_ENABLED(DEBUG) && ((!in && inlen > 0) || !out || !outlen ||
9666d7fb94SJason A. Donenfeld outlen > BLAKE2S_HASH_SIZE || keylen > BLAKE2S_KEY_SIZE ||
9766d7fb94SJason A. Donenfeld (!key && keylen)));
9866d7fb94SJason A. Donenfeld
9942ad8cf8SEric Biggers __blake2s_init(&state, outlen, key, keylen);
10066d7fb94SJason A. Donenfeld blake2s_update(&state, in, inlen);
10166d7fb94SJason A. Donenfeld blake2s_final(&state, out);
10266d7fb94SJason A. Donenfeld }
10366d7fb94SJason A. Donenfeld
1048786841bSEric Biggers #endif /* _CRYPTO_BLAKE2S_H */
105