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 bool blake2s_selftest(void);
22 void blake2s_update(struct blake2s_state
*state
, const u8
*in
, size_t inlen
)
24 const size_t fill
= BLAKE2S_BLOCK_SIZE
- state
->buflen
;
29 memcpy(state
->buf
+ state
->buflen
, in
, fill
);
30 if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S
))
31 blake2s_compress_arch(state
, state
->buf
, 1,
34 blake2s_compress_generic(state
, state
->buf
, 1,
40 if (inlen
> BLAKE2S_BLOCK_SIZE
) {
41 const size_t nblocks
= DIV_ROUND_UP(inlen
, BLAKE2S_BLOCK_SIZE
);
42 /* Hash one less (full) block than strictly possible */
43 if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S
))
44 blake2s_compress_arch(state
, in
, nblocks
- 1,
47 blake2s_compress_generic(state
, in
, nblocks
- 1,
49 in
+= BLAKE2S_BLOCK_SIZE
* (nblocks
- 1);
50 inlen
-= BLAKE2S_BLOCK_SIZE
* (nblocks
- 1);
52 memcpy(state
->buf
+ state
->buflen
, in
, inlen
);
53 state
->buflen
+= inlen
;
55 EXPORT_SYMBOL(blake2s_update
);
57 void blake2s_final(struct blake2s_state
*state
, u8
*out
)
59 WARN_ON(IS_ENABLED(DEBUG
) && !out
);
60 blake2s_set_lastblock(state
);
61 memset(state
->buf
+ state
->buflen
, 0,
62 BLAKE2S_BLOCK_SIZE
- state
->buflen
); /* Padding */
63 if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S
))
64 blake2s_compress_arch(state
, state
->buf
, 1, state
->buflen
);
66 blake2s_compress_generic(state
, state
->buf
, 1, state
->buflen
);
67 cpu_to_le32_array(state
->h
, ARRAY_SIZE(state
->h
));
68 memcpy(out
, state
->h
, state
->outlen
);
69 memzero_explicit(state
, sizeof(*state
));
71 EXPORT_SYMBOL(blake2s_final
);
73 void blake2s256_hmac(u8
*out
, const u8
*in
, const u8
*key
, const size_t inlen
,
76 struct blake2s_state state
;
77 u8 x_key
[BLAKE2S_BLOCK_SIZE
] __aligned(__alignof__(u32
)) = { 0 };
78 u8 i_hash
[BLAKE2S_HASH_SIZE
] __aligned(__alignof__(u32
));
81 if (keylen
> BLAKE2S_BLOCK_SIZE
) {
82 blake2s_init(&state
, BLAKE2S_HASH_SIZE
);
83 blake2s_update(&state
, key
, keylen
);
84 blake2s_final(&state
, x_key
);
86 memcpy(x_key
, key
, keylen
);
88 for (i
= 0; i
< BLAKE2S_BLOCK_SIZE
; ++i
)
91 blake2s_init(&state
, BLAKE2S_HASH_SIZE
);
92 blake2s_update(&state
, x_key
, BLAKE2S_BLOCK_SIZE
);
93 blake2s_update(&state
, in
, inlen
);
94 blake2s_final(&state
, i_hash
);
96 for (i
= 0; i
< BLAKE2S_BLOCK_SIZE
; ++i
)
97 x_key
[i
] ^= 0x5c ^ 0x36;
99 blake2s_init(&state
, BLAKE2S_HASH_SIZE
);
100 blake2s_update(&state
, x_key
, BLAKE2S_BLOCK_SIZE
);
101 blake2s_update(&state
, i_hash
, BLAKE2S_HASH_SIZE
);
102 blake2s_final(&state
, i_hash
);
104 memcpy(out
, i_hash
, BLAKE2S_HASH_SIZE
);
105 memzero_explicit(x_key
, BLAKE2S_BLOCK_SIZE
);
106 memzero_explicit(i_hash
, BLAKE2S_HASH_SIZE
);
108 EXPORT_SYMBOL(blake2s256_hmac
);
110 static int __init
mod_init(void)
112 if (!IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
) &&
113 WARN_ON(!blake2s_selftest()))
118 static void __exit
mod_exit(void)
122 module_init(mod_init
);
123 module_exit(mod_exit
);
124 MODULE_LICENSE("GPL v2");
125 MODULE_DESCRIPTION("BLAKE2s hash function");
126 MODULE_AUTHOR("Jason A. Donenfeld <Jason@zx2c4.com>");