Skip to content

Commit

Permalink
crypto: s390/ghash - Fix incorrect ghash icv buffer handling.
Browse files Browse the repository at this point in the history
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.

Cc: stable@vger.kernel.org
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>
  • Loading branch information
Harald Freudenberger authored and herbertx committed May 22, 2015
1 parent 7b2a18e commit a1cae34
Showing 1 changed file with 13 additions and 12 deletions.
25 changes: 13 additions & 12 deletions arch/s390/crypto/ghash_s390.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,23 @@
#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;
};

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;
}
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}

Expand Down

0 comments on commit a1cae34

Please sign in to comment.