18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 OR MIT */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Helper functions for BLAKE2s implementations. 48c2ecf20Sopenharmony_ci * Keep this in sync with the corresponding BLAKE2b header. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#ifndef _CRYPTO_INTERNAL_BLAKE2S_H 88c2ecf20Sopenharmony_ci#define _CRYPTO_INTERNAL_BLAKE2S_H 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <crypto/blake2s.h> 118c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h> 128c2ecf20Sopenharmony_ci#include <linux/string.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_civoid blake2s_compress_generic(struct blake2s_state *state, const u8 *block, 158c2ecf20Sopenharmony_ci size_t nblocks, const u32 inc); 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_civoid blake2s_compress(struct blake2s_state *state, const u8 *block, 188c2ecf20Sopenharmony_ci size_t nblocks, const u32 inc); 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cibool blake2s_selftest(void); 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic inline void blake2s_set_lastblock(struct blake2s_state *state) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci state->f[0] = -1; 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* Helper functions for BLAKE2s shared by the library and shash APIs */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic __always_inline void 308c2ecf20Sopenharmony_ci__blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen, 318c2ecf20Sopenharmony_ci bool force_generic) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci const size_t fill = BLAKE2S_BLOCK_SIZE - state->buflen; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci if (unlikely(!inlen)) 368c2ecf20Sopenharmony_ci return; 378c2ecf20Sopenharmony_ci if (inlen > fill) { 388c2ecf20Sopenharmony_ci memcpy(state->buf + state->buflen, in, fill); 398c2ecf20Sopenharmony_ci if (force_generic) 408c2ecf20Sopenharmony_ci blake2s_compress_generic(state, state->buf, 1, 418c2ecf20Sopenharmony_ci BLAKE2S_BLOCK_SIZE); 428c2ecf20Sopenharmony_ci else 438c2ecf20Sopenharmony_ci blake2s_compress(state, state->buf, 1, 448c2ecf20Sopenharmony_ci BLAKE2S_BLOCK_SIZE); 458c2ecf20Sopenharmony_ci state->buflen = 0; 468c2ecf20Sopenharmony_ci in += fill; 478c2ecf20Sopenharmony_ci inlen -= fill; 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci if (inlen > BLAKE2S_BLOCK_SIZE) { 508c2ecf20Sopenharmony_ci const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE); 518c2ecf20Sopenharmony_ci /* Hash one less (full) block than strictly possible */ 528c2ecf20Sopenharmony_ci if (force_generic) 538c2ecf20Sopenharmony_ci blake2s_compress_generic(state, in, nblocks - 1, 548c2ecf20Sopenharmony_ci BLAKE2S_BLOCK_SIZE); 558c2ecf20Sopenharmony_ci else 568c2ecf20Sopenharmony_ci blake2s_compress(state, in, nblocks - 1, 578c2ecf20Sopenharmony_ci BLAKE2S_BLOCK_SIZE); 588c2ecf20Sopenharmony_ci in += BLAKE2S_BLOCK_SIZE * (nblocks - 1); 598c2ecf20Sopenharmony_ci inlen -= BLAKE2S_BLOCK_SIZE * (nblocks - 1); 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci memcpy(state->buf + state->buflen, in, inlen); 628c2ecf20Sopenharmony_ci state->buflen += inlen; 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic __always_inline void 668c2ecf20Sopenharmony_ci__blake2s_final(struct blake2s_state *state, u8 *out, bool force_generic) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci blake2s_set_lastblock(state); 698c2ecf20Sopenharmony_ci memset(state->buf + state->buflen, 0, 708c2ecf20Sopenharmony_ci BLAKE2S_BLOCK_SIZE - state->buflen); /* Padding */ 718c2ecf20Sopenharmony_ci if (force_generic) 728c2ecf20Sopenharmony_ci blake2s_compress_generic(state, state->buf, 1, state->buflen); 738c2ecf20Sopenharmony_ci else 748c2ecf20Sopenharmony_ci blake2s_compress(state, state->buf, 1, state->buflen); 758c2ecf20Sopenharmony_ci cpu_to_le32_array(state->h, ARRAY_SIZE(state->h)); 768c2ecf20Sopenharmony_ci memcpy(out, state->h, state->outlen); 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* Helper functions for shash implementations of BLAKE2s */ 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistruct blake2s_tfm_ctx { 828c2ecf20Sopenharmony_ci u8 key[BLAKE2S_KEY_SIZE]; 838c2ecf20Sopenharmony_ci unsigned int keylen; 848c2ecf20Sopenharmony_ci}; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic inline int crypto_blake2s_setkey(struct crypto_shash *tfm, 878c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci struct blake2s_tfm_ctx *tctx = crypto_shash_ctx(tfm); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci if (keylen == 0 || keylen > BLAKE2S_KEY_SIZE) 928c2ecf20Sopenharmony_ci return -EINVAL; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci memcpy(tctx->key, key, keylen); 958c2ecf20Sopenharmony_ci tctx->keylen = keylen; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci return 0; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic inline int crypto_blake2s_init(struct shash_desc *desc) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci const struct blake2s_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); 1038c2ecf20Sopenharmony_ci struct blake2s_state *state = shash_desc_ctx(desc); 1048c2ecf20Sopenharmony_ci unsigned int outlen = crypto_shash_digestsize(desc->tfm); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci __blake2s_init(state, outlen, tctx->key, tctx->keylen); 1078c2ecf20Sopenharmony_ci return 0; 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic inline int crypto_blake2s_update(struct shash_desc *desc, 1118c2ecf20Sopenharmony_ci const u8 *in, unsigned int inlen, 1128c2ecf20Sopenharmony_ci bool force_generic) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci struct blake2s_state *state = shash_desc_ctx(desc); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci __blake2s_update(state, in, inlen, force_generic); 1178c2ecf20Sopenharmony_ci return 0; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic inline int crypto_blake2s_final(struct shash_desc *desc, u8 *out, 1218c2ecf20Sopenharmony_ci bool force_generic) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci struct blake2s_state *state = shash_desc_ctx(desc); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci __blake2s_final(state, out, force_generic); 1268c2ecf20Sopenharmony_ci return 0; 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci#endif /* _CRYPTO_INTERNAL_BLAKE2S_H */ 130