1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Shared crypto simd helpers
5 * Copyright (c) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
6 * Copyright (c) 2016 Herbert Xu <herbert@gondor.apana.org.au>
7 * Copyright (c) 2019 Google LLC
9 * Based on aesni-intel_glue.c by:
10 * Copyright (C) 2008, Intel Corp.
11 * Author: Huang Ying <ying.huang@intel.com>
15 * Shared crypto SIMD helpers. These functions dynamically create and register
16 * an skcipher or AEAD algorithm that wraps another, internal algorithm. The
17 * wrapper ensures that the internal algorithm is only executed in a context
18 * where SIMD instructions are usable, i.e. where may_use_simd() returns true.
19 * If SIMD is already usable, the wrapper directly calls the internal algorithm.
20 * Otherwise it defers execution to a workqueue via cryptd.
22 * This is an alternative to the internal algorithm implementing a fallback for
23 * the !may_use_simd() case itself.
25 * Note that the wrapper algorithm is asynchronous, i.e. it has the
26 * CRYPTO_ALG_ASYNC flag set. Therefore it won't be found by users who
27 * explicitly allocate a synchronous algorithm.
30 #include <crypto/cryptd.h>
31 #include <crypto/internal/aead.h>
32 #include <crypto/internal/simd.h>
33 #include <crypto/internal/skcipher.h>
34 #include <linux/kernel.h>
35 #include <linux/module.h>
36 #include <linux/preempt.h>
39 /* skcipher support */
41 struct simd_skcipher_alg
{
42 const char *ialg_name
;
43 struct skcipher_alg alg
;
46 struct simd_skcipher_ctx
{
47 struct cryptd_skcipher
*cryptd_tfm
;
50 static int simd_skcipher_setkey(struct crypto_skcipher
*tfm
, const u8
*key
,
53 struct simd_skcipher_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
54 struct crypto_skcipher
*child
= &ctx
->cryptd_tfm
->base
;
56 crypto_skcipher_clear_flags(child
, CRYPTO_TFM_REQ_MASK
);
57 crypto_skcipher_set_flags(child
, crypto_skcipher_get_flags(tfm
) &
59 return crypto_skcipher_setkey(child
, key
, key_len
);
62 static int simd_skcipher_encrypt(struct skcipher_request
*req
)
64 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
65 struct simd_skcipher_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
66 struct skcipher_request
*subreq
;
67 struct crypto_skcipher
*child
;
69 subreq
= skcipher_request_ctx(req
);
72 if (!crypto_simd_usable() ||
73 (in_atomic() && cryptd_skcipher_queued(ctx
->cryptd_tfm
)))
74 child
= &ctx
->cryptd_tfm
->base
;
76 child
= cryptd_skcipher_child(ctx
->cryptd_tfm
);
78 skcipher_request_set_tfm(subreq
, child
);
80 return crypto_skcipher_encrypt(subreq
);
83 static int simd_skcipher_decrypt(struct skcipher_request
*req
)
85 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
86 struct simd_skcipher_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
87 struct skcipher_request
*subreq
;
88 struct crypto_skcipher
*child
;
90 subreq
= skcipher_request_ctx(req
);
93 if (!crypto_simd_usable() ||
94 (in_atomic() && cryptd_skcipher_queued(ctx
->cryptd_tfm
)))
95 child
= &ctx
->cryptd_tfm
->base
;
97 child
= cryptd_skcipher_child(ctx
->cryptd_tfm
);
99 skcipher_request_set_tfm(subreq
, child
);
101 return crypto_skcipher_decrypt(subreq
);
104 static void simd_skcipher_exit(struct crypto_skcipher
*tfm
)
106 struct simd_skcipher_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
108 cryptd_free_skcipher(ctx
->cryptd_tfm
);
111 static int simd_skcipher_init(struct crypto_skcipher
*tfm
)
113 struct simd_skcipher_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
114 struct cryptd_skcipher
*cryptd_tfm
;
115 struct simd_skcipher_alg
*salg
;
116 struct skcipher_alg
*alg
;
119 alg
= crypto_skcipher_alg(tfm
);
120 salg
= container_of(alg
, struct simd_skcipher_alg
, alg
);
122 cryptd_tfm
= cryptd_alloc_skcipher(salg
->ialg_name
,
124 CRYPTO_ALG_INTERNAL
);
125 if (IS_ERR(cryptd_tfm
))
126 return PTR_ERR(cryptd_tfm
);
128 ctx
->cryptd_tfm
= cryptd_tfm
;
130 reqsize
= crypto_skcipher_reqsize(cryptd_skcipher_child(cryptd_tfm
));
131 reqsize
= max(reqsize
, crypto_skcipher_reqsize(&cryptd_tfm
->base
));
132 reqsize
+= sizeof(struct skcipher_request
);
134 crypto_skcipher_set_reqsize(tfm
, reqsize
);
139 struct simd_skcipher_alg
*simd_skcipher_create_compat(const char *algname
,
141 const char *basename
)
143 struct simd_skcipher_alg
*salg
;
144 struct crypto_skcipher
*tfm
;
145 struct skcipher_alg
*ialg
;
146 struct skcipher_alg
*alg
;
149 tfm
= crypto_alloc_skcipher(basename
, CRYPTO_ALG_INTERNAL
,
150 CRYPTO_ALG_INTERNAL
| CRYPTO_ALG_ASYNC
);
152 return ERR_CAST(tfm
);
154 ialg
= crypto_skcipher_alg(tfm
);
156 salg
= kzalloc(sizeof(*salg
), GFP_KERNEL
);
158 salg
= ERR_PTR(-ENOMEM
);
162 salg
->ialg_name
= basename
;
166 if (snprintf(alg
->base
.cra_name
, CRYPTO_MAX_ALG_NAME
, "%s", algname
) >=
170 if (snprintf(alg
->base
.cra_driver_name
, CRYPTO_MAX_ALG_NAME
, "%s",
171 drvname
) >= CRYPTO_MAX_ALG_NAME
)
174 alg
->base
.cra_flags
= CRYPTO_ALG_ASYNC
|
175 (ialg
->base
.cra_flags
& CRYPTO_ALG_INHERITED_FLAGS
);
176 alg
->base
.cra_priority
= ialg
->base
.cra_priority
;
177 alg
->base
.cra_blocksize
= ialg
->base
.cra_blocksize
;
178 alg
->base
.cra_alignmask
= ialg
->base
.cra_alignmask
;
179 alg
->base
.cra_module
= ialg
->base
.cra_module
;
180 alg
->base
.cra_ctxsize
= sizeof(struct simd_skcipher_ctx
);
182 alg
->ivsize
= ialg
->ivsize
;
183 alg
->chunksize
= ialg
->chunksize
;
184 alg
->min_keysize
= ialg
->min_keysize
;
185 alg
->max_keysize
= ialg
->max_keysize
;
187 alg
->init
= simd_skcipher_init
;
188 alg
->exit
= simd_skcipher_exit
;
190 alg
->setkey
= simd_skcipher_setkey
;
191 alg
->encrypt
= simd_skcipher_encrypt
;
192 alg
->decrypt
= simd_skcipher_decrypt
;
194 err
= crypto_register_skcipher(alg
);
199 crypto_free_skcipher(tfm
);
207 EXPORT_SYMBOL_GPL(simd_skcipher_create_compat
);
209 struct simd_skcipher_alg
*simd_skcipher_create(const char *algname
,
210 const char *basename
)
212 char drvname
[CRYPTO_MAX_ALG_NAME
];
214 if (snprintf(drvname
, CRYPTO_MAX_ALG_NAME
, "simd-%s", basename
) >=
216 return ERR_PTR(-ENAMETOOLONG
);
218 return simd_skcipher_create_compat(algname
, drvname
, basename
);
220 EXPORT_SYMBOL_GPL(simd_skcipher_create
);
222 void simd_skcipher_free(struct simd_skcipher_alg
*salg
)
224 crypto_unregister_skcipher(&salg
->alg
);
227 EXPORT_SYMBOL_GPL(simd_skcipher_free
);
229 int simd_register_skciphers_compat(struct skcipher_alg
*algs
, int count
,
230 struct simd_skcipher_alg
**simd_algs
)
236 const char *basename
;
237 struct simd_skcipher_alg
*simd
;
239 err
= crypto_register_skciphers(algs
, count
);
243 for (i
= 0; i
< count
; i
++) {
244 WARN_ON(strncmp(algs
[i
].base
.cra_name
, "__", 2));
245 WARN_ON(strncmp(algs
[i
].base
.cra_driver_name
, "__", 2));
246 algname
= algs
[i
].base
.cra_name
+ 2;
247 drvname
= algs
[i
].base
.cra_driver_name
+ 2;
248 basename
= algs
[i
].base
.cra_driver_name
;
249 simd
= simd_skcipher_create_compat(algname
, drvname
, basename
);
258 simd_unregister_skciphers(algs
, count
, simd_algs
);
261 EXPORT_SYMBOL_GPL(simd_register_skciphers_compat
);
263 void simd_unregister_skciphers(struct skcipher_alg
*algs
, int count
,
264 struct simd_skcipher_alg
**simd_algs
)
268 crypto_unregister_skciphers(algs
, count
);
270 for (i
= 0; i
< count
; i
++) {
272 simd_skcipher_free(simd_algs
[i
]);
277 EXPORT_SYMBOL_GPL(simd_unregister_skciphers
);
281 struct simd_aead_alg
{
282 const char *ialg_name
;
286 struct simd_aead_ctx
{
287 struct cryptd_aead
*cryptd_tfm
;
290 static int simd_aead_setkey(struct crypto_aead
*tfm
, const u8
*key
,
291 unsigned int key_len
)
293 struct simd_aead_ctx
*ctx
= crypto_aead_ctx(tfm
);
294 struct crypto_aead
*child
= &ctx
->cryptd_tfm
->base
;
296 crypto_aead_clear_flags(child
, CRYPTO_TFM_REQ_MASK
);
297 crypto_aead_set_flags(child
, crypto_aead_get_flags(tfm
) &
298 CRYPTO_TFM_REQ_MASK
);
299 return crypto_aead_setkey(child
, key
, key_len
);
302 static int simd_aead_setauthsize(struct crypto_aead
*tfm
, unsigned int authsize
)
304 struct simd_aead_ctx
*ctx
= crypto_aead_ctx(tfm
);
305 struct crypto_aead
*child
= &ctx
->cryptd_tfm
->base
;
307 return crypto_aead_setauthsize(child
, authsize
);
310 static int simd_aead_encrypt(struct aead_request
*req
)
312 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
313 struct simd_aead_ctx
*ctx
= crypto_aead_ctx(tfm
);
314 struct aead_request
*subreq
;
315 struct crypto_aead
*child
;
317 subreq
= aead_request_ctx(req
);
320 if (!crypto_simd_usable() ||
321 (in_atomic() && cryptd_aead_queued(ctx
->cryptd_tfm
)))
322 child
= &ctx
->cryptd_tfm
->base
;
324 child
= cryptd_aead_child(ctx
->cryptd_tfm
);
326 aead_request_set_tfm(subreq
, child
);
328 return crypto_aead_encrypt(subreq
);
331 static int simd_aead_decrypt(struct aead_request
*req
)
333 struct crypto_aead
*tfm
= crypto_aead_reqtfm(req
);
334 struct simd_aead_ctx
*ctx
= crypto_aead_ctx(tfm
);
335 struct aead_request
*subreq
;
336 struct crypto_aead
*child
;
338 subreq
= aead_request_ctx(req
);
341 if (!crypto_simd_usable() ||
342 (in_atomic() && cryptd_aead_queued(ctx
->cryptd_tfm
)))
343 child
= &ctx
->cryptd_tfm
->base
;
345 child
= cryptd_aead_child(ctx
->cryptd_tfm
);
347 aead_request_set_tfm(subreq
, child
);
349 return crypto_aead_decrypt(subreq
);
352 static void simd_aead_exit(struct crypto_aead
*tfm
)
354 struct simd_aead_ctx
*ctx
= crypto_aead_ctx(tfm
);
356 cryptd_free_aead(ctx
->cryptd_tfm
);
359 static int simd_aead_init(struct crypto_aead
*tfm
)
361 struct simd_aead_ctx
*ctx
= crypto_aead_ctx(tfm
);
362 struct cryptd_aead
*cryptd_tfm
;
363 struct simd_aead_alg
*salg
;
364 struct aead_alg
*alg
;
367 alg
= crypto_aead_alg(tfm
);
368 salg
= container_of(alg
, struct simd_aead_alg
, alg
);
370 cryptd_tfm
= cryptd_alloc_aead(salg
->ialg_name
, CRYPTO_ALG_INTERNAL
,
371 CRYPTO_ALG_INTERNAL
);
372 if (IS_ERR(cryptd_tfm
))
373 return PTR_ERR(cryptd_tfm
);
375 ctx
->cryptd_tfm
= cryptd_tfm
;
377 reqsize
= crypto_aead_reqsize(cryptd_aead_child(cryptd_tfm
));
378 reqsize
= max(reqsize
, crypto_aead_reqsize(&cryptd_tfm
->base
));
379 reqsize
+= sizeof(struct aead_request
);
381 crypto_aead_set_reqsize(tfm
, reqsize
);
386 struct simd_aead_alg
*simd_aead_create_compat(const char *algname
,
388 const char *basename
)
390 struct simd_aead_alg
*salg
;
391 struct crypto_aead
*tfm
;
392 struct aead_alg
*ialg
;
393 struct aead_alg
*alg
;
396 tfm
= crypto_alloc_aead(basename
, CRYPTO_ALG_INTERNAL
,
397 CRYPTO_ALG_INTERNAL
| CRYPTO_ALG_ASYNC
);
399 return ERR_CAST(tfm
);
401 ialg
= crypto_aead_alg(tfm
);
403 salg
= kzalloc(sizeof(*salg
), GFP_KERNEL
);
405 salg
= ERR_PTR(-ENOMEM
);
409 salg
->ialg_name
= basename
;
413 if (snprintf(alg
->base
.cra_name
, CRYPTO_MAX_ALG_NAME
, "%s", algname
) >=
417 if (snprintf(alg
->base
.cra_driver_name
, CRYPTO_MAX_ALG_NAME
, "%s",
418 drvname
) >= CRYPTO_MAX_ALG_NAME
)
421 alg
->base
.cra_flags
= CRYPTO_ALG_ASYNC
|
422 (ialg
->base
.cra_flags
& CRYPTO_ALG_INHERITED_FLAGS
);
423 alg
->base
.cra_priority
= ialg
->base
.cra_priority
;
424 alg
->base
.cra_blocksize
= ialg
->base
.cra_blocksize
;
425 alg
->base
.cra_alignmask
= ialg
->base
.cra_alignmask
;
426 alg
->base
.cra_module
= ialg
->base
.cra_module
;
427 alg
->base
.cra_ctxsize
= sizeof(struct simd_aead_ctx
);
429 alg
->ivsize
= ialg
->ivsize
;
430 alg
->maxauthsize
= ialg
->maxauthsize
;
431 alg
->chunksize
= ialg
->chunksize
;
433 alg
->init
= simd_aead_init
;
434 alg
->exit
= simd_aead_exit
;
436 alg
->setkey
= simd_aead_setkey
;
437 alg
->setauthsize
= simd_aead_setauthsize
;
438 alg
->encrypt
= simd_aead_encrypt
;
439 alg
->decrypt
= simd_aead_decrypt
;
441 err
= crypto_register_aead(alg
);
446 crypto_free_aead(tfm
);
454 EXPORT_SYMBOL_GPL(simd_aead_create_compat
);
456 struct simd_aead_alg
*simd_aead_create(const char *algname
,
457 const char *basename
)
459 char drvname
[CRYPTO_MAX_ALG_NAME
];
461 if (snprintf(drvname
, CRYPTO_MAX_ALG_NAME
, "simd-%s", basename
) >=
463 return ERR_PTR(-ENAMETOOLONG
);
465 return simd_aead_create_compat(algname
, drvname
, basename
);
467 EXPORT_SYMBOL_GPL(simd_aead_create
);
469 void simd_aead_free(struct simd_aead_alg
*salg
)
471 crypto_unregister_aead(&salg
->alg
);
474 EXPORT_SYMBOL_GPL(simd_aead_free
);
476 int simd_register_aeads_compat(struct aead_alg
*algs
, int count
,
477 struct simd_aead_alg
**simd_algs
)
483 const char *basename
;
484 struct simd_aead_alg
*simd
;
486 err
= crypto_register_aeads(algs
, count
);
490 for (i
= 0; i
< count
; i
++) {
491 WARN_ON(strncmp(algs
[i
].base
.cra_name
, "__", 2));
492 WARN_ON(strncmp(algs
[i
].base
.cra_driver_name
, "__", 2));
493 algname
= algs
[i
].base
.cra_name
+ 2;
494 drvname
= algs
[i
].base
.cra_driver_name
+ 2;
495 basename
= algs
[i
].base
.cra_driver_name
;
496 simd
= simd_aead_create_compat(algname
, drvname
, basename
);
505 simd_unregister_aeads(algs
, count
, simd_algs
);
508 EXPORT_SYMBOL_GPL(simd_register_aeads_compat
);
510 void simd_unregister_aeads(struct aead_alg
*algs
, int count
,
511 struct simd_aead_alg
**simd_algs
)
515 crypto_unregister_aeads(algs
, count
);
517 for (i
= 0; i
< count
; i
++) {
519 simd_aead_free(simd_algs
[i
]);
524 EXPORT_SYMBOL_GPL(simd_unregister_aeads
);
526 MODULE_LICENSE("GPL");