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