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