diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-05-22 14:26:36 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-05-22 14:26:36 -0700 | 
| commit | 2a058f388db8f2bf83ed43f6170a2bb79567dedb (patch) | |
| tree | 6d20da1081029e71d72c287249f037638eb9b17e | |
| parent | 865d872280c848dc78b060088171724c3fb98bbb (diff) | |
| parent | a1cae34e23b1293eccbcc8ee9b39298039c3952a (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull another crypto fix from Herbert Xu:
 "Fix ICV corruption in s390/ghash when the same tfm is used by more
  than one thread"
* git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6:
  crypto: s390/ghash - Fix incorrect ghash icv buffer handling.
| -rw-r--r-- | arch/s390/crypto/ghash_s390.c | 25 | 
1 files changed, 13 insertions, 12 deletions
| diff --git a/arch/s390/crypto/ghash_s390.c b/arch/s390/crypto/ghash_s390.c index 7940dc90e80b..b258110da952 100644 --- a/arch/s390/crypto/ghash_s390.c +++ b/arch/s390/crypto/ghash_s390.c @@ -16,11 +16,12 @@  #define GHASH_DIGEST_SIZE	16  struct ghash_ctx { -	u8 icv[16]; -	u8 key[16]; +	u8 key[GHASH_BLOCK_SIZE];  };  struct ghash_desc_ctx { +	u8 icv[GHASH_BLOCK_SIZE]; +	u8 key[GHASH_BLOCK_SIZE];  	u8 buffer[GHASH_BLOCK_SIZE];  	u32 bytes;  }; @@ -28,8 +29,10 @@ struct ghash_desc_ctx {  static int ghash_init(struct shash_desc *desc)  {  	struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); +	struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);  	memset(dctx, 0, sizeof(*dctx)); +	memcpy(dctx->key, ctx->key, GHASH_BLOCK_SIZE);  	return 0;  } @@ -45,7 +48,6 @@ static int ghash_setkey(struct crypto_shash *tfm,  	}  	memcpy(ctx->key, key, GHASH_BLOCK_SIZE); -	memset(ctx->icv, 0, GHASH_BLOCK_SIZE);  	return 0;  } @@ -54,7 +56,6 @@ static int ghash_update(struct shash_desc *desc,  			 const u8 *src, unsigned int srclen)  {  	struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); -	struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);  	unsigned int n;  	u8 *buf = dctx->buffer;  	int ret; @@ -70,7 +71,7 @@ static int ghash_update(struct shash_desc *desc,  		src += n;  		if (!dctx->bytes) { -			ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, +			ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf,  					      GHASH_BLOCK_SIZE);  			if (ret != GHASH_BLOCK_SIZE)  				return -EIO; @@ -79,7 +80,7 @@ static int ghash_update(struct shash_desc *desc,  	n = srclen & ~(GHASH_BLOCK_SIZE - 1);  	if (n) { -		ret = crypt_s390_kimd(KIMD_GHASH, ctx, src, n); +		ret = crypt_s390_kimd(KIMD_GHASH, dctx, src, n);  		if (ret != n)  			return -EIO;  		src += n; @@ -94,7 +95,7 @@ static int ghash_update(struct shash_desc *desc,  	return 0;  } -static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx) +static int ghash_flush(struct ghash_desc_ctx *dctx)  {  	u8 *buf = dctx->buffer;  	int ret; @@ -104,24 +105,24 @@ static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)  		memset(pos, 0, dctx->bytes); -		ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, GHASH_BLOCK_SIZE); +		ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE);  		if (ret != GHASH_BLOCK_SIZE)  			return -EIO; + +		dctx->bytes = 0;  	} -	dctx->bytes = 0;  	return 0;  }  static int ghash_final(struct shash_desc *desc, u8 *dst)  {  	struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); -	struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);  	int ret; -	ret = ghash_flush(ctx, dctx); +	ret = ghash_flush(dctx);  	if (!ret) -		memcpy(dst, ctx->icv, GHASH_BLOCK_SIZE); +		memcpy(dst, dctx->icv, GHASH_BLOCK_SIZE);  	return ret;  } | 
