| From a1cae34e23b1293eccbcc8ee9b39298039c3952a Mon Sep 17 00:00:00 2001 |
| From: Harald Freudenberger <freude@linux.vnet.ibm.com> |
| Date: Thu, 21 May 2015 10:01:11 +0200 |
| Subject: crypto: s390/ghash - Fix incorrect ghash icv buffer handling. |
| |
| From: Harald Freudenberger <freude@linux.vnet.ibm.com> |
| |
| commit a1cae34e23b1293eccbcc8ee9b39298039c3952a upstream. |
| |
| Multitheaded tests showed that the icv buffer in the current ghash |
| implementation is not handled correctly. A move of this working ghash |
| buffer value to the descriptor context fixed this. Code is tested and |
| verified with an multithreaded application via af_alg interface. |
| |
| Signed-off-by: Harald Freudenberger <freude@linux.vnet.ibm.com> |
| Signed-off-by: Gerald Schaefer <geraldsc@linux.vnet.ibm.com> |
| Reported-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/s390/crypto/ghash_s390.c | 25 +++++++++++++------------ |
| 1 file changed, 13 insertions(+), 12 deletions(-) |
| |
| --- 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_sh |
| } |
| |
| 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_des |
| 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_des |
| 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_des |
| |
| 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_des |
| 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 |
| |
| 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; |
| } |
| |