From patchwork Tue May 28 09:52:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Iuliana Prodan X-Patchwork-Id: 10964501 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9AC2E6C5 for ; Tue, 28 May 2019 09:52:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8AF0528501 for ; Tue, 28 May 2019 09:52:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7F730286BC; Tue, 28 May 2019 09:52:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DEC4628501 for ; Tue, 28 May 2019 09:52:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726711AbfE1JwS (ORCPT ); Tue, 28 May 2019 05:52:18 -0400 Received: from inva021.nxp.com ([92.121.34.21]:58686 "EHLO inva021.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726203AbfE1JwS (ORCPT ); Tue, 28 May 2019 05:52:18 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 114BE200DED; Tue, 28 May 2019 11:52:15 +0200 (CEST) Received: from inva024.eu-rdc02.nxp.com (inva024.eu-rdc02.nxp.com [134.27.226.22]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 03288200123; Tue, 28 May 2019 11:52:15 +0200 (CEST) Received: from lorenz.ea.freescale.net (lorenz.ea.freescale.net [10.171.71.5]) by inva024.eu-rdc02.nxp.com (Postfix) with ESMTP id AC472205F4; Tue, 28 May 2019 11:52:14 +0200 (CEST) From: Iuliana Prodan To: Herbert Xu , Horia Geanta , Aymen Sghaier Cc: "David S. Miller" , linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, linux-imx Subject: [PATCH v5 1/2] crypto: caam - fix pkcs1pad(rsa-caam, sha256) failure because of invalid input Date: Tue, 28 May 2019 12:52:10 +0300 Message-Id: <1559037131-4601-1-git-send-email-iuliana.prodan@nxp.com> X-Mailer: git-send-email 2.1.0 X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The problem is with the input data size sent to CAAM for encrypt/decrypt. Pkcs1pad is failing due to pkcs1 padding done in SW starting with0x01 instead of 0x00 0x01. CAAM expects an input of modulus size. For this we strip the leading zeros in case the size is more than modulus or pad the input with zeros until the modulus size is reached. Signed-off-by: Iuliana Prodan Reviewed-by: Horia Geantă --- Changes since V4: - return -ENOMEM in case zero_buffer cannot be allocated. --- drivers/crypto/caam/caampkc.c | 89 ++++++++++++++++++++++++++++++++++--------- drivers/crypto/caam/caampkc.h | 2 + 2 files changed, 74 insertions(+), 17 deletions(-) diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index 34e37f9..2bd3a17 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -24,6 +24,10 @@ sizeof(struct rsa_priv_f2_pdb)) #define DESC_RSA_PRIV_F3_LEN (2 * CAAM_CMD_SZ + \ sizeof(struct rsa_priv_f3_pdb)) +#define CAAM_RSA_MAX_INPUT_SIZE 512 /* for a 4096-bit modulus */ + +/* buffer filled with zeros, used for padding */ +static u8 *zero_buffer; static void rsa_io_unmap(struct device *dev, struct rsa_edesc *edesc, struct akcipher_request *req) @@ -168,6 +172,13 @@ static void rsa_priv_f3_done(struct device *dev, u32 *desc, u32 err, akcipher_request_complete(req, err); } +/** + * Count leading zeros, need it to strip, from a given scatterlist + * + * @sgl : scatterlist to count zeros from + * @nbytes: number of zeros, in bytes, to strip + * @flags : operation flags + */ static int caam_rsa_count_leading_zeros(struct scatterlist *sgl, unsigned int nbytes, unsigned int flags) @@ -187,7 +198,8 @@ static int caam_rsa_count_leading_zeros(struct scatterlist *sgl, lzeros = 0; len = 0; while (nbytes > 0) { - while (len && !*buff) { + /* do not strip more than given bytes */ + while (len && !*buff && lzeros < nbytes) { lzeros++; len--; buff++; @@ -218,6 +230,7 @@ static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req, struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm); struct device *dev = ctx->dev; struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req); + struct caam_rsa_key *key = &ctx->key; struct rsa_edesc *edesc; gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : GFP_ATOMIC; @@ -225,21 +238,37 @@ static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req, int sgc; int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes; int src_nents, dst_nents; + unsigned int diff_size = 0; int lzeros; - lzeros = caam_rsa_count_leading_zeros(req->src, req->src_len, sg_flags); - if (lzeros < 0) - return ERR_PTR(lzeros); - - req->src_len -= lzeros; - req->src = scatterwalk_ffwd(req_ctx->src, req->src, lzeros); + if (req->src_len > key->n_sz) { + /* + * strip leading zeros and + * return the number of zeros to skip + */ + lzeros = caam_rsa_count_leading_zeros(req->src, req->src_len - + key->n_sz, sg_flags); + if (lzeros < 0) + return ERR_PTR(lzeros); + + req->src_len -= lzeros; + req->src = scatterwalk_ffwd(req_ctx->src, req->src, lzeros); + } else { + /* + * input src is less then n key modulus, + * so there will be zero padding + */ + diff_size = key->n_sz - req->src_len; + } src_nents = sg_nents_for_len(req->src, req->src_len); dst_nents = sg_nents_for_len(req->dst, req->dst_len); - if (src_nents > 1) - sec4_sg_len = src_nents; - + if (!diff_size && src_nents == 1) + sec4_sg_len = 0; /* no need for an input hw s/g table */ + else + sec4_sg_len = src_nents + !!diff_size; + sec4_sg_index = sec4_sg_len; if (dst_nents > 1) sec4_sg_len += pad_sg_nents(dst_nents); else @@ -266,12 +295,14 @@ static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req, } edesc->sec4_sg = (void *)edesc + sizeof(*edesc) + desclen; + if (diff_size) + dma_to_sec4_sg_one(edesc->sec4_sg, ctx->padding_dma, diff_size, + 0); + + if (sec4_sg_index) + sg_to_sec4_sg_last(req->src, src_nents, edesc->sec4_sg + + !!diff_size, 0); - sec4_sg_index = 0; - if (src_nents > 1) { - sg_to_sec4_sg_last(req->src, src_nents, edesc->sec4_sg, 0); - sec4_sg_index += src_nents; - } if (dst_nents > 1) sg_to_sec4_sg_last(req->dst, dst_nents, edesc->sec4_sg + sec4_sg_index, 0); @@ -292,6 +323,10 @@ static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req, edesc->sec4_sg_bytes = sec4_sg_bytes; + print_hex_dump_debug("caampkc sec4_sg@" __stringify(__LINE__) ": ", + DUMP_PREFIX_ADDRESS, 16, 4, edesc->sec4_sg, + edesc->sec4_sg_bytes, 1); + return edesc; sec4_sg_fail: @@ -981,6 +1016,15 @@ static int caam_rsa_init_tfm(struct crypto_akcipher *tfm) return PTR_ERR(ctx->dev); } + ctx->padding_dma = dma_map_single(ctx->dev, zero_buffer, + CAAM_RSA_MAX_INPUT_SIZE - 1, + DMA_TO_DEVICE); + if (dma_mapping_error(ctx->dev, ctx->padding_dma)) { + dev_err(ctx->dev, "unable to map padding\n"); + caam_jr_free(ctx->dev); + return -ENOMEM; + } + return 0; } @@ -990,6 +1034,8 @@ static void caam_rsa_exit_tfm(struct crypto_akcipher *tfm) struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm); struct caam_rsa_key *key = &ctx->key; + dma_unmap_single(ctx->dev, ctx->padding_dma, CAAM_RSA_MAX_INPUT_SIZE - + 1, DMA_TO_DEVICE); caam_rsa_free_key(key); caam_jr_free(ctx->dev); } @@ -1030,17 +1076,26 @@ int caam_pkc_init(struct device *ctrldev) if (!pk_inst) return 0; + /* allocate zero buffer, used for padding input */ + zero_buffer = kzalloc(CAAM_RSA_MAX_INPUT_SIZE - 1, GFP_DMA | + GFP_KERNEL); + if (!zero_buffer) + return -ENOMEM; + err = crypto_register_akcipher(&caam_rsa); - if (err) + if (err) { + kfree(zero_buffer); dev_warn(ctrldev, "%s alg registration failed\n", caam_rsa.base.cra_driver_name); - else + } else { dev_info(ctrldev, "caam pkc algorithms registered in /proc/crypto\n"); + } return err; } void caam_pkc_exit(void) { + kfree(zero_buffer); crypto_unregister_akcipher(&caam_rsa); } diff --git a/drivers/crypto/caam/caampkc.h b/drivers/crypto/caam/caampkc.h index 82645bc..5ac7201 100644 --- a/drivers/crypto/caam/caampkc.h +++ b/drivers/crypto/caam/caampkc.h @@ -89,10 +89,12 @@ struct caam_rsa_key { * caam_rsa_ctx - per session context. * @key : RSA key in DMA zone * @dev : device structure + * @padding_dma : dma address of padding, for adding it to the input */ struct caam_rsa_ctx { struct caam_rsa_key key; struct device *dev; + dma_addr_t padding_dma; }; /** From patchwork Tue May 28 09:52:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iuliana Prodan X-Patchwork-Id: 10964499 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B9DC56C5 for ; Tue, 28 May 2019 09:52:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AA02E28501 for ; Tue, 28 May 2019 09:52:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9DE15286BC; Tue, 28 May 2019 09:52:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9E8B928501 for ; Tue, 28 May 2019 09:52:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726418AbfE1JwR (ORCPT ); Tue, 28 May 2019 05:52:17 -0400 Received: from inva020.nxp.com ([92.121.34.13]:44018 "EHLO inva020.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726362AbfE1JwR (ORCPT ); Tue, 28 May 2019 05:52:17 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 6AC421A0DFB; Tue, 28 May 2019 11:52:15 +0200 (CEST) Received: from inva024.eu-rdc02.nxp.com (inva024.eu-rdc02.nxp.com [134.27.226.22]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 5E3381A02B9; Tue, 28 May 2019 11:52:15 +0200 (CEST) Received: from lorenz.ea.freescale.net (lorenz.ea.freescale.net [10.171.71.5]) by inva024.eu-rdc02.nxp.com (Postfix) with ESMTP id 11CFF205F4; Tue, 28 May 2019 11:52:15 +0200 (CEST) From: Iuliana Prodan To: Herbert Xu , Horia Geanta , Aymen Sghaier Cc: "David S. Miller" , linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, linux-imx Subject: [PATCH v5 2/2] crypto: caam - strip input without changing crypto request Date: Tue, 28 May 2019 12:52:11 +0300 Message-Id: <1559037131-4601-2-git-send-email-iuliana.prodan@nxp.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1559037131-4601-1-git-send-email-iuliana.prodan@nxp.com> References: <1559037131-4601-1-git-send-email-iuliana.prodan@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP For rsa and pkcs1pad, CAAM expects an input of modulus size. For this we strip the leading zeros in case the size is more than modulus. This commit avoids modifying the crypto request while stripping zeros from input, to comply with the crypto API requirement. This is done by adding a fixup input pointer and length. Signed-off-by: Iuliana Prodan Reviewed-by: Horia Geanta --- Changes since V4: - added Reviewed-by; - changed version to be in sync with patch 1/2. --- drivers/crypto/caam/caampkc.c | 39 ++++++++++++++++++++++++++------------- drivers/crypto/caam/caampkc.h | 7 ++++++- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index 2bd3a17..19b02c1 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -32,8 +32,10 @@ static u8 *zero_buffer; static void rsa_io_unmap(struct device *dev, struct rsa_edesc *edesc, struct akcipher_request *req) { + struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req); + dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE); - dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE); + dma_unmap_sg(dev, req_ctx->fixup_src, edesc->src_nents, DMA_TO_DEVICE); if (edesc->sec4_sg_bytes) dma_unmap_single(dev, edesc->sec4_sg_dma, edesc->sec4_sg_bytes, @@ -251,17 +253,21 @@ static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req, if (lzeros < 0) return ERR_PTR(lzeros); - req->src_len -= lzeros; - req->src = scatterwalk_ffwd(req_ctx->src, req->src, lzeros); + req_ctx->fixup_src = scatterwalk_ffwd(req_ctx->src, req->src, + lzeros); + req_ctx->fixup_src_len = req->src_len - lzeros; } else { /* * input src is less then n key modulus, * so there will be zero padding */ diff_size = key->n_sz - req->src_len; + req_ctx->fixup_src = req->src; + req_ctx->fixup_src_len = req->src_len; } - src_nents = sg_nents_for_len(req->src, req->src_len); + src_nents = sg_nents_for_len(req_ctx->fixup_src, + req_ctx->fixup_src_len); dst_nents = sg_nents_for_len(req->dst, req->dst_len); if (!diff_size && src_nents == 1) @@ -282,7 +288,7 @@ static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req, if (!edesc) return ERR_PTR(-ENOMEM); - sgc = dma_map_sg(dev, req->src, src_nents, DMA_TO_DEVICE); + sgc = dma_map_sg(dev, req_ctx->fixup_src, src_nents, DMA_TO_DEVICE); if (unlikely(!sgc)) { dev_err(dev, "unable to map source\n"); goto src_fail; @@ -300,8 +306,8 @@ static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req, 0); if (sec4_sg_index) - sg_to_sec4_sg_last(req->src, src_nents, edesc->sec4_sg + - !!diff_size, 0); + sg_to_sec4_sg_last(req_ctx->fixup_src, src_nents, + edesc->sec4_sg + !!diff_size, 0); if (dst_nents > 1) sg_to_sec4_sg_last(req->dst, dst_nents, @@ -332,7 +338,7 @@ static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req, sec4_sg_fail: dma_unmap_sg(dev, req->dst, dst_nents, DMA_FROM_DEVICE); dst_fail: - dma_unmap_sg(dev, req->src, src_nents, DMA_TO_DEVICE); + dma_unmap_sg(dev, req_ctx->fixup_src, src_nents, DMA_TO_DEVICE); src_fail: kfree(edesc); return ERR_PTR(-ENOMEM); @@ -342,6 +348,7 @@ static int set_rsa_pub_pdb(struct akcipher_request *req, struct rsa_edesc *edesc) { struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); + struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req); struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm); struct caam_rsa_key *key = &ctx->key; struct device *dev = ctx->dev; @@ -366,7 +373,7 @@ static int set_rsa_pub_pdb(struct akcipher_request *req, pdb->f_dma = edesc->sec4_sg_dma; sec4_sg_index += edesc->src_nents; } else { - pdb->f_dma = sg_dma_address(req->src); + pdb->f_dma = sg_dma_address(req_ctx->fixup_src); } if (edesc->dst_nents > 1) { @@ -378,7 +385,7 @@ static int set_rsa_pub_pdb(struct akcipher_request *req, } pdb->sgf |= (key->e_sz << RSA_PDB_E_SHIFT) | key->n_sz; - pdb->f_len = req->src_len; + pdb->f_len = req_ctx->fixup_src_len; return 0; } @@ -411,7 +418,9 @@ static int set_rsa_priv_f1_pdb(struct akcipher_request *req, pdb->g_dma = edesc->sec4_sg_dma; sec4_sg_index += edesc->src_nents; } else { - pdb->g_dma = sg_dma_address(req->src); + struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req); + + pdb->g_dma = sg_dma_address(req_ctx->fixup_src); } if (edesc->dst_nents > 1) { @@ -474,7 +483,9 @@ static int set_rsa_priv_f2_pdb(struct akcipher_request *req, pdb->g_dma = edesc->sec4_sg_dma; sec4_sg_index += edesc->src_nents; } else { - pdb->g_dma = sg_dma_address(req->src); + struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req); + + pdb->g_dma = sg_dma_address(req_ctx->fixup_src); } if (edesc->dst_nents > 1) { @@ -561,7 +572,9 @@ static int set_rsa_priv_f3_pdb(struct akcipher_request *req, pdb->g_dma = edesc->sec4_sg_dma; sec4_sg_index += edesc->src_nents; } else { - pdb->g_dma = sg_dma_address(req->src); + struct caam_rsa_req_ctx *req_ctx = akcipher_request_ctx(req); + + pdb->g_dma = sg_dma_address(req_ctx->fixup_src); } if (edesc->dst_nents > 1) { diff --git a/drivers/crypto/caam/caampkc.h b/drivers/crypto/caam/caampkc.h index 5ac7201..2c488c9 100644 --- a/drivers/crypto/caam/caampkc.h +++ b/drivers/crypto/caam/caampkc.h @@ -95,14 +95,19 @@ struct caam_rsa_ctx { struct caam_rsa_key key; struct device *dev; dma_addr_t padding_dma; + }; /** * caam_rsa_req_ctx - per request context. - * @src: input scatterlist (stripped of leading zeros) + * @src : input scatterlist (stripped of leading zeros) + * @fixup_src : input scatterlist (that might be stripped of leading zeros) + * @fixup_src_len : length of the fixup_src input scatterlist */ struct caam_rsa_req_ctx { struct scatterlist src[2]; + struct scatterlist *fixup_src; + unsigned int fixup_src_len; }; /**