1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. |
4 | */ |
5 | |
6 | #include <linux/device.h> |
7 | #include <linux/dma-mapping.h> |
8 | #include <linux/interrupt.h> |
9 | #include <linux/moduleparam.h> |
10 | #include <linux/types.h> |
11 | #include <linux/errno.h> |
12 | #include <crypto/aes.h> |
13 | #include <crypto/internal/des.h> |
14 | #include <crypto/internal/skcipher.h> |
15 | |
16 | #include "cipher.h" |
17 | |
18 | static unsigned int aes_sw_max_len = CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN; |
19 | module_param(aes_sw_max_len, uint, 0644); |
20 | MODULE_PARM_DESC(aes_sw_max_len, |
21 | "Only use hardware for AES requests larger than this " |
22 | "[0=always use hardware; anything <16 breaks AES-GCM; default=" |
23 | __stringify(CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN)"]" ); |
24 | |
25 | static LIST_HEAD(skcipher_algs); |
26 | |
27 | static void qce_skcipher_done(void *data) |
28 | { |
29 | struct crypto_async_request *async_req = data; |
30 | struct skcipher_request *req = skcipher_request_cast(req: async_req); |
31 | struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); |
32 | struct qce_alg_template *tmpl = to_cipher_tmpl(tfm: crypto_skcipher_reqtfm(req)); |
33 | struct qce_device *qce = tmpl->qce; |
34 | struct qce_result_dump *result_buf = qce->dma.result_buf; |
35 | enum dma_data_direction dir_src, dir_dst; |
36 | u32 status; |
37 | int error; |
38 | bool diff_dst; |
39 | |
40 | diff_dst = (req->src != req->dst) ? true : false; |
41 | dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; |
42 | dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; |
43 | |
44 | error = qce_dma_terminate_all(dma: &qce->dma); |
45 | if (error) |
46 | dev_dbg(qce->dev, "skcipher dma termination error (%d)\n" , |
47 | error); |
48 | |
49 | if (diff_dst) |
50 | dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); |
51 | dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); |
52 | |
53 | sg_free_table(&rctx->dst_tbl); |
54 | |
55 | error = qce_check_status(qce, status: &status); |
56 | if (error < 0) |
57 | dev_dbg(qce->dev, "skcipher operation error (%x)\n" , status); |
58 | |
59 | memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); |
60 | qce->async_req_done(tmpl->qce, error); |
61 | } |
62 | |
63 | static int |
64 | qce_skcipher_async_req_handle(struct crypto_async_request *async_req) |
65 | { |
66 | struct skcipher_request *req = skcipher_request_cast(req: async_req); |
67 | struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); |
68 | struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); |
69 | struct qce_alg_template *tmpl = to_cipher_tmpl(tfm: crypto_skcipher_reqtfm(req)); |
70 | struct qce_device *qce = tmpl->qce; |
71 | enum dma_data_direction dir_src, dir_dst; |
72 | struct scatterlist *sg; |
73 | bool diff_dst; |
74 | gfp_t gfp; |
75 | int dst_nents, src_nents, ret; |
76 | |
77 | rctx->iv = req->iv; |
78 | rctx->ivsize = crypto_skcipher_ivsize(tfm: skcipher); |
79 | rctx->cryptlen = req->cryptlen; |
80 | |
81 | diff_dst = (req->src != req->dst) ? true : false; |
82 | dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; |
83 | dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; |
84 | |
85 | rctx->src_nents = sg_nents_for_len(sg: req->src, len: req->cryptlen); |
86 | if (diff_dst) |
87 | rctx->dst_nents = sg_nents_for_len(sg: req->dst, len: req->cryptlen); |
88 | else |
89 | rctx->dst_nents = rctx->src_nents; |
90 | if (rctx->src_nents < 0) { |
91 | dev_err(qce->dev, "Invalid numbers of src SG.\n" ); |
92 | return rctx->src_nents; |
93 | } |
94 | if (rctx->dst_nents < 0) { |
95 | dev_err(qce->dev, "Invalid numbers of dst SG.\n" ); |
96 | return -rctx->dst_nents; |
97 | } |
98 | |
99 | rctx->dst_nents += 1; |
100 | |
101 | gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? |
102 | GFP_KERNEL : GFP_ATOMIC; |
103 | |
104 | ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp); |
105 | if (ret) |
106 | return ret; |
107 | |
108 | sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); |
109 | |
110 | sg = qce_sgtable_add(sgt: &rctx->dst_tbl, sg_add: req->dst, max_len: req->cryptlen); |
111 | if (IS_ERR(ptr: sg)) { |
112 | ret = PTR_ERR(ptr: sg); |
113 | goto error_free; |
114 | } |
115 | |
116 | sg = qce_sgtable_add(sgt: &rctx->dst_tbl, sg_add: &rctx->result_sg, |
117 | QCE_RESULT_BUF_SZ); |
118 | if (IS_ERR(ptr: sg)) { |
119 | ret = PTR_ERR(ptr: sg); |
120 | goto error_free; |
121 | } |
122 | |
123 | sg_mark_end(sg); |
124 | rctx->dst_sg = rctx->dst_tbl.sgl; |
125 | |
126 | dst_nents = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); |
127 | if (!dst_nents) { |
128 | ret = -EIO; |
129 | goto error_free; |
130 | } |
131 | |
132 | if (diff_dst) { |
133 | src_nents = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src); |
134 | if (!src_nents) { |
135 | ret = -EIO; |
136 | goto error_unmap_dst; |
137 | } |
138 | rctx->src_sg = req->src; |
139 | } else { |
140 | rctx->src_sg = rctx->dst_sg; |
141 | src_nents = dst_nents - 1; |
142 | } |
143 | |
144 | ret = qce_dma_prep_sgs(dma: &qce->dma, sg_in: rctx->src_sg, in_ents: src_nents, |
145 | sg_out: rctx->dst_sg, out_ents: dst_nents, |
146 | cb: qce_skcipher_done, cb_param: async_req); |
147 | if (ret) |
148 | goto error_unmap_src; |
149 | |
150 | qce_dma_issue_pending(dma: &qce->dma); |
151 | |
152 | ret = qce_start(async_req, type: tmpl->crypto_alg_type); |
153 | if (ret) |
154 | goto error_terminate; |
155 | |
156 | return 0; |
157 | |
158 | error_terminate: |
159 | qce_dma_terminate_all(dma: &qce->dma); |
160 | error_unmap_src: |
161 | if (diff_dst) |
162 | dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src); |
163 | error_unmap_dst: |
164 | dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); |
165 | error_free: |
166 | sg_free_table(&rctx->dst_tbl); |
167 | return ret; |
168 | } |
169 | |
170 | static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, |
171 | unsigned int keylen) |
172 | { |
173 | struct crypto_tfm *tfm = crypto_skcipher_tfm(tfm: ablk); |
174 | struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); |
175 | unsigned long flags = to_cipher_tmpl(tfm: ablk)->alg_flags; |
176 | unsigned int __keylen; |
177 | int ret; |
178 | |
179 | if (!key || !keylen) |
180 | return -EINVAL; |
181 | |
182 | /* |
183 | * AES XTS key1 = key2 not supported by crypto engine. |
184 | * Revisit to request a fallback cipher in this case. |
185 | */ |
186 | if (IS_XTS(flags)) { |
187 | __keylen = keylen >> 1; |
188 | if (!memcmp(p: key, q: key + __keylen, size: __keylen)) |
189 | return -ENOKEY; |
190 | } else { |
191 | __keylen = keylen; |
192 | } |
193 | |
194 | switch (__keylen) { |
195 | case AES_KEYSIZE_128: |
196 | case AES_KEYSIZE_256: |
197 | memcpy(ctx->enc_key, key, keylen); |
198 | break; |
199 | case AES_KEYSIZE_192: |
200 | break; |
201 | default: |
202 | return -EINVAL; |
203 | } |
204 | |
205 | ret = crypto_skcipher_setkey(tfm: ctx->fallback, key, keylen); |
206 | if (!ret) |
207 | ctx->enc_keylen = keylen; |
208 | return ret; |
209 | } |
210 | |
211 | static int qce_des_setkey(struct crypto_skcipher *ablk, const u8 *key, |
212 | unsigned int keylen) |
213 | { |
214 | struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm: ablk); |
215 | int err; |
216 | |
217 | err = verify_skcipher_des_key(tfm: ablk, key); |
218 | if (err) |
219 | return err; |
220 | |
221 | ctx->enc_keylen = keylen; |
222 | memcpy(ctx->enc_key, key, keylen); |
223 | return 0; |
224 | } |
225 | |
226 | static int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key, |
227 | unsigned int keylen) |
228 | { |
229 | struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm: ablk); |
230 | u32 _key[6]; |
231 | int err; |
232 | |
233 | err = verify_skcipher_des3_key(tfm: ablk, key); |
234 | if (err) |
235 | return err; |
236 | |
237 | /* |
238 | * The crypto engine does not support any two keys |
239 | * being the same for triple des algorithms. The |
240 | * verify_skcipher_des3_key does not check for all the |
241 | * below conditions. Return -ENOKEY in case any two keys |
242 | * are the same. Revisit to see if a fallback cipher |
243 | * is needed to handle this condition. |
244 | */ |
245 | memcpy(_key, key, DES3_EDE_KEY_SIZE); |
246 | if (!((_key[0] ^ _key[2]) | (_key[1] ^ _key[3])) || |
247 | !((_key[2] ^ _key[4]) | (_key[3] ^ _key[5])) || |
248 | !((_key[0] ^ _key[4]) | (_key[1] ^ _key[5]))) |
249 | return -ENOKEY; |
250 | |
251 | ctx->enc_keylen = keylen; |
252 | memcpy(ctx->enc_key, key, keylen); |
253 | return 0; |
254 | } |
255 | |
256 | static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) |
257 | { |
258 | struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); |
259 | struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); |
260 | struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); |
261 | struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); |
262 | unsigned int blocksize = crypto_skcipher_blocksize(tfm); |
263 | int keylen; |
264 | int ret; |
265 | |
266 | rctx->flags = tmpl->alg_flags; |
267 | rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; |
268 | keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; |
269 | |
270 | /* CE does not handle 0 length messages */ |
271 | if (!req->cryptlen) |
272 | return 0; |
273 | |
274 | /* |
275 | * ECB and CBC algorithms require message lengths to be |
276 | * multiples of block size. |
277 | */ |
278 | if (IS_ECB(rctx->flags) || IS_CBC(rctx->flags)) |
279 | if (!IS_ALIGNED(req->cryptlen, blocksize)) |
280 | return -EINVAL; |
281 | |
282 | /* |
283 | * Conditions for requesting a fallback cipher |
284 | * AES-192 (not supported by crypto engine (CE)) |
285 | * AES-XTS request with len <= 512 byte (not recommended to use CE) |
286 | * AES-XTS request with len > QCE_SECTOR_SIZE and |
287 | * is not a multiple of it.(Revisit this condition to check if it is |
288 | * needed in all versions of CE) |
289 | */ |
290 | if (IS_AES(rctx->flags) && |
291 | ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || |
292 | (IS_XTS(rctx->flags) && ((req->cryptlen <= aes_sw_max_len) || |
293 | (req->cryptlen > QCE_SECTOR_SIZE && |
294 | req->cryptlen % QCE_SECTOR_SIZE))))) { |
295 | skcipher_request_set_tfm(req: &rctx->fallback_req, tfm: ctx->fallback); |
296 | skcipher_request_set_callback(req: &rctx->fallback_req, |
297 | flags: req->base.flags, |
298 | compl: req->base.complete, |
299 | data: req->base.data); |
300 | skcipher_request_set_crypt(req: &rctx->fallback_req, src: req->src, |
301 | dst: req->dst, cryptlen: req->cryptlen, iv: req->iv); |
302 | ret = encrypt ? crypto_skcipher_encrypt(req: &rctx->fallback_req) : |
303 | crypto_skcipher_decrypt(req: &rctx->fallback_req); |
304 | return ret; |
305 | } |
306 | |
307 | return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); |
308 | } |
309 | |
310 | static int qce_skcipher_encrypt(struct skcipher_request *req) |
311 | { |
312 | return qce_skcipher_crypt(req, encrypt: 1); |
313 | } |
314 | |
315 | static int qce_skcipher_decrypt(struct skcipher_request *req) |
316 | { |
317 | return qce_skcipher_crypt(req, encrypt: 0); |
318 | } |
319 | |
320 | static int qce_skcipher_init(struct crypto_skcipher *tfm) |
321 | { |
322 | /* take the size without the fallback skcipher_request at the end */ |
323 | crypto_skcipher_set_reqsize(skcipher: tfm, offsetof(struct qce_cipher_reqctx, |
324 | fallback_req)); |
325 | return 0; |
326 | } |
327 | |
328 | static int qce_skcipher_init_fallback(struct crypto_skcipher *tfm) |
329 | { |
330 | struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); |
331 | |
332 | ctx->fallback = crypto_alloc_skcipher(alg_name: crypto_tfm_alg_name(tfm: &tfm->base), |
333 | type: 0, CRYPTO_ALG_NEED_FALLBACK); |
334 | if (IS_ERR(ptr: ctx->fallback)) |
335 | return PTR_ERR(ptr: ctx->fallback); |
336 | |
337 | crypto_skcipher_set_reqsize(skcipher: tfm, reqsize: sizeof(struct qce_cipher_reqctx) + |
338 | crypto_skcipher_reqsize(tfm: ctx->fallback)); |
339 | return 0; |
340 | } |
341 | |
342 | static void qce_skcipher_exit(struct crypto_skcipher *tfm) |
343 | { |
344 | struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); |
345 | |
346 | crypto_free_skcipher(tfm: ctx->fallback); |
347 | } |
348 | |
349 | struct qce_skcipher_def { |
350 | unsigned long flags; |
351 | const char *name; |
352 | const char *drv_name; |
353 | unsigned int blocksize; |
354 | unsigned int chunksize; |
355 | unsigned int ivsize; |
356 | unsigned int min_keysize; |
357 | unsigned int max_keysize; |
358 | }; |
359 | |
360 | static const struct qce_skcipher_def skcipher_def[] = { |
361 | { |
362 | .flags = QCE_ALG_AES | QCE_MODE_ECB, |
363 | .name = "ecb(aes)" , |
364 | .drv_name = "ecb-aes-qce" , |
365 | .blocksize = AES_BLOCK_SIZE, |
366 | .ivsize = 0, |
367 | .min_keysize = AES_MIN_KEY_SIZE, |
368 | .max_keysize = AES_MAX_KEY_SIZE, |
369 | }, |
370 | { |
371 | .flags = QCE_ALG_AES | QCE_MODE_CBC, |
372 | .name = "cbc(aes)" , |
373 | .drv_name = "cbc-aes-qce" , |
374 | .blocksize = AES_BLOCK_SIZE, |
375 | .ivsize = AES_BLOCK_SIZE, |
376 | .min_keysize = AES_MIN_KEY_SIZE, |
377 | .max_keysize = AES_MAX_KEY_SIZE, |
378 | }, |
379 | { |
380 | .flags = QCE_ALG_AES | QCE_MODE_CTR, |
381 | .name = "ctr(aes)" , |
382 | .drv_name = "ctr-aes-qce" , |
383 | .blocksize = 1, |
384 | .chunksize = AES_BLOCK_SIZE, |
385 | .ivsize = AES_BLOCK_SIZE, |
386 | .min_keysize = AES_MIN_KEY_SIZE, |
387 | .max_keysize = AES_MAX_KEY_SIZE, |
388 | }, |
389 | { |
390 | .flags = QCE_ALG_AES | QCE_MODE_XTS, |
391 | .name = "xts(aes)" , |
392 | .drv_name = "xts-aes-qce" , |
393 | .blocksize = AES_BLOCK_SIZE, |
394 | .ivsize = AES_BLOCK_SIZE, |
395 | .min_keysize = AES_MIN_KEY_SIZE * 2, |
396 | .max_keysize = AES_MAX_KEY_SIZE * 2, |
397 | }, |
398 | { |
399 | .flags = QCE_ALG_DES | QCE_MODE_ECB, |
400 | .name = "ecb(des)" , |
401 | .drv_name = "ecb-des-qce" , |
402 | .blocksize = DES_BLOCK_SIZE, |
403 | .ivsize = 0, |
404 | .min_keysize = DES_KEY_SIZE, |
405 | .max_keysize = DES_KEY_SIZE, |
406 | }, |
407 | { |
408 | .flags = QCE_ALG_DES | QCE_MODE_CBC, |
409 | .name = "cbc(des)" , |
410 | .drv_name = "cbc-des-qce" , |
411 | .blocksize = DES_BLOCK_SIZE, |
412 | .ivsize = DES_BLOCK_SIZE, |
413 | .min_keysize = DES_KEY_SIZE, |
414 | .max_keysize = DES_KEY_SIZE, |
415 | }, |
416 | { |
417 | .flags = QCE_ALG_3DES | QCE_MODE_ECB, |
418 | .name = "ecb(des3_ede)" , |
419 | .drv_name = "ecb-3des-qce" , |
420 | .blocksize = DES3_EDE_BLOCK_SIZE, |
421 | .ivsize = 0, |
422 | .min_keysize = DES3_EDE_KEY_SIZE, |
423 | .max_keysize = DES3_EDE_KEY_SIZE, |
424 | }, |
425 | { |
426 | .flags = QCE_ALG_3DES | QCE_MODE_CBC, |
427 | .name = "cbc(des3_ede)" , |
428 | .drv_name = "cbc-3des-qce" , |
429 | .blocksize = DES3_EDE_BLOCK_SIZE, |
430 | .ivsize = DES3_EDE_BLOCK_SIZE, |
431 | .min_keysize = DES3_EDE_KEY_SIZE, |
432 | .max_keysize = DES3_EDE_KEY_SIZE, |
433 | }, |
434 | }; |
435 | |
436 | static int qce_skcipher_register_one(const struct qce_skcipher_def *def, |
437 | struct qce_device *qce) |
438 | { |
439 | struct qce_alg_template *tmpl; |
440 | struct skcipher_alg *alg; |
441 | int ret; |
442 | |
443 | tmpl = kzalloc(size: sizeof(*tmpl), GFP_KERNEL); |
444 | if (!tmpl) |
445 | return -ENOMEM; |
446 | |
447 | alg = &tmpl->alg.skcipher; |
448 | |
449 | snprintf(buf: alg->base.cra_name, CRYPTO_MAX_ALG_NAME, fmt: "%s" , def->name); |
450 | snprintf(buf: alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, fmt: "%s" , |
451 | def->drv_name); |
452 | |
453 | alg->base.cra_blocksize = def->blocksize; |
454 | alg->chunksize = def->chunksize; |
455 | alg->ivsize = def->ivsize; |
456 | alg->min_keysize = def->min_keysize; |
457 | alg->max_keysize = def->max_keysize; |
458 | alg->setkey = IS_3DES(def->flags) ? qce_des3_setkey : |
459 | IS_DES(def->flags) ? qce_des_setkey : |
460 | qce_skcipher_setkey; |
461 | alg->encrypt = qce_skcipher_encrypt; |
462 | alg->decrypt = qce_skcipher_decrypt; |
463 | |
464 | alg->base.cra_priority = 300; |
465 | alg->base.cra_flags = CRYPTO_ALG_ASYNC | |
466 | CRYPTO_ALG_ALLOCATES_MEMORY | |
467 | CRYPTO_ALG_KERN_DRIVER_ONLY; |
468 | alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); |
469 | alg->base.cra_alignmask = 0; |
470 | alg->base.cra_module = THIS_MODULE; |
471 | |
472 | if (IS_AES(def->flags)) { |
473 | alg->base.cra_flags |= CRYPTO_ALG_NEED_FALLBACK; |
474 | alg->init = qce_skcipher_init_fallback; |
475 | alg->exit = qce_skcipher_exit; |
476 | } else { |
477 | alg->init = qce_skcipher_init; |
478 | } |
479 | |
480 | INIT_LIST_HEAD(list: &tmpl->entry); |
481 | tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; |
482 | tmpl->alg_flags = def->flags; |
483 | tmpl->qce = qce; |
484 | |
485 | ret = crypto_register_skcipher(alg); |
486 | if (ret) { |
487 | dev_err(qce->dev, "%s registration failed\n" , alg->base.cra_name); |
488 | kfree(objp: tmpl); |
489 | return ret; |
490 | } |
491 | |
492 | list_add_tail(new: &tmpl->entry, head: &skcipher_algs); |
493 | dev_dbg(qce->dev, "%s is registered\n" , alg->base.cra_name); |
494 | return 0; |
495 | } |
496 | |
497 | static void qce_skcipher_unregister(struct qce_device *qce) |
498 | { |
499 | struct qce_alg_template *tmpl, *n; |
500 | |
501 | list_for_each_entry_safe(tmpl, n, &skcipher_algs, entry) { |
502 | crypto_unregister_skcipher(alg: &tmpl->alg.skcipher); |
503 | list_del(entry: &tmpl->entry); |
504 | kfree(objp: tmpl); |
505 | } |
506 | } |
507 | |
508 | static int qce_skcipher_register(struct qce_device *qce) |
509 | { |
510 | int ret, i; |
511 | |
512 | for (i = 0; i < ARRAY_SIZE(skcipher_def); i++) { |
513 | ret = qce_skcipher_register_one(def: &skcipher_def[i], qce); |
514 | if (ret) |
515 | goto err; |
516 | } |
517 | |
518 | return 0; |
519 | err: |
520 | qce_skcipher_unregister(qce); |
521 | return ret; |
522 | } |
523 | |
524 | const struct qce_algo_ops skcipher_ops = { |
525 | .type = CRYPTO_ALG_TYPE_SKCIPHER, |
526 | .register_algs = qce_skcipher_register, |
527 | .unregister_algs = qce_skcipher_unregister, |
528 | .async_req_handle = qce_skcipher_async_req_handle, |
529 | }; |
530 | |