162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * BLAKE2b digest algorithm, NEON accelerated 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2020 Google LLC 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <crypto/internal/blake2b.h> 962306a36Sopenharmony_ci#include <crypto/internal/hash.h> 1062306a36Sopenharmony_ci#include <crypto/internal/simd.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/sizes.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <asm/neon.h> 1662306a36Sopenharmony_ci#include <asm/simd.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciasmlinkage void blake2b_compress_neon(struct blake2b_state *state, 1962306a36Sopenharmony_ci const u8 *block, size_t nblocks, u32 inc); 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic void blake2b_compress_arch(struct blake2b_state *state, 2262306a36Sopenharmony_ci const u8 *block, size_t nblocks, u32 inc) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci if (!crypto_simd_usable()) { 2562306a36Sopenharmony_ci blake2b_compress_generic(state, block, nblocks, inc); 2662306a36Sopenharmony_ci return; 2762306a36Sopenharmony_ci } 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci do { 3062306a36Sopenharmony_ci const size_t blocks = min_t(size_t, nblocks, 3162306a36Sopenharmony_ci SZ_4K / BLAKE2B_BLOCK_SIZE); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci kernel_neon_begin(); 3462306a36Sopenharmony_ci blake2b_compress_neon(state, block, blocks, inc); 3562306a36Sopenharmony_ci kernel_neon_end(); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci nblocks -= blocks; 3862306a36Sopenharmony_ci block += blocks * BLAKE2B_BLOCK_SIZE; 3962306a36Sopenharmony_ci } while (nblocks); 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic int crypto_blake2b_update_neon(struct shash_desc *desc, 4362306a36Sopenharmony_ci const u8 *in, unsigned int inlen) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci return crypto_blake2b_update(desc, in, inlen, blake2b_compress_arch); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic int crypto_blake2b_final_neon(struct shash_desc *desc, u8 *out) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci return crypto_blake2b_final(desc, out, blake2b_compress_arch); 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#define BLAKE2B_ALG(name, driver_name, digest_size) \ 5462306a36Sopenharmony_ci { \ 5562306a36Sopenharmony_ci .base.cra_name = name, \ 5662306a36Sopenharmony_ci .base.cra_driver_name = driver_name, \ 5762306a36Sopenharmony_ci .base.cra_priority = 200, \ 5862306a36Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, \ 5962306a36Sopenharmony_ci .base.cra_blocksize = BLAKE2B_BLOCK_SIZE, \ 6062306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct blake2b_tfm_ctx), \ 6162306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, \ 6262306a36Sopenharmony_ci .digestsize = digest_size, \ 6362306a36Sopenharmony_ci .setkey = crypto_blake2b_setkey, \ 6462306a36Sopenharmony_ci .init = crypto_blake2b_init, \ 6562306a36Sopenharmony_ci .update = crypto_blake2b_update_neon, \ 6662306a36Sopenharmony_ci .final = crypto_blake2b_final_neon, \ 6762306a36Sopenharmony_ci .descsize = sizeof(struct blake2b_state), \ 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic struct shash_alg blake2b_neon_algs[] = { 7162306a36Sopenharmony_ci BLAKE2B_ALG("blake2b-160", "blake2b-160-neon", BLAKE2B_160_HASH_SIZE), 7262306a36Sopenharmony_ci BLAKE2B_ALG("blake2b-256", "blake2b-256-neon", BLAKE2B_256_HASH_SIZE), 7362306a36Sopenharmony_ci BLAKE2B_ALG("blake2b-384", "blake2b-384-neon", BLAKE2B_384_HASH_SIZE), 7462306a36Sopenharmony_ci BLAKE2B_ALG("blake2b-512", "blake2b-512-neon", BLAKE2B_512_HASH_SIZE), 7562306a36Sopenharmony_ci}; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic int __init blake2b_neon_mod_init(void) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci if (!(elf_hwcap & HWCAP_NEON)) 8062306a36Sopenharmony_ci return -ENODEV; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci return crypto_register_shashes(blake2b_neon_algs, 8362306a36Sopenharmony_ci ARRAY_SIZE(blake2b_neon_algs)); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic void __exit blake2b_neon_mod_exit(void) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci crypto_unregister_shashes(blake2b_neon_algs, 8962306a36Sopenharmony_ci ARRAY_SIZE(blake2b_neon_algs)); 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cimodule_init(blake2b_neon_mod_init); 9362306a36Sopenharmony_cimodule_exit(blake2b_neon_mod_exit); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ciMODULE_DESCRIPTION("BLAKE2b digest algorithm, NEON accelerated"); 9662306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 9762306a36Sopenharmony_ciMODULE_AUTHOR("Eric Biggers <ebiggers@google.com>"); 9862306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("blake2b-160"); 9962306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("blake2b-160-neon"); 10062306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("blake2b-256"); 10162306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("blake2b-256-neon"); 10262306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("blake2b-384"); 10362306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("blake2b-384-neon"); 10462306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("blake2b-512"); 10562306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("blake2b-512-neon"); 106