18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Linux/arm64 port of the OpenSSL SHA512 implementation for AArch64
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2016 Linaro Ltd. <ard.biesheuvel@linaro.org>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h>
98c2ecf20Sopenharmony_ci#include <linux/types.h>
108c2ecf20Sopenharmony_ci#include <linux/string.h>
118c2ecf20Sopenharmony_ci#include <crypto/sha.h>
128c2ecf20Sopenharmony_ci#include <crypto/sha512_base.h>
138c2ecf20Sopenharmony_ci#include <asm/neon.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("SHA-384/SHA-512 secure hash for arm64");
168c2ecf20Sopenharmony_ciMODULE_AUTHOR("Andy Polyakov <appro@openssl.org>");
178c2ecf20Sopenharmony_ciMODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
188c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
198c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("sha384");
208c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("sha512");
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ciasmlinkage void sha512_block_data_order(u64 *digest, const void *data,
238c2ecf20Sopenharmony_ci					unsigned int num_blks);
248c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sha512_block_data_order);
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistatic void __sha512_block_data_order(struct sha512_state *sst, u8 const *src,
278c2ecf20Sopenharmony_ci				      int blocks)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	sha512_block_data_order(sst->state, src, blocks);
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic int sha512_update(struct shash_desc *desc, const u8 *data,
338c2ecf20Sopenharmony_ci			 unsigned int len)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	return sha512_base_do_update(desc, data, len,
368c2ecf20Sopenharmony_ci				     __sha512_block_data_order);
378c2ecf20Sopenharmony_ci}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic int sha512_finup(struct shash_desc *desc, const u8 *data,
408c2ecf20Sopenharmony_ci			unsigned int len, u8 *out)
418c2ecf20Sopenharmony_ci{
428c2ecf20Sopenharmony_ci	if (len)
438c2ecf20Sopenharmony_ci		sha512_base_do_update(desc, data, len,
448c2ecf20Sopenharmony_ci				      __sha512_block_data_order);
458c2ecf20Sopenharmony_ci	sha512_base_do_finalize(desc, __sha512_block_data_order);
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	return sha512_base_finish(desc, out);
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic int sha512_final(struct shash_desc *desc, u8 *out)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	return sha512_finup(desc, NULL, 0, out);
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic struct shash_alg algs[] = { {
568c2ecf20Sopenharmony_ci	.digestsize		= SHA512_DIGEST_SIZE,
578c2ecf20Sopenharmony_ci	.init			= sha512_base_init,
588c2ecf20Sopenharmony_ci	.update			= sha512_update,
598c2ecf20Sopenharmony_ci	.final			= sha512_final,
608c2ecf20Sopenharmony_ci	.finup			= sha512_finup,
618c2ecf20Sopenharmony_ci	.descsize		= sizeof(struct sha512_state),
628c2ecf20Sopenharmony_ci	.base.cra_name		= "sha512",
638c2ecf20Sopenharmony_ci	.base.cra_driver_name	= "sha512-arm64",
648c2ecf20Sopenharmony_ci	.base.cra_priority	= 150,
658c2ecf20Sopenharmony_ci	.base.cra_blocksize	= SHA512_BLOCK_SIZE,
668c2ecf20Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
678c2ecf20Sopenharmony_ci}, {
688c2ecf20Sopenharmony_ci	.digestsize		= SHA384_DIGEST_SIZE,
698c2ecf20Sopenharmony_ci	.init			= sha384_base_init,
708c2ecf20Sopenharmony_ci	.update			= sha512_update,
718c2ecf20Sopenharmony_ci	.final			= sha512_final,
728c2ecf20Sopenharmony_ci	.finup			= sha512_finup,
738c2ecf20Sopenharmony_ci	.descsize		= sizeof(struct sha512_state),
748c2ecf20Sopenharmony_ci	.base.cra_name		= "sha384",
758c2ecf20Sopenharmony_ci	.base.cra_driver_name	= "sha384-arm64",
768c2ecf20Sopenharmony_ci	.base.cra_priority	= 150,
778c2ecf20Sopenharmony_ci	.base.cra_blocksize	= SHA384_BLOCK_SIZE,
788c2ecf20Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
798c2ecf20Sopenharmony_ci} };
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic int __init sha512_mod_init(void)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	return crypto_register_shashes(algs, ARRAY_SIZE(algs));
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic void __exit sha512_mod_fini(void)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cimodule_init(sha512_mod_init);
928c2ecf20Sopenharmony_cimodule_exit(sha512_mod_fini);
93