18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * caam - Freescale FSL CAAM support for Public Key Cryptography
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2016 Freescale Semiconductor, Inc.
68c2ecf20Sopenharmony_ci * Copyright 2018-2019 NXP
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * There is no Shared Descriptor for PKC so that the Job Descriptor must carry
98c2ecf20Sopenharmony_ci * all the desired key parameters, input and output pointers.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci#include "compat.h"
128c2ecf20Sopenharmony_ci#include "regs.h"
138c2ecf20Sopenharmony_ci#include "intern.h"
148c2ecf20Sopenharmony_ci#include "jr.h"
158c2ecf20Sopenharmony_ci#include "error.h"
168c2ecf20Sopenharmony_ci#include "desc_constr.h"
178c2ecf20Sopenharmony_ci#include "sg_sw_sec4.h"
188c2ecf20Sopenharmony_ci#include "caampkc.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define DESC_RSA_PUB_LEN	(2 * CAAM_CMD_SZ + SIZEOF_RSA_PUB_PDB)
218c2ecf20Sopenharmony_ci#define DESC_RSA_PRIV_F1_LEN	(2 * CAAM_CMD_SZ + \
228c2ecf20Sopenharmony_ci				 SIZEOF_RSA_PRIV_F1_PDB)
238c2ecf20Sopenharmony_ci#define DESC_RSA_PRIV_F2_LEN	(2 * CAAM_CMD_SZ + \
248c2ecf20Sopenharmony_ci				 SIZEOF_RSA_PRIV_F2_PDB)
258c2ecf20Sopenharmony_ci#define DESC_RSA_PRIV_F3_LEN	(2 * CAAM_CMD_SZ + \
268c2ecf20Sopenharmony_ci				 SIZEOF_RSA_PRIV_F3_PDB)
278c2ecf20Sopenharmony_ci#define CAAM_RSA_MAX_INPUT_SIZE	512 /* for a 4096-bit modulus */
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci/* buffer filled with zeros, used for padding */
308c2ecf20Sopenharmony_cistatic u8 *zero_buffer;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/*
338c2ecf20Sopenharmony_ci * variable used to avoid double free of resources in case
348c2ecf20Sopenharmony_ci * algorithm registration was unsuccessful
358c2ecf20Sopenharmony_ci */
368c2ecf20Sopenharmony_cistatic bool init_done;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_cistruct caam_akcipher_alg {
398c2ecf20Sopenharmony_ci	struct akcipher_alg akcipher;
408c2ecf20Sopenharmony_ci	bool registered;
418c2ecf20Sopenharmony_ci};
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistatic void rsa_io_unmap(struct device *dev, struct rsa_edesc *edesc,
448c2ecf20Sopenharmony_ci			 struct akcipher_request *req)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
498c2ecf20Sopenharmony_ci	dma_unmap_sg(dev, req_ctx->fixup_src, edesc->src_nents, DMA_TO_DEVICE);
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	if (edesc->sec4_sg_bytes)
528c2ecf20Sopenharmony_ci		dma_unmap_single(dev, edesc->sec4_sg_dma, edesc->sec4_sg_bytes,
538c2ecf20Sopenharmony_ci				 DMA_TO_DEVICE);
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic void rsa_pub_unmap(struct device *dev, struct rsa_edesc *edesc,
578c2ecf20Sopenharmony_ci			  struct akcipher_request *req)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
608c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
618c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
628c2ecf20Sopenharmony_ci	struct rsa_pub_pdb *pdb = &edesc->pdb.pub;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->n_dma, key->n_sz, DMA_TO_DEVICE);
658c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->e_dma, key->e_sz, DMA_TO_DEVICE);
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic void rsa_priv_f1_unmap(struct device *dev, struct rsa_edesc *edesc,
698c2ecf20Sopenharmony_ci			      struct akcipher_request *req)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
728c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
738c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
748c2ecf20Sopenharmony_ci	struct rsa_priv_f1_pdb *pdb = &edesc->pdb.priv_f1;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->n_dma, key->n_sz, DMA_TO_DEVICE);
778c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->d_dma, key->d_sz, DMA_TO_DEVICE);
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistatic void rsa_priv_f2_unmap(struct device *dev, struct rsa_edesc *edesc,
818c2ecf20Sopenharmony_ci			      struct akcipher_request *req)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
848c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
858c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
868c2ecf20Sopenharmony_ci	struct rsa_priv_f2_pdb *pdb = &edesc->pdb.priv_f2;
878c2ecf20Sopenharmony_ci	size_t p_sz = key->p_sz;
888c2ecf20Sopenharmony_ci	size_t q_sz = key->q_sz;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->d_dma, key->d_sz, DMA_TO_DEVICE);
918c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE);
928c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE);
938c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL);
948c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->tmp2_dma, q_sz, DMA_BIDIRECTIONAL);
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic void rsa_priv_f3_unmap(struct device *dev, struct rsa_edesc *edesc,
988c2ecf20Sopenharmony_ci			      struct akcipher_request *req)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
1018c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
1028c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
1038c2ecf20Sopenharmony_ci	struct rsa_priv_f3_pdb *pdb = &edesc->pdb.priv_f3;
1048c2ecf20Sopenharmony_ci	size_t p_sz = key->p_sz;
1058c2ecf20Sopenharmony_ci	size_t q_sz = key->q_sz;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE);
1088c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE);
1098c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->dp_dma, p_sz, DMA_TO_DEVICE);
1108c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->dq_dma, q_sz, DMA_TO_DEVICE);
1118c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->c_dma, p_sz, DMA_TO_DEVICE);
1128c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL);
1138c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->tmp2_dma, q_sz, DMA_BIDIRECTIONAL);
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci/* RSA Job Completion handler */
1178c2ecf20Sopenharmony_cistatic void rsa_pub_done(struct device *dev, u32 *desc, u32 err, void *context)
1188c2ecf20Sopenharmony_ci{
1198c2ecf20Sopenharmony_ci	struct akcipher_request *req = context;
1208c2ecf20Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
1218c2ecf20Sopenharmony_ci	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
1228c2ecf20Sopenharmony_ci	struct rsa_edesc *edesc;
1238c2ecf20Sopenharmony_ci	int ecode = 0;
1248c2ecf20Sopenharmony_ci	bool has_bklog;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	if (err)
1278c2ecf20Sopenharmony_ci		ecode = caam_jr_strstatus(dev, err);
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	edesc = req_ctx->edesc;
1308c2ecf20Sopenharmony_ci	has_bklog = edesc->bklog;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	rsa_pub_unmap(dev, edesc, req);
1338c2ecf20Sopenharmony_ci	rsa_io_unmap(dev, edesc, req);
1348c2ecf20Sopenharmony_ci	kfree(edesc);
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	/*
1378c2ecf20Sopenharmony_ci	 * If no backlog flag, the completion of the request is done
1388c2ecf20Sopenharmony_ci	 * by CAAM, not crypto engine.
1398c2ecf20Sopenharmony_ci	 */
1408c2ecf20Sopenharmony_ci	if (!has_bklog)
1418c2ecf20Sopenharmony_ci		akcipher_request_complete(req, ecode);
1428c2ecf20Sopenharmony_ci	else
1438c2ecf20Sopenharmony_ci		crypto_finalize_akcipher_request(jrp->engine, req, ecode);
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic void rsa_priv_f_done(struct device *dev, u32 *desc, u32 err,
1478c2ecf20Sopenharmony_ci			    void *context)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	struct akcipher_request *req = context;
1508c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
1518c2ecf20Sopenharmony_ci	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
1528c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
1538c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
1548c2ecf20Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
1558c2ecf20Sopenharmony_ci	struct rsa_edesc *edesc;
1568c2ecf20Sopenharmony_ci	int ecode = 0;
1578c2ecf20Sopenharmony_ci	bool has_bklog;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	if (err)
1608c2ecf20Sopenharmony_ci		ecode = caam_jr_strstatus(dev, err);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	edesc = req_ctx->edesc;
1638c2ecf20Sopenharmony_ci	has_bklog = edesc->bklog;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	switch (key->priv_form) {
1668c2ecf20Sopenharmony_ci	case FORM1:
1678c2ecf20Sopenharmony_ci		rsa_priv_f1_unmap(dev, edesc, req);
1688c2ecf20Sopenharmony_ci		break;
1698c2ecf20Sopenharmony_ci	case FORM2:
1708c2ecf20Sopenharmony_ci		rsa_priv_f2_unmap(dev, edesc, req);
1718c2ecf20Sopenharmony_ci		break;
1728c2ecf20Sopenharmony_ci	case FORM3:
1738c2ecf20Sopenharmony_ci		rsa_priv_f3_unmap(dev, edesc, req);
1748c2ecf20Sopenharmony_ci	}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	rsa_io_unmap(dev, edesc, req);
1778c2ecf20Sopenharmony_ci	kfree(edesc);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	/*
1808c2ecf20Sopenharmony_ci	 * If no backlog flag, the completion of the request is done
1818c2ecf20Sopenharmony_ci	 * by CAAM, not crypto engine.
1828c2ecf20Sopenharmony_ci	 */
1838c2ecf20Sopenharmony_ci	if (!has_bklog)
1848c2ecf20Sopenharmony_ci		akcipher_request_complete(req, ecode);
1858c2ecf20Sopenharmony_ci	else
1868c2ecf20Sopenharmony_ci		crypto_finalize_akcipher_request(jrp->engine, req, ecode);
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci/**
1908c2ecf20Sopenharmony_ci * Count leading zeros, need it to strip, from a given scatterlist
1918c2ecf20Sopenharmony_ci *
1928c2ecf20Sopenharmony_ci * @sgl   : scatterlist to count zeros from
1938c2ecf20Sopenharmony_ci * @nbytes: number of zeros, in bytes, to strip
1948c2ecf20Sopenharmony_ci * @flags : operation flags
1958c2ecf20Sopenharmony_ci */
1968c2ecf20Sopenharmony_cistatic int caam_rsa_count_leading_zeros(struct scatterlist *sgl,
1978c2ecf20Sopenharmony_ci					unsigned int nbytes,
1988c2ecf20Sopenharmony_ci					unsigned int flags)
1998c2ecf20Sopenharmony_ci{
2008c2ecf20Sopenharmony_ci	struct sg_mapping_iter miter;
2018c2ecf20Sopenharmony_ci	int lzeros, ents;
2028c2ecf20Sopenharmony_ci	unsigned int len;
2038c2ecf20Sopenharmony_ci	unsigned int tbytes = nbytes;
2048c2ecf20Sopenharmony_ci	const u8 *buff;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	ents = sg_nents_for_len(sgl, nbytes);
2078c2ecf20Sopenharmony_ci	if (ents < 0)
2088c2ecf20Sopenharmony_ci		return ents;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	sg_miter_start(&miter, sgl, ents, SG_MITER_FROM_SG | flags);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	lzeros = 0;
2138c2ecf20Sopenharmony_ci	len = 0;
2148c2ecf20Sopenharmony_ci	while (nbytes > 0) {
2158c2ecf20Sopenharmony_ci		/* do not strip more than given bytes */
2168c2ecf20Sopenharmony_ci		while (len && !*buff && lzeros < nbytes) {
2178c2ecf20Sopenharmony_ci			lzeros++;
2188c2ecf20Sopenharmony_ci			len--;
2198c2ecf20Sopenharmony_ci			buff++;
2208c2ecf20Sopenharmony_ci		}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci		if (len && *buff)
2238c2ecf20Sopenharmony_ci			break;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci		if (!sg_miter_next(&miter))
2268c2ecf20Sopenharmony_ci			break;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci		buff = miter.addr;
2298c2ecf20Sopenharmony_ci		len = miter.length;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci		nbytes -= lzeros;
2328c2ecf20Sopenharmony_ci		lzeros = 0;
2338c2ecf20Sopenharmony_ci	}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	miter.consumed = lzeros;
2368c2ecf20Sopenharmony_ci	sg_miter_stop(&miter);
2378c2ecf20Sopenharmony_ci	nbytes -= lzeros;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	return tbytes - nbytes;
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_cistatic struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req,
2438c2ecf20Sopenharmony_ci					 size_t desclen)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
2468c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
2478c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
2488c2ecf20Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
2498c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
2508c2ecf20Sopenharmony_ci	struct rsa_edesc *edesc;
2518c2ecf20Sopenharmony_ci	gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
2528c2ecf20Sopenharmony_ci		       GFP_KERNEL : GFP_ATOMIC;
2538c2ecf20Sopenharmony_ci	int sg_flags = (flags == GFP_ATOMIC) ? SG_MITER_ATOMIC : 0;
2548c2ecf20Sopenharmony_ci	int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
2558c2ecf20Sopenharmony_ci	int src_nents, dst_nents;
2568c2ecf20Sopenharmony_ci	int mapped_src_nents, mapped_dst_nents;
2578c2ecf20Sopenharmony_ci	unsigned int diff_size = 0;
2588c2ecf20Sopenharmony_ci	int lzeros;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	if (req->src_len > key->n_sz) {
2618c2ecf20Sopenharmony_ci		/*
2628c2ecf20Sopenharmony_ci		 * strip leading zeros and
2638c2ecf20Sopenharmony_ci		 * return the number of zeros to skip
2648c2ecf20Sopenharmony_ci		 */
2658c2ecf20Sopenharmony_ci		lzeros = caam_rsa_count_leading_zeros(req->src, req->src_len -
2668c2ecf20Sopenharmony_ci						      key->n_sz, sg_flags);
2678c2ecf20Sopenharmony_ci		if (lzeros < 0)
2688c2ecf20Sopenharmony_ci			return ERR_PTR(lzeros);
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci		req_ctx->fixup_src = scatterwalk_ffwd(req_ctx->src, req->src,
2718c2ecf20Sopenharmony_ci						      lzeros);
2728c2ecf20Sopenharmony_ci		req_ctx->fixup_src_len = req->src_len - lzeros;
2738c2ecf20Sopenharmony_ci	} else {
2748c2ecf20Sopenharmony_ci		/*
2758c2ecf20Sopenharmony_ci		 * input src is less then n key modulus,
2768c2ecf20Sopenharmony_ci		 * so there will be zero padding
2778c2ecf20Sopenharmony_ci		 */
2788c2ecf20Sopenharmony_ci		diff_size = key->n_sz - req->src_len;
2798c2ecf20Sopenharmony_ci		req_ctx->fixup_src = req->src;
2808c2ecf20Sopenharmony_ci		req_ctx->fixup_src_len = req->src_len;
2818c2ecf20Sopenharmony_ci	}
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	src_nents = sg_nents_for_len(req_ctx->fixup_src,
2848c2ecf20Sopenharmony_ci				     req_ctx->fixup_src_len);
2858c2ecf20Sopenharmony_ci	dst_nents = sg_nents_for_len(req->dst, req->dst_len);
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	mapped_src_nents = dma_map_sg(dev, req_ctx->fixup_src, src_nents,
2888c2ecf20Sopenharmony_ci				      DMA_TO_DEVICE);
2898c2ecf20Sopenharmony_ci	if (unlikely(!mapped_src_nents)) {
2908c2ecf20Sopenharmony_ci		dev_err(dev, "unable to map source\n");
2918c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci	mapped_dst_nents = dma_map_sg(dev, req->dst, dst_nents,
2948c2ecf20Sopenharmony_ci				      DMA_FROM_DEVICE);
2958c2ecf20Sopenharmony_ci	if (unlikely(!mapped_dst_nents)) {
2968c2ecf20Sopenharmony_ci		dev_err(dev, "unable to map destination\n");
2978c2ecf20Sopenharmony_ci		goto src_fail;
2988c2ecf20Sopenharmony_ci	}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	if (!diff_size && mapped_src_nents == 1)
3018c2ecf20Sopenharmony_ci		sec4_sg_len = 0; /* no need for an input hw s/g table */
3028c2ecf20Sopenharmony_ci	else
3038c2ecf20Sopenharmony_ci		sec4_sg_len = mapped_src_nents + !!diff_size;
3048c2ecf20Sopenharmony_ci	sec4_sg_index = sec4_sg_len;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	if (mapped_dst_nents > 1)
3078c2ecf20Sopenharmony_ci		sec4_sg_len += pad_sg_nents(mapped_dst_nents);
3088c2ecf20Sopenharmony_ci	else
3098c2ecf20Sopenharmony_ci		sec4_sg_len = pad_sg_nents(sec4_sg_len);
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	/* allocate space for base edesc, hw desc commands and link tables */
3148c2ecf20Sopenharmony_ci	edesc = kzalloc(sizeof(*edesc) + desclen + sec4_sg_bytes,
3158c2ecf20Sopenharmony_ci			GFP_DMA | flags);
3168c2ecf20Sopenharmony_ci	if (!edesc)
3178c2ecf20Sopenharmony_ci		goto dst_fail;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	edesc->sec4_sg = (void *)edesc + sizeof(*edesc) + desclen;
3208c2ecf20Sopenharmony_ci	if (diff_size)
3218c2ecf20Sopenharmony_ci		dma_to_sec4_sg_one(edesc->sec4_sg, ctx->padding_dma, diff_size,
3228c2ecf20Sopenharmony_ci				   0);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	if (sec4_sg_index)
3258c2ecf20Sopenharmony_ci		sg_to_sec4_sg_last(req_ctx->fixup_src, req_ctx->fixup_src_len,
3268c2ecf20Sopenharmony_ci				   edesc->sec4_sg + !!diff_size, 0);
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	if (mapped_dst_nents > 1)
3298c2ecf20Sopenharmony_ci		sg_to_sec4_sg_last(req->dst, req->dst_len,
3308c2ecf20Sopenharmony_ci				   edesc->sec4_sg + sec4_sg_index, 0);
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	/* Save nents for later use in Job Descriptor */
3338c2ecf20Sopenharmony_ci	edesc->src_nents = src_nents;
3348c2ecf20Sopenharmony_ci	edesc->dst_nents = dst_nents;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	req_ctx->edesc = edesc;
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	if (!sec4_sg_bytes)
3398c2ecf20Sopenharmony_ci		return edesc;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	edesc->mapped_src_nents = mapped_src_nents;
3428c2ecf20Sopenharmony_ci	edesc->mapped_dst_nents = mapped_dst_nents;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	edesc->sec4_sg_dma = dma_map_single(dev, edesc->sec4_sg,
3458c2ecf20Sopenharmony_ci					    sec4_sg_bytes, DMA_TO_DEVICE);
3468c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, edesc->sec4_sg_dma)) {
3478c2ecf20Sopenharmony_ci		dev_err(dev, "unable to map S/G table\n");
3488c2ecf20Sopenharmony_ci		goto sec4_sg_fail;
3498c2ecf20Sopenharmony_ci	}
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	edesc->sec4_sg_bytes = sec4_sg_bytes;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	print_hex_dump_debug("caampkc sec4_sg@" __stringify(__LINE__) ": ",
3548c2ecf20Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, edesc->sec4_sg,
3558c2ecf20Sopenharmony_ci			     edesc->sec4_sg_bytes, 1);
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	return edesc;
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_cisec4_sg_fail:
3608c2ecf20Sopenharmony_ci	kfree(edesc);
3618c2ecf20Sopenharmony_cidst_fail:
3628c2ecf20Sopenharmony_ci	dma_unmap_sg(dev, req->dst, dst_nents, DMA_FROM_DEVICE);
3638c2ecf20Sopenharmony_cisrc_fail:
3648c2ecf20Sopenharmony_ci	dma_unmap_sg(dev, req_ctx->fixup_src, src_nents, DMA_TO_DEVICE);
3658c2ecf20Sopenharmony_ci	return ERR_PTR(-ENOMEM);
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_cistatic int akcipher_do_one_req(struct crypto_engine *engine, void *areq)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	struct akcipher_request *req = container_of(areq,
3718c2ecf20Sopenharmony_ci						    struct akcipher_request,
3728c2ecf20Sopenharmony_ci						    base);
3738c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
3748c2ecf20Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
3758c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
3768c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->dev;
3778c2ecf20Sopenharmony_ci	u32 *desc = req_ctx->edesc->hw_desc;
3788c2ecf20Sopenharmony_ci	int ret;
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	req_ctx->edesc->bklog = true;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	ret = caam_jr_enqueue(jrdev, desc, req_ctx->akcipher_op_done, req);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	if (ret != -EINPROGRESS) {
3858c2ecf20Sopenharmony_ci		rsa_pub_unmap(jrdev, req_ctx->edesc, req);
3868c2ecf20Sopenharmony_ci		rsa_io_unmap(jrdev, req_ctx->edesc, req);
3878c2ecf20Sopenharmony_ci		kfree(req_ctx->edesc);
3888c2ecf20Sopenharmony_ci	} else {
3898c2ecf20Sopenharmony_ci		ret = 0;
3908c2ecf20Sopenharmony_ci	}
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	return ret;
3938c2ecf20Sopenharmony_ci}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_cistatic int set_rsa_pub_pdb(struct akcipher_request *req,
3968c2ecf20Sopenharmony_ci			   struct rsa_edesc *edesc)
3978c2ecf20Sopenharmony_ci{
3988c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
3998c2ecf20Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
4008c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
4018c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
4028c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
4038c2ecf20Sopenharmony_ci	struct rsa_pub_pdb *pdb = &edesc->pdb.pub;
4048c2ecf20Sopenharmony_ci	int sec4_sg_index = 0;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	pdb->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
4078c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->n_dma)) {
4088c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA modulus memory\n");
4098c2ecf20Sopenharmony_ci		return -ENOMEM;
4108c2ecf20Sopenharmony_ci	}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	pdb->e_dma = dma_map_single(dev, key->e, key->e_sz, DMA_TO_DEVICE);
4138c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->e_dma)) {
4148c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA public exponent memory\n");
4158c2ecf20Sopenharmony_ci		dma_unmap_single(dev, pdb->n_dma, key->n_sz, DMA_TO_DEVICE);
4168c2ecf20Sopenharmony_ci		return -ENOMEM;
4178c2ecf20Sopenharmony_ci	}
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	if (edesc->mapped_src_nents > 1) {
4208c2ecf20Sopenharmony_ci		pdb->sgf |= RSA_PDB_SGF_F;
4218c2ecf20Sopenharmony_ci		pdb->f_dma = edesc->sec4_sg_dma;
4228c2ecf20Sopenharmony_ci		sec4_sg_index += edesc->mapped_src_nents;
4238c2ecf20Sopenharmony_ci	} else {
4248c2ecf20Sopenharmony_ci		pdb->f_dma = sg_dma_address(req_ctx->fixup_src);
4258c2ecf20Sopenharmony_ci	}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	if (edesc->mapped_dst_nents > 1) {
4288c2ecf20Sopenharmony_ci		pdb->sgf |= RSA_PDB_SGF_G;
4298c2ecf20Sopenharmony_ci		pdb->g_dma = edesc->sec4_sg_dma +
4308c2ecf20Sopenharmony_ci			     sec4_sg_index * sizeof(struct sec4_sg_entry);
4318c2ecf20Sopenharmony_ci	} else {
4328c2ecf20Sopenharmony_ci		pdb->g_dma = sg_dma_address(req->dst);
4338c2ecf20Sopenharmony_ci	}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	pdb->sgf |= (key->e_sz << RSA_PDB_E_SHIFT) | key->n_sz;
4368c2ecf20Sopenharmony_ci	pdb->f_len = req_ctx->fixup_src_len;
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	return 0;
4398c2ecf20Sopenharmony_ci}
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_cistatic int set_rsa_priv_f1_pdb(struct akcipher_request *req,
4428c2ecf20Sopenharmony_ci			       struct rsa_edesc *edesc)
4438c2ecf20Sopenharmony_ci{
4448c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
4458c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
4468c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
4478c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
4488c2ecf20Sopenharmony_ci	struct rsa_priv_f1_pdb *pdb = &edesc->pdb.priv_f1;
4498c2ecf20Sopenharmony_ci	int sec4_sg_index = 0;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	pdb->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
4528c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->n_dma)) {
4538c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map modulus memory\n");
4548c2ecf20Sopenharmony_ci		return -ENOMEM;
4558c2ecf20Sopenharmony_ci	}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	pdb->d_dma = dma_map_single(dev, key->d, key->d_sz, DMA_TO_DEVICE);
4588c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->d_dma)) {
4598c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA private exponent memory\n");
4608c2ecf20Sopenharmony_ci		dma_unmap_single(dev, pdb->n_dma, key->n_sz, DMA_TO_DEVICE);
4618c2ecf20Sopenharmony_ci		return -ENOMEM;
4628c2ecf20Sopenharmony_ci	}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	if (edesc->mapped_src_nents > 1) {
4658c2ecf20Sopenharmony_ci		pdb->sgf |= RSA_PRIV_PDB_SGF_G;
4668c2ecf20Sopenharmony_ci		pdb->g_dma = edesc->sec4_sg_dma;
4678c2ecf20Sopenharmony_ci		sec4_sg_index += edesc->mapped_src_nents;
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	} else {
4708c2ecf20Sopenharmony_ci		struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci		pdb->g_dma = sg_dma_address(req_ctx->fixup_src);
4738c2ecf20Sopenharmony_ci	}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	if (edesc->mapped_dst_nents > 1) {
4768c2ecf20Sopenharmony_ci		pdb->sgf |= RSA_PRIV_PDB_SGF_F;
4778c2ecf20Sopenharmony_ci		pdb->f_dma = edesc->sec4_sg_dma +
4788c2ecf20Sopenharmony_ci			     sec4_sg_index * sizeof(struct sec4_sg_entry);
4798c2ecf20Sopenharmony_ci	} else {
4808c2ecf20Sopenharmony_ci		pdb->f_dma = sg_dma_address(req->dst);
4818c2ecf20Sopenharmony_ci	}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	pdb->sgf |= (key->d_sz << RSA_PDB_D_SHIFT) | key->n_sz;
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	return 0;
4868c2ecf20Sopenharmony_ci}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_cistatic int set_rsa_priv_f2_pdb(struct akcipher_request *req,
4898c2ecf20Sopenharmony_ci			       struct rsa_edesc *edesc)
4908c2ecf20Sopenharmony_ci{
4918c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
4928c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
4938c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
4948c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
4958c2ecf20Sopenharmony_ci	struct rsa_priv_f2_pdb *pdb = &edesc->pdb.priv_f2;
4968c2ecf20Sopenharmony_ci	int sec4_sg_index = 0;
4978c2ecf20Sopenharmony_ci	size_t p_sz = key->p_sz;
4988c2ecf20Sopenharmony_ci	size_t q_sz = key->q_sz;
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	pdb->d_dma = dma_map_single(dev, key->d, key->d_sz, DMA_TO_DEVICE);
5018c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->d_dma)) {
5028c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA private exponent memory\n");
5038c2ecf20Sopenharmony_ci		return -ENOMEM;
5048c2ecf20Sopenharmony_ci	}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	pdb->p_dma = dma_map_single(dev, key->p, p_sz, DMA_TO_DEVICE);
5078c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->p_dma)) {
5088c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA prime factor p memory\n");
5098c2ecf20Sopenharmony_ci		goto unmap_d;
5108c2ecf20Sopenharmony_ci	}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	pdb->q_dma = dma_map_single(dev, key->q, q_sz, DMA_TO_DEVICE);
5138c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->q_dma)) {
5148c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA prime factor q memory\n");
5158c2ecf20Sopenharmony_ci		goto unmap_p;
5168c2ecf20Sopenharmony_ci	}
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci	pdb->tmp1_dma = dma_map_single(dev, key->tmp1, p_sz, DMA_BIDIRECTIONAL);
5198c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->tmp1_dma)) {
5208c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA tmp1 memory\n");
5218c2ecf20Sopenharmony_ci		goto unmap_q;
5228c2ecf20Sopenharmony_ci	}
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	pdb->tmp2_dma = dma_map_single(dev, key->tmp2, q_sz, DMA_BIDIRECTIONAL);
5258c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->tmp2_dma)) {
5268c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA tmp2 memory\n");
5278c2ecf20Sopenharmony_ci		goto unmap_tmp1;
5288c2ecf20Sopenharmony_ci	}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	if (edesc->mapped_src_nents > 1) {
5318c2ecf20Sopenharmony_ci		pdb->sgf |= RSA_PRIV_PDB_SGF_G;
5328c2ecf20Sopenharmony_ci		pdb->g_dma = edesc->sec4_sg_dma;
5338c2ecf20Sopenharmony_ci		sec4_sg_index += edesc->mapped_src_nents;
5348c2ecf20Sopenharmony_ci	} else {
5358c2ecf20Sopenharmony_ci		struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci		pdb->g_dma = sg_dma_address(req_ctx->fixup_src);
5388c2ecf20Sopenharmony_ci	}
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	if (edesc->mapped_dst_nents > 1) {
5418c2ecf20Sopenharmony_ci		pdb->sgf |= RSA_PRIV_PDB_SGF_F;
5428c2ecf20Sopenharmony_ci		pdb->f_dma = edesc->sec4_sg_dma +
5438c2ecf20Sopenharmony_ci			     sec4_sg_index * sizeof(struct sec4_sg_entry);
5448c2ecf20Sopenharmony_ci	} else {
5458c2ecf20Sopenharmony_ci		pdb->f_dma = sg_dma_address(req->dst);
5468c2ecf20Sopenharmony_ci	}
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	pdb->sgf |= (key->d_sz << RSA_PDB_D_SHIFT) | key->n_sz;
5498c2ecf20Sopenharmony_ci	pdb->p_q_len = (q_sz << RSA_PDB_Q_SHIFT) | p_sz;
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	return 0;
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ciunmap_tmp1:
5548c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL);
5558c2ecf20Sopenharmony_ciunmap_q:
5568c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE);
5578c2ecf20Sopenharmony_ciunmap_p:
5588c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE);
5598c2ecf20Sopenharmony_ciunmap_d:
5608c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->d_dma, key->d_sz, DMA_TO_DEVICE);
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	return -ENOMEM;
5638c2ecf20Sopenharmony_ci}
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_cistatic int set_rsa_priv_f3_pdb(struct akcipher_request *req,
5668c2ecf20Sopenharmony_ci			       struct rsa_edesc *edesc)
5678c2ecf20Sopenharmony_ci{
5688c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
5698c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
5708c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
5718c2ecf20Sopenharmony_ci	struct device *dev = ctx->dev;
5728c2ecf20Sopenharmony_ci	struct rsa_priv_f3_pdb *pdb = &edesc->pdb.priv_f3;
5738c2ecf20Sopenharmony_ci	int sec4_sg_index = 0;
5748c2ecf20Sopenharmony_ci	size_t p_sz = key->p_sz;
5758c2ecf20Sopenharmony_ci	size_t q_sz = key->q_sz;
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	pdb->p_dma = dma_map_single(dev, key->p, p_sz, DMA_TO_DEVICE);
5788c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->p_dma)) {
5798c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA prime factor p memory\n");
5808c2ecf20Sopenharmony_ci		return -ENOMEM;
5818c2ecf20Sopenharmony_ci	}
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	pdb->q_dma = dma_map_single(dev, key->q, q_sz, DMA_TO_DEVICE);
5848c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->q_dma)) {
5858c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA prime factor q memory\n");
5868c2ecf20Sopenharmony_ci		goto unmap_p;
5878c2ecf20Sopenharmony_ci	}
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	pdb->dp_dma = dma_map_single(dev, key->dp, p_sz, DMA_TO_DEVICE);
5908c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->dp_dma)) {
5918c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA exponent dp memory\n");
5928c2ecf20Sopenharmony_ci		goto unmap_q;
5938c2ecf20Sopenharmony_ci	}
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	pdb->dq_dma = dma_map_single(dev, key->dq, q_sz, DMA_TO_DEVICE);
5968c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->dq_dma)) {
5978c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA exponent dq memory\n");
5988c2ecf20Sopenharmony_ci		goto unmap_dp;
5998c2ecf20Sopenharmony_ci	}
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	pdb->c_dma = dma_map_single(dev, key->qinv, p_sz, DMA_TO_DEVICE);
6028c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->c_dma)) {
6038c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA CRT coefficient qinv memory\n");
6048c2ecf20Sopenharmony_ci		goto unmap_dq;
6058c2ecf20Sopenharmony_ci	}
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	pdb->tmp1_dma = dma_map_single(dev, key->tmp1, p_sz, DMA_BIDIRECTIONAL);
6088c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->tmp1_dma)) {
6098c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA tmp1 memory\n");
6108c2ecf20Sopenharmony_ci		goto unmap_qinv;
6118c2ecf20Sopenharmony_ci	}
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	pdb->tmp2_dma = dma_map_single(dev, key->tmp2, q_sz, DMA_BIDIRECTIONAL);
6148c2ecf20Sopenharmony_ci	if (dma_mapping_error(dev, pdb->tmp2_dma)) {
6158c2ecf20Sopenharmony_ci		dev_err(dev, "Unable to map RSA tmp2 memory\n");
6168c2ecf20Sopenharmony_ci		goto unmap_tmp1;
6178c2ecf20Sopenharmony_ci	}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	if (edesc->mapped_src_nents > 1) {
6208c2ecf20Sopenharmony_ci		pdb->sgf |= RSA_PRIV_PDB_SGF_G;
6218c2ecf20Sopenharmony_ci		pdb->g_dma = edesc->sec4_sg_dma;
6228c2ecf20Sopenharmony_ci		sec4_sg_index += edesc->mapped_src_nents;
6238c2ecf20Sopenharmony_ci	} else {
6248c2ecf20Sopenharmony_ci		struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci		pdb->g_dma = sg_dma_address(req_ctx->fixup_src);
6278c2ecf20Sopenharmony_ci	}
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	if (edesc->mapped_dst_nents > 1) {
6308c2ecf20Sopenharmony_ci		pdb->sgf |= RSA_PRIV_PDB_SGF_F;
6318c2ecf20Sopenharmony_ci		pdb->f_dma = edesc->sec4_sg_dma +
6328c2ecf20Sopenharmony_ci			     sec4_sg_index * sizeof(struct sec4_sg_entry);
6338c2ecf20Sopenharmony_ci	} else {
6348c2ecf20Sopenharmony_ci		pdb->f_dma = sg_dma_address(req->dst);
6358c2ecf20Sopenharmony_ci	}
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	pdb->sgf |= key->n_sz;
6388c2ecf20Sopenharmony_ci	pdb->p_q_len = (q_sz << RSA_PDB_Q_SHIFT) | p_sz;
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	return 0;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ciunmap_tmp1:
6438c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL);
6448c2ecf20Sopenharmony_ciunmap_qinv:
6458c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->c_dma, p_sz, DMA_TO_DEVICE);
6468c2ecf20Sopenharmony_ciunmap_dq:
6478c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->dq_dma, q_sz, DMA_TO_DEVICE);
6488c2ecf20Sopenharmony_ciunmap_dp:
6498c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->dp_dma, p_sz, DMA_TO_DEVICE);
6508c2ecf20Sopenharmony_ciunmap_q:
6518c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE);
6528c2ecf20Sopenharmony_ciunmap_p:
6538c2ecf20Sopenharmony_ci	dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE);
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	return -ENOMEM;
6568c2ecf20Sopenharmony_ci}
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_cistatic int akcipher_enqueue_req(struct device *jrdev,
6598c2ecf20Sopenharmony_ci				void (*cbk)(struct device *jrdev, u32 *desc,
6608c2ecf20Sopenharmony_ci					    u32 err, void *context),
6618c2ecf20Sopenharmony_ci				struct akcipher_request *req)
6628c2ecf20Sopenharmony_ci{
6638c2ecf20Sopenharmony_ci	struct caam_drv_private_jr *jrpriv = dev_get_drvdata(jrdev);
6648c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
6658c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
6668c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
6678c2ecf20Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
6688c2ecf20Sopenharmony_ci	struct rsa_edesc *edesc = req_ctx->edesc;
6698c2ecf20Sopenharmony_ci	u32 *desc = edesc->hw_desc;
6708c2ecf20Sopenharmony_ci	int ret;
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	req_ctx->akcipher_op_done = cbk;
6738c2ecf20Sopenharmony_ci	/*
6748c2ecf20Sopenharmony_ci	 * Only the backlog request are sent to crypto-engine since the others
6758c2ecf20Sopenharmony_ci	 * can be handled by CAAM, if free, especially since JR has up to 1024
6768c2ecf20Sopenharmony_ci	 * entries (more than the 10 entries from crypto-engine).
6778c2ecf20Sopenharmony_ci	 */
6788c2ecf20Sopenharmony_ci	if (req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)
6798c2ecf20Sopenharmony_ci		ret = crypto_transfer_akcipher_request_to_engine(jrpriv->engine,
6808c2ecf20Sopenharmony_ci								 req);
6818c2ecf20Sopenharmony_ci	else
6828c2ecf20Sopenharmony_ci		ret = caam_jr_enqueue(jrdev, desc, cbk, req);
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	if ((ret != -EINPROGRESS) && (ret != -EBUSY)) {
6858c2ecf20Sopenharmony_ci		switch (key->priv_form) {
6868c2ecf20Sopenharmony_ci		case FORM1:
6878c2ecf20Sopenharmony_ci			rsa_priv_f1_unmap(jrdev, edesc, req);
6888c2ecf20Sopenharmony_ci			break;
6898c2ecf20Sopenharmony_ci		case FORM2:
6908c2ecf20Sopenharmony_ci			rsa_priv_f2_unmap(jrdev, edesc, req);
6918c2ecf20Sopenharmony_ci			break;
6928c2ecf20Sopenharmony_ci		case FORM3:
6938c2ecf20Sopenharmony_ci			rsa_priv_f3_unmap(jrdev, edesc, req);
6948c2ecf20Sopenharmony_ci			break;
6958c2ecf20Sopenharmony_ci		default:
6968c2ecf20Sopenharmony_ci			rsa_pub_unmap(jrdev, edesc, req);
6978c2ecf20Sopenharmony_ci		}
6988c2ecf20Sopenharmony_ci		rsa_io_unmap(jrdev, edesc, req);
6998c2ecf20Sopenharmony_ci		kfree(edesc);
7008c2ecf20Sopenharmony_ci	}
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	return ret;
7038c2ecf20Sopenharmony_ci}
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_cistatic int caam_rsa_enc(struct akcipher_request *req)
7068c2ecf20Sopenharmony_ci{
7078c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
7088c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
7098c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
7108c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->dev;
7118c2ecf20Sopenharmony_ci	struct rsa_edesc *edesc;
7128c2ecf20Sopenharmony_ci	int ret;
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	if (unlikely(!key->n || !key->e))
7158c2ecf20Sopenharmony_ci		return -EINVAL;
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	if (req->dst_len < key->n_sz) {
7188c2ecf20Sopenharmony_ci		req->dst_len = key->n_sz;
7198c2ecf20Sopenharmony_ci		dev_err(jrdev, "Output buffer length less than parameter n\n");
7208c2ecf20Sopenharmony_ci		return -EOVERFLOW;
7218c2ecf20Sopenharmony_ci	}
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	/* Allocate extended descriptor */
7248c2ecf20Sopenharmony_ci	edesc = rsa_edesc_alloc(req, DESC_RSA_PUB_LEN);
7258c2ecf20Sopenharmony_ci	if (IS_ERR(edesc))
7268c2ecf20Sopenharmony_ci		return PTR_ERR(edesc);
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	/* Set RSA Encrypt Protocol Data Block */
7298c2ecf20Sopenharmony_ci	ret = set_rsa_pub_pdb(req, edesc);
7308c2ecf20Sopenharmony_ci	if (ret)
7318c2ecf20Sopenharmony_ci		goto init_fail;
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	/* Initialize Job Descriptor */
7348c2ecf20Sopenharmony_ci	init_rsa_pub_desc(edesc->hw_desc, &edesc->pdb.pub);
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	return akcipher_enqueue_req(jrdev, rsa_pub_done, req);
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ciinit_fail:
7398c2ecf20Sopenharmony_ci	rsa_io_unmap(jrdev, edesc, req);
7408c2ecf20Sopenharmony_ci	kfree(edesc);
7418c2ecf20Sopenharmony_ci	return ret;
7428c2ecf20Sopenharmony_ci}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_cistatic int caam_rsa_dec_priv_f1(struct akcipher_request *req)
7458c2ecf20Sopenharmony_ci{
7468c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
7478c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
7488c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->dev;
7498c2ecf20Sopenharmony_ci	struct rsa_edesc *edesc;
7508c2ecf20Sopenharmony_ci	int ret;
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	/* Allocate extended descriptor */
7538c2ecf20Sopenharmony_ci	edesc = rsa_edesc_alloc(req, DESC_RSA_PRIV_F1_LEN);
7548c2ecf20Sopenharmony_ci	if (IS_ERR(edesc))
7558c2ecf20Sopenharmony_ci		return PTR_ERR(edesc);
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	/* Set RSA Decrypt Protocol Data Block - Private Key Form #1 */
7588c2ecf20Sopenharmony_ci	ret = set_rsa_priv_f1_pdb(req, edesc);
7598c2ecf20Sopenharmony_ci	if (ret)
7608c2ecf20Sopenharmony_ci		goto init_fail;
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	/* Initialize Job Descriptor */
7638c2ecf20Sopenharmony_ci	init_rsa_priv_f1_desc(edesc->hw_desc, &edesc->pdb.priv_f1);
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	return akcipher_enqueue_req(jrdev, rsa_priv_f_done, req);
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ciinit_fail:
7688c2ecf20Sopenharmony_ci	rsa_io_unmap(jrdev, edesc, req);
7698c2ecf20Sopenharmony_ci	kfree(edesc);
7708c2ecf20Sopenharmony_ci	return ret;
7718c2ecf20Sopenharmony_ci}
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_cistatic int caam_rsa_dec_priv_f2(struct akcipher_request *req)
7748c2ecf20Sopenharmony_ci{
7758c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
7768c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
7778c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->dev;
7788c2ecf20Sopenharmony_ci	struct rsa_edesc *edesc;
7798c2ecf20Sopenharmony_ci	int ret;
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	/* Allocate extended descriptor */
7828c2ecf20Sopenharmony_ci	edesc = rsa_edesc_alloc(req, DESC_RSA_PRIV_F2_LEN);
7838c2ecf20Sopenharmony_ci	if (IS_ERR(edesc))
7848c2ecf20Sopenharmony_ci		return PTR_ERR(edesc);
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	/* Set RSA Decrypt Protocol Data Block - Private Key Form #2 */
7878c2ecf20Sopenharmony_ci	ret = set_rsa_priv_f2_pdb(req, edesc);
7888c2ecf20Sopenharmony_ci	if (ret)
7898c2ecf20Sopenharmony_ci		goto init_fail;
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	/* Initialize Job Descriptor */
7928c2ecf20Sopenharmony_ci	init_rsa_priv_f2_desc(edesc->hw_desc, &edesc->pdb.priv_f2);
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	return akcipher_enqueue_req(jrdev, rsa_priv_f_done, req);
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ciinit_fail:
7978c2ecf20Sopenharmony_ci	rsa_io_unmap(jrdev, edesc, req);
7988c2ecf20Sopenharmony_ci	kfree(edesc);
7998c2ecf20Sopenharmony_ci	return ret;
8008c2ecf20Sopenharmony_ci}
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_cistatic int caam_rsa_dec_priv_f3(struct akcipher_request *req)
8038c2ecf20Sopenharmony_ci{
8048c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
8058c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
8068c2ecf20Sopenharmony_ci	struct device *jrdev = ctx->dev;
8078c2ecf20Sopenharmony_ci	struct rsa_edesc *edesc;
8088c2ecf20Sopenharmony_ci	int ret;
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci	/* Allocate extended descriptor */
8118c2ecf20Sopenharmony_ci	edesc = rsa_edesc_alloc(req, DESC_RSA_PRIV_F3_LEN);
8128c2ecf20Sopenharmony_ci	if (IS_ERR(edesc))
8138c2ecf20Sopenharmony_ci		return PTR_ERR(edesc);
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	/* Set RSA Decrypt Protocol Data Block - Private Key Form #3 */
8168c2ecf20Sopenharmony_ci	ret = set_rsa_priv_f3_pdb(req, edesc);
8178c2ecf20Sopenharmony_ci	if (ret)
8188c2ecf20Sopenharmony_ci		goto init_fail;
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	/* Initialize Job Descriptor */
8218c2ecf20Sopenharmony_ci	init_rsa_priv_f3_desc(edesc->hw_desc, &edesc->pdb.priv_f3);
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	return akcipher_enqueue_req(jrdev, rsa_priv_f_done, req);
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ciinit_fail:
8268c2ecf20Sopenharmony_ci	rsa_io_unmap(jrdev, edesc, req);
8278c2ecf20Sopenharmony_ci	kfree(edesc);
8288c2ecf20Sopenharmony_ci	return ret;
8298c2ecf20Sopenharmony_ci}
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_cistatic int caam_rsa_dec(struct akcipher_request *req)
8328c2ecf20Sopenharmony_ci{
8338c2ecf20Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
8348c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
8358c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
8368c2ecf20Sopenharmony_ci	int ret;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	if (unlikely(!key->n || !key->d))
8398c2ecf20Sopenharmony_ci		return -EINVAL;
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	if (req->dst_len < key->n_sz) {
8428c2ecf20Sopenharmony_ci		req->dst_len = key->n_sz;
8438c2ecf20Sopenharmony_ci		dev_err(ctx->dev, "Output buffer length less than parameter n\n");
8448c2ecf20Sopenharmony_ci		return -EOVERFLOW;
8458c2ecf20Sopenharmony_ci	}
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	if (key->priv_form == FORM3)
8488c2ecf20Sopenharmony_ci		ret = caam_rsa_dec_priv_f3(req);
8498c2ecf20Sopenharmony_ci	else if (key->priv_form == FORM2)
8508c2ecf20Sopenharmony_ci		ret = caam_rsa_dec_priv_f2(req);
8518c2ecf20Sopenharmony_ci	else
8528c2ecf20Sopenharmony_ci		ret = caam_rsa_dec_priv_f1(req);
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	return ret;
8558c2ecf20Sopenharmony_ci}
8568c2ecf20Sopenharmony_ci
8578c2ecf20Sopenharmony_cistatic void caam_rsa_free_key(struct caam_rsa_key *key)
8588c2ecf20Sopenharmony_ci{
8598c2ecf20Sopenharmony_ci	kfree_sensitive(key->d);
8608c2ecf20Sopenharmony_ci	kfree_sensitive(key->p);
8618c2ecf20Sopenharmony_ci	kfree_sensitive(key->q);
8628c2ecf20Sopenharmony_ci	kfree_sensitive(key->dp);
8638c2ecf20Sopenharmony_ci	kfree_sensitive(key->dq);
8648c2ecf20Sopenharmony_ci	kfree_sensitive(key->qinv);
8658c2ecf20Sopenharmony_ci	kfree_sensitive(key->tmp1);
8668c2ecf20Sopenharmony_ci	kfree_sensitive(key->tmp2);
8678c2ecf20Sopenharmony_ci	kfree(key->e);
8688c2ecf20Sopenharmony_ci	kfree(key->n);
8698c2ecf20Sopenharmony_ci	memset(key, 0, sizeof(*key));
8708c2ecf20Sopenharmony_ci}
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_cistatic void caam_rsa_drop_leading_zeros(const u8 **ptr, size_t *nbytes)
8738c2ecf20Sopenharmony_ci{
8748c2ecf20Sopenharmony_ci	while (!**ptr && *nbytes) {
8758c2ecf20Sopenharmony_ci		(*ptr)++;
8768c2ecf20Sopenharmony_ci		(*nbytes)--;
8778c2ecf20Sopenharmony_ci	}
8788c2ecf20Sopenharmony_ci}
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci/**
8818c2ecf20Sopenharmony_ci * caam_read_rsa_crt - Used for reading dP, dQ, qInv CRT members.
8828c2ecf20Sopenharmony_ci * dP, dQ and qInv could decode to less than corresponding p, q length, as the
8838c2ecf20Sopenharmony_ci * BER-encoding requires that the minimum number of bytes be used to encode the
8848c2ecf20Sopenharmony_ci * integer. dP, dQ, qInv decoded values have to be zero-padded to appropriate
8858c2ecf20Sopenharmony_ci * length.
8868c2ecf20Sopenharmony_ci *
8878c2ecf20Sopenharmony_ci * @ptr   : pointer to {dP, dQ, qInv} CRT member
8888c2ecf20Sopenharmony_ci * @nbytes: length in bytes of {dP, dQ, qInv} CRT member
8898c2ecf20Sopenharmony_ci * @dstlen: length in bytes of corresponding p or q prime factor
8908c2ecf20Sopenharmony_ci */
8918c2ecf20Sopenharmony_cistatic u8 *caam_read_rsa_crt(const u8 *ptr, size_t nbytes, size_t dstlen)
8928c2ecf20Sopenharmony_ci{
8938c2ecf20Sopenharmony_ci	u8 *dst;
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	caam_rsa_drop_leading_zeros(&ptr, &nbytes);
8968c2ecf20Sopenharmony_ci	if (!nbytes)
8978c2ecf20Sopenharmony_ci		return NULL;
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci	dst = kzalloc(dstlen, GFP_DMA | GFP_KERNEL);
9008c2ecf20Sopenharmony_ci	if (!dst)
9018c2ecf20Sopenharmony_ci		return NULL;
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci	memcpy(dst + (dstlen - nbytes), ptr, nbytes);
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	return dst;
9068c2ecf20Sopenharmony_ci}
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci/**
9098c2ecf20Sopenharmony_ci * caam_read_raw_data - Read a raw byte stream as a positive integer.
9108c2ecf20Sopenharmony_ci * The function skips buffer's leading zeros, copies the remained data
9118c2ecf20Sopenharmony_ci * to a buffer allocated in the GFP_DMA | GFP_KERNEL zone and returns
9128c2ecf20Sopenharmony_ci * the address of the new buffer.
9138c2ecf20Sopenharmony_ci *
9148c2ecf20Sopenharmony_ci * @buf   : The data to read
9158c2ecf20Sopenharmony_ci * @nbytes: The amount of data to read
9168c2ecf20Sopenharmony_ci */
9178c2ecf20Sopenharmony_cistatic inline u8 *caam_read_raw_data(const u8 *buf, size_t *nbytes)
9188c2ecf20Sopenharmony_ci{
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	caam_rsa_drop_leading_zeros(&buf, nbytes);
9218c2ecf20Sopenharmony_ci	if (!*nbytes)
9228c2ecf20Sopenharmony_ci		return NULL;
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	return kmemdup(buf, *nbytes, GFP_DMA | GFP_KERNEL);
9258c2ecf20Sopenharmony_ci}
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_cistatic int caam_rsa_check_key_length(unsigned int len)
9288c2ecf20Sopenharmony_ci{
9298c2ecf20Sopenharmony_ci	if (len > 4096)
9308c2ecf20Sopenharmony_ci		return -EINVAL;
9318c2ecf20Sopenharmony_ci	return 0;
9328c2ecf20Sopenharmony_ci}
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_cistatic int caam_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
9358c2ecf20Sopenharmony_ci				unsigned int keylen)
9368c2ecf20Sopenharmony_ci{
9378c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
9388c2ecf20Sopenharmony_ci	struct rsa_key raw_key = {NULL};
9398c2ecf20Sopenharmony_ci	struct caam_rsa_key *rsa_key = &ctx->key;
9408c2ecf20Sopenharmony_ci	int ret;
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	/* Free the old RSA key if any */
9438c2ecf20Sopenharmony_ci	caam_rsa_free_key(rsa_key);
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	ret = rsa_parse_pub_key(&raw_key, key, keylen);
9468c2ecf20Sopenharmony_ci	if (ret)
9478c2ecf20Sopenharmony_ci		return ret;
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	/* Copy key in DMA zone */
9508c2ecf20Sopenharmony_ci	rsa_key->e = kmemdup(raw_key.e, raw_key.e_sz, GFP_DMA | GFP_KERNEL);
9518c2ecf20Sopenharmony_ci	if (!rsa_key->e)
9528c2ecf20Sopenharmony_ci		goto err;
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ci	/*
9558c2ecf20Sopenharmony_ci	 * Skip leading zeros and copy the positive integer to a buffer
9568c2ecf20Sopenharmony_ci	 * allocated in the GFP_DMA | GFP_KERNEL zone. The decryption descriptor
9578c2ecf20Sopenharmony_ci	 * expects a positive integer for the RSA modulus and uses its length as
9588c2ecf20Sopenharmony_ci	 * decryption output length.
9598c2ecf20Sopenharmony_ci	 */
9608c2ecf20Sopenharmony_ci	rsa_key->n = caam_read_raw_data(raw_key.n, &raw_key.n_sz);
9618c2ecf20Sopenharmony_ci	if (!rsa_key->n)
9628c2ecf20Sopenharmony_ci		goto err;
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci	if (caam_rsa_check_key_length(raw_key.n_sz << 3)) {
9658c2ecf20Sopenharmony_ci		caam_rsa_free_key(rsa_key);
9668c2ecf20Sopenharmony_ci		return -EINVAL;
9678c2ecf20Sopenharmony_ci	}
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci	rsa_key->e_sz = raw_key.e_sz;
9708c2ecf20Sopenharmony_ci	rsa_key->n_sz = raw_key.n_sz;
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	return 0;
9738c2ecf20Sopenharmony_cierr:
9748c2ecf20Sopenharmony_ci	caam_rsa_free_key(rsa_key);
9758c2ecf20Sopenharmony_ci	return -ENOMEM;
9768c2ecf20Sopenharmony_ci}
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_cistatic void caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx,
9798c2ecf20Sopenharmony_ci				       struct rsa_key *raw_key)
9808c2ecf20Sopenharmony_ci{
9818c2ecf20Sopenharmony_ci	struct caam_rsa_key *rsa_key = &ctx->key;
9828c2ecf20Sopenharmony_ci	size_t p_sz = raw_key->p_sz;
9838c2ecf20Sopenharmony_ci	size_t q_sz = raw_key->q_sz;
9848c2ecf20Sopenharmony_ci
9858c2ecf20Sopenharmony_ci	rsa_key->p = caam_read_raw_data(raw_key->p, &p_sz);
9868c2ecf20Sopenharmony_ci	if (!rsa_key->p)
9878c2ecf20Sopenharmony_ci		return;
9888c2ecf20Sopenharmony_ci	rsa_key->p_sz = p_sz;
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	rsa_key->q = caam_read_raw_data(raw_key->q, &q_sz);
9918c2ecf20Sopenharmony_ci	if (!rsa_key->q)
9928c2ecf20Sopenharmony_ci		goto free_p;
9938c2ecf20Sopenharmony_ci	rsa_key->q_sz = q_sz;
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci	rsa_key->tmp1 = kzalloc(raw_key->p_sz, GFP_DMA | GFP_KERNEL);
9968c2ecf20Sopenharmony_ci	if (!rsa_key->tmp1)
9978c2ecf20Sopenharmony_ci		goto free_q;
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci	rsa_key->tmp2 = kzalloc(raw_key->q_sz, GFP_DMA | GFP_KERNEL);
10008c2ecf20Sopenharmony_ci	if (!rsa_key->tmp2)
10018c2ecf20Sopenharmony_ci		goto free_tmp1;
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	rsa_key->priv_form = FORM2;
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	rsa_key->dp = caam_read_rsa_crt(raw_key->dp, raw_key->dp_sz, p_sz);
10068c2ecf20Sopenharmony_ci	if (!rsa_key->dp)
10078c2ecf20Sopenharmony_ci		goto free_tmp2;
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci	rsa_key->dq = caam_read_rsa_crt(raw_key->dq, raw_key->dq_sz, q_sz);
10108c2ecf20Sopenharmony_ci	if (!rsa_key->dq)
10118c2ecf20Sopenharmony_ci		goto free_dp;
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	rsa_key->qinv = caam_read_rsa_crt(raw_key->qinv, raw_key->qinv_sz,
10148c2ecf20Sopenharmony_ci					  q_sz);
10158c2ecf20Sopenharmony_ci	if (!rsa_key->qinv)
10168c2ecf20Sopenharmony_ci		goto free_dq;
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	rsa_key->priv_form = FORM3;
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci	return;
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_cifree_dq:
10238c2ecf20Sopenharmony_ci	kfree_sensitive(rsa_key->dq);
10248c2ecf20Sopenharmony_cifree_dp:
10258c2ecf20Sopenharmony_ci	kfree_sensitive(rsa_key->dp);
10268c2ecf20Sopenharmony_cifree_tmp2:
10278c2ecf20Sopenharmony_ci	kfree_sensitive(rsa_key->tmp2);
10288c2ecf20Sopenharmony_cifree_tmp1:
10298c2ecf20Sopenharmony_ci	kfree_sensitive(rsa_key->tmp1);
10308c2ecf20Sopenharmony_cifree_q:
10318c2ecf20Sopenharmony_ci	kfree_sensitive(rsa_key->q);
10328c2ecf20Sopenharmony_cifree_p:
10338c2ecf20Sopenharmony_ci	kfree_sensitive(rsa_key->p);
10348c2ecf20Sopenharmony_ci}
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_cistatic int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
10378c2ecf20Sopenharmony_ci				 unsigned int keylen)
10388c2ecf20Sopenharmony_ci{
10398c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
10408c2ecf20Sopenharmony_ci	struct rsa_key raw_key = {NULL};
10418c2ecf20Sopenharmony_ci	struct caam_rsa_key *rsa_key = &ctx->key;
10428c2ecf20Sopenharmony_ci	int ret;
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci	/* Free the old RSA key if any */
10458c2ecf20Sopenharmony_ci	caam_rsa_free_key(rsa_key);
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	ret = rsa_parse_priv_key(&raw_key, key, keylen);
10488c2ecf20Sopenharmony_ci	if (ret)
10498c2ecf20Sopenharmony_ci		return ret;
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci	/* Copy key in DMA zone */
10528c2ecf20Sopenharmony_ci	rsa_key->d = kmemdup(raw_key.d, raw_key.d_sz, GFP_DMA | GFP_KERNEL);
10538c2ecf20Sopenharmony_ci	if (!rsa_key->d)
10548c2ecf20Sopenharmony_ci		goto err;
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci	rsa_key->e = kmemdup(raw_key.e, raw_key.e_sz, GFP_DMA | GFP_KERNEL);
10578c2ecf20Sopenharmony_ci	if (!rsa_key->e)
10588c2ecf20Sopenharmony_ci		goto err;
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci	/*
10618c2ecf20Sopenharmony_ci	 * Skip leading zeros and copy the positive integer to a buffer
10628c2ecf20Sopenharmony_ci	 * allocated in the GFP_DMA | GFP_KERNEL zone. The decryption descriptor
10638c2ecf20Sopenharmony_ci	 * expects a positive integer for the RSA modulus and uses its length as
10648c2ecf20Sopenharmony_ci	 * decryption output length.
10658c2ecf20Sopenharmony_ci	 */
10668c2ecf20Sopenharmony_ci	rsa_key->n = caam_read_raw_data(raw_key.n, &raw_key.n_sz);
10678c2ecf20Sopenharmony_ci	if (!rsa_key->n)
10688c2ecf20Sopenharmony_ci		goto err;
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	if (caam_rsa_check_key_length(raw_key.n_sz << 3)) {
10718c2ecf20Sopenharmony_ci		caam_rsa_free_key(rsa_key);
10728c2ecf20Sopenharmony_ci		return -EINVAL;
10738c2ecf20Sopenharmony_ci	}
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci	rsa_key->d_sz = raw_key.d_sz;
10768c2ecf20Sopenharmony_ci	rsa_key->e_sz = raw_key.e_sz;
10778c2ecf20Sopenharmony_ci	rsa_key->n_sz = raw_key.n_sz;
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci	caam_rsa_set_priv_key_form(ctx, &raw_key);
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci	return 0;
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_cierr:
10848c2ecf20Sopenharmony_ci	caam_rsa_free_key(rsa_key);
10858c2ecf20Sopenharmony_ci	return -ENOMEM;
10868c2ecf20Sopenharmony_ci}
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_cistatic unsigned int caam_rsa_max_size(struct crypto_akcipher *tfm)
10898c2ecf20Sopenharmony_ci{
10908c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	return ctx->key.n_sz;
10938c2ecf20Sopenharmony_ci}
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci/* Per session pkc's driver context creation function */
10968c2ecf20Sopenharmony_cistatic int caam_rsa_init_tfm(struct crypto_akcipher *tfm)
10978c2ecf20Sopenharmony_ci{
10988c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci	ctx->dev = caam_jr_alloc();
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci	if (IS_ERR(ctx->dev)) {
11038c2ecf20Sopenharmony_ci		pr_err("Job Ring Device allocation for transform failed\n");
11048c2ecf20Sopenharmony_ci		return PTR_ERR(ctx->dev);
11058c2ecf20Sopenharmony_ci	}
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	ctx->padding_dma = dma_map_single(ctx->dev, zero_buffer,
11088c2ecf20Sopenharmony_ci					  CAAM_RSA_MAX_INPUT_SIZE - 1,
11098c2ecf20Sopenharmony_ci					  DMA_TO_DEVICE);
11108c2ecf20Sopenharmony_ci	if (dma_mapping_error(ctx->dev, ctx->padding_dma)) {
11118c2ecf20Sopenharmony_ci		dev_err(ctx->dev, "unable to map padding\n");
11128c2ecf20Sopenharmony_ci		caam_jr_free(ctx->dev);
11138c2ecf20Sopenharmony_ci		return -ENOMEM;
11148c2ecf20Sopenharmony_ci	}
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	ctx->enginectx.op.do_one_request = akcipher_do_one_req;
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci	return 0;
11198c2ecf20Sopenharmony_ci}
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci/* Per session pkc's driver context cleanup function */
11228c2ecf20Sopenharmony_cistatic void caam_rsa_exit_tfm(struct crypto_akcipher *tfm)
11238c2ecf20Sopenharmony_ci{
11248c2ecf20Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
11258c2ecf20Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	dma_unmap_single(ctx->dev, ctx->padding_dma, CAAM_RSA_MAX_INPUT_SIZE -
11288c2ecf20Sopenharmony_ci			 1, DMA_TO_DEVICE);
11298c2ecf20Sopenharmony_ci	caam_rsa_free_key(key);
11308c2ecf20Sopenharmony_ci	caam_jr_free(ctx->dev);
11318c2ecf20Sopenharmony_ci}
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_cistatic struct caam_akcipher_alg caam_rsa = {
11348c2ecf20Sopenharmony_ci	.akcipher = {
11358c2ecf20Sopenharmony_ci		.encrypt = caam_rsa_enc,
11368c2ecf20Sopenharmony_ci		.decrypt = caam_rsa_dec,
11378c2ecf20Sopenharmony_ci		.set_pub_key = caam_rsa_set_pub_key,
11388c2ecf20Sopenharmony_ci		.set_priv_key = caam_rsa_set_priv_key,
11398c2ecf20Sopenharmony_ci		.max_size = caam_rsa_max_size,
11408c2ecf20Sopenharmony_ci		.init = caam_rsa_init_tfm,
11418c2ecf20Sopenharmony_ci		.exit = caam_rsa_exit_tfm,
11428c2ecf20Sopenharmony_ci		.reqsize = sizeof(struct caam_rsa_req_ctx),
11438c2ecf20Sopenharmony_ci		.base = {
11448c2ecf20Sopenharmony_ci			.cra_name = "rsa",
11458c2ecf20Sopenharmony_ci			.cra_driver_name = "rsa-caam",
11468c2ecf20Sopenharmony_ci			.cra_priority = 3000,
11478c2ecf20Sopenharmony_ci			.cra_module = THIS_MODULE,
11488c2ecf20Sopenharmony_ci			.cra_ctxsize = sizeof(struct caam_rsa_ctx),
11498c2ecf20Sopenharmony_ci		},
11508c2ecf20Sopenharmony_ci	}
11518c2ecf20Sopenharmony_ci};
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci/* Public Key Cryptography module initialization handler */
11548c2ecf20Sopenharmony_ciint caam_pkc_init(struct device *ctrldev)
11558c2ecf20Sopenharmony_ci{
11568c2ecf20Sopenharmony_ci	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
11578c2ecf20Sopenharmony_ci	u32 pk_inst, pkha;
11588c2ecf20Sopenharmony_ci	int err;
11598c2ecf20Sopenharmony_ci	init_done = false;
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci	/* Determine public key hardware accelerator presence. */
11628c2ecf20Sopenharmony_ci	if (priv->era < 10) {
11638c2ecf20Sopenharmony_ci		pk_inst = (rd_reg32(&priv->ctrl->perfmon.cha_num_ls) &
11648c2ecf20Sopenharmony_ci			   CHA_ID_LS_PK_MASK) >> CHA_ID_LS_PK_SHIFT;
11658c2ecf20Sopenharmony_ci	} else {
11668c2ecf20Sopenharmony_ci		pkha = rd_reg32(&priv->ctrl->vreg.pkha);
11678c2ecf20Sopenharmony_ci		pk_inst = pkha & CHA_VER_NUM_MASK;
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_ci		/*
11708c2ecf20Sopenharmony_ci		 * Newer CAAMs support partially disabled functionality. If this is the
11718c2ecf20Sopenharmony_ci		 * case, the number is non-zero, but this bit is set to indicate that
11728c2ecf20Sopenharmony_ci		 * no encryption or decryption is supported. Only signing and verifying
11738c2ecf20Sopenharmony_ci		 * is supported.
11748c2ecf20Sopenharmony_ci		 */
11758c2ecf20Sopenharmony_ci		if (pkha & CHA_VER_MISC_PKHA_NO_CRYPT)
11768c2ecf20Sopenharmony_ci			pk_inst = 0;
11778c2ecf20Sopenharmony_ci	}
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	/* Do not register algorithms if PKHA is not present. */
11808c2ecf20Sopenharmony_ci	if (!pk_inst)
11818c2ecf20Sopenharmony_ci		return 0;
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	/* allocate zero buffer, used for padding input */
11848c2ecf20Sopenharmony_ci	zero_buffer = kzalloc(CAAM_RSA_MAX_INPUT_SIZE - 1, GFP_DMA |
11858c2ecf20Sopenharmony_ci			      GFP_KERNEL);
11868c2ecf20Sopenharmony_ci	if (!zero_buffer)
11878c2ecf20Sopenharmony_ci		return -ENOMEM;
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci	err = crypto_register_akcipher(&caam_rsa.akcipher);
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_ci	if (err) {
11928c2ecf20Sopenharmony_ci		kfree(zero_buffer);
11938c2ecf20Sopenharmony_ci		dev_warn(ctrldev, "%s alg registration failed\n",
11948c2ecf20Sopenharmony_ci			 caam_rsa.akcipher.base.cra_driver_name);
11958c2ecf20Sopenharmony_ci	} else {
11968c2ecf20Sopenharmony_ci		init_done = true;
11978c2ecf20Sopenharmony_ci		caam_rsa.registered = true;
11988c2ecf20Sopenharmony_ci		dev_info(ctrldev, "caam pkc algorithms registered in /proc/crypto\n");
11998c2ecf20Sopenharmony_ci	}
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	return err;
12028c2ecf20Sopenharmony_ci}
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_civoid caam_pkc_exit(void)
12058c2ecf20Sopenharmony_ci{
12068c2ecf20Sopenharmony_ci	if (!init_done)
12078c2ecf20Sopenharmony_ci		return;
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	if (caam_rsa.registered)
12108c2ecf20Sopenharmony_ci		crypto_unregister_akcipher(&caam_rsa.akcipher);
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	kfree(zero_buffer);
12138c2ecf20Sopenharmony_ci}
1214