1*cd6714f9STom Rix // SPDX-License-Identifier: GPL-2.0
2bb6c8c46SArd Biesheuvel /*
3bb6c8c46SArd Biesheuvel  * sha512-ce-glue.c - SHA-384/SHA-512 using ARMv8 Crypto Extensions
4bb6c8c46SArd Biesheuvel  *
5bb6c8c46SArd Biesheuvel  * Copyright (C) 2018 Linaro Ltd <ard.biesheuvel@linaro.org>
6bb6c8c46SArd Biesheuvel  *
7bb6c8c46SArd Biesheuvel  * This program is free software; you can redistribute it and/or modify
8bb6c8c46SArd Biesheuvel  * it under the terms of the GNU General Public License version 2 as
9bb6c8c46SArd Biesheuvel  * published by the Free Software Foundation.
10bb6c8c46SArd Biesheuvel  */
11bb6c8c46SArd Biesheuvel 
12bb6c8c46SArd Biesheuvel #include <asm/neon.h>
13bb6c8c46SArd Biesheuvel #include <asm/simd.h>
14bb6c8c46SArd Biesheuvel #include <asm/unaligned.h>
15bb6c8c46SArd Biesheuvel #include <crypto/internal/hash.h>
16e52b7023SEric Biggers #include <crypto/internal/simd.h>
17a24d22b2SEric Biggers #include <crypto/sha2.h>
18bb6c8c46SArd Biesheuvel #include <crypto/sha512_base.h>
19bb6c8c46SArd Biesheuvel #include <linux/cpufeature.h>
20bb6c8c46SArd Biesheuvel #include <linux/crypto.h>
21bb6c8c46SArd Biesheuvel #include <linux/module.h>
22bb6c8c46SArd Biesheuvel 
23bb6c8c46SArd Biesheuvel MODULE_DESCRIPTION("SHA-384/SHA-512 secure hash using ARMv8 Crypto Extensions");
24bb6c8c46SArd Biesheuvel MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
25bb6c8c46SArd Biesheuvel MODULE_LICENSE("GPL v2");
260df07d81SArd Biesheuvel MODULE_ALIAS_CRYPTO("sha384");
270df07d81SArd Biesheuvel MODULE_ALIAS_CRYPTO("sha512");
28bb6c8c46SArd Biesheuvel 
295f6cb2e6SArd Biesheuvel asmlinkage int sha512_ce_transform(struct sha512_state *sst, u8 const *src,
30bb6c8c46SArd Biesheuvel 				   int blocks);
31bb6c8c46SArd Biesheuvel 
32bb6c8c46SArd Biesheuvel asmlinkage void sha512_block_data_order(u64 *digest, u8 const *src, int blocks);
33bb6c8c46SArd Biesheuvel 
__sha512_ce_transform(struct sha512_state * sst,u8 const * src,int blocks)345f6cb2e6SArd Biesheuvel static void __sha512_ce_transform(struct sha512_state *sst, u8 const *src,
355f6cb2e6SArd Biesheuvel 				  int blocks)
365f6cb2e6SArd Biesheuvel {
375f6cb2e6SArd Biesheuvel 	while (blocks) {
385f6cb2e6SArd Biesheuvel 		int rem;
395f6cb2e6SArd Biesheuvel 
405f6cb2e6SArd Biesheuvel 		kernel_neon_begin();
415f6cb2e6SArd Biesheuvel 		rem = sha512_ce_transform(sst, src, blocks);
425f6cb2e6SArd Biesheuvel 		kernel_neon_end();
435f6cb2e6SArd Biesheuvel 		src += (blocks - rem) * SHA512_BLOCK_SIZE;
445f6cb2e6SArd Biesheuvel 		blocks = rem;
455f6cb2e6SArd Biesheuvel 	}
465f6cb2e6SArd Biesheuvel }
475f6cb2e6SArd Biesheuvel 
__sha512_block_data_order(struct sha512_state * sst,u8 const * src,int blocks)486320a15eSSami Tolvanen static void __sha512_block_data_order(struct sha512_state *sst, u8 const *src,
496320a15eSSami Tolvanen 				      int blocks)
506320a15eSSami Tolvanen {
516320a15eSSami Tolvanen 	sha512_block_data_order(sst->state, src, blocks);
526320a15eSSami Tolvanen }
536320a15eSSami Tolvanen 
sha512_ce_update(struct shash_desc * desc,const u8 * data,unsigned int len)54bb6c8c46SArd Biesheuvel static int sha512_ce_update(struct shash_desc *desc, const u8 *data,
55bb6c8c46SArd Biesheuvel 			    unsigned int len)
56bb6c8c46SArd Biesheuvel {
575f6cb2e6SArd Biesheuvel 	sha512_block_fn *fn = crypto_simd_usable() ? __sha512_ce_transform
585f6cb2e6SArd Biesheuvel 						   : __sha512_block_data_order;
59bb6c8c46SArd Biesheuvel 
605f6cb2e6SArd Biesheuvel 	sha512_base_do_update(desc, data, len, fn);
61bb6c8c46SArd Biesheuvel 	return 0;
62bb6c8c46SArd Biesheuvel }
63bb6c8c46SArd Biesheuvel 
sha512_ce_finup(struct shash_desc * desc,const u8 * data,unsigned int len,u8 * out)64bb6c8c46SArd Biesheuvel static int sha512_ce_finup(struct shash_desc *desc, const u8 *data,
65bb6c8c46SArd Biesheuvel 			   unsigned int len, u8 *out)
66bb6c8c46SArd Biesheuvel {
675f6cb2e6SArd Biesheuvel 	sha512_block_fn *fn = crypto_simd_usable() ? __sha512_ce_transform
685f6cb2e6SArd Biesheuvel 						   : __sha512_block_data_order;
69bb6c8c46SArd Biesheuvel 
705f6cb2e6SArd Biesheuvel 	sha512_base_do_update(desc, data, len, fn);
715f6cb2e6SArd Biesheuvel 	sha512_base_do_finalize(desc, fn);
72bb6c8c46SArd Biesheuvel 	return sha512_base_finish(desc, out);
73bb6c8c46SArd Biesheuvel }
74bb6c8c46SArd Biesheuvel 
sha512_ce_final(struct shash_desc * desc,u8 * out)75bb6c8c46SArd Biesheuvel static int sha512_ce_final(struct shash_desc *desc, u8 *out)
76bb6c8c46SArd Biesheuvel {
775f6cb2e6SArd Biesheuvel 	sha512_block_fn *fn = crypto_simd_usable() ? __sha512_ce_transform
785f6cb2e6SArd Biesheuvel 						   : __sha512_block_data_order;
79bb6c8c46SArd Biesheuvel 
805f6cb2e6SArd Biesheuvel 	sha512_base_do_finalize(desc, fn);
81bb6c8c46SArd Biesheuvel 	return sha512_base_finish(desc, out);
82bb6c8c46SArd Biesheuvel }
83bb6c8c46SArd Biesheuvel 
84bb6c8c46SArd Biesheuvel static struct shash_alg algs[] = { {
85bb6c8c46SArd Biesheuvel 	.init			= sha384_base_init,
86bb6c8c46SArd Biesheuvel 	.update			= sha512_ce_update,
87bb6c8c46SArd Biesheuvel 	.final			= sha512_ce_final,
88bb6c8c46SArd Biesheuvel 	.finup			= sha512_ce_finup,
89bb6c8c46SArd Biesheuvel 	.descsize		= sizeof(struct sha512_state),
90bb6c8c46SArd Biesheuvel 	.digestsize		= SHA384_DIGEST_SIZE,
91bb6c8c46SArd Biesheuvel 	.base.cra_name		= "sha384",
92bb6c8c46SArd Biesheuvel 	.base.cra_driver_name	= "sha384-ce",
93bb6c8c46SArd Biesheuvel 	.base.cra_priority	= 200,
94bb6c8c46SArd Biesheuvel 	.base.cra_blocksize	= SHA512_BLOCK_SIZE,
95bb6c8c46SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
96bb6c8c46SArd Biesheuvel }, {
97bb6c8c46SArd Biesheuvel 	.init			= sha512_base_init,
98bb6c8c46SArd Biesheuvel 	.update			= sha512_ce_update,
99bb6c8c46SArd Biesheuvel 	.final			= sha512_ce_final,
100bb6c8c46SArd Biesheuvel 	.finup			= sha512_ce_finup,
101bb6c8c46SArd Biesheuvel 	.descsize		= sizeof(struct sha512_state),
102bb6c8c46SArd Biesheuvel 	.digestsize		= SHA512_DIGEST_SIZE,
103bb6c8c46SArd Biesheuvel 	.base.cra_name		= "sha512",
104bb6c8c46SArd Biesheuvel 	.base.cra_driver_name	= "sha512-ce",
105bb6c8c46SArd Biesheuvel 	.base.cra_priority	= 200,
106bb6c8c46SArd Biesheuvel 	.base.cra_blocksize	= SHA512_BLOCK_SIZE,
107bb6c8c46SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
108bb6c8c46SArd Biesheuvel } };
109bb6c8c46SArd Biesheuvel 
sha512_ce_mod_init(void)110bb6c8c46SArd Biesheuvel static int __init sha512_ce_mod_init(void)
111bb6c8c46SArd Biesheuvel {
112bb6c8c46SArd Biesheuvel 	return crypto_register_shashes(algs, ARRAY_SIZE(algs));
113bb6c8c46SArd Biesheuvel }
114bb6c8c46SArd Biesheuvel 
sha512_ce_mod_fini(void)115bb6c8c46SArd Biesheuvel static void __exit sha512_ce_mod_fini(void)
116bb6c8c46SArd Biesheuvel {
117bb6c8c46SArd Biesheuvel 	crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
118bb6c8c46SArd Biesheuvel }
119bb6c8c46SArd Biesheuvel 
120bb6c8c46SArd Biesheuvel module_cpu_feature_match(SHA512, sha512_ce_mod_init);
121bb6c8c46SArd Biesheuvel module_exit(sha512_ce_mod_fini);
122