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