diff mbox series

[RFC,v2,2/7] crypto: polyval - Add POLYVAL support

Message ID 20220210232812.798387-3-nhuck@google.com
State New
Headers show
Series crypto: HCTR2 support | expand

Commit Message

Nathan Huckleberry Feb. 10, 2022, 11:28 p.m. UTC
Add support for POLYVAL, an ε-Δ-universal hash function similar to
GHASH.  POLYVAL is used as a component to implement HCTR2 mode.

POLYVAL is implemented as an shash algorithm.  The implementation is
modified from ghash-generic.c.

More information on POLYVAL can be found in the HCTR2 paper:
https://eprint.iacr.org/2021/1441.pdf

Signed-off-by: Nathan Huckleberry <nhuck@google.com>
---

Changes since v1:
 * Added comments explaining the GHASH/POLYVAL trick
 * Fixed a bug on non-block-multiple messages

 crypto/Kconfig           |   8 ++
 crypto/Makefile          |   1 +
 crypto/polyval-generic.c | 199 +++++++++++++++++++++++++++
 crypto/tcrypt.c          |   4 +
 crypto/testmgr.c         |   6 +
 crypto/testmgr.h         | 284 +++++++++++++++++++++++++++++++++++++++
 include/crypto/polyval.h |  22 +++
 7 files changed, 524 insertions(+)
 create mode 100644 crypto/polyval-generic.c
 create mode 100644 include/crypto/polyval.h

Comments

Eric Biggers Feb. 16, 2022, 11:16 p.m. UTC | #1
On Thu, Feb 10, 2022 at 11:28:07PM +0000, Nathan Huckleberry wrote:
> +config CRYPTO_POLYVAL
> +	tristate
> +	select CRYPTO_GF128MUL
> +	select CRYPTO_HASH
> +	help
> +	  POLYVAL is the hash function used in HCTR2.  It is not a general-purpose
> +	  cryptographic hash function.

As with XCTR: as this option is no longer user-selectable, no one will see this
help text.  I think it should just be removed.

> +static int polyval_update(struct shash_desc *desc,
> +			 const u8 *src, unsigned int srclen)
> +{
> +	struct polyval_desc_ctx *dctx = shash_desc_ctx(desc);
> +	const struct polyval_tfm_ctx *ctx = crypto_shash_ctx(desc->tfm);
> +	u8 *dst = dctx->buffer;

The dst variable doesn't seem to serve a purpose.  It would be clearer to just
write dctx->buffer directly (or &dctx->buffer[...], etc).

> +	u8 *pos;
> +	u8 tmp[POLYVAL_BLOCK_SIZE];
> +	int n;
> +
> +	if (dctx->bytes) {
> +		n = min(srclen, dctx->bytes);
> +		pos = dst + dctx->bytes - 1;
> +
> +		dctx->bytes -= n;
> +		srclen -= n;
> +
> +		while (n--)
> +			*pos-- ^= *src++;
> +
> +		if (!dctx->bytes)
> +			gf128mul_4k_lle((be128 *)dst, ctx->gf128);

I thought I mentioned this on v1, but the cast to be128 is violating alignment
rules.  If the alignment to be128 is needed then a union should be used, e.g.:

struct polyval_desc_ctx {
        union {
                u8 buffer[POLYVAL_BLOCK_SIZE];
                be128 buffer128;
        };
        u32 bytes;
};

> +static int polyval_final(struct shash_desc *desc, u8 *dst)
> +{
> +	struct polyval_desc_ctx *dctx = shash_desc_ctx(desc);
> +	const struct polyval_tfm_ctx *ctx = crypto_shash_ctx(desc->tfm);
> +	u8 *buf = dctx->buffer;
> +
> +	if (dctx->bytes)
> +		gf128mul_4k_lle((be128 *)buf, ctx->gf128);
> +	dctx->bytes = 0;
> +
> +	reverse_block(buf);
> +	memcpy(dst, buf, POLYVAL_BLOCK_SIZE);
> +
> +	return 0;
> +}

Same issues as polyval_update().

> +
> diff --git a/include/crypto/polyval.h b/include/crypto/polyval.h
> new file mode 100644
> index 000000000000..fd0c6e124b65
> --- /dev/null
> +++ b/include/crypto/polyval.h
> @@ -0,0 +1,22 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Common values for the Polyval hash algorithm
> + *
> + * Copyright 2021 Google LLC
> + */
> +
> +#ifndef _CRYPTO_POLYVAL_H
> +#define _CRYPTO_POLYVAL_H
> +
> +#include <linux/types.h>
> +#include <linux/crypto.h>
> +
> +#define POLYVAL_BLOCK_SIZE	16
> +#define POLYVAL_DIGEST_SIZE	16
> +
> +struct polyval_desc_ctx {
> +	u8 buffer[POLYVAL_BLOCK_SIZE];
> +	u32 bytes;
> +};
> +
> +#endif

As-is, polyval_desc_ctx is only used by crypto/polyval-generic.c, so it
shouldn't be in this header.  Either it should be moved to polyval-generic.c, or
all implementations should be made to use the same struct.

- Eric
diff mbox series

Patch

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 8543f34fa200..0c61d03530a6 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -760,6 +760,14 @@  config CRYPTO_GHASH
 	  GHASH is the hash function used in GCM (Galois/Counter Mode).
 	  It is not a general-purpose cryptographic hash function.
 
+config CRYPTO_POLYVAL
+	tristate
+	select CRYPTO_GF128MUL
+	select CRYPTO_HASH
+	help
+	  POLYVAL is the hash function used in HCTR2.  It is not a general-purpose
+	  cryptographic hash function.
+
 config CRYPTO_POLY1305
 	tristate "Poly1305 authenticator algorithm"
 	select CRYPTO_HASH
diff --git a/crypto/Makefile b/crypto/Makefile
index 6b3fe3df1489..561f901a91d4 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -169,6 +169,7 @@  UBSAN_SANITIZE_jitterentropy.o = n
 jitterentropy_rng-y := jitterentropy.o jitterentropy-kcapi.o
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
 obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
+obj-$(CONFIG_CRYPTO_POLYVAL) += polyval-generic.o
 obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o
 obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o
 obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
diff --git a/crypto/polyval-generic.c b/crypto/polyval-generic.c
new file mode 100644
index 000000000000..e8d7e34e5355
--- /dev/null
+++ b/crypto/polyval-generic.c
@@ -0,0 +1,199 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * POLYVAL: hash function for HCTR2.
+ *
+ * Copyright (c) 2007 Nokia Siemens Networks - Mikko Herranen <mh1@iki.fi>
+ * Copyright (c) 2009 Intel Corp.
+ *   Author: Huang Ying <ying.huang@intel.com>
+ * Copyright 2021 Google LLC
+ */
+
+/*
+ * Code based on crypto/ghash-generic.c
+ *
+ * POLYVAL is a keyed hash function similar to GHASH. POLYVAL uses a
+ * different modulus for finite field multiplication which makes hardware
+ * accelerated implementations on little-endian machines faster.
+ *
+ * Like GHASH, POLYVAL is not a cryptographic hash function and should
+ * not be used outside of crypto modes explicitly designed to use POLYVAL.
+ *
+ * This implementation uses a convenient trick involving the GHASH and POLYVAL
+ * fields. This trick allows multiplication in the POLYVAL field to be
+ * implemented by using multiplication in the GHASH field as a subroutine. An
+ * element of the POLYVAL field can be converted to an element of the GHASH
+ * field by computing x*REVERSE(a), where REVERSE reverses the byte-ordering of
+ * a. Similarly, an element of the GHASH field can be converted back to the
+ * POLYVAL field by computing REVERSE(x^{-1}*a).
+ *
+ * By using this trick, we do not need to implement the POLYVAL field for the
+ * generic implementation.
+ *
+ * Warning: this generic implementation is not intended to be used in practice
+ * and is not constant time. For practical use, a hardware accelerated
+ * implementation of POLYVAL should be used instead.
+ *
+ */
+
+#include <asm/unaligned.h>
+#include <crypto/algapi.h>
+#include <crypto/gf128mul.h>
+#include <crypto/polyval.h>
+#include <crypto/internal/hash.h>
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+struct polyval_tfm_ctx {
+	struct gf128mul_4k *gf128;
+};
+
+static int polyval_init(struct shash_desc *desc)
+{
+	struct polyval_desc_ctx *dctx = shash_desc_ctx(desc);
+
+	memset(dctx, 0, sizeof(*dctx));
+
+	return 0;
+}
+
+static void reverse_block(u8 block[POLYVAL_BLOCK_SIZE])
+{
+	u64 *p1 = (u64 *)block;
+	u64 *p2 = (u64 *)&block[8];
+	u64 a = get_unaligned(p1);
+	u64 b = get_unaligned(p2);
+
+	put_unaligned(swab64(a), p2);
+	put_unaligned(swab64(b), p1);
+}
+
+static int polyval_setkey(struct crypto_shash *tfm,
+			const u8 *key, unsigned int keylen)
+{
+	struct polyval_tfm_ctx *ctx = crypto_shash_ctx(tfm);
+	be128 k;
+
+	if (keylen != POLYVAL_BLOCK_SIZE)
+		return -EINVAL;
+
+	gf128mul_free_4k(ctx->gf128);
+
+	BUILD_BUG_ON(sizeof(k) != POLYVAL_BLOCK_SIZE);
+	// avoid violating alignment rules
+	memcpy(&k, key, POLYVAL_BLOCK_SIZE);
+
+	reverse_block((u8 *)&k);
+	gf128mul_x_lle(&k, &k);
+
+	ctx->gf128 = gf128mul_init_4k_lle(&k);
+	memzero_explicit(&k, POLYVAL_BLOCK_SIZE);
+
+	if (!ctx->gf128)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int polyval_update(struct shash_desc *desc,
+			 const u8 *src, unsigned int srclen)
+{
+	struct polyval_desc_ctx *dctx = shash_desc_ctx(desc);
+	const struct polyval_tfm_ctx *ctx = crypto_shash_ctx(desc->tfm);
+	u8 *dst = dctx->buffer;
+	u8 *pos;
+	u8 tmp[POLYVAL_BLOCK_SIZE];
+	int n;
+
+	if (dctx->bytes) {
+		n = min(srclen, dctx->bytes);
+		pos = dst + dctx->bytes - 1;
+
+		dctx->bytes -= n;
+		srclen -= n;
+
+		while (n--)
+			*pos-- ^= *src++;
+
+		if (!dctx->bytes)
+			gf128mul_4k_lle((be128 *)dst, ctx->gf128);
+	}
+
+	while (srclen >= POLYVAL_BLOCK_SIZE) {
+		memcpy(tmp, src, POLYVAL_BLOCK_SIZE);
+		reverse_block(tmp);
+		crypto_xor(dst, tmp, POLYVAL_BLOCK_SIZE);
+		gf128mul_4k_lle((be128 *)dst, ctx->gf128);
+		src += POLYVAL_BLOCK_SIZE;
+		srclen -= POLYVAL_BLOCK_SIZE;
+	}
+
+	if (srclen) {
+		dctx->bytes = POLYVAL_BLOCK_SIZE - srclen;
+		pos = dst + POLYVAL_BLOCK_SIZE - 1;
+		while (srclen--)
+			*pos-- ^= *src++;
+	}
+
+	return 0;
+}
+
+static int polyval_final(struct shash_desc *desc, u8 *dst)
+{
+	struct polyval_desc_ctx *dctx = shash_desc_ctx(desc);
+	const struct polyval_tfm_ctx *ctx = crypto_shash_ctx(desc->tfm);
+	u8 *buf = dctx->buffer;
+
+	if (dctx->bytes)
+		gf128mul_4k_lle((be128 *)buf, ctx->gf128);
+	dctx->bytes = 0;
+
+	reverse_block(buf);
+	memcpy(dst, buf, POLYVAL_BLOCK_SIZE);
+
+	return 0;
+}
+
+static void polyval_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct polyval_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	gf128mul_free_4k(ctx->gf128);
+}
+
+static struct shash_alg polyval_alg = {
+	.digestsize	= POLYVAL_DIGEST_SIZE,
+	.init		= polyval_init,
+	.update		= polyval_update,
+	.final		= polyval_final,
+	.setkey		= polyval_setkey,
+	.descsize	= sizeof(struct polyval_desc_ctx),
+	.base		= {
+		.cra_name		= "polyval",
+		.cra_driver_name	= "polyval-generic",
+		.cra_priority		= 100,
+		.cra_blocksize		= POLYVAL_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct polyval_tfm_ctx),
+		.cra_module		= THIS_MODULE,
+		.cra_exit		= polyval_exit_tfm,
+	},
+};
+
+static int __init polyval_mod_init(void)
+{
+	return crypto_register_shash(&polyval_alg);
+}
+
+static void __exit polyval_mod_exit(void)
+{
+	crypto_unregister_shash(&polyval_alg);
+}
+
+subsys_initcall(polyval_mod_init);
+module_exit(polyval_mod_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("POLYVAL hash function");
+MODULE_ALIAS_CRYPTO("polyval");
+MODULE_ALIAS_CRYPTO("polyval-generic");
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index b3a23dbf5b14..ced7467bb481 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -1730,6 +1730,10 @@  static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
 		ret += tcrypt_test("ccm(sm4)");
 		break;
 
+	case 57:
+		ret += tcrypt_test("polyval");
+		break;
+
 	case 100:
 		ret += tcrypt_test("hmac(md5)");
 		break;
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index d2b42ff0b04a..3e54d17fe644 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -5245,6 +5245,12 @@  static const struct alg_test_desc alg_test_descs[] = {
 		.suite = {
 			.hash = __VECS(poly1305_tv_template)
 		}
+	}, {
+		.alg = "polyval",
+		.test = alg_test_hash,
+		.suite = {
+			.hash = __VECS(polyval_tv_template)
+		}
 	}, {
 		.alg = "rfc3686(ctr(aes))",
 		.test = alg_test_skcipher,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index e1ebbb3c4d4c..da3736e51982 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -33346,4 +33346,288 @@  static const struct cipher_testvec aes_xctr_tv_template[] = {
 	},
 };
 
+/*
+ * Test vectors generated using https://github.com/google/hctr2
+ */
+static const struct hash_testvec polyval_tv_template[] = {
+	{
+		.key	= "\x31\x07\x28\xd9\x91\x1f\x1f\x38"
+			  "\x37\xb2\x43\x16\xc3\xfa\xb9\xa0",
+		.plaintext	= "\x65\x78\x61\x6d\x70\x6c\x65\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x48\x65\x6c\x6c\x6f\x20\x77\x6f"
+			  "\x72\x6c\x64\x00\x00\x00\x00\x00"
+			  "\x38\x00\x00\x00\x00\x00\x00\x00"
+			  "\x58\x00\x00\x00\x00\x00\x00\x00",
+		.digest	= "\xad\x7f\xcf\x0b\x51\x69\x85\x16"
+			  "\x62\x67\x2f\x3c\x5f\x95\x13\x8f",
+		.psize	= 48,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\xd9\xb3\x60\x27\x96\x94\x94\x1a"
+			  "\xc5\xdb\xc6\x98\x7a\xda\x73\x77",
+		.plaintext	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.digest	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.psize	= 16,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\xd9\xb3\x60\x27\x96\x94\x94\x1a"
+			  "\xc5\xdb\xc6\x98\x7a\xda\x73\x77",
+		.plaintext	= "\x01\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x40\x00\x00\x00\x00\x00\x00\x00",
+		.digest	= "\xeb\x93\xb7\x74\x09\x62\xc5\xe4"
+			  "\x9d\x2a\x90\xa7\xdc\x5c\xec\x74",
+		.psize	= 32,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\xd9\xb3\x60\x27\x96\x94\x94\x1a"
+			  "\xc5\xdb\xc6\x98\x7a\xda\x73\x77",
+		.plaintext	= "\x01\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x60\x00\x00\x00\x00\x00\x00\x00",
+		.digest	= "\x48\xeb\x6c\x6c\x5a\x2d\xbe\x4a"
+			  "\x1d\xde\x50\x8f\xee\x06\x36\x1b",
+		.psize	= 32,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\xd9\xb3\x60\x27\x96\x94\x94\x1a"
+			  "\xc5\xdb\xc6\x98\x7a\xda\x73\x77",
+		.plaintext	= "\x01\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x02\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x01\x00\x00\x00\x00\x00\x00",
+		.digest	= "\xce\x6e\xdc\x9a\x50\xb3\x6d\x9a"
+			  "\x98\x98\x6b\xbf\x6a\x26\x1c\x3b",
+		.psize	= 48,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\xd9\xb3\x60\x27\x96\x94\x94\x1a"
+			  "\xc5\xdb\xc6\x98\x7a\xda\x73\x77",
+		.plaintext	= "\x01\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x02\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x03\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x80\x01\x00\x00\x00\x00\x00\x00",
+		.digest	= "\x81\x38\x87\x46\xbc\x22\xd2\x6b"
+			  "\x2a\xbc\x3d\xcb\x15\x75\x42\x22",
+		.psize	= 64,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\xd9\xb3\x60\x27\x96\x94\x94\x1a"
+			  "\xc5\xdb\xc6\x98\x7a\xda\x73\x77",
+		.plaintext	= "\x01\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x02\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x03\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x04\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x02\x00\x00\x00\x00\x00\x00",
+		.digest	= "\x1e\x39\xb6\xd3\x34\x4d\x34\x8f"
+			  "\x60\x44\xf8\x99\x35\xd1\xcf\x78",
+		.psize	= 80,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\xd9\xb3\x60\x27\x96\x94\x94\x1a"
+			  "\xc5\xdb\xc6\x98\x7a\xda\x73\x77",
+		.plaintext	= "\x01\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x02\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x03\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x08\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x01\x00\x00\x00\x00\x00\x00",
+		.digest	= "\x2c\xe7\xda\xaf\x7c\x89\x49\x08"
+			  "\x22\x05\x12\x55\xb1\x2e\xca\x6b",
+		.psize	= 64,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\xd9\xb3\x60\x27\x96\x94\x94\x1a"
+			  "\xc5\xdb\xc6\x98\x7a\xda\x73\x77",
+		.plaintext	= "\x01\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x02\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x03\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x04\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x08\x00\x00\x00\x00\x00\x00\x00"
+			  "\x80\x01\x00\x00\x00\x00\x00\x00",
+		.digest	= "\x9c\xa9\x87\x71\x5d\x69\xc1\x78"
+			  "\x67\x11\xdf\xcd\x22\xf8\x30\xfc",
+		.psize	= 80,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\xd9\xb3\x60\x27\x96\x94\x94\x1a"
+			  "\xc5\xdb\xc6\x98\x7a\xda\x73\x77",
+		.plaintext	= "\x01\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x02\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x03\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x04\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x05\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x08\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x02\x00\x00\x00\x00\x00\x00",
+		.digest	= "\xff\xcd\x05\xd5\x77\x0f\x34\xad"
+			  "\x92\x67\xf0\xa5\x99\x94\xb1\x5a",
+		.psize	= 96,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\x03\x6e\xe1\xfe\x2d\x79\x26\xaf"
+			  "\x68\x89\x80\x95\xe5\x4e\x7b\x3c",
+		.plaintext	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.digest	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.psize	= 16,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\x37\x24\xf5\x5f\x1d\x22\xac\x0a"
+			  "\xb8\x30\xda\x0b\x6a\x99\x5d\x74",
+		.plaintext	= "\x75\x76\xf7\x02\x8e\xc6\xeb\x5e"
+			  "\xa7\xe2\x98\x34\x2a\x94\xd4\xb2"
+			  "\x02\xb3\x70\xef\x97\x68\xec\x65"
+			  "\x61\xc4\xfe\x6b\x7e\x72\x96\xfa"
+			  "\x85\x9c\x21\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\xe4\x2a\x3c\x02\xc2\x5b\x64\x86"
+			  "\x9e\x14\x6d\x7b\x23\x39\x87\xbd"
+			  "\xdf\xc2\x40\x87\x1d\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x18\x01\x00\x00\x00\x00\x00\x00"
+			  "\xa8\x00\x00\x00\x00\x00\x00\x00",
+		.digest	= "\x4c\xbb\xa0\x90\xf0\x3f\x7d\x11"
+			  "\x88\xea\x55\x74\x9f\xa6\xc7\xbd",
+		.psize	= 96,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\x90\xcc\xac\xee\xba\xd7\xd4\x68"
+			  "\x98\xa6\x79\x70\xdf\x66\x15\x6c",
+		.plaintext	= "",
+		.digest	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.psize	= 0,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\x89\xc9\x4b\xde\x40\xa6\xf9\x62"
+			  "\x58\x04\x51\x26\xb4\xb1\x14\xe4",
+		.plaintext	= "",
+		.digest	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.psize	= 0,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\x37\xbe\x68\x16\x50\xb9\x4e\xb0"
+			  "\x47\xde\xe2\xbd\xde\xe4\x48\x09",
+		.plaintext	= "\x87\xfc\x68\x9f\xff\xf2\x4a\x1e"
+			  "\x82\x3b\x73\x8f\xc1\xb2\x1b\x7a"
+			  "\x6c\x4f\x81\xbc\x88\x9b\x6c\xa3"
+			  "\x9c\xc2\xa5\xbc\x14\x70\x4c\x9b"
+			  "\x0c\x9f\x59\x92\x16\x4b\x91\x3d"
+			  "\x18\x55\x22\x68\x12\x8c\x63\xb2"
+			  "\x51\xcb\x85\x4b\xd2\xae\x0b\x1c"
+			  "\x5d\x28\x9d\x1d\xb1\xc8\xf0\x77"
+			  "\xe9\xb5\x07\x4e\x06\xc8\xee\xf8"
+			  "\x1b\xed\x72\x2a\x55\x7d\x16\xc9"
+			  "\xf2\x54\xe7\xe9\xe0\x44\x5b\x33"
+			  "\xb1\x49\xee\xff\x43\xfb\x82\xcd"
+			  "\x4a\x70\x78\x81\xa4\x34\x36\xe8"
+			  "\x4c\x28\x54\xa6\x6c\xc3\x6b\x78"
+			  "\xe7\xc0\x5d\xc6\x5d\x81\xab\x70"
+			  "\x08\x86\xa1\xfd\xf4\x77\x55\xfd"
+			  "\xa3\xe9\xe2\x1b\xdf\x99\xb7\x80"
+			  "\xf9\x0a\x4f\x72\x4a\xd3\xaf\xbb"
+			  "\xb3\x3b\xeb\x08\x58\x0f\x79\xce"
+			  "\xa5\x99\x05\x12\x34\xd4\xf4\x86"
+			  "\x37\x23\x1d\xc8\x49\xc0\x92\xae"
+			  "\xa6\xac\x9b\x31\x55\xed\x15\xc6"
+			  "\x05\x17\x37\x8d\x90\x42\xe4\x87"
+			  "\x89\x62\x88\x69\x1c\x6a\xfd\xe3"
+			  "\x00\x2b\x47\x1a\x73\xc1\x51\xc2"
+			  "\xc0\x62\x74\x6a\x9e\xb2\xe5\x21"
+			  "\xbe\x90\xb5\xb0\x50\xca\x88\x68"
+			  "\xe1\x9d\x7a\xdf\x6c\xb7\xb9\x98"
+			  "\xee\x28\x62\x61\x8b\xd1\x47\xf9"
+			  "\x04\x7a\x0b\x5d\xcd\x2b\x65\xf5"
+			  "\x12\xa3\xfe\x1a\xaa\x2c\x78\x42"
+			  "\xb8\xbe\x7d\x74\xeb\x59\xba\xba",
+		.digest	= "\xae\x11\xd4\x60\x2a\x5f\x9e\x42"
+			  "\x89\x04\xc2\x34\x8d\x55\x94\x0a",
+		.psize	= 256,
+		.ksize	= 16,
+	},
+	{
+		.key	= "\xc8\x53\xde\xaa\xb1\x4b\x6b\xd5"
+			  "\x88\xd6\x4c\xe9\xba\x35\x3d\x5a",
+		.plaintext	= "\xc1\xeb\xba\x8d\xb7\x20\x09\xe0"
+			  "\x28\x4f\x29\xf3\xd8\x26\x50\x40"
+			  "\xd9\x06\xa8\xa8\xc0\xbe\xf0\xfb"
+			  "\x75\x7c\x02\x86\x16\x83\x9d\x65"
+			  "\x8f\x5e\xc4\x58\xed\x6a\xb3\x10"
+			  "\xd2\xf7\x23\xc2\x4a\xb0\x00\x6a"
+			  "\x01\x7c\xf7\xf7\x69\x42\xb2\x12"
+			  "\xb0\xeb\x65\x07\xd7\x8e\x2d\x27"
+			  "\x67\xa2\x57\xf0\x49\x0f\x3f\x0e"
+			  "\xc9\xf7\x1b\xe0\x5b\xdd\x87\xfb"
+			  "\x89\xd1\xfa\xb1\x46\xaf\xa2\x93"
+			  "\x01\x65\xb6\x6f\xbe\x29\x7d\x9f"
+			  "\xfa\xf5\x58\xc6\xb5\x92\x55\x25"
+			  "\x4c\xb5\x0c\xc2\x61\x9f\xc4\xb1"
+			  "\x7f\xe3\x61\x18\x3f\x8c\xb2\xd6"
+			  "\xfd\x9f\xd8\xe5\x3d\x03\x05\xa2"
+			  "\x5d\x1a\xa8\xf0\x04\x41\xea\xa6"
+			  "\x07\x67\x86\x00\xe8\x86\xfc\xb1"
+			  "\xc3\x15\x3e\xc8\x84\x2e\x5e\x5f"
+			  "\x7b\x75\x6a\xc4\x48\xb4\xee\x5f"
+			  "\xe9\x76\xdf\xe6\x1a\xd4\x15\x92"
+			  "\x23\x03\x06\xc1\x2d\x0f\x94\xcb"
+			  "\xe6\x5e\x18\xa6\x3b\x38\x1f\xc2"
+			  "\x28\x73\x8a\xbd\x3a\x6f\xb0\x95"
+			  "\x0f\x1c\xc7\xdf\x10\x0b\x2a\x7d"
+			  "\xf9\x6b\xe1\x4a\xfb\xe1\x07\xc9"
+			  "\x69\x7b\x27\x65\xc0\x08\x49\xc0"
+			  "\xf3\x0b\x5b\xa6\x8b\xf7\x1a\xfe"
+			  "\xe3\x9f\x87\x1d\x68\x07\xf4\x53"
+			  "\x8d\x54\xe9\x3f\xd5\x02\x3a\x09"
+			  "\x72\xa9\x84\xdc\x25\xd3\xad\xdb"
+			  "\x4e\x45\x4f\x7f\xe8\x02\x69\x45",
+		.digest	= "\x7b\x4f\x29\xb3\x0b\x4d\x2b\xa3"
+			  "\x40\xc8\x56\x5a\x0a\xcf\xbd\x9b",
+		.psize	= 256,
+		.ksize	= 16,
+	},
+};
+
 #endif	/* _CRYPTO_TESTMGR_H */
diff --git a/include/crypto/polyval.h b/include/crypto/polyval.h
new file mode 100644
index 000000000000..fd0c6e124b65
--- /dev/null
+++ b/include/crypto/polyval.h
@@ -0,0 +1,22 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Common values for the Polyval hash algorithm
+ *
+ * Copyright 2021 Google LLC
+ */
+
+#ifndef _CRYPTO_POLYVAL_H
+#define _CRYPTO_POLYVAL_H
+
+#include <linux/types.h>
+#include <linux/crypto.h>
+
+#define POLYVAL_BLOCK_SIZE	16
+#define POLYVAL_DIGEST_SIZE	16
+
+struct polyval_desc_ctx {
+	u8 buffer[POLYVAL_BLOCK_SIZE];
+	u32 bytes;
+};
+
+#endif