xref: /openbmc/linux/arch/arm64/crypto/sha512-ce-glue.c (revision bb6c8c467bce25ccd0c485b7c3214dde6b0bcb33)
1*bb6c8c46SArd Biesheuvel /* SPDX-License-Identifier: GPL-2.0 */
2*bb6c8c46SArd Biesheuvel /*
3*bb6c8c46SArd Biesheuvel  * sha512-ce-glue.c - SHA-384/SHA-512 using ARMv8 Crypto Extensions
4*bb6c8c46SArd Biesheuvel  *
5*bb6c8c46SArd Biesheuvel  * Copyright (C) 2018 Linaro Ltd <ard.biesheuvel@linaro.org>
6*bb6c8c46SArd Biesheuvel  *
7*bb6c8c46SArd Biesheuvel  * This program is free software; you can redistribute it and/or modify
8*bb6c8c46SArd Biesheuvel  * it under the terms of the GNU General Public License version 2 as
9*bb6c8c46SArd Biesheuvel  * published by the Free Software Foundation.
10*bb6c8c46SArd Biesheuvel  */
11*bb6c8c46SArd Biesheuvel 
12*bb6c8c46SArd Biesheuvel #include <asm/neon.h>
13*bb6c8c46SArd Biesheuvel #include <asm/simd.h>
14*bb6c8c46SArd Biesheuvel #include <asm/unaligned.h>
15*bb6c8c46SArd Biesheuvel #include <crypto/internal/hash.h>
16*bb6c8c46SArd Biesheuvel #include <crypto/sha.h>
17*bb6c8c46SArd Biesheuvel #include <crypto/sha512_base.h>
18*bb6c8c46SArd Biesheuvel #include <linux/cpufeature.h>
19*bb6c8c46SArd Biesheuvel #include <linux/crypto.h>
20*bb6c8c46SArd Biesheuvel #include <linux/module.h>
21*bb6c8c46SArd Biesheuvel 
22*bb6c8c46SArd Biesheuvel MODULE_DESCRIPTION("SHA-384/SHA-512 secure hash using ARMv8 Crypto Extensions");
23*bb6c8c46SArd Biesheuvel MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
24*bb6c8c46SArd Biesheuvel MODULE_LICENSE("GPL v2");
25*bb6c8c46SArd Biesheuvel 
26*bb6c8c46SArd Biesheuvel asmlinkage void sha512_ce_transform(struct sha512_state *sst, u8 const *src,
27*bb6c8c46SArd Biesheuvel 				    int blocks);
28*bb6c8c46SArd Biesheuvel 
29*bb6c8c46SArd Biesheuvel asmlinkage void sha512_block_data_order(u64 *digest, u8 const *src, int blocks);
30*bb6c8c46SArd Biesheuvel 
31*bb6c8c46SArd Biesheuvel static int sha512_ce_update(struct shash_desc *desc, const u8 *data,
32*bb6c8c46SArd Biesheuvel 			    unsigned int len)
33*bb6c8c46SArd Biesheuvel {
34*bb6c8c46SArd Biesheuvel 	if (!may_use_simd())
35*bb6c8c46SArd Biesheuvel 		return sha512_base_do_update(desc, data, len,
36*bb6c8c46SArd Biesheuvel 				(sha512_block_fn *)sha512_block_data_order);
37*bb6c8c46SArd Biesheuvel 
38*bb6c8c46SArd Biesheuvel 	kernel_neon_begin();
39*bb6c8c46SArd Biesheuvel 	sha512_base_do_update(desc, data, len,
40*bb6c8c46SArd Biesheuvel 			      (sha512_block_fn *)sha512_ce_transform);
41*bb6c8c46SArd Biesheuvel 	kernel_neon_end();
42*bb6c8c46SArd Biesheuvel 
43*bb6c8c46SArd Biesheuvel 	return 0;
44*bb6c8c46SArd Biesheuvel }
45*bb6c8c46SArd Biesheuvel 
46*bb6c8c46SArd Biesheuvel static int sha512_ce_finup(struct shash_desc *desc, const u8 *data,
47*bb6c8c46SArd Biesheuvel 			   unsigned int len, u8 *out)
48*bb6c8c46SArd Biesheuvel {
49*bb6c8c46SArd Biesheuvel 	if (!may_use_simd()) {
50*bb6c8c46SArd Biesheuvel 		if (len)
51*bb6c8c46SArd Biesheuvel 			sha512_base_do_update(desc, data, len,
52*bb6c8c46SArd Biesheuvel 				(sha512_block_fn *)sha512_block_data_order);
53*bb6c8c46SArd Biesheuvel 		sha512_base_do_finalize(desc,
54*bb6c8c46SArd Biesheuvel 				(sha512_block_fn *)sha512_block_data_order);
55*bb6c8c46SArd Biesheuvel 		return sha512_base_finish(desc, out);
56*bb6c8c46SArd Biesheuvel 	}
57*bb6c8c46SArd Biesheuvel 
58*bb6c8c46SArd Biesheuvel 	kernel_neon_begin();
59*bb6c8c46SArd Biesheuvel 	sha512_base_do_update(desc, data, len,
60*bb6c8c46SArd Biesheuvel 			      (sha512_block_fn *)sha512_ce_transform);
61*bb6c8c46SArd Biesheuvel 	sha512_base_do_finalize(desc, (sha512_block_fn *)sha512_ce_transform);
62*bb6c8c46SArd Biesheuvel 	kernel_neon_end();
63*bb6c8c46SArd Biesheuvel 	return sha512_base_finish(desc, out);
64*bb6c8c46SArd Biesheuvel }
65*bb6c8c46SArd Biesheuvel 
66*bb6c8c46SArd Biesheuvel static int sha512_ce_final(struct shash_desc *desc, u8 *out)
67*bb6c8c46SArd Biesheuvel {
68*bb6c8c46SArd Biesheuvel 	if (!may_use_simd()) {
69*bb6c8c46SArd Biesheuvel 		sha512_base_do_finalize(desc,
70*bb6c8c46SArd Biesheuvel 				(sha512_block_fn *)sha512_block_data_order);
71*bb6c8c46SArd Biesheuvel 		return sha512_base_finish(desc, out);
72*bb6c8c46SArd Biesheuvel 	}
73*bb6c8c46SArd Biesheuvel 
74*bb6c8c46SArd Biesheuvel 	kernel_neon_begin();
75*bb6c8c46SArd Biesheuvel 	sha512_base_do_finalize(desc, (sha512_block_fn *)sha512_ce_transform);
76*bb6c8c46SArd Biesheuvel 	kernel_neon_end();
77*bb6c8c46SArd Biesheuvel 	return sha512_base_finish(desc, out);
78*bb6c8c46SArd Biesheuvel }
79*bb6c8c46SArd Biesheuvel 
80*bb6c8c46SArd Biesheuvel static struct shash_alg algs[] = { {
81*bb6c8c46SArd Biesheuvel 	.init			= sha384_base_init,
82*bb6c8c46SArd Biesheuvel 	.update			= sha512_ce_update,
83*bb6c8c46SArd Biesheuvel 	.final			= sha512_ce_final,
84*bb6c8c46SArd Biesheuvel 	.finup			= sha512_ce_finup,
85*bb6c8c46SArd Biesheuvel 	.descsize		= sizeof(struct sha512_state),
86*bb6c8c46SArd Biesheuvel 	.digestsize		= SHA384_DIGEST_SIZE,
87*bb6c8c46SArd Biesheuvel 	.base.cra_name		= "sha384",
88*bb6c8c46SArd Biesheuvel 	.base.cra_driver_name	= "sha384-ce",
89*bb6c8c46SArd Biesheuvel 	.base.cra_priority	= 200,
90*bb6c8c46SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
91*bb6c8c46SArd Biesheuvel 	.base.cra_blocksize	= SHA512_BLOCK_SIZE,
92*bb6c8c46SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
93*bb6c8c46SArd Biesheuvel }, {
94*bb6c8c46SArd Biesheuvel 	.init			= sha512_base_init,
95*bb6c8c46SArd Biesheuvel 	.update			= sha512_ce_update,
96*bb6c8c46SArd Biesheuvel 	.final			= sha512_ce_final,
97*bb6c8c46SArd Biesheuvel 	.finup			= sha512_ce_finup,
98*bb6c8c46SArd Biesheuvel 	.descsize		= sizeof(struct sha512_state),
99*bb6c8c46SArd Biesheuvel 	.digestsize		= SHA512_DIGEST_SIZE,
100*bb6c8c46SArd Biesheuvel 	.base.cra_name		= "sha512",
101*bb6c8c46SArd Biesheuvel 	.base.cra_driver_name	= "sha512-ce",
102*bb6c8c46SArd Biesheuvel 	.base.cra_priority	= 200,
103*bb6c8c46SArd Biesheuvel 	.base.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
104*bb6c8c46SArd Biesheuvel 	.base.cra_blocksize	= SHA512_BLOCK_SIZE,
105*bb6c8c46SArd Biesheuvel 	.base.cra_module	= THIS_MODULE,
106*bb6c8c46SArd Biesheuvel } };
107*bb6c8c46SArd Biesheuvel 
108*bb6c8c46SArd Biesheuvel static int __init sha512_ce_mod_init(void)
109*bb6c8c46SArd Biesheuvel {
110*bb6c8c46SArd Biesheuvel 	return crypto_register_shashes(algs, ARRAY_SIZE(algs));
111*bb6c8c46SArd Biesheuvel }
112*bb6c8c46SArd Biesheuvel 
113*bb6c8c46SArd Biesheuvel static void __exit sha512_ce_mod_fini(void)
114*bb6c8c46SArd Biesheuvel {
115*bb6c8c46SArd Biesheuvel 	crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
116*bb6c8c46SArd Biesheuvel }
117*bb6c8c46SArd Biesheuvel 
118*bb6c8c46SArd Biesheuvel module_cpu_feature_match(SHA512, sha512_ce_mod_init);
119*bb6c8c46SArd Biesheuvel module_exit(sha512_ce_mod_fini);
120