162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * caam - Freescale FSL CAAM support for Public Key Cryptography
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2016 Freescale Semiconductor, Inc.
662306a36Sopenharmony_ci * Copyright 2018-2019, 2023 NXP
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * There is no Shared Descriptor for PKC so that the Job Descriptor must carry
962306a36Sopenharmony_ci * all the desired key parameters, input and output pointers.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci#include "compat.h"
1262306a36Sopenharmony_ci#include "regs.h"
1362306a36Sopenharmony_ci#include "intern.h"
1462306a36Sopenharmony_ci#include "jr.h"
1562306a36Sopenharmony_ci#include "error.h"
1662306a36Sopenharmony_ci#include "desc_constr.h"
1762306a36Sopenharmony_ci#include "sg_sw_sec4.h"
1862306a36Sopenharmony_ci#include "caampkc.h"
1962306a36Sopenharmony_ci#include <crypto/internal/engine.h>
2062306a36Sopenharmony_ci#include <linux/dma-mapping.h>
2162306a36Sopenharmony_ci#include <linux/err.h>
2262306a36Sopenharmony_ci#include <linux/kernel.h>
2362306a36Sopenharmony_ci#include <linux/slab.h>
2462306a36Sopenharmony_ci#include <linux/string.h>
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define DESC_RSA_PUB_LEN	(2 * CAAM_CMD_SZ + SIZEOF_RSA_PUB_PDB)
2762306a36Sopenharmony_ci#define DESC_RSA_PRIV_F1_LEN	(2 * CAAM_CMD_SZ + \
2862306a36Sopenharmony_ci				 SIZEOF_RSA_PRIV_F1_PDB)
2962306a36Sopenharmony_ci#define DESC_RSA_PRIV_F2_LEN	(2 * CAAM_CMD_SZ + \
3062306a36Sopenharmony_ci				 SIZEOF_RSA_PRIV_F2_PDB)
3162306a36Sopenharmony_ci#define DESC_RSA_PRIV_F3_LEN	(2 * CAAM_CMD_SZ + \
3262306a36Sopenharmony_ci				 SIZEOF_RSA_PRIV_F3_PDB)
3362306a36Sopenharmony_ci#define CAAM_RSA_MAX_INPUT_SIZE	512 /* for a 4096-bit modulus */
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/* buffer filled with zeros, used for padding */
3662306a36Sopenharmony_cistatic u8 *zero_buffer;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/*
3962306a36Sopenharmony_ci * variable used to avoid double free of resources in case
4062306a36Sopenharmony_ci * algorithm registration was unsuccessful
4162306a36Sopenharmony_ci */
4262306a36Sopenharmony_cistatic bool init_done;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistruct caam_akcipher_alg {
4562306a36Sopenharmony_ci	struct akcipher_engine_alg akcipher;
4662306a36Sopenharmony_ci	bool registered;
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic void rsa_io_unmap(struct device *dev, struct rsa_edesc *edesc,
5062306a36Sopenharmony_ci			 struct akcipher_request *req)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
5562306a36Sopenharmony_ci	dma_unmap_sg(dev, req_ctx->fixup_src, edesc->src_nents, DMA_TO_DEVICE);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	if (edesc->sec4_sg_bytes)
5862306a36Sopenharmony_ci		dma_unmap_single(dev, edesc->sec4_sg_dma, edesc->sec4_sg_bytes,
5962306a36Sopenharmony_ci				 DMA_TO_DEVICE);
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cistatic void rsa_pub_unmap(struct device *dev, struct rsa_edesc *edesc,
6362306a36Sopenharmony_ci			  struct akcipher_request *req)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
6662306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
6762306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
6862306a36Sopenharmony_ci	struct rsa_pub_pdb *pdb = &edesc->pdb.pub;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->n_dma, key->n_sz, DMA_TO_DEVICE);
7162306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->e_dma, key->e_sz, DMA_TO_DEVICE);
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistatic void rsa_priv_f1_unmap(struct device *dev, struct rsa_edesc *edesc,
7562306a36Sopenharmony_ci			      struct akcipher_request *req)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
7862306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
7962306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
8062306a36Sopenharmony_ci	struct rsa_priv_f1_pdb *pdb = &edesc->pdb.priv_f1;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->n_dma, key->n_sz, DMA_TO_DEVICE);
8362306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->d_dma, key->d_sz, DMA_TO_DEVICE);
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic void rsa_priv_f2_unmap(struct device *dev, struct rsa_edesc *edesc,
8762306a36Sopenharmony_ci			      struct akcipher_request *req)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
9062306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
9162306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
9262306a36Sopenharmony_ci	struct rsa_priv_f2_pdb *pdb = &edesc->pdb.priv_f2;
9362306a36Sopenharmony_ci	size_t p_sz = key->p_sz;
9462306a36Sopenharmony_ci	size_t q_sz = key->q_sz;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->d_dma, key->d_sz, DMA_TO_DEVICE);
9762306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE);
9862306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE);
9962306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL);
10062306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->tmp2_dma, q_sz, DMA_BIDIRECTIONAL);
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic void rsa_priv_f3_unmap(struct device *dev, struct rsa_edesc *edesc,
10462306a36Sopenharmony_ci			      struct akcipher_request *req)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
10762306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
10862306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
10962306a36Sopenharmony_ci	struct rsa_priv_f3_pdb *pdb = &edesc->pdb.priv_f3;
11062306a36Sopenharmony_ci	size_t p_sz = key->p_sz;
11162306a36Sopenharmony_ci	size_t q_sz = key->q_sz;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE);
11462306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE);
11562306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->dp_dma, p_sz, DMA_TO_DEVICE);
11662306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->dq_dma, q_sz, DMA_TO_DEVICE);
11762306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->c_dma, p_sz, DMA_TO_DEVICE);
11862306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL);
11962306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->tmp2_dma, q_sz, DMA_BIDIRECTIONAL);
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci/* RSA Job Completion handler */
12362306a36Sopenharmony_cistatic void rsa_pub_done(struct device *dev, u32 *desc, u32 err, void *context)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	struct akcipher_request *req = context;
12662306a36Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
12762306a36Sopenharmony_ci	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
12862306a36Sopenharmony_ci	struct rsa_edesc *edesc;
12962306a36Sopenharmony_ci	int ecode = 0;
13062306a36Sopenharmony_ci	bool has_bklog;
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	if (err)
13362306a36Sopenharmony_ci		ecode = caam_jr_strstatus(dev, err);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	edesc = req_ctx->edesc;
13662306a36Sopenharmony_ci	has_bklog = edesc->bklog;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	rsa_pub_unmap(dev, edesc, req);
13962306a36Sopenharmony_ci	rsa_io_unmap(dev, edesc, req);
14062306a36Sopenharmony_ci	kfree(edesc);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	/*
14362306a36Sopenharmony_ci	 * If no backlog flag, the completion of the request is done
14462306a36Sopenharmony_ci	 * by CAAM, not crypto engine.
14562306a36Sopenharmony_ci	 */
14662306a36Sopenharmony_ci	if (!has_bklog)
14762306a36Sopenharmony_ci		akcipher_request_complete(req, ecode);
14862306a36Sopenharmony_ci	else
14962306a36Sopenharmony_ci		crypto_finalize_akcipher_request(jrp->engine, req, ecode);
15062306a36Sopenharmony_ci}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_cistatic void rsa_priv_f_done(struct device *dev, u32 *desc, u32 err,
15362306a36Sopenharmony_ci			    void *context)
15462306a36Sopenharmony_ci{
15562306a36Sopenharmony_ci	struct akcipher_request *req = context;
15662306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
15762306a36Sopenharmony_ci	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
15862306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
15962306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
16062306a36Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
16162306a36Sopenharmony_ci	struct rsa_edesc *edesc;
16262306a36Sopenharmony_ci	int ecode = 0;
16362306a36Sopenharmony_ci	bool has_bklog;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	if (err)
16662306a36Sopenharmony_ci		ecode = caam_jr_strstatus(dev, err);
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	edesc = req_ctx->edesc;
16962306a36Sopenharmony_ci	has_bklog = edesc->bklog;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	switch (key->priv_form) {
17262306a36Sopenharmony_ci	case FORM1:
17362306a36Sopenharmony_ci		rsa_priv_f1_unmap(dev, edesc, req);
17462306a36Sopenharmony_ci		break;
17562306a36Sopenharmony_ci	case FORM2:
17662306a36Sopenharmony_ci		rsa_priv_f2_unmap(dev, edesc, req);
17762306a36Sopenharmony_ci		break;
17862306a36Sopenharmony_ci	case FORM3:
17962306a36Sopenharmony_ci		rsa_priv_f3_unmap(dev, edesc, req);
18062306a36Sopenharmony_ci	}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	rsa_io_unmap(dev, edesc, req);
18362306a36Sopenharmony_ci	kfree(edesc);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	/*
18662306a36Sopenharmony_ci	 * If no backlog flag, the completion of the request is done
18762306a36Sopenharmony_ci	 * by CAAM, not crypto engine.
18862306a36Sopenharmony_ci	 */
18962306a36Sopenharmony_ci	if (!has_bklog)
19062306a36Sopenharmony_ci		akcipher_request_complete(req, ecode);
19162306a36Sopenharmony_ci	else
19262306a36Sopenharmony_ci		crypto_finalize_akcipher_request(jrp->engine, req, ecode);
19362306a36Sopenharmony_ci}
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci/**
19662306a36Sopenharmony_ci * caam_rsa_count_leading_zeros - Count leading zeros, need it to strip,
19762306a36Sopenharmony_ci *                                from a given scatterlist
19862306a36Sopenharmony_ci *
19962306a36Sopenharmony_ci * @sgl   : scatterlist to count zeros from
20062306a36Sopenharmony_ci * @nbytes: number of zeros, in bytes, to strip
20162306a36Sopenharmony_ci * @flags : operation flags
20262306a36Sopenharmony_ci */
20362306a36Sopenharmony_cistatic int caam_rsa_count_leading_zeros(struct scatterlist *sgl,
20462306a36Sopenharmony_ci					unsigned int nbytes,
20562306a36Sopenharmony_ci					unsigned int flags)
20662306a36Sopenharmony_ci{
20762306a36Sopenharmony_ci	struct sg_mapping_iter miter;
20862306a36Sopenharmony_ci	int lzeros, ents;
20962306a36Sopenharmony_ci	unsigned int len;
21062306a36Sopenharmony_ci	unsigned int tbytes = nbytes;
21162306a36Sopenharmony_ci	const u8 *buff;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	ents = sg_nents_for_len(sgl, nbytes);
21462306a36Sopenharmony_ci	if (ents < 0)
21562306a36Sopenharmony_ci		return ents;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	sg_miter_start(&miter, sgl, ents, SG_MITER_FROM_SG | flags);
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	lzeros = 0;
22062306a36Sopenharmony_ci	len = 0;
22162306a36Sopenharmony_ci	while (nbytes > 0) {
22262306a36Sopenharmony_ci		/* do not strip more than given bytes */
22362306a36Sopenharmony_ci		while (len && !*buff && lzeros < nbytes) {
22462306a36Sopenharmony_ci			lzeros++;
22562306a36Sopenharmony_ci			len--;
22662306a36Sopenharmony_ci			buff++;
22762306a36Sopenharmony_ci		}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci		if (len && *buff)
23062306a36Sopenharmony_ci			break;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci		if (!sg_miter_next(&miter))
23362306a36Sopenharmony_ci			break;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci		buff = miter.addr;
23662306a36Sopenharmony_ci		len = miter.length;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci		nbytes -= lzeros;
23962306a36Sopenharmony_ci		lzeros = 0;
24062306a36Sopenharmony_ci	}
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	miter.consumed = lzeros;
24362306a36Sopenharmony_ci	sg_miter_stop(&miter);
24462306a36Sopenharmony_ci	nbytes -= lzeros;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	return tbytes - nbytes;
24762306a36Sopenharmony_ci}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_cistatic struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req,
25062306a36Sopenharmony_ci					 size_t desclen)
25162306a36Sopenharmony_ci{
25262306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
25362306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
25462306a36Sopenharmony_ci	struct device *dev = ctx->dev;
25562306a36Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
25662306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
25762306a36Sopenharmony_ci	struct rsa_edesc *edesc;
25862306a36Sopenharmony_ci	gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
25962306a36Sopenharmony_ci		       GFP_KERNEL : GFP_ATOMIC;
26062306a36Sopenharmony_ci	int sg_flags = (flags == GFP_ATOMIC) ? SG_MITER_ATOMIC : 0;
26162306a36Sopenharmony_ci	int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
26262306a36Sopenharmony_ci	int src_nents, dst_nents;
26362306a36Sopenharmony_ci	int mapped_src_nents, mapped_dst_nents;
26462306a36Sopenharmony_ci	unsigned int diff_size = 0;
26562306a36Sopenharmony_ci	int lzeros;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	if (req->src_len > key->n_sz) {
26862306a36Sopenharmony_ci		/*
26962306a36Sopenharmony_ci		 * strip leading zeros and
27062306a36Sopenharmony_ci		 * return the number of zeros to skip
27162306a36Sopenharmony_ci		 */
27262306a36Sopenharmony_ci		lzeros = caam_rsa_count_leading_zeros(req->src, req->src_len -
27362306a36Sopenharmony_ci						      key->n_sz, sg_flags);
27462306a36Sopenharmony_ci		if (lzeros < 0)
27562306a36Sopenharmony_ci			return ERR_PTR(lzeros);
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci		req_ctx->fixup_src = scatterwalk_ffwd(req_ctx->src, req->src,
27862306a36Sopenharmony_ci						      lzeros);
27962306a36Sopenharmony_ci		req_ctx->fixup_src_len = req->src_len - lzeros;
28062306a36Sopenharmony_ci	} else {
28162306a36Sopenharmony_ci		/*
28262306a36Sopenharmony_ci		 * input src is less then n key modulus,
28362306a36Sopenharmony_ci		 * so there will be zero padding
28462306a36Sopenharmony_ci		 */
28562306a36Sopenharmony_ci		diff_size = key->n_sz - req->src_len;
28662306a36Sopenharmony_ci		req_ctx->fixup_src = req->src;
28762306a36Sopenharmony_ci		req_ctx->fixup_src_len = req->src_len;
28862306a36Sopenharmony_ci	}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	src_nents = sg_nents_for_len(req_ctx->fixup_src,
29162306a36Sopenharmony_ci				     req_ctx->fixup_src_len);
29262306a36Sopenharmony_ci	dst_nents = sg_nents_for_len(req->dst, req->dst_len);
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	mapped_src_nents = dma_map_sg(dev, req_ctx->fixup_src, src_nents,
29562306a36Sopenharmony_ci				      DMA_TO_DEVICE);
29662306a36Sopenharmony_ci	if (unlikely(!mapped_src_nents)) {
29762306a36Sopenharmony_ci		dev_err(dev, "unable to map source\n");
29862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
29962306a36Sopenharmony_ci	}
30062306a36Sopenharmony_ci	mapped_dst_nents = dma_map_sg(dev, req->dst, dst_nents,
30162306a36Sopenharmony_ci				      DMA_FROM_DEVICE);
30262306a36Sopenharmony_ci	if (unlikely(!mapped_dst_nents)) {
30362306a36Sopenharmony_ci		dev_err(dev, "unable to map destination\n");
30462306a36Sopenharmony_ci		goto src_fail;
30562306a36Sopenharmony_ci	}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	if (!diff_size && mapped_src_nents == 1)
30862306a36Sopenharmony_ci		sec4_sg_len = 0; /* no need for an input hw s/g table */
30962306a36Sopenharmony_ci	else
31062306a36Sopenharmony_ci		sec4_sg_len = mapped_src_nents + !!diff_size;
31162306a36Sopenharmony_ci	sec4_sg_index = sec4_sg_len;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	if (mapped_dst_nents > 1)
31462306a36Sopenharmony_ci		sec4_sg_len += pad_sg_nents(mapped_dst_nents);
31562306a36Sopenharmony_ci	else
31662306a36Sopenharmony_ci		sec4_sg_len = pad_sg_nents(sec4_sg_len);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry);
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	/* allocate space for base edesc, hw desc commands and link tables */
32162306a36Sopenharmony_ci	edesc = kzalloc(sizeof(*edesc) + desclen + sec4_sg_bytes, flags);
32262306a36Sopenharmony_ci	if (!edesc)
32362306a36Sopenharmony_ci		goto dst_fail;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	edesc->sec4_sg = (void *)edesc + sizeof(*edesc) + desclen;
32662306a36Sopenharmony_ci	if (diff_size)
32762306a36Sopenharmony_ci		dma_to_sec4_sg_one(edesc->sec4_sg, ctx->padding_dma, diff_size,
32862306a36Sopenharmony_ci				   0);
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	if (sec4_sg_index)
33162306a36Sopenharmony_ci		sg_to_sec4_sg_last(req_ctx->fixup_src, req_ctx->fixup_src_len,
33262306a36Sopenharmony_ci				   edesc->sec4_sg + !!diff_size, 0);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	if (mapped_dst_nents > 1)
33562306a36Sopenharmony_ci		sg_to_sec4_sg_last(req->dst, req->dst_len,
33662306a36Sopenharmony_ci				   edesc->sec4_sg + sec4_sg_index, 0);
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	/* Save nents for later use in Job Descriptor */
33962306a36Sopenharmony_ci	edesc->src_nents = src_nents;
34062306a36Sopenharmony_ci	edesc->dst_nents = dst_nents;
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	req_ctx->edesc = edesc;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	if (!sec4_sg_bytes)
34562306a36Sopenharmony_ci		return edesc;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	edesc->mapped_src_nents = mapped_src_nents;
34862306a36Sopenharmony_ci	edesc->mapped_dst_nents = mapped_dst_nents;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	edesc->sec4_sg_dma = dma_map_single(dev, edesc->sec4_sg,
35162306a36Sopenharmony_ci					    sec4_sg_bytes, DMA_TO_DEVICE);
35262306a36Sopenharmony_ci	if (dma_mapping_error(dev, edesc->sec4_sg_dma)) {
35362306a36Sopenharmony_ci		dev_err(dev, "unable to map S/G table\n");
35462306a36Sopenharmony_ci		goto sec4_sg_fail;
35562306a36Sopenharmony_ci	}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	edesc->sec4_sg_bytes = sec4_sg_bytes;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	print_hex_dump_debug("caampkc sec4_sg@" __stringify(__LINE__) ": ",
36062306a36Sopenharmony_ci			     DUMP_PREFIX_ADDRESS, 16, 4, edesc->sec4_sg,
36162306a36Sopenharmony_ci			     edesc->sec4_sg_bytes, 1);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	return edesc;
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_cisec4_sg_fail:
36662306a36Sopenharmony_ci	kfree(edesc);
36762306a36Sopenharmony_cidst_fail:
36862306a36Sopenharmony_ci	dma_unmap_sg(dev, req->dst, dst_nents, DMA_FROM_DEVICE);
36962306a36Sopenharmony_cisrc_fail:
37062306a36Sopenharmony_ci	dma_unmap_sg(dev, req_ctx->fixup_src, src_nents, DMA_TO_DEVICE);
37162306a36Sopenharmony_ci	return ERR_PTR(-ENOMEM);
37262306a36Sopenharmony_ci}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_cistatic int akcipher_do_one_req(struct crypto_engine *engine, void *areq)
37562306a36Sopenharmony_ci{
37662306a36Sopenharmony_ci	struct akcipher_request *req = container_of(areq,
37762306a36Sopenharmony_ci						    struct akcipher_request,
37862306a36Sopenharmony_ci						    base);
37962306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
38062306a36Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
38162306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
38262306a36Sopenharmony_ci	struct device *jrdev = ctx->dev;
38362306a36Sopenharmony_ci	u32 *desc = req_ctx->edesc->hw_desc;
38462306a36Sopenharmony_ci	int ret;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	req_ctx->edesc->bklog = true;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	ret = caam_jr_enqueue(jrdev, desc, req_ctx->akcipher_op_done, req);
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	if (ret == -ENOSPC && engine->retry_support)
39162306a36Sopenharmony_ci		return ret;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	if (ret != -EINPROGRESS) {
39462306a36Sopenharmony_ci		rsa_pub_unmap(jrdev, req_ctx->edesc, req);
39562306a36Sopenharmony_ci		rsa_io_unmap(jrdev, req_ctx->edesc, req);
39662306a36Sopenharmony_ci		kfree(req_ctx->edesc);
39762306a36Sopenharmony_ci	} else {
39862306a36Sopenharmony_ci		ret = 0;
39962306a36Sopenharmony_ci	}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	return ret;
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_cistatic int set_rsa_pub_pdb(struct akcipher_request *req,
40562306a36Sopenharmony_ci			   struct rsa_edesc *edesc)
40662306a36Sopenharmony_ci{
40762306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
40862306a36Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
40962306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
41062306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
41162306a36Sopenharmony_ci	struct device *dev = ctx->dev;
41262306a36Sopenharmony_ci	struct rsa_pub_pdb *pdb = &edesc->pdb.pub;
41362306a36Sopenharmony_ci	int sec4_sg_index = 0;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	pdb->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
41662306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->n_dma)) {
41762306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA modulus memory\n");
41862306a36Sopenharmony_ci		return -ENOMEM;
41962306a36Sopenharmony_ci	}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	pdb->e_dma = dma_map_single(dev, key->e, key->e_sz, DMA_TO_DEVICE);
42262306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->e_dma)) {
42362306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA public exponent memory\n");
42462306a36Sopenharmony_ci		dma_unmap_single(dev, pdb->n_dma, key->n_sz, DMA_TO_DEVICE);
42562306a36Sopenharmony_ci		return -ENOMEM;
42662306a36Sopenharmony_ci	}
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	if (edesc->mapped_src_nents > 1) {
42962306a36Sopenharmony_ci		pdb->sgf |= RSA_PDB_SGF_F;
43062306a36Sopenharmony_ci		pdb->f_dma = edesc->sec4_sg_dma;
43162306a36Sopenharmony_ci		sec4_sg_index += edesc->mapped_src_nents;
43262306a36Sopenharmony_ci	} else {
43362306a36Sopenharmony_ci		pdb->f_dma = sg_dma_address(req_ctx->fixup_src);
43462306a36Sopenharmony_ci	}
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	if (edesc->mapped_dst_nents > 1) {
43762306a36Sopenharmony_ci		pdb->sgf |= RSA_PDB_SGF_G;
43862306a36Sopenharmony_ci		pdb->g_dma = edesc->sec4_sg_dma +
43962306a36Sopenharmony_ci			     sec4_sg_index * sizeof(struct sec4_sg_entry);
44062306a36Sopenharmony_ci	} else {
44162306a36Sopenharmony_ci		pdb->g_dma = sg_dma_address(req->dst);
44262306a36Sopenharmony_ci	}
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	pdb->sgf |= (key->e_sz << RSA_PDB_E_SHIFT) | key->n_sz;
44562306a36Sopenharmony_ci	pdb->f_len = req_ctx->fixup_src_len;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	return 0;
44862306a36Sopenharmony_ci}
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_cistatic int set_rsa_priv_f1_pdb(struct akcipher_request *req,
45162306a36Sopenharmony_ci			       struct rsa_edesc *edesc)
45262306a36Sopenharmony_ci{
45362306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
45462306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
45562306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
45662306a36Sopenharmony_ci	struct device *dev = ctx->dev;
45762306a36Sopenharmony_ci	struct rsa_priv_f1_pdb *pdb = &edesc->pdb.priv_f1;
45862306a36Sopenharmony_ci	int sec4_sg_index = 0;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	pdb->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
46162306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->n_dma)) {
46262306a36Sopenharmony_ci		dev_err(dev, "Unable to map modulus memory\n");
46362306a36Sopenharmony_ci		return -ENOMEM;
46462306a36Sopenharmony_ci	}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	pdb->d_dma = dma_map_single(dev, key->d, key->d_sz, DMA_TO_DEVICE);
46762306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->d_dma)) {
46862306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA private exponent memory\n");
46962306a36Sopenharmony_ci		dma_unmap_single(dev, pdb->n_dma, key->n_sz, DMA_TO_DEVICE);
47062306a36Sopenharmony_ci		return -ENOMEM;
47162306a36Sopenharmony_ci	}
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	if (edesc->mapped_src_nents > 1) {
47462306a36Sopenharmony_ci		pdb->sgf |= RSA_PRIV_PDB_SGF_G;
47562306a36Sopenharmony_ci		pdb->g_dma = edesc->sec4_sg_dma;
47662306a36Sopenharmony_ci		sec4_sg_index += edesc->mapped_src_nents;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	} else {
47962306a36Sopenharmony_ci		struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci		pdb->g_dma = sg_dma_address(req_ctx->fixup_src);
48262306a36Sopenharmony_ci	}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	if (edesc->mapped_dst_nents > 1) {
48562306a36Sopenharmony_ci		pdb->sgf |= RSA_PRIV_PDB_SGF_F;
48662306a36Sopenharmony_ci		pdb->f_dma = edesc->sec4_sg_dma +
48762306a36Sopenharmony_ci			     sec4_sg_index * sizeof(struct sec4_sg_entry);
48862306a36Sopenharmony_ci	} else {
48962306a36Sopenharmony_ci		pdb->f_dma = sg_dma_address(req->dst);
49062306a36Sopenharmony_ci	}
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	pdb->sgf |= (key->d_sz << RSA_PDB_D_SHIFT) | key->n_sz;
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	return 0;
49562306a36Sopenharmony_ci}
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_cistatic int set_rsa_priv_f2_pdb(struct akcipher_request *req,
49862306a36Sopenharmony_ci			       struct rsa_edesc *edesc)
49962306a36Sopenharmony_ci{
50062306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
50162306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
50262306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
50362306a36Sopenharmony_ci	struct device *dev = ctx->dev;
50462306a36Sopenharmony_ci	struct rsa_priv_f2_pdb *pdb = &edesc->pdb.priv_f2;
50562306a36Sopenharmony_ci	int sec4_sg_index = 0;
50662306a36Sopenharmony_ci	size_t p_sz = key->p_sz;
50762306a36Sopenharmony_ci	size_t q_sz = key->q_sz;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	pdb->d_dma = dma_map_single(dev, key->d, key->d_sz, DMA_TO_DEVICE);
51062306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->d_dma)) {
51162306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA private exponent memory\n");
51262306a36Sopenharmony_ci		return -ENOMEM;
51362306a36Sopenharmony_ci	}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	pdb->p_dma = dma_map_single(dev, key->p, p_sz, DMA_TO_DEVICE);
51662306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->p_dma)) {
51762306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA prime factor p memory\n");
51862306a36Sopenharmony_ci		goto unmap_d;
51962306a36Sopenharmony_ci	}
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	pdb->q_dma = dma_map_single(dev, key->q, q_sz, DMA_TO_DEVICE);
52262306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->q_dma)) {
52362306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA prime factor q memory\n");
52462306a36Sopenharmony_ci		goto unmap_p;
52562306a36Sopenharmony_ci	}
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	pdb->tmp1_dma = dma_map_single(dev, key->tmp1, p_sz, DMA_BIDIRECTIONAL);
52862306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->tmp1_dma)) {
52962306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA tmp1 memory\n");
53062306a36Sopenharmony_ci		goto unmap_q;
53162306a36Sopenharmony_ci	}
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	pdb->tmp2_dma = dma_map_single(dev, key->tmp2, q_sz, DMA_BIDIRECTIONAL);
53462306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->tmp2_dma)) {
53562306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA tmp2 memory\n");
53662306a36Sopenharmony_ci		goto unmap_tmp1;
53762306a36Sopenharmony_ci	}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	if (edesc->mapped_src_nents > 1) {
54062306a36Sopenharmony_ci		pdb->sgf |= RSA_PRIV_PDB_SGF_G;
54162306a36Sopenharmony_ci		pdb->g_dma = edesc->sec4_sg_dma;
54262306a36Sopenharmony_ci		sec4_sg_index += edesc->mapped_src_nents;
54362306a36Sopenharmony_ci	} else {
54462306a36Sopenharmony_ci		struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci		pdb->g_dma = sg_dma_address(req_ctx->fixup_src);
54762306a36Sopenharmony_ci	}
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	if (edesc->mapped_dst_nents > 1) {
55062306a36Sopenharmony_ci		pdb->sgf |= RSA_PRIV_PDB_SGF_F;
55162306a36Sopenharmony_ci		pdb->f_dma = edesc->sec4_sg_dma +
55262306a36Sopenharmony_ci			     sec4_sg_index * sizeof(struct sec4_sg_entry);
55362306a36Sopenharmony_ci	} else {
55462306a36Sopenharmony_ci		pdb->f_dma = sg_dma_address(req->dst);
55562306a36Sopenharmony_ci	}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	pdb->sgf |= (key->d_sz << RSA_PDB_D_SHIFT) | key->n_sz;
55862306a36Sopenharmony_ci	pdb->p_q_len = (q_sz << RSA_PDB_Q_SHIFT) | p_sz;
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	return 0;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ciunmap_tmp1:
56362306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL);
56462306a36Sopenharmony_ciunmap_q:
56562306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE);
56662306a36Sopenharmony_ciunmap_p:
56762306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE);
56862306a36Sopenharmony_ciunmap_d:
56962306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->d_dma, key->d_sz, DMA_TO_DEVICE);
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	return -ENOMEM;
57262306a36Sopenharmony_ci}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_cistatic int set_rsa_priv_f3_pdb(struct akcipher_request *req,
57562306a36Sopenharmony_ci			       struct rsa_edesc *edesc)
57662306a36Sopenharmony_ci{
57762306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
57862306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
57962306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
58062306a36Sopenharmony_ci	struct device *dev = ctx->dev;
58162306a36Sopenharmony_ci	struct rsa_priv_f3_pdb *pdb = &edesc->pdb.priv_f3;
58262306a36Sopenharmony_ci	int sec4_sg_index = 0;
58362306a36Sopenharmony_ci	size_t p_sz = key->p_sz;
58462306a36Sopenharmony_ci	size_t q_sz = key->q_sz;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	pdb->p_dma = dma_map_single(dev, key->p, p_sz, DMA_TO_DEVICE);
58762306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->p_dma)) {
58862306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA prime factor p memory\n");
58962306a36Sopenharmony_ci		return -ENOMEM;
59062306a36Sopenharmony_ci	}
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	pdb->q_dma = dma_map_single(dev, key->q, q_sz, DMA_TO_DEVICE);
59362306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->q_dma)) {
59462306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA prime factor q memory\n");
59562306a36Sopenharmony_ci		goto unmap_p;
59662306a36Sopenharmony_ci	}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	pdb->dp_dma = dma_map_single(dev, key->dp, p_sz, DMA_TO_DEVICE);
59962306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->dp_dma)) {
60062306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA exponent dp memory\n");
60162306a36Sopenharmony_ci		goto unmap_q;
60262306a36Sopenharmony_ci	}
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	pdb->dq_dma = dma_map_single(dev, key->dq, q_sz, DMA_TO_DEVICE);
60562306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->dq_dma)) {
60662306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA exponent dq memory\n");
60762306a36Sopenharmony_ci		goto unmap_dp;
60862306a36Sopenharmony_ci	}
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	pdb->c_dma = dma_map_single(dev, key->qinv, p_sz, DMA_TO_DEVICE);
61162306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->c_dma)) {
61262306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA CRT coefficient qinv memory\n");
61362306a36Sopenharmony_ci		goto unmap_dq;
61462306a36Sopenharmony_ci	}
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	pdb->tmp1_dma = dma_map_single(dev, key->tmp1, p_sz, DMA_BIDIRECTIONAL);
61762306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->tmp1_dma)) {
61862306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA tmp1 memory\n");
61962306a36Sopenharmony_ci		goto unmap_qinv;
62062306a36Sopenharmony_ci	}
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	pdb->tmp2_dma = dma_map_single(dev, key->tmp2, q_sz, DMA_BIDIRECTIONAL);
62362306a36Sopenharmony_ci	if (dma_mapping_error(dev, pdb->tmp2_dma)) {
62462306a36Sopenharmony_ci		dev_err(dev, "Unable to map RSA tmp2 memory\n");
62562306a36Sopenharmony_ci		goto unmap_tmp1;
62662306a36Sopenharmony_ci	}
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	if (edesc->mapped_src_nents > 1) {
62962306a36Sopenharmony_ci		pdb->sgf |= RSA_PRIV_PDB_SGF_G;
63062306a36Sopenharmony_ci		pdb->g_dma = edesc->sec4_sg_dma;
63162306a36Sopenharmony_ci		sec4_sg_index += edesc->mapped_src_nents;
63262306a36Sopenharmony_ci	} else {
63362306a36Sopenharmony_ci		struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci		pdb->g_dma = sg_dma_address(req_ctx->fixup_src);
63662306a36Sopenharmony_ci	}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci	if (edesc->mapped_dst_nents > 1) {
63962306a36Sopenharmony_ci		pdb->sgf |= RSA_PRIV_PDB_SGF_F;
64062306a36Sopenharmony_ci		pdb->f_dma = edesc->sec4_sg_dma +
64162306a36Sopenharmony_ci			     sec4_sg_index * sizeof(struct sec4_sg_entry);
64262306a36Sopenharmony_ci	} else {
64362306a36Sopenharmony_ci		pdb->f_dma = sg_dma_address(req->dst);
64462306a36Sopenharmony_ci	}
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	pdb->sgf |= key->n_sz;
64762306a36Sopenharmony_ci	pdb->p_q_len = (q_sz << RSA_PDB_Q_SHIFT) | p_sz;
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci	return 0;
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ciunmap_tmp1:
65262306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL);
65362306a36Sopenharmony_ciunmap_qinv:
65462306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->c_dma, p_sz, DMA_TO_DEVICE);
65562306a36Sopenharmony_ciunmap_dq:
65662306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->dq_dma, q_sz, DMA_TO_DEVICE);
65762306a36Sopenharmony_ciunmap_dp:
65862306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->dp_dma, p_sz, DMA_TO_DEVICE);
65962306a36Sopenharmony_ciunmap_q:
66062306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE);
66162306a36Sopenharmony_ciunmap_p:
66262306a36Sopenharmony_ci	dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE);
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	return -ENOMEM;
66562306a36Sopenharmony_ci}
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_cistatic int akcipher_enqueue_req(struct device *jrdev,
66862306a36Sopenharmony_ci				void (*cbk)(struct device *jrdev, u32 *desc,
66962306a36Sopenharmony_ci					    u32 err, void *context),
67062306a36Sopenharmony_ci				struct akcipher_request *req)
67162306a36Sopenharmony_ci{
67262306a36Sopenharmony_ci	struct caam_drv_private_jr *jrpriv = dev_get_drvdata(jrdev);
67362306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
67462306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
67562306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
67662306a36Sopenharmony_ci	struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req);
67762306a36Sopenharmony_ci	struct rsa_edesc *edesc = req_ctx->edesc;
67862306a36Sopenharmony_ci	u32 *desc = edesc->hw_desc;
67962306a36Sopenharmony_ci	int ret;
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	req_ctx->akcipher_op_done = cbk;
68262306a36Sopenharmony_ci	/*
68362306a36Sopenharmony_ci	 * Only the backlog request are sent to crypto-engine since the others
68462306a36Sopenharmony_ci	 * can be handled by CAAM, if free, especially since JR has up to 1024
68562306a36Sopenharmony_ci	 * entries (more than the 10 entries from crypto-engine).
68662306a36Sopenharmony_ci	 */
68762306a36Sopenharmony_ci	if (req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)
68862306a36Sopenharmony_ci		ret = crypto_transfer_akcipher_request_to_engine(jrpriv->engine,
68962306a36Sopenharmony_ci								 req);
69062306a36Sopenharmony_ci	else
69162306a36Sopenharmony_ci		ret = caam_jr_enqueue(jrdev, desc, cbk, req);
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	if ((ret != -EINPROGRESS) && (ret != -EBUSY)) {
69462306a36Sopenharmony_ci		switch (key->priv_form) {
69562306a36Sopenharmony_ci		case FORM1:
69662306a36Sopenharmony_ci			rsa_priv_f1_unmap(jrdev, edesc, req);
69762306a36Sopenharmony_ci			break;
69862306a36Sopenharmony_ci		case FORM2:
69962306a36Sopenharmony_ci			rsa_priv_f2_unmap(jrdev, edesc, req);
70062306a36Sopenharmony_ci			break;
70162306a36Sopenharmony_ci		case FORM3:
70262306a36Sopenharmony_ci			rsa_priv_f3_unmap(jrdev, edesc, req);
70362306a36Sopenharmony_ci			break;
70462306a36Sopenharmony_ci		default:
70562306a36Sopenharmony_ci			rsa_pub_unmap(jrdev, edesc, req);
70662306a36Sopenharmony_ci		}
70762306a36Sopenharmony_ci		rsa_io_unmap(jrdev, edesc, req);
70862306a36Sopenharmony_ci		kfree(edesc);
70962306a36Sopenharmony_ci	}
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	return ret;
71262306a36Sopenharmony_ci}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_cistatic int caam_rsa_enc(struct akcipher_request *req)
71562306a36Sopenharmony_ci{
71662306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
71762306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
71862306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
71962306a36Sopenharmony_ci	struct device *jrdev = ctx->dev;
72062306a36Sopenharmony_ci	struct rsa_edesc *edesc;
72162306a36Sopenharmony_ci	int ret;
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ci	if (unlikely(!key->n || !key->e))
72462306a36Sopenharmony_ci		return -EINVAL;
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	if (req->dst_len < key->n_sz) {
72762306a36Sopenharmony_ci		req->dst_len = key->n_sz;
72862306a36Sopenharmony_ci		dev_err(jrdev, "Output buffer length less than parameter n\n");
72962306a36Sopenharmony_ci		return -EOVERFLOW;
73062306a36Sopenharmony_ci	}
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	/* Allocate extended descriptor */
73362306a36Sopenharmony_ci	edesc = rsa_edesc_alloc(req, DESC_RSA_PUB_LEN);
73462306a36Sopenharmony_ci	if (IS_ERR(edesc))
73562306a36Sopenharmony_ci		return PTR_ERR(edesc);
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	/* Set RSA Encrypt Protocol Data Block */
73862306a36Sopenharmony_ci	ret = set_rsa_pub_pdb(req, edesc);
73962306a36Sopenharmony_ci	if (ret)
74062306a36Sopenharmony_ci		goto init_fail;
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	/* Initialize Job Descriptor */
74362306a36Sopenharmony_ci	init_rsa_pub_desc(edesc->hw_desc, &edesc->pdb.pub);
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	return akcipher_enqueue_req(jrdev, rsa_pub_done, req);
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ciinit_fail:
74862306a36Sopenharmony_ci	rsa_io_unmap(jrdev, edesc, req);
74962306a36Sopenharmony_ci	kfree(edesc);
75062306a36Sopenharmony_ci	return ret;
75162306a36Sopenharmony_ci}
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_cistatic int caam_rsa_dec_priv_f1(struct akcipher_request *req)
75462306a36Sopenharmony_ci{
75562306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
75662306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
75762306a36Sopenharmony_ci	struct device *jrdev = ctx->dev;
75862306a36Sopenharmony_ci	struct rsa_edesc *edesc;
75962306a36Sopenharmony_ci	int ret;
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci	/* Allocate extended descriptor */
76262306a36Sopenharmony_ci	edesc = rsa_edesc_alloc(req, DESC_RSA_PRIV_F1_LEN);
76362306a36Sopenharmony_ci	if (IS_ERR(edesc))
76462306a36Sopenharmony_ci		return PTR_ERR(edesc);
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci	/* Set RSA Decrypt Protocol Data Block - Private Key Form #1 */
76762306a36Sopenharmony_ci	ret = set_rsa_priv_f1_pdb(req, edesc);
76862306a36Sopenharmony_ci	if (ret)
76962306a36Sopenharmony_ci		goto init_fail;
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	/* Initialize Job Descriptor */
77262306a36Sopenharmony_ci	init_rsa_priv_f1_desc(edesc->hw_desc, &edesc->pdb.priv_f1);
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	return akcipher_enqueue_req(jrdev, rsa_priv_f_done, req);
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ciinit_fail:
77762306a36Sopenharmony_ci	rsa_io_unmap(jrdev, edesc, req);
77862306a36Sopenharmony_ci	kfree(edesc);
77962306a36Sopenharmony_ci	return ret;
78062306a36Sopenharmony_ci}
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_cistatic int caam_rsa_dec_priv_f2(struct akcipher_request *req)
78362306a36Sopenharmony_ci{
78462306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
78562306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
78662306a36Sopenharmony_ci	struct device *jrdev = ctx->dev;
78762306a36Sopenharmony_ci	struct rsa_edesc *edesc;
78862306a36Sopenharmony_ci	int ret;
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	/* Allocate extended descriptor */
79162306a36Sopenharmony_ci	edesc = rsa_edesc_alloc(req, DESC_RSA_PRIV_F2_LEN);
79262306a36Sopenharmony_ci	if (IS_ERR(edesc))
79362306a36Sopenharmony_ci		return PTR_ERR(edesc);
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	/* Set RSA Decrypt Protocol Data Block - Private Key Form #2 */
79662306a36Sopenharmony_ci	ret = set_rsa_priv_f2_pdb(req, edesc);
79762306a36Sopenharmony_ci	if (ret)
79862306a36Sopenharmony_ci		goto init_fail;
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	/* Initialize Job Descriptor */
80162306a36Sopenharmony_ci	init_rsa_priv_f2_desc(edesc->hw_desc, &edesc->pdb.priv_f2);
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	return akcipher_enqueue_req(jrdev, rsa_priv_f_done, req);
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ciinit_fail:
80662306a36Sopenharmony_ci	rsa_io_unmap(jrdev, edesc, req);
80762306a36Sopenharmony_ci	kfree(edesc);
80862306a36Sopenharmony_ci	return ret;
80962306a36Sopenharmony_ci}
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_cistatic int caam_rsa_dec_priv_f3(struct akcipher_request *req)
81262306a36Sopenharmony_ci{
81362306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
81462306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
81562306a36Sopenharmony_ci	struct device *jrdev = ctx->dev;
81662306a36Sopenharmony_ci	struct rsa_edesc *edesc;
81762306a36Sopenharmony_ci	int ret;
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci	/* Allocate extended descriptor */
82062306a36Sopenharmony_ci	edesc = rsa_edesc_alloc(req, DESC_RSA_PRIV_F3_LEN);
82162306a36Sopenharmony_ci	if (IS_ERR(edesc))
82262306a36Sopenharmony_ci		return PTR_ERR(edesc);
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	/* Set RSA Decrypt Protocol Data Block - Private Key Form #3 */
82562306a36Sopenharmony_ci	ret = set_rsa_priv_f3_pdb(req, edesc);
82662306a36Sopenharmony_ci	if (ret)
82762306a36Sopenharmony_ci		goto init_fail;
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	/* Initialize Job Descriptor */
83062306a36Sopenharmony_ci	init_rsa_priv_f3_desc(edesc->hw_desc, &edesc->pdb.priv_f3);
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	return akcipher_enqueue_req(jrdev, rsa_priv_f_done, req);
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ciinit_fail:
83562306a36Sopenharmony_ci	rsa_io_unmap(jrdev, edesc, req);
83662306a36Sopenharmony_ci	kfree(edesc);
83762306a36Sopenharmony_ci	return ret;
83862306a36Sopenharmony_ci}
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_cistatic int caam_rsa_dec(struct akcipher_request *req)
84162306a36Sopenharmony_ci{
84262306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
84362306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
84462306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
84562306a36Sopenharmony_ci	int ret;
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	if (unlikely(!key->n || !key->d))
84862306a36Sopenharmony_ci		return -EINVAL;
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	if (req->dst_len < key->n_sz) {
85162306a36Sopenharmony_ci		req->dst_len = key->n_sz;
85262306a36Sopenharmony_ci		dev_err(ctx->dev, "Output buffer length less than parameter n\n");
85362306a36Sopenharmony_ci		return -EOVERFLOW;
85462306a36Sopenharmony_ci	}
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	if (key->priv_form == FORM3)
85762306a36Sopenharmony_ci		ret = caam_rsa_dec_priv_f3(req);
85862306a36Sopenharmony_ci	else if (key->priv_form == FORM2)
85962306a36Sopenharmony_ci		ret = caam_rsa_dec_priv_f2(req);
86062306a36Sopenharmony_ci	else
86162306a36Sopenharmony_ci		ret = caam_rsa_dec_priv_f1(req);
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci	return ret;
86462306a36Sopenharmony_ci}
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_cistatic void caam_rsa_free_key(struct caam_rsa_key *key)
86762306a36Sopenharmony_ci{
86862306a36Sopenharmony_ci	kfree_sensitive(key->d);
86962306a36Sopenharmony_ci	kfree_sensitive(key->p);
87062306a36Sopenharmony_ci	kfree_sensitive(key->q);
87162306a36Sopenharmony_ci	kfree_sensitive(key->dp);
87262306a36Sopenharmony_ci	kfree_sensitive(key->dq);
87362306a36Sopenharmony_ci	kfree_sensitive(key->qinv);
87462306a36Sopenharmony_ci	kfree_sensitive(key->tmp1);
87562306a36Sopenharmony_ci	kfree_sensitive(key->tmp2);
87662306a36Sopenharmony_ci	kfree(key->e);
87762306a36Sopenharmony_ci	kfree(key->n);
87862306a36Sopenharmony_ci	memset(key, 0, sizeof(*key));
87962306a36Sopenharmony_ci}
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_cistatic void caam_rsa_drop_leading_zeros(const u8 **ptr, size_t *nbytes)
88262306a36Sopenharmony_ci{
88362306a36Sopenharmony_ci	while (!**ptr && *nbytes) {
88462306a36Sopenharmony_ci		(*ptr)++;
88562306a36Sopenharmony_ci		(*nbytes)--;
88662306a36Sopenharmony_ci	}
88762306a36Sopenharmony_ci}
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci/**
89062306a36Sopenharmony_ci * caam_read_rsa_crt - Used for reading dP, dQ, qInv CRT members.
89162306a36Sopenharmony_ci * dP, dQ and qInv could decode to less than corresponding p, q length, as the
89262306a36Sopenharmony_ci * BER-encoding requires that the minimum number of bytes be used to encode the
89362306a36Sopenharmony_ci * integer. dP, dQ, qInv decoded values have to be zero-padded to appropriate
89462306a36Sopenharmony_ci * length.
89562306a36Sopenharmony_ci *
89662306a36Sopenharmony_ci * @ptr   : pointer to {dP, dQ, qInv} CRT member
89762306a36Sopenharmony_ci * @nbytes: length in bytes of {dP, dQ, qInv} CRT member
89862306a36Sopenharmony_ci * @dstlen: length in bytes of corresponding p or q prime factor
89962306a36Sopenharmony_ci */
90062306a36Sopenharmony_cistatic u8 *caam_read_rsa_crt(const u8 *ptr, size_t nbytes, size_t dstlen)
90162306a36Sopenharmony_ci{
90262306a36Sopenharmony_ci	u8 *dst;
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	caam_rsa_drop_leading_zeros(&ptr, &nbytes);
90562306a36Sopenharmony_ci	if (!nbytes)
90662306a36Sopenharmony_ci		return NULL;
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci	dst = kzalloc(dstlen, GFP_KERNEL);
90962306a36Sopenharmony_ci	if (!dst)
91062306a36Sopenharmony_ci		return NULL;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	memcpy(dst + (dstlen - nbytes), ptr, nbytes);
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	return dst;
91562306a36Sopenharmony_ci}
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci/**
91862306a36Sopenharmony_ci * caam_read_raw_data - Read a raw byte stream as a positive integer.
91962306a36Sopenharmony_ci * The function skips buffer's leading zeros, copies the remained data
92062306a36Sopenharmony_ci * to a buffer allocated in the GFP_KERNEL zone and returns
92162306a36Sopenharmony_ci * the address of the new buffer.
92262306a36Sopenharmony_ci *
92362306a36Sopenharmony_ci * @buf   : The data to read
92462306a36Sopenharmony_ci * @nbytes: The amount of data to read
92562306a36Sopenharmony_ci */
92662306a36Sopenharmony_cistatic inline u8 *caam_read_raw_data(const u8 *buf, size_t *nbytes)
92762306a36Sopenharmony_ci{
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci	caam_rsa_drop_leading_zeros(&buf, nbytes);
93062306a36Sopenharmony_ci	if (!*nbytes)
93162306a36Sopenharmony_ci		return NULL;
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci	return kmemdup(buf, *nbytes, GFP_KERNEL);
93462306a36Sopenharmony_ci}
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_cistatic int caam_rsa_check_key_length(unsigned int len)
93762306a36Sopenharmony_ci{
93862306a36Sopenharmony_ci	if (len > 4096)
93962306a36Sopenharmony_ci		return -EINVAL;
94062306a36Sopenharmony_ci	return 0;
94162306a36Sopenharmony_ci}
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_cistatic int caam_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
94462306a36Sopenharmony_ci				unsigned int keylen)
94562306a36Sopenharmony_ci{
94662306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
94762306a36Sopenharmony_ci	struct rsa_key raw_key = {NULL};
94862306a36Sopenharmony_ci	struct caam_rsa_key *rsa_key = &ctx->key;
94962306a36Sopenharmony_ci	int ret;
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci	/* Free the old RSA key if any */
95262306a36Sopenharmony_ci	caam_rsa_free_key(rsa_key);
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_ci	ret = rsa_parse_pub_key(&raw_key, key, keylen);
95562306a36Sopenharmony_ci	if (ret)
95662306a36Sopenharmony_ci		return ret;
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci	/* Copy key in DMA zone */
95962306a36Sopenharmony_ci	rsa_key->e = kmemdup(raw_key.e, raw_key.e_sz, GFP_KERNEL);
96062306a36Sopenharmony_ci	if (!rsa_key->e)
96162306a36Sopenharmony_ci		goto err;
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci	/*
96462306a36Sopenharmony_ci	 * Skip leading zeros and copy the positive integer to a buffer
96562306a36Sopenharmony_ci	 * allocated in the GFP_KERNEL zone. The decryption descriptor
96662306a36Sopenharmony_ci	 * expects a positive integer for the RSA modulus and uses its length as
96762306a36Sopenharmony_ci	 * decryption output length.
96862306a36Sopenharmony_ci	 */
96962306a36Sopenharmony_ci	rsa_key->n = caam_read_raw_data(raw_key.n, &raw_key.n_sz);
97062306a36Sopenharmony_ci	if (!rsa_key->n)
97162306a36Sopenharmony_ci		goto err;
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	if (caam_rsa_check_key_length(raw_key.n_sz << 3)) {
97462306a36Sopenharmony_ci		caam_rsa_free_key(rsa_key);
97562306a36Sopenharmony_ci		return -EINVAL;
97662306a36Sopenharmony_ci	}
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	rsa_key->e_sz = raw_key.e_sz;
97962306a36Sopenharmony_ci	rsa_key->n_sz = raw_key.n_sz;
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	return 0;
98262306a36Sopenharmony_cierr:
98362306a36Sopenharmony_ci	caam_rsa_free_key(rsa_key);
98462306a36Sopenharmony_ci	return -ENOMEM;
98562306a36Sopenharmony_ci}
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_cistatic void caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx,
98862306a36Sopenharmony_ci				       struct rsa_key *raw_key)
98962306a36Sopenharmony_ci{
99062306a36Sopenharmony_ci	struct caam_rsa_key *rsa_key = &ctx->key;
99162306a36Sopenharmony_ci	size_t p_sz = raw_key->p_sz;
99262306a36Sopenharmony_ci	size_t q_sz = raw_key->q_sz;
99362306a36Sopenharmony_ci	unsigned aligned_size;
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci	rsa_key->p = caam_read_raw_data(raw_key->p, &p_sz);
99662306a36Sopenharmony_ci	if (!rsa_key->p)
99762306a36Sopenharmony_ci		return;
99862306a36Sopenharmony_ci	rsa_key->p_sz = p_sz;
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci	rsa_key->q = caam_read_raw_data(raw_key->q, &q_sz);
100162306a36Sopenharmony_ci	if (!rsa_key->q)
100262306a36Sopenharmony_ci		goto free_p;
100362306a36Sopenharmony_ci	rsa_key->q_sz = q_sz;
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci	aligned_size = ALIGN(raw_key->p_sz, dma_get_cache_alignment());
100662306a36Sopenharmony_ci	rsa_key->tmp1 = kzalloc(aligned_size, GFP_KERNEL);
100762306a36Sopenharmony_ci	if (!rsa_key->tmp1)
100862306a36Sopenharmony_ci		goto free_q;
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	aligned_size = ALIGN(raw_key->q_sz, dma_get_cache_alignment());
101162306a36Sopenharmony_ci	rsa_key->tmp2 = kzalloc(aligned_size, GFP_KERNEL);
101262306a36Sopenharmony_ci	if (!rsa_key->tmp2)
101362306a36Sopenharmony_ci		goto free_tmp1;
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci	rsa_key->priv_form = FORM2;
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci	rsa_key->dp = caam_read_rsa_crt(raw_key->dp, raw_key->dp_sz, p_sz);
101862306a36Sopenharmony_ci	if (!rsa_key->dp)
101962306a36Sopenharmony_ci		goto free_tmp2;
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci	rsa_key->dq = caam_read_rsa_crt(raw_key->dq, raw_key->dq_sz, q_sz);
102262306a36Sopenharmony_ci	if (!rsa_key->dq)
102362306a36Sopenharmony_ci		goto free_dp;
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci	rsa_key->qinv = caam_read_rsa_crt(raw_key->qinv, raw_key->qinv_sz,
102662306a36Sopenharmony_ci					  q_sz);
102762306a36Sopenharmony_ci	if (!rsa_key->qinv)
102862306a36Sopenharmony_ci		goto free_dq;
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci	rsa_key->priv_form = FORM3;
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci	return;
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_cifree_dq:
103562306a36Sopenharmony_ci	kfree_sensitive(rsa_key->dq);
103662306a36Sopenharmony_cifree_dp:
103762306a36Sopenharmony_ci	kfree_sensitive(rsa_key->dp);
103862306a36Sopenharmony_cifree_tmp2:
103962306a36Sopenharmony_ci	kfree_sensitive(rsa_key->tmp2);
104062306a36Sopenharmony_cifree_tmp1:
104162306a36Sopenharmony_ci	kfree_sensitive(rsa_key->tmp1);
104262306a36Sopenharmony_cifree_q:
104362306a36Sopenharmony_ci	kfree_sensitive(rsa_key->q);
104462306a36Sopenharmony_cifree_p:
104562306a36Sopenharmony_ci	kfree_sensitive(rsa_key->p);
104662306a36Sopenharmony_ci}
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_cistatic int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
104962306a36Sopenharmony_ci				 unsigned int keylen)
105062306a36Sopenharmony_ci{
105162306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
105262306a36Sopenharmony_ci	struct rsa_key raw_key = {NULL};
105362306a36Sopenharmony_ci	struct caam_rsa_key *rsa_key = &ctx->key;
105462306a36Sopenharmony_ci	int ret;
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	/* Free the old RSA key if any */
105762306a36Sopenharmony_ci	caam_rsa_free_key(rsa_key);
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	ret = rsa_parse_priv_key(&raw_key, key, keylen);
106062306a36Sopenharmony_ci	if (ret)
106162306a36Sopenharmony_ci		return ret;
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	/* Copy key in DMA zone */
106462306a36Sopenharmony_ci	rsa_key->d = kmemdup(raw_key.d, raw_key.d_sz, GFP_KERNEL);
106562306a36Sopenharmony_ci	if (!rsa_key->d)
106662306a36Sopenharmony_ci		goto err;
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci	rsa_key->e = kmemdup(raw_key.e, raw_key.e_sz, GFP_KERNEL);
106962306a36Sopenharmony_ci	if (!rsa_key->e)
107062306a36Sopenharmony_ci		goto err;
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci	/*
107362306a36Sopenharmony_ci	 * Skip leading zeros and copy the positive integer to a buffer
107462306a36Sopenharmony_ci	 * allocated in the GFP_KERNEL zone. The decryption descriptor
107562306a36Sopenharmony_ci	 * expects a positive integer for the RSA modulus and uses its length as
107662306a36Sopenharmony_ci	 * decryption output length.
107762306a36Sopenharmony_ci	 */
107862306a36Sopenharmony_ci	rsa_key->n = caam_read_raw_data(raw_key.n, &raw_key.n_sz);
107962306a36Sopenharmony_ci	if (!rsa_key->n)
108062306a36Sopenharmony_ci		goto err;
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	if (caam_rsa_check_key_length(raw_key.n_sz << 3)) {
108362306a36Sopenharmony_ci		caam_rsa_free_key(rsa_key);
108462306a36Sopenharmony_ci		return -EINVAL;
108562306a36Sopenharmony_ci	}
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci	rsa_key->d_sz = raw_key.d_sz;
108862306a36Sopenharmony_ci	rsa_key->e_sz = raw_key.e_sz;
108962306a36Sopenharmony_ci	rsa_key->n_sz = raw_key.n_sz;
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci	caam_rsa_set_priv_key_form(ctx, &raw_key);
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	return 0;
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_cierr:
109662306a36Sopenharmony_ci	caam_rsa_free_key(rsa_key);
109762306a36Sopenharmony_ci	return -ENOMEM;
109862306a36Sopenharmony_ci}
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_cistatic unsigned int caam_rsa_max_size(struct crypto_akcipher *tfm)
110162306a36Sopenharmony_ci{
110262306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	return ctx->key.n_sz;
110562306a36Sopenharmony_ci}
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci/* Per session pkc's driver context creation function */
110862306a36Sopenharmony_cistatic int caam_rsa_init_tfm(struct crypto_akcipher *tfm)
110962306a36Sopenharmony_ci{
111062306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	akcipher_set_reqsize(tfm, sizeof(struct caam_rsa_req_ctx));
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci	ctx->dev = caam_jr_alloc();
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_ci	if (IS_ERR(ctx->dev)) {
111762306a36Sopenharmony_ci		pr_err("Job Ring Device allocation for transform failed\n");
111862306a36Sopenharmony_ci		return PTR_ERR(ctx->dev);
111962306a36Sopenharmony_ci	}
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	ctx->padding_dma = dma_map_single(ctx->dev, zero_buffer,
112262306a36Sopenharmony_ci					  CAAM_RSA_MAX_INPUT_SIZE - 1,
112362306a36Sopenharmony_ci					  DMA_TO_DEVICE);
112462306a36Sopenharmony_ci	if (dma_mapping_error(ctx->dev, ctx->padding_dma)) {
112562306a36Sopenharmony_ci		dev_err(ctx->dev, "unable to map padding\n");
112662306a36Sopenharmony_ci		caam_jr_free(ctx->dev);
112762306a36Sopenharmony_ci		return -ENOMEM;
112862306a36Sopenharmony_ci	}
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	return 0;
113162306a36Sopenharmony_ci}
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_ci/* Per session pkc's driver context cleanup function */
113462306a36Sopenharmony_cistatic void caam_rsa_exit_tfm(struct crypto_akcipher *tfm)
113562306a36Sopenharmony_ci{
113662306a36Sopenharmony_ci	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx_dma(tfm);
113762306a36Sopenharmony_ci	struct caam_rsa_key *key = &ctx->key;
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci	dma_unmap_single(ctx->dev, ctx->padding_dma, CAAM_RSA_MAX_INPUT_SIZE -
114062306a36Sopenharmony_ci			 1, DMA_TO_DEVICE);
114162306a36Sopenharmony_ci	caam_rsa_free_key(key);
114262306a36Sopenharmony_ci	caam_jr_free(ctx->dev);
114362306a36Sopenharmony_ci}
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_cistatic struct caam_akcipher_alg caam_rsa = {
114662306a36Sopenharmony_ci	.akcipher.base = {
114762306a36Sopenharmony_ci		.encrypt = caam_rsa_enc,
114862306a36Sopenharmony_ci		.decrypt = caam_rsa_dec,
114962306a36Sopenharmony_ci		.set_pub_key = caam_rsa_set_pub_key,
115062306a36Sopenharmony_ci		.set_priv_key = caam_rsa_set_priv_key,
115162306a36Sopenharmony_ci		.max_size = caam_rsa_max_size,
115262306a36Sopenharmony_ci		.init = caam_rsa_init_tfm,
115362306a36Sopenharmony_ci		.exit = caam_rsa_exit_tfm,
115462306a36Sopenharmony_ci		.base = {
115562306a36Sopenharmony_ci			.cra_name = "rsa",
115662306a36Sopenharmony_ci			.cra_driver_name = "rsa-caam",
115762306a36Sopenharmony_ci			.cra_priority = 3000,
115862306a36Sopenharmony_ci			.cra_module = THIS_MODULE,
115962306a36Sopenharmony_ci			.cra_ctxsize = sizeof(struct caam_rsa_ctx) +
116062306a36Sopenharmony_ci				       CRYPTO_DMA_PADDING,
116162306a36Sopenharmony_ci		},
116262306a36Sopenharmony_ci	},
116362306a36Sopenharmony_ci	.akcipher.op = {
116462306a36Sopenharmony_ci		.do_one_request = akcipher_do_one_req,
116562306a36Sopenharmony_ci	},
116662306a36Sopenharmony_ci};
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci/* Public Key Cryptography module initialization handler */
116962306a36Sopenharmony_ciint caam_pkc_init(struct device *ctrldev)
117062306a36Sopenharmony_ci{
117162306a36Sopenharmony_ci	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
117262306a36Sopenharmony_ci	u32 pk_inst, pkha;
117362306a36Sopenharmony_ci	int err;
117462306a36Sopenharmony_ci	init_done = false;
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci	/* Determine public key hardware accelerator presence. */
117762306a36Sopenharmony_ci	if (priv->era < 10) {
117862306a36Sopenharmony_ci		pk_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) &
117962306a36Sopenharmony_ci			   CHA_ID_LS_PK_MASK) >> CHA_ID_LS_PK_SHIFT;
118062306a36Sopenharmony_ci	} else {
118162306a36Sopenharmony_ci		pkha = rd_reg32(&priv->jr[0]->vreg.pkha);
118262306a36Sopenharmony_ci		pk_inst = pkha & CHA_VER_NUM_MASK;
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci		/*
118562306a36Sopenharmony_ci		 * Newer CAAMs support partially disabled functionality. If this is the
118662306a36Sopenharmony_ci		 * case, the number is non-zero, but this bit is set to indicate that
118762306a36Sopenharmony_ci		 * no encryption or decryption is supported. Only signing and verifying
118862306a36Sopenharmony_ci		 * is supported.
118962306a36Sopenharmony_ci		 */
119062306a36Sopenharmony_ci		if (pkha & CHA_VER_MISC_PKHA_NO_CRYPT)
119162306a36Sopenharmony_ci			pk_inst = 0;
119262306a36Sopenharmony_ci	}
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci	/* Do not register algorithms if PKHA is not present. */
119562306a36Sopenharmony_ci	if (!pk_inst)
119662306a36Sopenharmony_ci		return 0;
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci	/* allocate zero buffer, used for padding input */
119962306a36Sopenharmony_ci	zero_buffer = kzalloc(CAAM_RSA_MAX_INPUT_SIZE - 1, GFP_KERNEL);
120062306a36Sopenharmony_ci	if (!zero_buffer)
120162306a36Sopenharmony_ci		return -ENOMEM;
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	err = crypto_engine_register_akcipher(&caam_rsa.akcipher);
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci	if (err) {
120662306a36Sopenharmony_ci		kfree(zero_buffer);
120762306a36Sopenharmony_ci		dev_warn(ctrldev, "%s alg registration failed\n",
120862306a36Sopenharmony_ci			 caam_rsa.akcipher.base.base.cra_driver_name);
120962306a36Sopenharmony_ci	} else {
121062306a36Sopenharmony_ci		init_done = true;
121162306a36Sopenharmony_ci		caam_rsa.registered = true;
121262306a36Sopenharmony_ci		dev_info(ctrldev, "caam pkc algorithms registered in /proc/crypto\n");
121362306a36Sopenharmony_ci	}
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	return err;
121662306a36Sopenharmony_ci}
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_civoid caam_pkc_exit(void)
121962306a36Sopenharmony_ci{
122062306a36Sopenharmony_ci	if (!init_done)
122162306a36Sopenharmony_ci		return;
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci	if (caam_rsa.registered)
122462306a36Sopenharmony_ci		crypto_engine_unregister_akcipher(&caam_rsa.akcipher);
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	kfree(zero_buffer);
122762306a36Sopenharmony_ci}
1228