All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bjorn Andersson <bjorn.andersson@linaro.org>
To: Thara Gopinath <thara.gopinath@linaro.org>
Cc: herbert@gondor.apana.org.au, davem@davemloft.net,
	ebiggers@google.com, ardb@kernel.org, sivaprak@codeaurora.org,
	linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 1/6] drivers: crypto: qce: sha: Restore/save ahash state with custom struct in export/import
Date: Mon, 25 Jan 2021 10:07:10 -0600	[thread overview]
Message-ID: <YA7srll6wXlSDASq@builder.lan> (raw)
In-Reply-To: <20210120184843.3217775-2-thara.gopinath@linaro.org>

On Wed 20 Jan 12:48 CST 2021, Thara Gopinath wrote:

Please drop "drivers: " from $subject.

> Export and import interfaces save and restore partial transformation
> states. The partial states were being stored and restored in struct
> sha1_state for sha1/hmac(sha1) transformations and sha256_state for
> sha256/hmac(sha256) transformations.This led to a bunch of corner cases
> where improper state was being stored and restored. A few of the corner
> cases that turned up during testing are:
> 
> - wrong byte_count restored if export/import is called twice without h/w
> transaction in between
> - wrong buflen restored back if the pending buffer
> length is exactly the block size.
> - wrong state restored if buffer length is 0.
> 
> To fix these issues, save and restore the partial transformation state
> using the newly introduced qce_sha_saved_state struct. This ensures that
> all the pieces required to properly restart the transformation is captured
> and restored back
> 
> Signed-off-by: Thara Gopinath <thara.gopinath@linaro.org>
> ---
> 
> v1->v2:
> 	- Introduced custom struct qce_sha_saved_state to store and
> 	  restore partial sha transformation. v1 was re-using
> 	  qce_sha_reqctx to save and restore partial states and this
> 	  could lead to potential memcpy issues around pointer copying.
> 
>  drivers/crypto/qce/sha.c | 122 +++++++++++----------------------------
>  1 file changed, 34 insertions(+), 88 deletions(-)
> 
> diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c
> index 61c418c12345..08aed03e2b59 100644
> --- a/drivers/crypto/qce/sha.c
> +++ b/drivers/crypto/qce/sha.c
> @@ -12,9 +12,15 @@
>  #include "core.h"
>  #include "sha.h"
>  
> -/* crypto hw padding constant for first operation */
> -#define SHA_PADDING		64
> -#define SHA_PADDING_MASK	(SHA_PADDING - 1)
> +struct qce_sha_saved_state {
> +	u8 pending_buf[QCE_SHA_MAX_BLOCKSIZE];
> +	u8 partial_digest[QCE_SHA_MAX_DIGESTSIZE];
> +	__be32 byte_count[2];
> +	unsigned int pending_buflen;
> +	unsigned int flags;
> +	u64 count;
> +	bool first_blk;
> +};
>  
>  static LIST_HEAD(ahash_algs);
>  
> @@ -139,97 +145,37 @@ static int qce_ahash_init(struct ahash_request *req)
>  
>  static int qce_ahash_export(struct ahash_request *req, void *out)
>  {
> -	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
>  	struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
> -	unsigned long flags = rctx->flags;
> -	unsigned int digestsize = crypto_ahash_digestsize(ahash);
> -	unsigned int blocksize =
> -			crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash));
> -
> -	if (IS_SHA1(flags) || IS_SHA1_HMAC(flags)) {
> -		struct sha1_state *out_state = out;
> -
> -		out_state->count = rctx->count;
> -		qce_cpu_to_be32p_array((__be32 *)out_state->state,
> -				       rctx->digest, digestsize);
> -		memcpy(out_state->buffer, rctx->buf, blocksize);
> -	} else if (IS_SHA256(flags) || IS_SHA256_HMAC(flags)) {
> -		struct sha256_state *out_state = out;
> -
> -		out_state->count = rctx->count;
> -		qce_cpu_to_be32p_array((__be32 *)out_state->state,
> -				       rctx->digest, digestsize);
> -		memcpy(out_state->buf, rctx->buf, blocksize);
> -	} else {
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
> -static int qce_import_common(struct ahash_request *req, u64 in_count,
> -			     const u32 *state, const u8 *buffer, bool hmac)
> -{
> -	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
> -	struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
> -	unsigned int digestsize = crypto_ahash_digestsize(ahash);
> -	unsigned int blocksize;
> -	u64 count = in_count;
> -
> -	blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash));
> -	rctx->count = in_count;
> -	memcpy(rctx->buf, buffer, blocksize);
> -
> -	if (in_count <= blocksize) {
> -		rctx->first_blk = 1;
> -	} else {
> -		rctx->first_blk = 0;
> -		/*
> -		 * For HMAC, there is a hardware padding done when first block
> -		 * is set. Therefore the byte_count must be incremened by 64
> -		 * after the first block operation.
> -		 */
> -		if (hmac)
> -			count += SHA_PADDING;
> -	}
> +	struct qce_sha_saved_state *export_state = out;
>  
> -	rctx->byte_count[0] = (__force __be32)(count & ~SHA_PADDING_MASK);
> -	rctx->byte_count[1] = (__force __be32)(count >> 32);
> -	qce_cpu_to_be32p_array((__be32 *)rctx->digest, (const u8 *)state,
> -			       digestsize);
> -	rctx->buflen = (unsigned int)(in_count & (blocksize - 1));
> +	memcpy(export_state->pending_buf, rctx->buf, rctx->buflen);
> +	memcpy(export_state->partial_digest, rctx->digest,
> +	       sizeof(rctx->digest));

No need to wrap this line.

> +	memcpy(export_state->byte_count, rctx->byte_count, 2);

You're only stashing 2 of the 8 bytes here. So you should either copy
sizeof(byte_count) bytes, or perhaps it's more obvious if you just
assigned byte_count[0] and byte_count[1]?

> +	export_state->pending_buflen = rctx->buflen;
> +	export_state->count = rctx->count;
> +	export_state->first_blk = rctx->first_blk;
> +	export_state->flags = rctx->flags;
>  
>  	return 0;
>  }
>  
>  static int qce_ahash_import(struct ahash_request *req, const void *in)
>  {
> -	struct qce_sha_reqctx *rctx;
> -	unsigned long flags;
> -	bool hmac;
> -	int ret;
> -
> -	ret = qce_ahash_init(req);
> -	if (ret)
> -		return ret;
> -
> -	rctx = ahash_request_ctx(req);
> -	flags = rctx->flags;
> -	hmac = IS_SHA_HMAC(flags);
> -
> -	if (IS_SHA1(flags) || IS_SHA1_HMAC(flags)) {
> -		const struct sha1_state *state = in;
> -
> -		ret = qce_import_common(req, state->count, state->state,
> -					state->buffer, hmac);
> -	} else if (IS_SHA256(flags) || IS_SHA256_HMAC(flags)) {
> -		const struct sha256_state *state = in;
> +	struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
> +	struct qce_sha_saved_state *import_state = in;
>  
> -		ret = qce_import_common(req, state->count, state->state,
> -					state->buf, hmac);
> -	}
> +	memset(rctx, 0, sizeof(*rctx));
> +	rctx->count = import_state->count;
> +	rctx->buflen = import_state->pending_buflen;
> +	rctx->first_blk = import_state->first_blk;
> +	rctx->flags = import_state->flags;
> +	memcpy(rctx->buf, import_state->pending_buf, rctx->buflen);
> +	memcpy(rctx->digest, import_state->partial_digest,
> +	       sizeof(rctx->digest));
> +	memcpy(rctx->byte_count, import_state->byte_count, 2);

Same as above, you're just restoring 2 of the 8 bytes.

Regards,
Bjorn

>  
> -	return ret;
> +	return 0;
>  }
>  
>  static int qce_ahash_update(struct ahash_request *req)
> @@ -450,7 +396,7 @@ static const struct qce_ahash_def ahash_def[] = {
>  		.drv_name	= "sha1-qce",
>  		.digestsize	= SHA1_DIGEST_SIZE,
>  		.blocksize	= SHA1_BLOCK_SIZE,
> -		.statesize	= sizeof(struct sha1_state),
> +		.statesize	= sizeof(struct qce_sha_saved_state),
>  		.std_iv		= std_iv_sha1,
>  	},
>  	{
> @@ -459,7 +405,7 @@ static const struct qce_ahash_def ahash_def[] = {
>  		.drv_name	= "sha256-qce",
>  		.digestsize	= SHA256_DIGEST_SIZE,
>  		.blocksize	= SHA256_BLOCK_SIZE,
> -		.statesize	= sizeof(struct sha256_state),
> +		.statesize	= sizeof(struct qce_sha_saved_state),
>  		.std_iv		= std_iv_sha256,
>  	},
>  	{
> @@ -468,7 +414,7 @@ static const struct qce_ahash_def ahash_def[] = {
>  		.drv_name	= "hmac-sha1-qce",
>  		.digestsize	= SHA1_DIGEST_SIZE,
>  		.blocksize	= SHA1_BLOCK_SIZE,
> -		.statesize	= sizeof(struct sha1_state),
> +		.statesize	= sizeof(struct qce_sha_saved_state),
>  		.std_iv		= std_iv_sha1,
>  	},
>  	{
> @@ -477,7 +423,7 @@ static const struct qce_ahash_def ahash_def[] = {
>  		.drv_name	= "hmac-sha256-qce",
>  		.digestsize	= SHA256_DIGEST_SIZE,
>  		.blocksize	= SHA256_BLOCK_SIZE,
> -		.statesize	= sizeof(struct sha256_state),
> +		.statesize	= sizeof(struct qce_sha_saved_state),
>  		.std_iv		= std_iv_sha256,
>  	},
>  };
> -- 
> 2.25.1
> 

  reply	other threads:[~2021-01-25 16:09 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-20 18:48 [PATCH v3 0/6] Regression fixes/clean ups in the Qualcomm crypto engine driver Thara Gopinath
2021-01-20 18:48 ` [PATCH v3 1/6] drivers: crypto: qce: sha: Restore/save ahash state with custom struct in export/import Thara Gopinath
2021-01-25 16:07   ` Bjorn Andersson [this message]
2021-02-02 23:49   ` kernel test robot
2021-02-02 23:49     ` kernel test robot
2021-01-20 18:48 ` [PATCH v3 2/6] drivers: crypto: qce: sha: Hold back a block of data to be transferred as part of final Thara Gopinath
2021-01-25 16:19   ` Bjorn Andersson
2021-01-20 18:48 ` [PATCH v3 3/6] drivers: crypto: qce: skcipher: Fix regressions found during fuzz testing Thara Gopinath
2021-01-25 16:25   ` Bjorn Andersson
2021-01-20 18:48 ` [PATCH v3 4/6] drivers: crypto: qce: common: Set data unit size to message length for AES XTS transformation Thara Gopinath
2021-01-25 16:31   ` Bjorn Andersson
2021-01-20 18:48 ` [PATCH v3 5/6] drivers: crypto: qce: Remover src_tbl from qce_cipher_reqctx Thara Gopinath
2021-01-25 16:32   ` Bjorn Andersson
2021-01-20 18:48 ` [PATCH v3 6/6] drivers: crypto: qce: Remove totallen and offset in qce_start Thara Gopinath
2021-01-25 16:34   ` Bjorn Andersson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YA7srll6wXlSDASq@builder.lan \
    --to=bjorn.andersson@linaro.org \
    --cc=ardb@kernel.org \
    --cc=davem@davemloft.net \
    --cc=ebiggers@google.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sivaprak@codeaurora.org \
    --cc=thara.gopinath@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.