162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * sha512-neon-glue.c - accelerated SHA-384/512 for ARM NEON
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <crypto/internal/hash.h>
962306a36Sopenharmony_ci#include <crypto/internal/simd.h>
1062306a36Sopenharmony_ci#include <crypto/sha2.h>
1162306a36Sopenharmony_ci#include <crypto/sha512_base.h>
1262306a36Sopenharmony_ci#include <linux/crypto.h>
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <asm/simd.h>
1662306a36Sopenharmony_ci#include <asm/neon.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include "sha512.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("sha384-neon");
2162306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("sha512-neon");
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ciasmlinkage void sha512_block_data_order_neon(struct sha512_state *state,
2462306a36Sopenharmony_ci					     const u8 *src, int blocks);
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic int sha512_neon_update(struct shash_desc *desc, const u8 *data,
2762306a36Sopenharmony_ci			      unsigned int len)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	struct sha512_state *sctx = shash_desc_ctx(desc);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	if (!crypto_simd_usable() ||
3262306a36Sopenharmony_ci	    (sctx->count[0] % SHA512_BLOCK_SIZE) + len < SHA512_BLOCK_SIZE)
3362306a36Sopenharmony_ci		return sha512_arm_update(desc, data, len);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	kernel_neon_begin();
3662306a36Sopenharmony_ci	sha512_base_do_update(desc, data, len, sha512_block_data_order_neon);
3762306a36Sopenharmony_ci	kernel_neon_end();
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	return 0;
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic int sha512_neon_finup(struct shash_desc *desc, const u8 *data,
4362306a36Sopenharmony_ci			     unsigned int len, u8 *out)
4462306a36Sopenharmony_ci{
4562306a36Sopenharmony_ci	if (!crypto_simd_usable())
4662306a36Sopenharmony_ci		return sha512_arm_finup(desc, data, len, out);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	kernel_neon_begin();
4962306a36Sopenharmony_ci	if (len)
5062306a36Sopenharmony_ci		sha512_base_do_update(desc, data, len,
5162306a36Sopenharmony_ci				      sha512_block_data_order_neon);
5262306a36Sopenharmony_ci	sha512_base_do_finalize(desc, sha512_block_data_order_neon);
5362306a36Sopenharmony_ci	kernel_neon_end();
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	return sha512_base_finish(desc, out);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic int sha512_neon_final(struct shash_desc *desc, u8 *out)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	return sha512_neon_finup(desc, NULL, 0, out);
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistruct shash_alg sha512_neon_algs[] = { {
6462306a36Sopenharmony_ci	.init			= sha384_base_init,
6562306a36Sopenharmony_ci	.update			= sha512_neon_update,
6662306a36Sopenharmony_ci	.final			= sha512_neon_final,
6762306a36Sopenharmony_ci	.finup			= sha512_neon_finup,
6862306a36Sopenharmony_ci	.descsize		= sizeof(struct sha512_state),
6962306a36Sopenharmony_ci	.digestsize		= SHA384_DIGEST_SIZE,
7062306a36Sopenharmony_ci	.base			= {
7162306a36Sopenharmony_ci		.cra_name		= "sha384",
7262306a36Sopenharmony_ci		.cra_driver_name	= "sha384-neon",
7362306a36Sopenharmony_ci		.cra_priority		= 300,
7462306a36Sopenharmony_ci		.cra_blocksize		= SHA384_BLOCK_SIZE,
7562306a36Sopenharmony_ci		.cra_module		= THIS_MODULE,
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	}
7862306a36Sopenharmony_ci},  {
7962306a36Sopenharmony_ci	.init			= sha512_base_init,
8062306a36Sopenharmony_ci	.update			= sha512_neon_update,
8162306a36Sopenharmony_ci	.final			= sha512_neon_final,
8262306a36Sopenharmony_ci	.finup			= sha512_neon_finup,
8362306a36Sopenharmony_ci	.descsize		= sizeof(struct sha512_state),
8462306a36Sopenharmony_ci	.digestsize		= SHA512_DIGEST_SIZE,
8562306a36Sopenharmony_ci	.base			= {
8662306a36Sopenharmony_ci		.cra_name		= "sha512",
8762306a36Sopenharmony_ci		.cra_driver_name	= "sha512-neon",
8862306a36Sopenharmony_ci		.cra_priority		= 300,
8962306a36Sopenharmony_ci		.cra_blocksize		= SHA512_BLOCK_SIZE,
9062306a36Sopenharmony_ci		.cra_module		= THIS_MODULE,
9162306a36Sopenharmony_ci	}
9262306a36Sopenharmony_ci} };
93