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