From patchwork Thu Jun 28 07:32:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gilad Ben-Yossef X-Patchwork-Id: 140422 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp1853469ljj; Thu, 28 Jun 2018 00:33:15 -0700 (PDT) X-Google-Smtp-Source: AAOMgpehH82asSpOfTdd9Oc3VW0Zs+juTRzQHjvOz8YE+wVO7LTbxqfU5ribQIgtoKrNWnab9o/7 X-Received: by 2002:aa7:8510:: with SMTP id v16-v6mr9076184pfn.77.1530171195036; Thu, 28 Jun 2018 00:33:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1530171195; cv=none; d=google.com; s=arc-20160816; b=Q42aladN24deoE/deMIeol+9JStVXbEIT3iYcd6awP3euB1QWNctueRALKqD12+lYs Y8QctxJ55xlhwKmHnDC+sxylyO8upbxe3CTrlsm0Ai7AmU/OGfRD2JngANR97UXb1X7B OwHgXvQZOe4XwpzzV8coP8SCVmLKv5X0ZGsZNwjj+iC4xPT6FkluZxToBSH3XQdf878H qqKX+xZc1QSjzvoztUXmQxzQe7yR61Lc6INRaRgNo++6Hc3bZZbpJcIkV4QkUDVYmLAJ /rBJkMZMmvJ8o/FmGSq29W75B31NHH5Jr88o4cD18VT4Ufl9Dnzf2qQ8RhMsGahOY/ZB A8AQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=jtk1de2ki177eHCEyMQXuPSmVpRu1pqIWrXNh/+ly0I=; b=u2VYl/5fJgR2dTRiDqKs8BX2mHVn116RN+vgEoi4rrzgsLDCFSO4kT0fsb5j8oqiKe d3vLlPsph1AS0flWfi+fSfggXHPPBtji4yf6Y+zXM8noSrOue6MAWth5elubmGqU69Lm p6UOn3AEbezxlKCugipGO3NOPMV4q++PjBTGZrL38DbsMQwbV0+6slnE6NUCtg4tjN4N jBC4qTf8BCIQCFBv4QcRiKhRi2ZwTZIHsgyDICJYebUTKX0lOosoiVyjdqgCIkoO3BFd 7Qgt7hBEDhA3XtucpiHhBRd+ECHwhH4FPS0wN/60YHYb48uA0b8r8fGMr20G7XSCnC+v u1Gw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b205-v6si3041584pfb.358.2018.06.28.00.33.14; Thu, 28 Jun 2018 00:33:15 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934233AbeF1HdL (ORCPT + 31 others); Thu, 28 Jun 2018 03:33:11 -0400 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70]:42228 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934128AbeF1HdI (ORCPT ); Thu, 28 Jun 2018 03:33:08 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4BDA518A; Thu, 28 Jun 2018 00:33:08 -0700 (PDT) Received: from sugar.kfn.arm.com (unknown [10.45.48.147]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6DD7D3F5C0; Thu, 28 Jun 2018 00:33:06 -0700 (PDT) From: Gilad Ben-Yossef To: Herbert Xu , "David S. Miller" Cc: Ofir Drang , Hadar Gat , stable@vger.kernel.org, linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/4] crypto: ccree: fix iv handling Date: Thu, 28 Jun 2018 08:32:53 +0100 Message-Id: <1530171175-31960-4-git-send-email-gilad@benyossef.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1530171175-31960-1-git-send-email-gilad@benyossef.com> References: <1530171175-31960-1-git-send-email-gilad@benyossef.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org We were copying our last cipher block into the request for use as IV for all modes of operations. Fix this by discerning the behaviour based on the mode of operation used: copy ciphertext for CBC, update counter for CTR. CC: stable@vger.kernel.org Fixes: 63ee04c8b491 ("crypto: ccree - add skcipher support") Reported by: Hadar Gat Signed-off-by: Gilad Ben-Yossef --- drivers/crypto/ccree/cc_cipher.c | 111 +++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 27 deletions(-) -- 2.7.4 diff --git a/drivers/crypto/ccree/cc_cipher.c b/drivers/crypto/ccree/cc_cipher.c index d2810c1..3af44a5 100644 --- a/drivers/crypto/ccree/cc_cipher.c +++ b/drivers/crypto/ccree/cc_cipher.c @@ -593,34 +593,82 @@ static void cc_setup_cipher_data(struct crypto_tfm *tfm, } } +/* + * Update a CTR-AES 128 bit counter + */ +void cc_update_ctr(u8 *ctr, unsigned int increment) +{ + if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || + IS_ALIGNED((unsigned long)ctr, 8)) { + + __be64 *high_be = (__be64 *)ctr; + __be64 *low_be = high_be + 1; + u64 orig_low = __be64_to_cpu(*low_be); + u64 new_low = orig_low + (u64)increment; + + *low_be = __cpu_to_be64(new_low); + + if (new_low < orig_low) + *high_be = __cpu_to_be64(__be64_to_cpu(*high_be) + 1); + } else { + u8 *pos = (ctr + AES_BLOCK_SIZE); + u8 val; + unsigned int size; + + for (; increment; increment--) + for (size = AES_BLOCK_SIZE; size; size--) { + val = *--pos + 1; + *pos = val; + if (val) + break; + } + } +} + static void cc_cipher_complete(struct device *dev, void *cc_req, int err) { struct skcipher_request *req = (struct skcipher_request *)cc_req; struct scatterlist *dst = req->dst; struct scatterlist *src = req->src; struct cipher_req_ctx *req_ctx = skcipher_request_ctx(req); - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); - unsigned int ivsize = crypto_skcipher_ivsize(tfm); + struct crypto_skcipher *sk_tfm = crypto_skcipher_reqtfm(req); + struct crypto_tfm *tfm = crypto_skcipher_tfm(sk_tfm); + struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); + unsigned int ivsize = crypto_skcipher_ivsize(sk_tfm); + unsigned int len; - cc_unmap_cipher_request(dev, req_ctx, ivsize, src, dst); - kzfree(req_ctx->iv); + switch (ctx_p->cipher_mode) { + case DRV_CIPHER_CBC: + /* + * The crypto API expects us to set the req->iv to the last + * ciphertext block. For encrypt, simply copy from the result. + * For decrypt, we must copy from a saved buffer since this + * could be an in-place decryption operation and the src is + * lost by this point. + */ + if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) { + memcpy(req->iv, req_ctx->backup_info, ivsize); + kzfree(req_ctx->backup_info); + } else if (!err) { + len = req->cryptlen - ivsize; + scatterwalk_map_and_copy(req->iv, req->dst, len, + ivsize, 0); + } + break; - /* - * The crypto API expects us to set the req->iv to the last - * ciphertext block. For encrypt, simply copy from the result. - * For decrypt, we must copy from a saved buffer since this - * could be an in-place decryption operation and the src is - * lost by this point. - */ - if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) { - memcpy(req->iv, req_ctx->backup_info, ivsize); - kzfree(req_ctx->backup_info); - } else if (!err) { - scatterwalk_map_and_copy(req->iv, req->dst, - (req->cryptlen - ivsize), - ivsize, 0); + case DRV_CIPHER_CTR: + /* Compute the counter of the last block */ + len = ALIGN(req->cryptlen, AES_BLOCK_SIZE) / AES_BLOCK_SIZE; + cc_update_ctr((u8 *)req->iv, len); + break; + + default: + break; } + cc_unmap_cipher_request(dev, req_ctx, ivsize, src, dst); + kzfree(req_ctx->iv); + skcipher_request_complete(req, err); } @@ -752,20 +800,29 @@ static int cc_cipher_encrypt(struct skcipher_request *req) static int cc_cipher_decrypt(struct skcipher_request *req) { struct crypto_skcipher *sk_tfm = crypto_skcipher_reqtfm(req); + struct crypto_tfm *tfm = crypto_skcipher_tfm(sk_tfm); + struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); struct cipher_req_ctx *req_ctx = skcipher_request_ctx(req); unsigned int ivsize = crypto_skcipher_ivsize(sk_tfm); gfp_t flags = cc_gfp_flags(&req->base); + unsigned int len; - /* - * Allocate and save the last IV sized bytes of the source, which will - * be lost in case of in-place decryption and might be needed for CTS. - */ - req_ctx->backup_info = kmalloc(ivsize, flags); - if (!req_ctx->backup_info) - return -ENOMEM; + if (ctx_p->cipher_mode == DRV_CIPHER_CBC) { + + /* Allocate and save the last IV sized bytes of the source, + * which will be lost in case of in-place decryption. + */ + req_ctx->backup_info = kzalloc(ivsize, flags); + if (!req_ctx->backup_info) + return -ENOMEM; + + len = req->cryptlen - ivsize; + scatterwalk_map_and_copy(req_ctx->backup_info, req->src, len, + ivsize, 0); + } else { + req_ctx->backup_info = NULL; + } - scatterwalk_map_and_copy(req_ctx->backup_info, req->src, - (req->cryptlen - ivsize), ivsize, 0); req_ctx->is_giv = false; return cc_cipher_process(req, DRV_CRYPTO_DIRECTION_DECRYPT);