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