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