Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756249AbdIHNUH (ORCPT ); Fri, 8 Sep 2017 09:20:07 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:34282 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755217AbdIHNUF (ORCPT ); Fri, 8 Sep 2017 09:20:05 -0400 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Gilad Ben-Yossef Subject: [PATCH 4.13 10/47] staging: ccree: save ciphertext for CTS IV Date: Fri, 8 Sep 2017 15:18:42 +0200 Message-Id: <20170908131824.001524610@linuxfoundation.org> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20170908131823.546721606@linuxfoundation.org> References: <20170908131823.546721606@linuxfoundation.org> User-Agent: quilt/0.65 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3918 Lines: 118 4.13-stable review patch. If anyone has any objections, please let me know. ------------------ From: Gilad Ben-Yossef commit 737aed947f9b5bd749a2684e13572ee99a1b8bae upstream. The crypto API requires saving the last blocks of ciphertext in req->info for use as IV for CTS mode. The ccree driver was not doing this. This patch fixes that. The bug was manifested with cts(cbc(aes)) mode in tcrypt tests. Fixes: 302ef8ebb4b2 ("Add CryptoCell skcipher support") Signed-off-by: Gilad Ben-Yossef Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ccree/ssi_cipher.c | 40 +++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) --- a/drivers/staging/ccree/ssi_cipher.c +++ b/drivers/staging/ccree/ssi_cipher.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "ssi_config.h" #include "ssi_driver.h" @@ -716,6 +717,7 @@ static int ssi_blkcipher_complete(struct { int completion_error = 0; u32 inflight_counter; + struct ablkcipher_request *req = (struct ablkcipher_request *)areq; ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst); @@ -726,6 +728,22 @@ static int ssi_blkcipher_complete(struct ctx_p->drvdata->inflight_counter--; if (areq) { + /* + * The crypto API expects us to set the req->info 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->info, req_ctx->backup_info, ivsize); + kfree(req_ctx->backup_info); + } else { + scatterwalk_map_and_copy(req->info, req->dst, + (req->nbytes - ivsize), + ivsize, 0); + } + ablkcipher_request_complete(areq, completion_error); return 0; } @@ -759,11 +777,13 @@ static int ssi_blkcipher_process( if (unlikely(validate_data_size(ctx_p, nbytes))) { SSI_LOG_ERR("Unsupported data size %d.\n", nbytes); crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_BLOCK_LEN); - return -EINVAL; + rc = -EINVAL; + goto exit_process; } if (nbytes == 0) { /* No data to process is valid */ - return 0; + rc = 0; + goto exit_process; } /*For CTS in case of data size aligned to 16 use CBC mode*/ if (((nbytes % AES_BLOCK_SIZE) == 0) && (ctx_p->cipher_mode == DRV_CIPHER_CBC_CTS)) { @@ -842,6 +862,9 @@ exit_process: if (cts_restore_flag != 0) ctx_p->cipher_mode = DRV_CIPHER_CBC_CTS; + if (rc != -EINPROGRESS) + kfree(req_ctx->backup_info); + return rc; } @@ -884,7 +907,6 @@ static int ssi_ablkcipher_encrypt(struct struct blkcipher_req_ctx *req_ctx = ablkcipher_request_ctx(req); unsigned int ivsize = crypto_ablkcipher_ivsize(ablk_tfm); - req_ctx->backup_info = req->info; req_ctx->is_giv = false; return ssi_blkcipher_process(tfm, req_ctx, req->dst, req->src, req->nbytes, req->info, ivsize, (void *)req, DRV_CRYPTO_DIRECTION_ENCRYPT); @@ -897,8 +919,18 @@ static int ssi_ablkcipher_decrypt(struct struct blkcipher_req_ctx *req_ctx = ablkcipher_request_ctx(req); unsigned int ivsize = crypto_ablkcipher_ivsize(ablk_tfm); - req_ctx->backup_info = req->info; + /* + * 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, GFP_KERNEL); + if (!req_ctx->backup_info) + return -ENOMEM; + + scatterwalk_map_and_copy(req_ctx->backup_info, req->src, + (req->nbytes - ivsize), ivsize, 0); req_ctx->is_giv = false; + return ssi_blkcipher_process(tfm, req_ctx, req->dst, req->src, req->nbytes, req->info, ivsize, (void *)req, DRV_CRYPTO_DIRECTION_DECRYPT); }