18bf08715SArd Biesheuvel // SPDX-License-Identifier: GPL-2.0-only 28bf08715SArd Biesheuvel /* 38bf08715SArd Biesheuvel * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. 48bf08715SArd Biesheuvel */ 58bf08715SArd Biesheuvel 68bf08715SArd Biesheuvel #include <linux/device.h> 78bf08715SArd Biesheuvel #include <linux/interrupt.h> 88bf08715SArd Biesheuvel #include <linux/types.h> 98bf08715SArd Biesheuvel #include <crypto/aes.h> 108bf08715SArd Biesheuvel #include <crypto/internal/des.h> 118bf08715SArd Biesheuvel #include <crypto/internal/skcipher.h> 128bf08715SArd Biesheuvel 138bf08715SArd Biesheuvel #include "cipher.h" 148bf08715SArd Biesheuvel 158bf08715SArd Biesheuvel static LIST_HEAD(skcipher_algs); 168bf08715SArd Biesheuvel 178bf08715SArd Biesheuvel static void qce_skcipher_done(void *data) 188bf08715SArd Biesheuvel { 198bf08715SArd Biesheuvel struct crypto_async_request *async_req = data; 208bf08715SArd Biesheuvel struct skcipher_request *req = skcipher_request_cast(async_req); 218bf08715SArd Biesheuvel struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); 228bf08715SArd Biesheuvel struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); 238bf08715SArd Biesheuvel struct qce_device *qce = tmpl->qce; 248bf08715SArd Biesheuvel enum dma_data_direction dir_src, dir_dst; 258bf08715SArd Biesheuvel u32 status; 268bf08715SArd Biesheuvel int error; 278bf08715SArd Biesheuvel bool diff_dst; 288bf08715SArd Biesheuvel 298bf08715SArd Biesheuvel diff_dst = (req->src != req->dst) ? true : false; 308bf08715SArd Biesheuvel dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; 318bf08715SArd Biesheuvel dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; 328bf08715SArd Biesheuvel 338bf08715SArd Biesheuvel error = qce_dma_terminate_all(&qce->dma); 348bf08715SArd Biesheuvel if (error) 358bf08715SArd Biesheuvel dev_dbg(qce->dev, "skcipher dma termination error (%d)\n", 368bf08715SArd Biesheuvel error); 378bf08715SArd Biesheuvel 388bf08715SArd Biesheuvel if (diff_dst) 398bf08715SArd Biesheuvel dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); 408bf08715SArd Biesheuvel dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); 418bf08715SArd Biesheuvel 428bf08715SArd Biesheuvel sg_free_table(&rctx->dst_tbl); 438bf08715SArd Biesheuvel 448bf08715SArd Biesheuvel error = qce_check_status(qce, &status); 458bf08715SArd Biesheuvel if (error < 0) 468bf08715SArd Biesheuvel dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); 478bf08715SArd Biesheuvel 488bf08715SArd Biesheuvel qce->async_req_done(tmpl->qce, error); 498bf08715SArd Biesheuvel } 508bf08715SArd Biesheuvel 518bf08715SArd Biesheuvel static int 528bf08715SArd Biesheuvel qce_skcipher_async_req_handle(struct crypto_async_request *async_req) 538bf08715SArd Biesheuvel { 548bf08715SArd Biesheuvel struct skcipher_request *req = skcipher_request_cast(async_req); 558bf08715SArd Biesheuvel struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); 568bf08715SArd Biesheuvel struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); 578bf08715SArd Biesheuvel struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); 588bf08715SArd Biesheuvel struct qce_device *qce = tmpl->qce; 598bf08715SArd Biesheuvel enum dma_data_direction dir_src, dir_dst; 608bf08715SArd Biesheuvel struct scatterlist *sg; 618bf08715SArd Biesheuvel bool diff_dst; 628bf08715SArd Biesheuvel gfp_t gfp; 638bf08715SArd Biesheuvel int ret; 648bf08715SArd Biesheuvel 658bf08715SArd Biesheuvel rctx->iv = req->iv; 668bf08715SArd Biesheuvel rctx->ivsize = crypto_skcipher_ivsize(skcipher); 678bf08715SArd Biesheuvel rctx->cryptlen = req->cryptlen; 688bf08715SArd Biesheuvel 698bf08715SArd Biesheuvel diff_dst = (req->src != req->dst) ? true : false; 708bf08715SArd Biesheuvel dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; 718bf08715SArd Biesheuvel dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; 728bf08715SArd Biesheuvel 738bf08715SArd Biesheuvel rctx->src_nents = sg_nents_for_len(req->src, req->cryptlen); 748bf08715SArd Biesheuvel if (diff_dst) 758bf08715SArd Biesheuvel rctx->dst_nents = sg_nents_for_len(req->dst, req->cryptlen); 768bf08715SArd Biesheuvel else 778bf08715SArd Biesheuvel rctx->dst_nents = rctx->src_nents; 788bf08715SArd Biesheuvel if (rctx->src_nents < 0) { 798bf08715SArd Biesheuvel dev_err(qce->dev, "Invalid numbers of src SG.\n"); 808bf08715SArd Biesheuvel return rctx->src_nents; 818bf08715SArd Biesheuvel } 828bf08715SArd Biesheuvel if (rctx->dst_nents < 0) { 838bf08715SArd Biesheuvel dev_err(qce->dev, "Invalid numbers of dst SG.\n"); 848bf08715SArd Biesheuvel return -rctx->dst_nents; 858bf08715SArd Biesheuvel } 868bf08715SArd Biesheuvel 878bf08715SArd Biesheuvel rctx->dst_nents += 1; 888bf08715SArd Biesheuvel 898bf08715SArd Biesheuvel gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? 908bf08715SArd Biesheuvel GFP_KERNEL : GFP_ATOMIC; 918bf08715SArd Biesheuvel 928bf08715SArd Biesheuvel ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp); 938bf08715SArd Biesheuvel if (ret) 948bf08715SArd Biesheuvel return ret; 958bf08715SArd Biesheuvel 968bf08715SArd Biesheuvel sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); 978bf08715SArd Biesheuvel 988bf08715SArd Biesheuvel sg = qce_sgtable_add(&rctx->dst_tbl, req->dst); 998bf08715SArd Biesheuvel if (IS_ERR(sg)) { 1008bf08715SArd Biesheuvel ret = PTR_ERR(sg); 1018bf08715SArd Biesheuvel goto error_free; 1028bf08715SArd Biesheuvel } 1038bf08715SArd Biesheuvel 1048bf08715SArd Biesheuvel sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg); 1058bf08715SArd Biesheuvel if (IS_ERR(sg)) { 1068bf08715SArd Biesheuvel ret = PTR_ERR(sg); 1078bf08715SArd Biesheuvel goto error_free; 1088bf08715SArd Biesheuvel } 1098bf08715SArd Biesheuvel 1108bf08715SArd Biesheuvel sg_mark_end(sg); 1118bf08715SArd Biesheuvel rctx->dst_sg = rctx->dst_tbl.sgl; 1128bf08715SArd Biesheuvel 1138bf08715SArd Biesheuvel ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); 1148bf08715SArd Biesheuvel if (ret < 0) 1158bf08715SArd Biesheuvel goto error_free; 1168bf08715SArd Biesheuvel 1178bf08715SArd Biesheuvel if (diff_dst) { 1188bf08715SArd Biesheuvel ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src); 1198bf08715SArd Biesheuvel if (ret < 0) 1208bf08715SArd Biesheuvel goto error_unmap_dst; 1218bf08715SArd Biesheuvel rctx->src_sg = req->src; 1228bf08715SArd Biesheuvel } else { 1238bf08715SArd Biesheuvel rctx->src_sg = rctx->dst_sg; 1248bf08715SArd Biesheuvel } 1258bf08715SArd Biesheuvel 1268bf08715SArd Biesheuvel ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents, 1278bf08715SArd Biesheuvel rctx->dst_sg, rctx->dst_nents, 1288bf08715SArd Biesheuvel qce_skcipher_done, async_req); 1298bf08715SArd Biesheuvel if (ret) 1308bf08715SArd Biesheuvel goto error_unmap_src; 1318bf08715SArd Biesheuvel 1328bf08715SArd Biesheuvel qce_dma_issue_pending(&qce->dma); 1338bf08715SArd Biesheuvel 1348bf08715SArd Biesheuvel ret = qce_start(async_req, tmpl->crypto_alg_type, req->cryptlen, 0); 1358bf08715SArd Biesheuvel if (ret) 1368bf08715SArd Biesheuvel goto error_terminate; 1378bf08715SArd Biesheuvel 1388bf08715SArd Biesheuvel return 0; 1398bf08715SArd Biesheuvel 1408bf08715SArd Biesheuvel error_terminate: 1418bf08715SArd Biesheuvel qce_dma_terminate_all(&qce->dma); 1428bf08715SArd Biesheuvel error_unmap_src: 1438bf08715SArd Biesheuvel if (diff_dst) 1448bf08715SArd Biesheuvel dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src); 1458bf08715SArd Biesheuvel error_unmap_dst: 1468bf08715SArd Biesheuvel dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); 1478bf08715SArd Biesheuvel error_free: 1488bf08715SArd Biesheuvel sg_free_table(&rctx->dst_tbl); 1498bf08715SArd Biesheuvel return ret; 1508bf08715SArd Biesheuvel } 1518bf08715SArd Biesheuvel 1528bf08715SArd Biesheuvel static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, 1538bf08715SArd Biesheuvel unsigned int keylen) 1548bf08715SArd Biesheuvel { 1558bf08715SArd Biesheuvel struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk); 1568bf08715SArd Biesheuvel struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); 1578bf08715SArd Biesheuvel int ret; 1588bf08715SArd Biesheuvel 1598bf08715SArd Biesheuvel if (!key || !keylen) 1608bf08715SArd Biesheuvel return -EINVAL; 1618bf08715SArd Biesheuvel 1628bf08715SArd Biesheuvel switch (keylen) { 1638bf08715SArd Biesheuvel case AES_KEYSIZE_128: 1648bf08715SArd Biesheuvel case AES_KEYSIZE_256: 1658bf08715SArd Biesheuvel break; 1668bf08715SArd Biesheuvel default: 1678bf08715SArd Biesheuvel goto fallback; 1688bf08715SArd Biesheuvel } 1698bf08715SArd Biesheuvel 1708bf08715SArd Biesheuvel ctx->enc_keylen = keylen; 1718bf08715SArd Biesheuvel memcpy(ctx->enc_key, key, keylen); 1728bf08715SArd Biesheuvel return 0; 1738bf08715SArd Biesheuvel fallback: 1748bf08715SArd Biesheuvel ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen); 1758bf08715SArd Biesheuvel if (!ret) 1768bf08715SArd Biesheuvel ctx->enc_keylen = keylen; 1778bf08715SArd Biesheuvel return ret; 1788bf08715SArd Biesheuvel } 1798bf08715SArd Biesheuvel 1808bf08715SArd Biesheuvel static int qce_des_setkey(struct crypto_skcipher *ablk, const u8 *key, 1818bf08715SArd Biesheuvel unsigned int keylen) 1828bf08715SArd Biesheuvel { 1838bf08715SArd Biesheuvel struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); 1848bf08715SArd Biesheuvel int err; 1858bf08715SArd Biesheuvel 1868bf08715SArd Biesheuvel err = verify_skcipher_des_key(ablk, key); 1878bf08715SArd Biesheuvel if (err) 1888bf08715SArd Biesheuvel return err; 1898bf08715SArd Biesheuvel 1908bf08715SArd Biesheuvel ctx->enc_keylen = keylen; 1918bf08715SArd Biesheuvel memcpy(ctx->enc_key, key, keylen); 1928bf08715SArd Biesheuvel return 0; 1938bf08715SArd Biesheuvel } 1948bf08715SArd Biesheuvel 1958bf08715SArd Biesheuvel static int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key, 1968bf08715SArd Biesheuvel unsigned int keylen) 1978bf08715SArd Biesheuvel { 1988bf08715SArd Biesheuvel struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); 1998bf08715SArd Biesheuvel int err; 2008bf08715SArd Biesheuvel 2018bf08715SArd Biesheuvel err = verify_skcipher_des3_key(ablk, key); 2028bf08715SArd Biesheuvel if (err) 2038bf08715SArd Biesheuvel return err; 2048bf08715SArd Biesheuvel 2058bf08715SArd Biesheuvel ctx->enc_keylen = keylen; 2068bf08715SArd Biesheuvel memcpy(ctx->enc_key, key, keylen); 2078bf08715SArd Biesheuvel return 0; 2088bf08715SArd Biesheuvel } 2098bf08715SArd Biesheuvel 2108bf08715SArd Biesheuvel static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) 2118bf08715SArd Biesheuvel { 2128bf08715SArd Biesheuvel struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 2138bf08715SArd Biesheuvel struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); 2148bf08715SArd Biesheuvel struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); 2158bf08715SArd Biesheuvel struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); 2168bf08715SArd Biesheuvel int ret; 2178bf08715SArd Biesheuvel 2188bf08715SArd Biesheuvel rctx->flags = tmpl->alg_flags; 2198bf08715SArd Biesheuvel rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; 2208bf08715SArd Biesheuvel 2218bf08715SArd Biesheuvel if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && 2228bf08715SArd Biesheuvel ctx->enc_keylen != AES_KEYSIZE_256) { 2238bf08715SArd Biesheuvel SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); 2248bf08715SArd Biesheuvel 2258bf08715SArd Biesheuvel skcipher_request_set_sync_tfm(subreq, ctx->fallback); 2268bf08715SArd Biesheuvel skcipher_request_set_callback(subreq, req->base.flags, 2278bf08715SArd Biesheuvel NULL, NULL); 2288bf08715SArd Biesheuvel skcipher_request_set_crypt(subreq, req->src, req->dst, 2298bf08715SArd Biesheuvel req->cryptlen, req->iv); 2308bf08715SArd Biesheuvel ret = encrypt ? crypto_skcipher_encrypt(subreq) : 2318bf08715SArd Biesheuvel crypto_skcipher_decrypt(subreq); 2328bf08715SArd Biesheuvel skcipher_request_zero(subreq); 2338bf08715SArd Biesheuvel return ret; 2348bf08715SArd Biesheuvel } 2358bf08715SArd Biesheuvel 2368bf08715SArd Biesheuvel return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); 2378bf08715SArd Biesheuvel } 2388bf08715SArd Biesheuvel 2398bf08715SArd Biesheuvel static int qce_skcipher_encrypt(struct skcipher_request *req) 2408bf08715SArd Biesheuvel { 2418bf08715SArd Biesheuvel return qce_skcipher_crypt(req, 1); 2428bf08715SArd Biesheuvel } 2438bf08715SArd Biesheuvel 2448bf08715SArd Biesheuvel static int qce_skcipher_decrypt(struct skcipher_request *req) 2458bf08715SArd Biesheuvel { 2468bf08715SArd Biesheuvel return qce_skcipher_crypt(req, 0); 2478bf08715SArd Biesheuvel } 2488bf08715SArd Biesheuvel 2498bf08715SArd Biesheuvel static int qce_skcipher_init(struct crypto_skcipher *tfm) 2508bf08715SArd Biesheuvel { 2518bf08715SArd Biesheuvel struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); 2528bf08715SArd Biesheuvel 2538bf08715SArd Biesheuvel memset(ctx, 0, sizeof(*ctx)); 2548bf08715SArd Biesheuvel crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx)); 2558bf08715SArd Biesheuvel 2568bf08715SArd Biesheuvel ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(&tfm->base), 2578bf08715SArd Biesheuvel 0, CRYPTO_ALG_NEED_FALLBACK); 2588bf08715SArd Biesheuvel return PTR_ERR_OR_ZERO(ctx->fallback); 2598bf08715SArd Biesheuvel } 2608bf08715SArd Biesheuvel 2618bf08715SArd Biesheuvel static void qce_skcipher_exit(struct crypto_skcipher *tfm) 2628bf08715SArd Biesheuvel { 2638bf08715SArd Biesheuvel struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); 2648bf08715SArd Biesheuvel 2658bf08715SArd Biesheuvel crypto_free_sync_skcipher(ctx->fallback); 2668bf08715SArd Biesheuvel } 2678bf08715SArd Biesheuvel 2688bf08715SArd Biesheuvel struct qce_skcipher_def { 2698bf08715SArd Biesheuvel unsigned long flags; 2708bf08715SArd Biesheuvel const char *name; 2718bf08715SArd Biesheuvel const char *drv_name; 2728bf08715SArd Biesheuvel unsigned int blocksize; 273bb5c863bSEneas U de Queiroz unsigned int chunksize; 2748bf08715SArd Biesheuvel unsigned int ivsize; 2758bf08715SArd Biesheuvel unsigned int min_keysize; 2768bf08715SArd Biesheuvel unsigned int max_keysize; 2778bf08715SArd Biesheuvel }; 2788bf08715SArd Biesheuvel 2798bf08715SArd Biesheuvel static const struct qce_skcipher_def skcipher_def[] = { 2808bf08715SArd Biesheuvel { 2818bf08715SArd Biesheuvel .flags = QCE_ALG_AES | QCE_MODE_ECB, 2828bf08715SArd Biesheuvel .name = "ecb(aes)", 2838bf08715SArd Biesheuvel .drv_name = "ecb-aes-qce", 2848bf08715SArd Biesheuvel .blocksize = AES_BLOCK_SIZE, 2858bf08715SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 2868bf08715SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE, 2878bf08715SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE, 2888bf08715SArd Biesheuvel }, 2898bf08715SArd Biesheuvel { 2908bf08715SArd Biesheuvel .flags = QCE_ALG_AES | QCE_MODE_CBC, 2918bf08715SArd Biesheuvel .name = "cbc(aes)", 2928bf08715SArd Biesheuvel .drv_name = "cbc-aes-qce", 2938bf08715SArd Biesheuvel .blocksize = AES_BLOCK_SIZE, 2948bf08715SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 2958bf08715SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE, 2968bf08715SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE, 2978bf08715SArd Biesheuvel }, 2988bf08715SArd Biesheuvel { 2998bf08715SArd Biesheuvel .flags = QCE_ALG_AES | QCE_MODE_CTR, 3008bf08715SArd Biesheuvel .name = "ctr(aes)", 3018bf08715SArd Biesheuvel .drv_name = "ctr-aes-qce", 302bb5c863bSEneas U de Queiroz .blocksize = 1, 303bb5c863bSEneas U de Queiroz .chunksize = AES_BLOCK_SIZE, 3048bf08715SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 3058bf08715SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE, 3068bf08715SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE, 3078bf08715SArd Biesheuvel }, 3088bf08715SArd Biesheuvel { 3098bf08715SArd Biesheuvel .flags = QCE_ALG_AES | QCE_MODE_XTS, 3108bf08715SArd Biesheuvel .name = "xts(aes)", 3118bf08715SArd Biesheuvel .drv_name = "xts-aes-qce", 3128bf08715SArd Biesheuvel .blocksize = AES_BLOCK_SIZE, 3138bf08715SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 3148bf08715SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE, 3158bf08715SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE, 3168bf08715SArd Biesheuvel }, 3178bf08715SArd Biesheuvel { 3188bf08715SArd Biesheuvel .flags = QCE_ALG_DES | QCE_MODE_ECB, 3198bf08715SArd Biesheuvel .name = "ecb(des)", 3208bf08715SArd Biesheuvel .drv_name = "ecb-des-qce", 3218bf08715SArd Biesheuvel .blocksize = DES_BLOCK_SIZE, 3228bf08715SArd Biesheuvel .ivsize = 0, 3238bf08715SArd Biesheuvel .min_keysize = DES_KEY_SIZE, 3248bf08715SArd Biesheuvel .max_keysize = DES_KEY_SIZE, 3258bf08715SArd Biesheuvel }, 3268bf08715SArd Biesheuvel { 3278bf08715SArd Biesheuvel .flags = QCE_ALG_DES | QCE_MODE_CBC, 3288bf08715SArd Biesheuvel .name = "cbc(des)", 3298bf08715SArd Biesheuvel .drv_name = "cbc-des-qce", 3308bf08715SArd Biesheuvel .blocksize = DES_BLOCK_SIZE, 3318bf08715SArd Biesheuvel .ivsize = DES_BLOCK_SIZE, 3328bf08715SArd Biesheuvel .min_keysize = DES_KEY_SIZE, 3338bf08715SArd Biesheuvel .max_keysize = DES_KEY_SIZE, 3348bf08715SArd Biesheuvel }, 3358bf08715SArd Biesheuvel { 3368bf08715SArd Biesheuvel .flags = QCE_ALG_3DES | QCE_MODE_ECB, 3378bf08715SArd Biesheuvel .name = "ecb(des3_ede)", 3388bf08715SArd Biesheuvel .drv_name = "ecb-3des-qce", 3398bf08715SArd Biesheuvel .blocksize = DES3_EDE_BLOCK_SIZE, 3408bf08715SArd Biesheuvel .ivsize = 0, 3418bf08715SArd Biesheuvel .min_keysize = DES3_EDE_KEY_SIZE, 3428bf08715SArd Biesheuvel .max_keysize = DES3_EDE_KEY_SIZE, 3438bf08715SArd Biesheuvel }, 3448bf08715SArd Biesheuvel { 3458bf08715SArd Biesheuvel .flags = QCE_ALG_3DES | QCE_MODE_CBC, 3468bf08715SArd Biesheuvel .name = "cbc(des3_ede)", 3478bf08715SArd Biesheuvel .drv_name = "cbc-3des-qce", 3488bf08715SArd Biesheuvel .blocksize = DES3_EDE_BLOCK_SIZE, 3498bf08715SArd Biesheuvel .ivsize = DES3_EDE_BLOCK_SIZE, 3508bf08715SArd Biesheuvel .min_keysize = DES3_EDE_KEY_SIZE, 3518bf08715SArd Biesheuvel .max_keysize = DES3_EDE_KEY_SIZE, 3528bf08715SArd Biesheuvel }, 3538bf08715SArd Biesheuvel }; 3548bf08715SArd Biesheuvel 3558bf08715SArd Biesheuvel static int qce_skcipher_register_one(const struct qce_skcipher_def *def, 3568bf08715SArd Biesheuvel struct qce_device *qce) 3578bf08715SArd Biesheuvel { 3588bf08715SArd Biesheuvel struct qce_alg_template *tmpl; 3598bf08715SArd Biesheuvel struct skcipher_alg *alg; 3608bf08715SArd Biesheuvel int ret; 3618bf08715SArd Biesheuvel 3628bf08715SArd Biesheuvel tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); 3638bf08715SArd Biesheuvel if (!tmpl) 3648bf08715SArd Biesheuvel return -ENOMEM; 3658bf08715SArd Biesheuvel 3668bf08715SArd Biesheuvel alg = &tmpl->alg.skcipher; 3678bf08715SArd Biesheuvel 3688bf08715SArd Biesheuvel snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); 3698bf08715SArd Biesheuvel snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 3708bf08715SArd Biesheuvel def->drv_name); 3718bf08715SArd Biesheuvel 3728bf08715SArd Biesheuvel alg->base.cra_blocksize = def->blocksize; 373bb5c863bSEneas U de Queiroz alg->chunksize = def->chunksize; 3748bf08715SArd Biesheuvel alg->ivsize = def->ivsize; 3758bf08715SArd Biesheuvel alg->min_keysize = def->min_keysize; 3768bf08715SArd Biesheuvel alg->max_keysize = def->max_keysize; 3778bf08715SArd Biesheuvel alg->setkey = IS_3DES(def->flags) ? qce_des3_setkey : 3788bf08715SArd Biesheuvel IS_DES(def->flags) ? qce_des_setkey : 3798bf08715SArd Biesheuvel qce_skcipher_setkey; 3808bf08715SArd Biesheuvel alg->encrypt = qce_skcipher_encrypt; 3818bf08715SArd Biesheuvel alg->decrypt = qce_skcipher_decrypt; 3828bf08715SArd Biesheuvel 3838bf08715SArd Biesheuvel alg->base.cra_priority = 300; 3848bf08715SArd Biesheuvel alg->base.cra_flags = CRYPTO_ALG_ASYNC | 3858bf08715SArd Biesheuvel CRYPTO_ALG_NEED_FALLBACK | 3868bf08715SArd Biesheuvel CRYPTO_ALG_KERN_DRIVER_ONLY; 3878bf08715SArd Biesheuvel alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); 3888bf08715SArd Biesheuvel alg->base.cra_alignmask = 0; 3898bf08715SArd Biesheuvel alg->base.cra_module = THIS_MODULE; 3908bf08715SArd Biesheuvel 3918bf08715SArd Biesheuvel alg->init = qce_skcipher_init; 3928bf08715SArd Biesheuvel alg->exit = qce_skcipher_exit; 3938bf08715SArd Biesheuvel 3948bf08715SArd Biesheuvel INIT_LIST_HEAD(&tmpl->entry); 3958bf08715SArd Biesheuvel tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; 3968bf08715SArd Biesheuvel tmpl->alg_flags = def->flags; 3978bf08715SArd Biesheuvel tmpl->qce = qce; 3988bf08715SArd Biesheuvel 3998bf08715SArd Biesheuvel ret = crypto_register_skcipher(alg); 4008bf08715SArd Biesheuvel if (ret) { 4018bf08715SArd Biesheuvel kfree(tmpl); 4028bf08715SArd Biesheuvel dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name); 4038bf08715SArd Biesheuvel return ret; 4048bf08715SArd Biesheuvel } 4058bf08715SArd Biesheuvel 4068bf08715SArd Biesheuvel list_add_tail(&tmpl->entry, &skcipher_algs); 4078bf08715SArd Biesheuvel dev_dbg(qce->dev, "%s is registered\n", alg->base.cra_name); 4088bf08715SArd Biesheuvel return 0; 4098bf08715SArd Biesheuvel } 4108bf08715SArd Biesheuvel 4118bf08715SArd Biesheuvel static void qce_skcipher_unregister(struct qce_device *qce) 4128bf08715SArd Biesheuvel { 4138bf08715SArd Biesheuvel struct qce_alg_template *tmpl, *n; 4148bf08715SArd Biesheuvel 4158bf08715SArd Biesheuvel list_for_each_entry_safe(tmpl, n, &skcipher_algs, entry) { 4168bf08715SArd Biesheuvel crypto_unregister_skcipher(&tmpl->alg.skcipher); 4178bf08715SArd Biesheuvel list_del(&tmpl->entry); 4188bf08715SArd Biesheuvel kfree(tmpl); 4198bf08715SArd Biesheuvel } 4208bf08715SArd Biesheuvel } 4218bf08715SArd Biesheuvel 4228bf08715SArd Biesheuvel static int qce_skcipher_register(struct qce_device *qce) 4238bf08715SArd Biesheuvel { 4248bf08715SArd Biesheuvel int ret, i; 4258bf08715SArd Biesheuvel 4268bf08715SArd Biesheuvel for (i = 0; i < ARRAY_SIZE(skcipher_def); i++) { 4278bf08715SArd Biesheuvel ret = qce_skcipher_register_one(&skcipher_def[i], qce); 4288bf08715SArd Biesheuvel if (ret) 4298bf08715SArd Biesheuvel goto err; 4308bf08715SArd Biesheuvel } 4318bf08715SArd Biesheuvel 4328bf08715SArd Biesheuvel return 0; 4338bf08715SArd Biesheuvel err: 4348bf08715SArd Biesheuvel qce_skcipher_unregister(qce); 4358bf08715SArd Biesheuvel return ret; 4368bf08715SArd Biesheuvel } 4378bf08715SArd Biesheuvel 4388bf08715SArd Biesheuvel const struct qce_algo_ops skcipher_ops = { 4398bf08715SArd Biesheuvel .type = CRYPTO_ALG_TYPE_SKCIPHER, 4408bf08715SArd Biesheuvel .register_algs = qce_skcipher_register, 4418bf08715SArd Biesheuvel .unregister_algs = qce_skcipher_unregister, 4428bf08715SArd Biesheuvel .async_req_handle = qce_skcipher_async_req_handle, 4438bf08715SArd Biesheuvel }; 444