1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Linux/arm64 port of the OpenSSL SHA256 implementation for AArch64
5 * Copyright (c) 2016 Linaro Ltd. <ard.biesheuvel@linaro.org>
11 #include <crypto/internal/hash.h>
12 #include <crypto/internal/simd.h>
13 #include <crypto/sha.h>
14 #include <crypto/sha256_base.h>
15 #include <linux/cryptohash.h>
16 #include <linux/types.h>
17 #include <linux/string.h>
19 MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash for arm64");
20 MODULE_AUTHOR("Andy Polyakov <appro@openssl.org>");
21 MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
22 MODULE_LICENSE("GPL v2");
23 MODULE_ALIAS_CRYPTO("sha224");
24 MODULE_ALIAS_CRYPTO("sha256");
26 asmlinkage
void sha256_block_data_order(u32
*digest
, const void *data
,
27 unsigned int num_blks
);
28 EXPORT_SYMBOL(sha256_block_data_order
);
30 asmlinkage
void sha256_block_neon(u32
*digest
, const void *data
,
31 unsigned int num_blks
);
33 static int sha256_update(struct shash_desc
*desc
, const u8
*data
,
36 return sha256_base_do_update(desc
, data
, len
,
37 (sha256_block_fn
*)sha256_block_data_order
);
40 static int sha256_finup(struct shash_desc
*desc
, const u8
*data
,
41 unsigned int len
, u8
*out
)
44 sha256_base_do_update(desc
, data
, len
,
45 (sha256_block_fn
*)sha256_block_data_order
);
46 sha256_base_do_finalize(desc
,
47 (sha256_block_fn
*)sha256_block_data_order
);
49 return sha256_base_finish(desc
, out
);
52 static int sha256_final(struct shash_desc
*desc
, u8
*out
)
54 return sha256_finup(desc
, NULL
, 0, out
);
57 static struct shash_alg algs
[] = { {
58 .digestsize
= SHA256_DIGEST_SIZE
,
59 .init
= sha256_base_init
,
60 .update
= sha256_update
,
61 .final
= sha256_final
,
62 .finup
= sha256_finup
,
63 .descsize
= sizeof(struct sha256_state
),
64 .base
.cra_name
= "sha256",
65 .base
.cra_driver_name
= "sha256-arm64",
66 .base
.cra_priority
= 125,
67 .base
.cra_blocksize
= SHA256_BLOCK_SIZE
,
68 .base
.cra_module
= THIS_MODULE
,
70 .digestsize
= SHA224_DIGEST_SIZE
,
71 .init
= sha224_base_init
,
72 .update
= sha256_update
,
73 .final
= sha256_final
,
74 .finup
= sha256_finup
,
75 .descsize
= sizeof(struct sha256_state
),
76 .base
.cra_name
= "sha224",
77 .base
.cra_driver_name
= "sha224-arm64",
78 .base
.cra_priority
= 125,
79 .base
.cra_blocksize
= SHA224_BLOCK_SIZE
,
80 .base
.cra_module
= THIS_MODULE
,
83 static int sha256_update_neon(struct shash_desc
*desc
, const u8
*data
,
86 struct sha256_state
*sctx
= shash_desc_ctx(desc
);
88 if (!crypto_simd_usable())
89 return sha256_base_do_update(desc
, data
, len
,
90 (sha256_block_fn
*)sha256_block_data_order
);
93 unsigned int chunk
= len
;
96 * Don't hog the CPU for the entire time it takes to process all
97 * input when running on a preemptible kernel, but process the
98 * data block by block instead.
100 if (IS_ENABLED(CONFIG_PREEMPT
) &&
101 chunk
+ sctx
->count
% SHA256_BLOCK_SIZE
> SHA256_BLOCK_SIZE
)
102 chunk
= SHA256_BLOCK_SIZE
-
103 sctx
->count
% SHA256_BLOCK_SIZE
;
106 sha256_base_do_update(desc
, data
, chunk
,
107 (sha256_block_fn
*)sha256_block_neon
);
115 static int sha256_finup_neon(struct shash_desc
*desc
, const u8
*data
,
116 unsigned int len
, u8
*out
)
118 if (!crypto_simd_usable()) {
120 sha256_base_do_update(desc
, data
, len
,
121 (sha256_block_fn
*)sha256_block_data_order
);
122 sha256_base_do_finalize(desc
,
123 (sha256_block_fn
*)sha256_block_data_order
);
126 sha256_update_neon(desc
, data
, len
);
128 sha256_base_do_finalize(desc
,
129 (sha256_block_fn
*)sha256_block_neon
);
132 return sha256_base_finish(desc
, out
);
135 static int sha256_final_neon(struct shash_desc
*desc
, u8
*out
)
137 return sha256_finup_neon(desc
, NULL
, 0, out
);
140 static struct shash_alg neon_algs
[] = { {
141 .digestsize
= SHA256_DIGEST_SIZE
,
142 .init
= sha256_base_init
,
143 .update
= sha256_update_neon
,
144 .final
= sha256_final_neon
,
145 .finup
= sha256_finup_neon
,
146 .descsize
= sizeof(struct sha256_state
),
147 .base
.cra_name
= "sha256",
148 .base
.cra_driver_name
= "sha256-arm64-neon",
149 .base
.cra_priority
= 150,
150 .base
.cra_blocksize
= SHA256_BLOCK_SIZE
,
151 .base
.cra_module
= THIS_MODULE
,
153 .digestsize
= SHA224_DIGEST_SIZE
,
154 .init
= sha224_base_init
,
155 .update
= sha256_update_neon
,
156 .final
= sha256_final_neon
,
157 .finup
= sha256_finup_neon
,
158 .descsize
= sizeof(struct sha256_state
),
159 .base
.cra_name
= "sha224",
160 .base
.cra_driver_name
= "sha224-arm64-neon",
161 .base
.cra_priority
= 150,
162 .base
.cra_blocksize
= SHA224_BLOCK_SIZE
,
163 .base
.cra_module
= THIS_MODULE
,
166 static int __init
sha256_mod_init(void)
168 int ret
= crypto_register_shashes(algs
, ARRAY_SIZE(algs
));
172 if (cpu_have_named_feature(ASIMD
)) {
173 ret
= crypto_register_shashes(neon_algs
, ARRAY_SIZE(neon_algs
));
175 crypto_unregister_shashes(algs
, ARRAY_SIZE(algs
));
180 static void __exit
sha256_mod_fini(void)
182 if (cpu_have_named_feature(ASIMD
))
183 crypto_unregister_shashes(neon_algs
, ARRAY_SIZE(neon_algs
));
184 crypto_unregister_shashes(algs
, ARRAY_SIZE(algs
));
187 module_init(sha256_mod_init
);
188 module_exit(sha256_mod_fini
);