xref: /openbmc/linux/drivers/crypto/qce/skcipher.c (revision bb5c863b)
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