xref: /linux/include/crypto/gf128hash.h (revision efd1d2c8f3c073c43d5616d0c2d698cbe8a3ecde)
161f66c52SEric Biggers /* SPDX-License-Identifier: GPL-2.0-or-later */
261f66c52SEric Biggers /*
361f66c52SEric Biggers  * GF(2^128) polynomial hashing: GHASH and POLYVAL
461f66c52SEric Biggers  *
561f66c52SEric Biggers  * Copyright 2025 Google LLC
661f66c52SEric Biggers  */
761f66c52SEric Biggers 
861f66c52SEric Biggers #ifndef _CRYPTO_GF128HASH_H
961f66c52SEric Biggers #define _CRYPTO_GF128HASH_H
1061f66c52SEric Biggers 
1161f66c52SEric Biggers #include <linux/string.h>
1261f66c52SEric Biggers #include <linux/types.h>
1361f66c52SEric Biggers 
14c417e704SEric Biggers #define GHASH_BLOCK_SIZE	16
15c417e704SEric Biggers #define GHASH_DIGEST_SIZE	16
1661f66c52SEric Biggers #define POLYVAL_BLOCK_SIZE	16
1761f66c52SEric Biggers #define POLYVAL_DIGEST_SIZE	16
1861f66c52SEric Biggers 
1961f66c52SEric Biggers /**
2061f66c52SEric Biggers  * struct polyval_elem - An element of the POLYVAL finite field
2161f66c52SEric Biggers  * @bytes: View of the element as a byte array (unioned with @lo and @hi)
2261f66c52SEric Biggers  * @lo: The low 64 terms of the element's polynomial
2361f66c52SEric Biggers  * @hi: The high 64 terms of the element's polynomial
2461f66c52SEric Biggers  *
2561f66c52SEric Biggers  * This represents an element of the finite field GF(2^128), using the POLYVAL
2661f66c52SEric Biggers  * convention: little-endian byte order and natural bit order.
2761f66c52SEric Biggers  */
2861f66c52SEric Biggers struct polyval_elem {
2961f66c52SEric Biggers 	union {
3061f66c52SEric Biggers 		u8 bytes[POLYVAL_BLOCK_SIZE];
3161f66c52SEric Biggers 		struct {
3261f66c52SEric Biggers 			__le64 lo;
3361f66c52SEric Biggers 			__le64 hi;
3461f66c52SEric Biggers 		};
3561f66c52SEric Biggers 	};
3661f66c52SEric Biggers };
3761f66c52SEric Biggers 
3861f66c52SEric Biggers /**
39c417e704SEric Biggers  * struct ghash_key - Prepared key for GHASH
40c417e704SEric Biggers  *
41c417e704SEric Biggers  * Use ghash_preparekey() to initialize this.
42c417e704SEric Biggers  */
43c417e704SEric Biggers struct ghash_key {
4473f315c1SEric Biggers #if defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && defined(CONFIG_PPC64)
4573f315c1SEric Biggers 	/** @htable: GHASH key format used by the POWER8 assembly code */
4673f315c1SEric Biggers 	u64 htable[4][2];
47*efd1d2c8SEric Biggers #elif defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && \
48*efd1d2c8SEric Biggers 	(defined(CONFIG_RISCV) || defined(CONFIG_S390))
49af413d71SEric Biggers 	/** @h_raw: The hash key H, in GHASH format */
50af413d71SEric Biggers 	u8 h_raw[GHASH_BLOCK_SIZE];
5173f315c1SEric Biggers #endif
52c417e704SEric Biggers 	/** @h: The hash key H, in POLYVAL format */
53c417e704SEric Biggers 	struct polyval_elem h;
54c417e704SEric Biggers };
55c417e704SEric Biggers 
56c417e704SEric Biggers /**
5761f66c52SEric Biggers  * struct polyval_key - Prepared key for POLYVAL
5861f66c52SEric Biggers  *
5961f66c52SEric Biggers  * This may contain just the raw key H, or it may contain precomputed key
6061f66c52SEric Biggers  * powers, depending on the platform's POLYVAL implementation.  Use
6161f66c52SEric Biggers  * polyval_preparekey() to initialize this.
6261f66c52SEric Biggers  *
6361f66c52SEric Biggers  * By H^i we mean H^(i-1) * H * x^-128, with base case H^1 = H.  I.e. the
6461f66c52SEric Biggers  * exponentiation repeats the POLYVAL dot operation, with its "extra" x^-128.
6561f66c52SEric Biggers  */
6661f66c52SEric Biggers struct polyval_key {
67b3b6e8f9SEric Biggers #if defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && \
68b3b6e8f9SEric Biggers 	(defined(CONFIG_ARM64) || defined(CONFIG_X86))
6961f66c52SEric Biggers 	/** @h_powers: Powers of the hash key H^8 through H^1 */
7061f66c52SEric Biggers 	struct polyval_elem h_powers[8];
7161f66c52SEric Biggers #else
7261f66c52SEric Biggers 	/** @h: The hash key H */
7361f66c52SEric Biggers 	struct polyval_elem h;
74b3b6e8f9SEric Biggers #endif
7561f66c52SEric Biggers };
7661f66c52SEric Biggers 
7761f66c52SEric Biggers /**
78c417e704SEric Biggers  * struct ghash_ctx - Context for computing a GHASH value
79c417e704SEric Biggers  * @key: Pointer to the prepared GHASH key.  The user of the API is
80c417e704SEric Biggers  *	 responsible for ensuring that the key lives as long as the context.
81c417e704SEric Biggers  * @acc: The accumulator.  It is stored in POLYVAL format rather than GHASH
82c417e704SEric Biggers  *	 format, since most implementations want it in POLYVAL format.
83c417e704SEric Biggers  * @partial: Number of data bytes processed so far modulo GHASH_BLOCK_SIZE
84c417e704SEric Biggers  */
85c417e704SEric Biggers struct ghash_ctx {
86c417e704SEric Biggers 	const struct ghash_key *key;
87c417e704SEric Biggers 	struct polyval_elem acc;
88c417e704SEric Biggers 	size_t partial;
89c417e704SEric Biggers };
90c417e704SEric Biggers 
91c417e704SEric Biggers /**
9261f66c52SEric Biggers  * struct polyval_ctx - Context for computing a POLYVAL value
9361f66c52SEric Biggers  * @key: Pointer to the prepared POLYVAL key.  The user of the API is
9461f66c52SEric Biggers  *	 responsible for ensuring that the key lives as long as the context.
9561f66c52SEric Biggers  * @acc: The accumulator
9661f66c52SEric Biggers  * @partial: Number of data bytes processed so far modulo POLYVAL_BLOCK_SIZE
9761f66c52SEric Biggers  */
9861f66c52SEric Biggers struct polyval_ctx {
9961f66c52SEric Biggers 	const struct polyval_key *key;
10061f66c52SEric Biggers 	struct polyval_elem acc;
10161f66c52SEric Biggers 	size_t partial;
10261f66c52SEric Biggers };
10361f66c52SEric Biggers 
10461f66c52SEric Biggers /**
105c417e704SEric Biggers  * ghash_preparekey() - Prepare a GHASH key
106c417e704SEric Biggers  * @key: (output) The key structure to initialize
107c417e704SEric Biggers  * @raw_key: The raw hash key
108c417e704SEric Biggers  *
109c417e704SEric Biggers  * Initialize a GHASH key structure from a raw key.
110c417e704SEric Biggers  *
111c417e704SEric Biggers  * Context: Any context.
112c417e704SEric Biggers  */
113c417e704SEric Biggers void ghash_preparekey(struct ghash_key *key,
114c417e704SEric Biggers 		      const u8 raw_key[GHASH_BLOCK_SIZE]);
115c417e704SEric Biggers 
116c417e704SEric Biggers /**
11761f66c52SEric Biggers  * polyval_preparekey() - Prepare a POLYVAL key
11861f66c52SEric Biggers  * @key: (output) The key structure to initialize
11961f66c52SEric Biggers  * @raw_key: The raw hash key
12061f66c52SEric Biggers  *
12161f66c52SEric Biggers  * Initialize a POLYVAL key structure from a raw key.  This may be a simple
12261f66c52SEric Biggers  * copy, or it may involve precomputing powers of the key, depending on the
12361f66c52SEric Biggers  * platform's POLYVAL implementation.
12461f66c52SEric Biggers  *
12561f66c52SEric Biggers  * Context: Any context.
12661f66c52SEric Biggers  */
12761f66c52SEric Biggers void polyval_preparekey(struct polyval_key *key,
12861f66c52SEric Biggers 			const u8 raw_key[POLYVAL_BLOCK_SIZE]);
12961f66c52SEric Biggers 
13061f66c52SEric Biggers /**
131c417e704SEric Biggers  * ghash_init() - Initialize a GHASH context for a new message
132c417e704SEric Biggers  * @ctx: The context to initialize
133c417e704SEric Biggers  * @key: The key to use.  Note that a pointer to the key is saved in the
134c417e704SEric Biggers  *	 context, so the key must live at least as long as the context.
135c417e704SEric Biggers  */
136c417e704SEric Biggers static inline void ghash_init(struct ghash_ctx *ctx,
137c417e704SEric Biggers 			      const struct ghash_key *key)
138c417e704SEric Biggers {
139c417e704SEric Biggers 	*ctx = (struct ghash_ctx){ .key = key };
140c417e704SEric Biggers }
141c417e704SEric Biggers 
142c417e704SEric Biggers /**
14361f66c52SEric Biggers  * polyval_init() - Initialize a POLYVAL context for a new message
14461f66c52SEric Biggers  * @ctx: The context to initialize
14561f66c52SEric Biggers  * @key: The key to use.  Note that a pointer to the key is saved in the
14661f66c52SEric Biggers  *	 context, so the key must live at least as long as the context.
14761f66c52SEric Biggers  */
14861f66c52SEric Biggers static inline void polyval_init(struct polyval_ctx *ctx,
14961f66c52SEric Biggers 				const struct polyval_key *key)
15061f66c52SEric Biggers {
15161f66c52SEric Biggers 	*ctx = (struct polyval_ctx){ .key = key };
15261f66c52SEric Biggers }
15361f66c52SEric Biggers 
15461f66c52SEric Biggers /**
15561f66c52SEric Biggers  * polyval_import_blkaligned() - Import a POLYVAL accumulator value
15661f66c52SEric Biggers  * @ctx: The context to initialize
15761f66c52SEric Biggers  * @key: The key to import.  Note that a pointer to the key is saved in the
15861f66c52SEric Biggers  *	 context, so the key must live at least as long as the context.
15961f66c52SEric Biggers  * @acc: The accumulator value to import.
16061f66c52SEric Biggers  *
16161f66c52SEric Biggers  * This imports an accumulator that was saved by polyval_export_blkaligned().
16261f66c52SEric Biggers  * The same key must be used.
16361f66c52SEric Biggers  */
16461f66c52SEric Biggers static inline void
16561f66c52SEric Biggers polyval_import_blkaligned(struct polyval_ctx *ctx,
16661f66c52SEric Biggers 			  const struct polyval_key *key,
16761f66c52SEric Biggers 			  const struct polyval_elem *acc)
16861f66c52SEric Biggers {
16961f66c52SEric Biggers 	*ctx = (struct polyval_ctx){ .key = key, .acc = *acc };
17061f66c52SEric Biggers }
17161f66c52SEric Biggers 
17261f66c52SEric Biggers /**
17361f66c52SEric Biggers  * polyval_export_blkaligned() - Export a POLYVAL accumulator value
17461f66c52SEric Biggers  * @ctx: The context to export the accumulator value from
17561f66c52SEric Biggers  * @acc: (output) The exported accumulator value
17661f66c52SEric Biggers  *
17761f66c52SEric Biggers  * This exports the accumulator from a POLYVAL context.  The number of data
17861f66c52SEric Biggers  * bytes processed so far must be a multiple of POLYVAL_BLOCK_SIZE.
17961f66c52SEric Biggers  */
18061f66c52SEric Biggers static inline void polyval_export_blkaligned(const struct polyval_ctx *ctx,
18161f66c52SEric Biggers 					     struct polyval_elem *acc)
18261f66c52SEric Biggers {
18361f66c52SEric Biggers 	*acc = ctx->acc;
18461f66c52SEric Biggers }
18561f66c52SEric Biggers 
18661f66c52SEric Biggers /**
187c417e704SEric Biggers  * ghash_update() - Update a GHASH context with message data
188c417e704SEric Biggers  * @ctx: The context to update; must have been initialized
189c417e704SEric Biggers  * @data: The message data
190c417e704SEric Biggers  * @len: The data length in bytes.  Doesn't need to be block-aligned.
191c417e704SEric Biggers  *
192c417e704SEric Biggers  * This can be called any number of times.
193c417e704SEric Biggers  *
194c417e704SEric Biggers  * Context: Any context.
195c417e704SEric Biggers  */
196c417e704SEric Biggers void ghash_update(struct ghash_ctx *ctx, const u8 *data, size_t len);
197c417e704SEric Biggers 
198c417e704SEric Biggers /**
19961f66c52SEric Biggers  * polyval_update() - Update a POLYVAL context with message data
20061f66c52SEric Biggers  * @ctx: The context to update; must have been initialized
20161f66c52SEric Biggers  * @data: The message data
20261f66c52SEric Biggers  * @len: The data length in bytes.  Doesn't need to be block-aligned.
20361f66c52SEric Biggers  *
20461f66c52SEric Biggers  * This can be called any number of times.
20561f66c52SEric Biggers  *
20661f66c52SEric Biggers  * Context: Any context.
20761f66c52SEric Biggers  */
20861f66c52SEric Biggers void polyval_update(struct polyval_ctx *ctx, const u8 *data, size_t len);
20961f66c52SEric Biggers 
21061f66c52SEric Biggers /**
211c417e704SEric Biggers  * ghash_final() - Finish computing a GHASH value
212c417e704SEric Biggers  * @ctx: The context to finalize
213c417e704SEric Biggers  * @out: The output value
214c417e704SEric Biggers  *
215c417e704SEric Biggers  * If the total data length isn't a multiple of GHASH_BLOCK_SIZE, then the
216c417e704SEric Biggers  * final block is automatically zero-padded.
217c417e704SEric Biggers  *
218c417e704SEric Biggers  * After finishing, this zeroizes @ctx.  So the caller does not need to do it.
219c417e704SEric Biggers  *
220c417e704SEric Biggers  * Context: Any context.
221c417e704SEric Biggers  */
222c417e704SEric Biggers void ghash_final(struct ghash_ctx *ctx, u8 out[GHASH_BLOCK_SIZE]);
223c417e704SEric Biggers 
224c417e704SEric Biggers /**
22561f66c52SEric Biggers  * polyval_final() - Finish computing a POLYVAL value
22661f66c52SEric Biggers  * @ctx: The context to finalize
22761f66c52SEric Biggers  * @out: The output value
22861f66c52SEric Biggers  *
22961f66c52SEric Biggers  * If the total data length isn't a multiple of POLYVAL_BLOCK_SIZE, then the
23061f66c52SEric Biggers  * final block is automatically zero-padded.
23161f66c52SEric Biggers  *
23261f66c52SEric Biggers  * After finishing, this zeroizes @ctx.  So the caller does not need to do it.
23361f66c52SEric Biggers  *
23461f66c52SEric Biggers  * Context: Any context.
23561f66c52SEric Biggers  */
23661f66c52SEric Biggers void polyval_final(struct polyval_ctx *ctx, u8 out[POLYVAL_BLOCK_SIZE]);
23761f66c52SEric Biggers 
23861f66c52SEric Biggers /**
239c417e704SEric Biggers  * ghash() - Compute a GHASH value
240c417e704SEric Biggers  * @key: The prepared key
241c417e704SEric Biggers  * @data: The message data
242c417e704SEric Biggers  * @len: The data length in bytes.  Doesn't need to be block-aligned.
243c417e704SEric Biggers  * @out: The output value
244c417e704SEric Biggers  *
245c417e704SEric Biggers  * Context: Any context.
246c417e704SEric Biggers  */
247c417e704SEric Biggers static inline void ghash(const struct ghash_key *key, const u8 *data,
248c417e704SEric Biggers 			 size_t len, u8 out[GHASH_BLOCK_SIZE])
249c417e704SEric Biggers {
250c417e704SEric Biggers 	struct ghash_ctx ctx;
251c417e704SEric Biggers 
252c417e704SEric Biggers 	ghash_init(&ctx, key);
253c417e704SEric Biggers 	ghash_update(&ctx, data, len);
254c417e704SEric Biggers 	ghash_final(&ctx, out);
255c417e704SEric Biggers }
256c417e704SEric Biggers 
257c417e704SEric Biggers /**
25861f66c52SEric Biggers  * polyval() - Compute a POLYVAL value
25961f66c52SEric Biggers  * @key: The prepared key
26061f66c52SEric Biggers  * @data: The message data
26161f66c52SEric Biggers  * @len: The data length in bytes.  Doesn't need to be block-aligned.
26261f66c52SEric Biggers  * @out: The output value
26361f66c52SEric Biggers  *
26461f66c52SEric Biggers  * Context: Any context.
26561f66c52SEric Biggers  */
26661f66c52SEric Biggers static inline void polyval(const struct polyval_key *key,
26761f66c52SEric Biggers 			   const u8 *data, size_t len,
26861f66c52SEric Biggers 			   u8 out[POLYVAL_BLOCK_SIZE])
26961f66c52SEric Biggers {
27061f66c52SEric Biggers 	struct polyval_ctx ctx;
27161f66c52SEric Biggers 
27261f66c52SEric Biggers 	polyval_init(&ctx, key);
27361f66c52SEric Biggers 	polyval_update(&ctx, data, len);
27461f66c52SEric Biggers 	polyval_final(&ctx, out);
27561f66c52SEric Biggers }
27661f66c52SEric Biggers 
27761f66c52SEric Biggers #endif /* _CRYPTO_GF128HASH_H */
278