1 // SPDX-License-Identifier: GPL-2.0 OR MIT
3 * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
5 * This is an implementation of the BLAKE2s hash and PRF functions.
7 * Information: https://blake2.net/
11 #include <crypto/internal/blake2s.h>
12 #include <linux/types.h>
13 #include <linux/string.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/bug.h>
18 #include <asm/unaligned.h>
20 void blake2s_update(struct blake2s_state
*state
, const u8
*in
, size_t inlen
)
22 const size_t fill
= BLAKE2S_BLOCK_SIZE
- state
->buflen
;
27 memcpy(state
->buf
+ state
->buflen
, in
, fill
);
28 if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S
))
29 blake2s_compress_arch(state
, state
->buf
, 1,
32 blake2s_compress_generic(state
, state
->buf
, 1,
38 if (inlen
> BLAKE2S_BLOCK_SIZE
) {
39 const size_t nblocks
= DIV_ROUND_UP(inlen
, BLAKE2S_BLOCK_SIZE
);
40 /* Hash one less (full) block than strictly possible */
41 if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S
))
42 blake2s_compress_arch(state
, in
, nblocks
- 1,
45 blake2s_compress_generic(state
, in
, nblocks
- 1,
47 in
+= BLAKE2S_BLOCK_SIZE
* (nblocks
- 1);
48 inlen
-= BLAKE2S_BLOCK_SIZE
* (nblocks
- 1);
50 memcpy(state
->buf
+ state
->buflen
, in
, inlen
);
51 state
->buflen
+= inlen
;
53 EXPORT_SYMBOL(blake2s_update
);
55 void blake2s_final(struct blake2s_state
*state
, u8
*out
)
57 WARN_ON(IS_ENABLED(DEBUG
) && !out
);
58 blake2s_set_lastblock(state
);
59 memset(state
->buf
+ state
->buflen
, 0,
60 BLAKE2S_BLOCK_SIZE
- state
->buflen
); /* Padding */
61 if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S
))
62 blake2s_compress_arch(state
, state
->buf
, 1, state
->buflen
);
64 blake2s_compress_generic(state
, state
->buf
, 1, state
->buflen
);
65 cpu_to_le32_array(state
->h
, ARRAY_SIZE(state
->h
));
66 memcpy(out
, state
->h
, state
->outlen
);
67 memzero_explicit(state
, sizeof(*state
));
69 EXPORT_SYMBOL(blake2s_final
);
71 void blake2s256_hmac(u8
*out
, const u8
*in
, const u8
*key
, const size_t inlen
,
74 struct blake2s_state state
;
75 u8 x_key
[BLAKE2S_BLOCK_SIZE
] __aligned(__alignof__(u32
)) = { 0 };
76 u8 i_hash
[BLAKE2S_HASH_SIZE
] __aligned(__alignof__(u32
));
79 if (keylen
> BLAKE2S_BLOCK_SIZE
) {
80 blake2s_init(&state
, BLAKE2S_HASH_SIZE
);
81 blake2s_update(&state
, key
, keylen
);
82 blake2s_final(&state
, x_key
);
84 memcpy(x_key
, key
, keylen
);
86 for (i
= 0; i
< BLAKE2S_BLOCK_SIZE
; ++i
)
89 blake2s_init(&state
, BLAKE2S_HASH_SIZE
);
90 blake2s_update(&state
, x_key
, BLAKE2S_BLOCK_SIZE
);
91 blake2s_update(&state
, in
, inlen
);
92 blake2s_final(&state
, i_hash
);
94 for (i
= 0; i
< BLAKE2S_BLOCK_SIZE
; ++i
)
95 x_key
[i
] ^= 0x5c ^ 0x36;
97 blake2s_init(&state
, BLAKE2S_HASH_SIZE
);
98 blake2s_update(&state
, x_key
, BLAKE2S_BLOCK_SIZE
);
99 blake2s_update(&state
, i_hash
, BLAKE2S_HASH_SIZE
);
100 blake2s_final(&state
, i_hash
);
102 memcpy(out
, i_hash
, BLAKE2S_HASH_SIZE
);
103 memzero_explicit(x_key
, BLAKE2S_BLOCK_SIZE
);
104 memzero_explicit(i_hash
, BLAKE2S_HASH_SIZE
);
106 EXPORT_SYMBOL(blake2s256_hmac
);
108 static int __init
mod_init(void)
110 if (!IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
) &&
111 WARN_ON(!blake2s_selftest()))
116 static void __exit
mod_exit(void)
120 module_init(mod_init
);
121 module_exit(mod_exit
);
122 MODULE_LICENSE("GPL v2");
123 MODULE_DESCRIPTION("BLAKE2s hash function");
124 MODULE_AUTHOR("Jason A. Donenfeld <Jason@zx2c4.com>");