162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR MIT 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This is an implementation of the BLAKE2s hash and PRF functions. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Information: https://blake2.net/ 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <crypto/internal/blake2s.h> 1262306a36Sopenharmony_ci#include <linux/types.h> 1362306a36Sopenharmony_ci#include <linux/string.h> 1462306a36Sopenharmony_ci#include <linux/kernel.h> 1562306a36Sopenharmony_ci#include <linux/init.h> 1662306a36Sopenharmony_ci#include <linux/bug.h> 1762306a36Sopenharmony_ci#include <asm/unaligned.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic const u8 blake2s_sigma[10][16] = { 2062306a36Sopenharmony_ci { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, 2162306a36Sopenharmony_ci { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, 2262306a36Sopenharmony_ci { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, 2362306a36Sopenharmony_ci { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, 2462306a36Sopenharmony_ci { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, 2562306a36Sopenharmony_ci { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, 2662306a36Sopenharmony_ci { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, 2762306a36Sopenharmony_ci { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, 2862306a36Sopenharmony_ci { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, 2962306a36Sopenharmony_ci { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic inline void blake2s_increment_counter(struct blake2s_state *state, 3362306a36Sopenharmony_ci const u32 inc) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci state->t[0] += inc; 3662306a36Sopenharmony_ci state->t[1] += (state->t[0] < inc); 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_civoid blake2s_compress(struct blake2s_state *state, const u8 *block, 4062306a36Sopenharmony_ci size_t nblocks, const u32 inc) 4162306a36Sopenharmony_ci __weak __alias(blake2s_compress_generic); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_civoid blake2s_compress_generic(struct blake2s_state *state, const u8 *block, 4462306a36Sopenharmony_ci size_t nblocks, const u32 inc) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci u32 m[16]; 4762306a36Sopenharmony_ci u32 v[16]; 4862306a36Sopenharmony_ci int i; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci WARN_ON(IS_ENABLED(DEBUG) && 5162306a36Sopenharmony_ci (nblocks > 1 && inc != BLAKE2S_BLOCK_SIZE)); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci while (nblocks > 0) { 5462306a36Sopenharmony_ci blake2s_increment_counter(state, inc); 5562306a36Sopenharmony_ci memcpy(m, block, BLAKE2S_BLOCK_SIZE); 5662306a36Sopenharmony_ci le32_to_cpu_array(m, ARRAY_SIZE(m)); 5762306a36Sopenharmony_ci memcpy(v, state->h, 32); 5862306a36Sopenharmony_ci v[ 8] = BLAKE2S_IV0; 5962306a36Sopenharmony_ci v[ 9] = BLAKE2S_IV1; 6062306a36Sopenharmony_ci v[10] = BLAKE2S_IV2; 6162306a36Sopenharmony_ci v[11] = BLAKE2S_IV3; 6262306a36Sopenharmony_ci v[12] = BLAKE2S_IV4 ^ state->t[0]; 6362306a36Sopenharmony_ci v[13] = BLAKE2S_IV5 ^ state->t[1]; 6462306a36Sopenharmony_ci v[14] = BLAKE2S_IV6 ^ state->f[0]; 6562306a36Sopenharmony_ci v[15] = BLAKE2S_IV7 ^ state->f[1]; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define G(r, i, a, b, c, d) do { \ 6862306a36Sopenharmony_ci a += b + m[blake2s_sigma[r][2 * i + 0]]; \ 6962306a36Sopenharmony_ci d = ror32(d ^ a, 16); \ 7062306a36Sopenharmony_ci c += d; \ 7162306a36Sopenharmony_ci b = ror32(b ^ c, 12); \ 7262306a36Sopenharmony_ci a += b + m[blake2s_sigma[r][2 * i + 1]]; \ 7362306a36Sopenharmony_ci d = ror32(d ^ a, 8); \ 7462306a36Sopenharmony_ci c += d; \ 7562306a36Sopenharmony_ci b = ror32(b ^ c, 7); \ 7662306a36Sopenharmony_ci} while (0) 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#define ROUND(r) do { \ 7962306a36Sopenharmony_ci G(r, 0, v[0], v[ 4], v[ 8], v[12]); \ 8062306a36Sopenharmony_ci G(r, 1, v[1], v[ 5], v[ 9], v[13]); \ 8162306a36Sopenharmony_ci G(r, 2, v[2], v[ 6], v[10], v[14]); \ 8262306a36Sopenharmony_ci G(r, 3, v[3], v[ 7], v[11], v[15]); \ 8362306a36Sopenharmony_ci G(r, 4, v[0], v[ 5], v[10], v[15]); \ 8462306a36Sopenharmony_ci G(r, 5, v[1], v[ 6], v[11], v[12]); \ 8562306a36Sopenharmony_ci G(r, 6, v[2], v[ 7], v[ 8], v[13]); \ 8662306a36Sopenharmony_ci G(r, 7, v[3], v[ 4], v[ 9], v[14]); \ 8762306a36Sopenharmony_ci} while (0) 8862306a36Sopenharmony_ci ROUND(0); 8962306a36Sopenharmony_ci ROUND(1); 9062306a36Sopenharmony_ci ROUND(2); 9162306a36Sopenharmony_ci ROUND(3); 9262306a36Sopenharmony_ci ROUND(4); 9362306a36Sopenharmony_ci ROUND(5); 9462306a36Sopenharmony_ci ROUND(6); 9562306a36Sopenharmony_ci ROUND(7); 9662306a36Sopenharmony_ci ROUND(8); 9762306a36Sopenharmony_ci ROUND(9); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci#undef G 10062306a36Sopenharmony_ci#undef ROUND 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci for (i = 0; i < 8; ++i) 10362306a36Sopenharmony_ci state->h[i] ^= v[i] ^ v[i + 8]; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci block += BLAKE2S_BLOCK_SIZE; 10662306a36Sopenharmony_ci --nblocks; 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ciEXPORT_SYMBOL(blake2s_compress_generic); 111