1
2
3
4
5
6
7
8
9
10
11
12
13#include <asm/hwcap.h>
14#include <asm/neon.h>
15#include <asm/simd.h>
16#include <crypto/internal/hash.h>
17#include <crypto/sha.h>
18#include <crypto/sha256_base.h>
19#include <linux/cryptohash.h>
20#include <linux/types.h>
21#include <linux/string.h>
22
23MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash for arm64");
24MODULE_AUTHOR("Andy Polyakov <appro@openssl.org>");
25MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
26MODULE_LICENSE("GPL v2");
27MODULE_ALIAS_CRYPTO("sha224");
28MODULE_ALIAS_CRYPTO("sha256");
29
30asmlinkage void sha256_block_data_order(u32 *digest, const void *data,
31 unsigned int num_blks);
32EXPORT_SYMBOL(sha256_block_data_order);
33
34asmlinkage void sha256_block_neon(u32 *digest, const void *data,
35 unsigned int num_blks);
36
37static int sha256_update(struct shash_desc *desc, const u8 *data,
38 unsigned int len)
39{
40 return sha256_base_do_update(desc, data, len,
41 (sha256_block_fn *)sha256_block_data_order);
42}
43
44static int sha256_finup(struct shash_desc *desc, const u8 *data,
45 unsigned int len, u8 *out)
46{
47 if (len)
48 sha256_base_do_update(desc, data, len,
49 (sha256_block_fn *)sha256_block_data_order);
50 sha256_base_do_finalize(desc,
51 (sha256_block_fn *)sha256_block_data_order);
52
53 return sha256_base_finish(desc, out);
54}
55
56static int sha256_final(struct shash_desc *desc, u8 *out)
57{
58 return sha256_finup(desc, NULL, 0, out);
59}
60
61static struct shash_alg algs[] = { {
62 .digestsize = SHA256_DIGEST_SIZE,
63 .init = sha256_base_init,
64 .update = sha256_update,
65 .final = sha256_final,
66 .finup = sha256_finup,
67 .descsize = sizeof(struct sha256_state),
68 .base.cra_name = "sha256",
69 .base.cra_driver_name = "sha256-arm64",
70 .base.cra_priority = 100,
71 .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
72 .base.cra_blocksize = SHA256_BLOCK_SIZE,
73 .base.cra_module = THIS_MODULE,
74}, {
75 .digestsize = SHA224_DIGEST_SIZE,
76 .init = sha224_base_init,
77 .update = sha256_update,
78 .final = sha256_final,
79 .finup = sha256_finup,
80 .descsize = sizeof(struct sha256_state),
81 .base.cra_name = "sha224",
82 .base.cra_driver_name = "sha224-arm64",
83 .base.cra_priority = 100,
84 .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
85 .base.cra_blocksize = SHA224_BLOCK_SIZE,
86 .base.cra_module = THIS_MODULE,
87} };
88
89static int sha256_update_neon(struct shash_desc *desc, const u8 *data,
90 unsigned int len)
91{
92
93
94
95
96
97
98 if (!may_use_simd())
99 return sha256_base_do_update(desc, data, len,
100 (sha256_block_fn *)sha256_block_data_order);
101
102 kernel_neon_begin();
103 sha256_base_do_update(desc, data, len,
104 (sha256_block_fn *)sha256_block_neon);
105 kernel_neon_end();
106
107 return 0;
108}
109
110static int sha256_finup_neon(struct shash_desc *desc, const u8 *data,
111 unsigned int len, u8 *out)
112{
113 if (!may_use_simd()) {
114 if (len)
115 sha256_base_do_update(desc, data, len,
116 (sha256_block_fn *)sha256_block_data_order);
117 sha256_base_do_finalize(desc,
118 (sha256_block_fn *)sha256_block_data_order);
119 } else {
120 kernel_neon_begin();
121 if (len)
122 sha256_base_do_update(desc, data, len,
123 (sha256_block_fn *)sha256_block_neon);
124 sha256_base_do_finalize(desc,
125 (sha256_block_fn *)sha256_block_neon);
126 kernel_neon_end();
127 }
128 return sha256_base_finish(desc, out);
129}
130
131static int sha256_final_neon(struct shash_desc *desc, u8 *out)
132{
133 return sha256_finup_neon(desc, NULL, 0, out);
134}
135
136static struct shash_alg neon_algs[] = { {
137 .digestsize = SHA256_DIGEST_SIZE,
138 .init = sha256_base_init,
139 .update = sha256_update_neon,
140 .final = sha256_final_neon,
141 .finup = sha256_finup_neon,
142 .descsize = sizeof(struct sha256_state),
143 .base.cra_name = "sha256",
144 .base.cra_driver_name = "sha256-arm64-neon",
145 .base.cra_priority = 150,
146 .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
147 .base.cra_blocksize = SHA256_BLOCK_SIZE,
148 .base.cra_module = THIS_MODULE,
149}, {
150 .digestsize = SHA224_DIGEST_SIZE,
151 .init = sha224_base_init,
152 .update = sha256_update_neon,
153 .final = sha256_final_neon,
154 .finup = sha256_finup_neon,
155 .descsize = sizeof(struct sha256_state),
156 .base.cra_name = "sha224",
157 .base.cra_driver_name = "sha224-arm64-neon",
158 .base.cra_priority = 150,
159 .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
160 .base.cra_blocksize = SHA224_BLOCK_SIZE,
161 .base.cra_module = THIS_MODULE,
162} };
163
164static int __init sha256_mod_init(void)
165{
166 int ret = crypto_register_shashes(algs, ARRAY_SIZE(algs));
167 if (ret)
168 return ret;
169
170 if (elf_hwcap & HWCAP_ASIMD) {
171 ret = crypto_register_shashes(neon_algs, ARRAY_SIZE(neon_algs));
172 if (ret)
173 crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
174 }
175 return ret;
176}
177
178static void __exit sha256_mod_fini(void)
179{
180 if (elf_hwcap & HWCAP_ASIMD)
181 crypto_unregister_shashes(neon_algs, ARRAY_SIZE(neon_algs));
182 crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
183}
184
185module_init(sha256_mod_init);
186module_exit(sha256_mod_fini);
187