Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a058f38 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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.
parents 865d8722 a1cae34e
Loading
Loading
Loading
Loading
+13 −12
Original line number Diff line number Diff line
@@ -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;
	}

	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;
}