13d176751SEric Biggers /* SPDX-License-Identifier: GPL-2.0-or-later */
2f3c923a0SNathan Huckleberry /*
361f66c52SEric Biggers * GF(2^128) polynomial hashing: GHASH and POLYVAL
4f3c923a0SNathan Huckleberry *
53d176751SEric Biggers * Copyright 2025 Google LLC
6f3c923a0SNathan Huckleberry */
7f3c923a0SNathan Huckleberry
861f66c52SEric Biggers #ifndef _CRYPTO_GF128HASH_H
961f66c52SEric Biggers #define _CRYPTO_GF128HASH_H
10f3c923a0SNathan Huckleberry
11*a78ae6e3SEric Biggers #include <crypto/ghash.h>
123d176751SEric Biggers #include <linux/string.h>
133d176751SEric Biggers #include <linux/types.h>
143d176751SEric Biggers
15f3c923a0SNathan Huckleberry #define POLYVAL_BLOCK_SIZE 16
16f3c923a0SNathan Huckleberry #define POLYVAL_DIGEST_SIZE 16
17f3c923a0SNathan Huckleberry
183d176751SEric Biggers /**
193d176751SEric Biggers * struct polyval_elem - An element of the POLYVAL finite field
203d176751SEric Biggers * @bytes: View of the element as a byte array (unioned with @lo and @hi)
213d176751SEric Biggers * @lo: The low 64 terms of the element's polynomial
223d176751SEric Biggers * @hi: The high 64 terms of the element's polynomial
233d176751SEric Biggers *
243d176751SEric Biggers * This represents an element of the finite field GF(2^128), using the POLYVAL
253d176751SEric Biggers * convention: little-endian byte order and natural bit order.
263d176751SEric Biggers */
273d176751SEric Biggers struct polyval_elem {
283d176751SEric Biggers union {
293d176751SEric Biggers u8 bytes[POLYVAL_BLOCK_SIZE];
303d176751SEric Biggers struct {
313d176751SEric Biggers __le64 lo;
323d176751SEric Biggers __le64 hi;
333d176751SEric Biggers };
343d176751SEric Biggers };
353d176751SEric Biggers };
363d176751SEric Biggers
373d176751SEric Biggers /**
38c417e704SEric Biggers * struct ghash_key - Prepared key for GHASH
39c417e704SEric Biggers *
40c417e704SEric Biggers * Use ghash_preparekey() to initialize this.
41c417e704SEric Biggers */
42c417e704SEric Biggers struct ghash_key {
4373f315c1SEric Biggers #if defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && defined(CONFIG_PPC64)
4473f315c1SEric Biggers /** @htable: GHASH key format used by the POWER8 assembly code */
4573f315c1SEric Biggers u64 htable[4][2];
46efd1d2c8SEric Biggers #elif defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && \
47efd1d2c8SEric Biggers (defined(CONFIG_RISCV) || defined(CONFIG_S390))
48af413d71SEric Biggers /** @h_raw: The hash key H, in GHASH format */
49af413d71SEric Biggers u8 h_raw[GHASH_BLOCK_SIZE];
5073f315c1SEric Biggers #endif
51c417e704SEric Biggers /** @h: The hash key H, in POLYVAL format */
52c417e704SEric Biggers struct polyval_elem h;
53c417e704SEric Biggers };
54c417e704SEric Biggers
55c417e704SEric Biggers /**
563d176751SEric Biggers * struct polyval_key - Prepared key for POLYVAL
573d176751SEric Biggers *
583d176751SEric Biggers * This may contain just the raw key H, or it may contain precomputed key
593d176751SEric Biggers * powers, depending on the platform's POLYVAL implementation. Use
603d176751SEric Biggers * polyval_preparekey() to initialize this.
6137919e23SEric Biggers *
6237919e23SEric Biggers * By H^i we mean H^(i-1) * H * x^-128, with base case H^1 = H. I.e. the
6337919e23SEric Biggers * exponentiation repeats the POLYVAL dot operation, with its "extra" x^-128.
643d176751SEric Biggers */
653d176751SEric Biggers struct polyval_key {
66b3b6e8f9SEric Biggers #if defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && \
67b3b6e8f9SEric Biggers (defined(CONFIG_ARM64) || defined(CONFIG_X86))
684d8da355SEric Biggers /** @h_powers: Powers of the hash key H^8 through H^1 */
694d8da355SEric Biggers struct polyval_elem h_powers[8];
7037919e23SEric Biggers #else
713d176751SEric Biggers /** @h: The hash key H */
723d176751SEric Biggers struct polyval_elem h;
73b3b6e8f9SEric Biggers #endif
743d176751SEric Biggers };
753d176751SEric Biggers
763d176751SEric Biggers /**
77c417e704SEric Biggers * struct ghash_ctx - Context for computing a GHASH value
78c417e704SEric Biggers * @key: Pointer to the prepared GHASH key. The user of the API is
79c417e704SEric Biggers * responsible for ensuring that the key lives as long as the context.
80c417e704SEric Biggers * @acc: The accumulator. It is stored in POLYVAL format rather than GHASH
81c417e704SEric Biggers * format, since most implementations want it in POLYVAL format.
82c417e704SEric Biggers * @partial: Number of data bytes processed so far modulo GHASH_BLOCK_SIZE
83c417e704SEric Biggers */
84c417e704SEric Biggers struct ghash_ctx {
85c417e704SEric Biggers const struct ghash_key *key;
86c417e704SEric Biggers struct polyval_elem acc;
87c417e704SEric Biggers size_t partial;
88c417e704SEric Biggers };
89c417e704SEric Biggers
90c417e704SEric Biggers /**
913d176751SEric Biggers * struct polyval_ctx - Context for computing a POLYVAL value
923d176751SEric Biggers * @key: Pointer to the prepared POLYVAL key. The user of the API is
933d176751SEric Biggers * responsible for ensuring that the key lives as long as the context.
943d176751SEric Biggers * @acc: The accumulator
953d176751SEric Biggers * @partial: Number of data bytes processed so far modulo POLYVAL_BLOCK_SIZE
963d176751SEric Biggers */
973d176751SEric Biggers struct polyval_ctx {
983d176751SEric Biggers const struct polyval_key *key;
993d176751SEric Biggers struct polyval_elem acc;
1003d176751SEric Biggers size_t partial;
1013d176751SEric Biggers };
1023d176751SEric Biggers
1033d176751SEric Biggers /**
104c417e704SEric Biggers * ghash_preparekey() - Prepare a GHASH key
105c417e704SEric Biggers * @key: (output) The key structure to initialize
106c417e704SEric Biggers * @raw_key: The raw hash key
107c417e704SEric Biggers *
108c417e704SEric Biggers * Initialize a GHASH key structure from a raw key.
109c417e704SEric Biggers *
110c417e704SEric Biggers * Context: Any context.
111c417e704SEric Biggers */
112c417e704SEric Biggers void ghash_preparekey(struct ghash_key *key,
113c417e704SEric Biggers const u8 raw_key[GHASH_BLOCK_SIZE]);
114c417e704SEric Biggers
115c417e704SEric Biggers /**
1163d176751SEric Biggers * polyval_preparekey() - Prepare a POLYVAL key
1173d176751SEric Biggers * @key: (output) The key structure to initialize
1183d176751SEric Biggers * @raw_key: The raw hash key
1193d176751SEric Biggers *
1203d176751SEric Biggers * Initialize a POLYVAL key structure from a raw key. This may be a simple
1213d176751SEric Biggers * copy, or it may involve precomputing powers of the key, depending on the
1223d176751SEric Biggers * platform's POLYVAL implementation.
1233d176751SEric Biggers *
1243d176751SEric Biggers * Context: Any context.
1253d176751SEric Biggers */
1263d176751SEric Biggers void polyval_preparekey(struct polyval_key *key,
1273d176751SEric Biggers const u8 raw_key[POLYVAL_BLOCK_SIZE]);
1283d176751SEric Biggers
1293d176751SEric Biggers /**
130c417e704SEric Biggers * ghash_init() - Initialize a GHASH context for a new message
131c417e704SEric Biggers * @ctx: The context to initialize
132c417e704SEric Biggers * @key: The key to use. Note that a pointer to the key is saved in the
133c417e704SEric Biggers * context, so the key must live at least as long as the context.
134c417e704SEric Biggers */
ghash_init(struct ghash_ctx * ctx,const struct ghash_key * key)135c417e704SEric Biggers static inline void ghash_init(struct ghash_ctx *ctx,
136c417e704SEric Biggers const struct ghash_key *key)
137c417e704SEric Biggers {
138c417e704SEric Biggers *ctx = (struct ghash_ctx){ .key = key };
139c417e704SEric Biggers }
140c417e704SEric Biggers
141c417e704SEric Biggers /**
1423d176751SEric Biggers * polyval_init() - Initialize a POLYVAL context for a new message
1433d176751SEric Biggers * @ctx: The context to initialize
1443d176751SEric Biggers * @key: The key to use. Note that a pointer to the key is saved in the
1453d176751SEric Biggers * context, so the key must live at least as long as the context.
1463d176751SEric Biggers */
polyval_init(struct polyval_ctx * ctx,const struct polyval_key * key)1473d176751SEric Biggers static inline void polyval_init(struct polyval_ctx *ctx,
1483d176751SEric Biggers const struct polyval_key *key)
1493d176751SEric Biggers {
1503d176751SEric Biggers *ctx = (struct polyval_ctx){ .key = key };
1513d176751SEric Biggers }
1523d176751SEric Biggers
1533d176751SEric Biggers /**
1543d176751SEric Biggers * polyval_import_blkaligned() - Import a POLYVAL accumulator value
1553d176751SEric Biggers * @ctx: The context to initialize
1563d176751SEric Biggers * @key: The key to import. Note that a pointer to the key is saved in the
1573d176751SEric Biggers * context, so the key must live at least as long as the context.
1583d176751SEric Biggers * @acc: The accumulator value to import.
1593d176751SEric Biggers *
1603d176751SEric Biggers * This imports an accumulator that was saved by polyval_export_blkaligned().
1613d176751SEric Biggers * The same key must be used.
1623d176751SEric Biggers */
1633d176751SEric Biggers static inline void
polyval_import_blkaligned(struct polyval_ctx * ctx,const struct polyval_key * key,const struct polyval_elem * acc)1643d176751SEric Biggers polyval_import_blkaligned(struct polyval_ctx *ctx,
1653d176751SEric Biggers const struct polyval_key *key,
1663d176751SEric Biggers const struct polyval_elem *acc)
1673d176751SEric Biggers {
1683d176751SEric Biggers *ctx = (struct polyval_ctx){ .key = key, .acc = *acc };
1693d176751SEric Biggers }
1703d176751SEric Biggers
1713d176751SEric Biggers /**
1723d176751SEric Biggers * polyval_export_blkaligned() - Export a POLYVAL accumulator value
1733d176751SEric Biggers * @ctx: The context to export the accumulator value from
1743d176751SEric Biggers * @acc: (output) The exported accumulator value
1753d176751SEric Biggers *
1763d176751SEric Biggers * This exports the accumulator from a POLYVAL context. The number of data
1773d176751SEric Biggers * bytes processed so far must be a multiple of POLYVAL_BLOCK_SIZE.
1783d176751SEric Biggers */
polyval_export_blkaligned(const struct polyval_ctx * ctx,struct polyval_elem * acc)1793d176751SEric Biggers static inline void polyval_export_blkaligned(const struct polyval_ctx *ctx,
1803d176751SEric Biggers struct polyval_elem *acc)
1813d176751SEric Biggers {
1823d176751SEric Biggers *acc = ctx->acc;
1833d176751SEric Biggers }
1843d176751SEric Biggers
1853d176751SEric Biggers /**
186c417e704SEric Biggers * ghash_update() - Update a GHASH context with message data
187c417e704SEric Biggers * @ctx: The context to update; must have been initialized
188c417e704SEric Biggers * @data: The message data
189c417e704SEric Biggers * @len: The data length in bytes. Doesn't need to be block-aligned.
190c417e704SEric Biggers *
191c417e704SEric Biggers * This can be called any number of times.
192c417e704SEric Biggers *
193c417e704SEric Biggers * Context: Any context.
194c417e704SEric Biggers */
195c417e704SEric Biggers void ghash_update(struct ghash_ctx *ctx, const u8 *data, size_t len);
196c417e704SEric Biggers
197c417e704SEric Biggers /**
1983d176751SEric Biggers * polyval_update() - Update a POLYVAL context with message data
1993d176751SEric Biggers * @ctx: The context to update; must have been initialized
2003d176751SEric Biggers * @data: The message data
2013d176751SEric Biggers * @len: The data length in bytes. Doesn't need to be block-aligned.
2023d176751SEric Biggers *
2033d176751SEric Biggers * This can be called any number of times.
2043d176751SEric Biggers *
2053d176751SEric Biggers * Context: Any context.
2063d176751SEric Biggers */
2073d176751SEric Biggers void polyval_update(struct polyval_ctx *ctx, const u8 *data, size_t len);
2083d176751SEric Biggers
2093d176751SEric Biggers /**
210c417e704SEric Biggers * ghash_final() - Finish computing a GHASH value
211c417e704SEric Biggers * @ctx: The context to finalize
212c417e704SEric Biggers * @out: The output value
213c417e704SEric Biggers *
214c417e704SEric Biggers * If the total data length isn't a multiple of GHASH_BLOCK_SIZE, then the
215c417e704SEric Biggers * final block is automatically zero-padded.
216c417e704SEric Biggers *
217c417e704SEric Biggers * After finishing, this zeroizes @ctx. So the caller does not need to do it.
218c417e704SEric Biggers *
219c417e704SEric Biggers * Context: Any context.
220c417e704SEric Biggers */
221c417e704SEric Biggers void ghash_final(struct ghash_ctx *ctx, u8 out[GHASH_BLOCK_SIZE]);
222c417e704SEric Biggers
223c417e704SEric Biggers /**
2243d176751SEric Biggers * polyval_final() - Finish computing a POLYVAL value
2253d176751SEric Biggers * @ctx: The context to finalize
2263d176751SEric Biggers * @out: The output value
2273d176751SEric Biggers *
2283d176751SEric Biggers * If the total data length isn't a multiple of POLYVAL_BLOCK_SIZE, then the
2293d176751SEric Biggers * final block is automatically zero-padded.
2303d176751SEric Biggers *
2313d176751SEric Biggers * After finishing, this zeroizes @ctx. So the caller does not need to do it.
2323d176751SEric Biggers *
2333d176751SEric Biggers * Context: Any context.
2343d176751SEric Biggers */
2353d176751SEric Biggers void polyval_final(struct polyval_ctx *ctx, u8 out[POLYVAL_BLOCK_SIZE]);
2363d176751SEric Biggers
2373d176751SEric Biggers /**
238c417e704SEric Biggers * ghash() - Compute a GHASH value
239c417e704SEric Biggers * @key: The prepared key
240c417e704SEric Biggers * @data: The message data
241c417e704SEric Biggers * @len: The data length in bytes. Doesn't need to be block-aligned.
242c417e704SEric Biggers * @out: The output value
243c417e704SEric Biggers *
244c417e704SEric Biggers * Context: Any context.
245c417e704SEric Biggers */
ghash(const struct ghash_key * key,const u8 * data,size_t len,u8 out[GHASH_BLOCK_SIZE])246c417e704SEric Biggers static inline void ghash(const struct ghash_key *key, const u8 *data,
247c417e704SEric Biggers size_t len, u8 out[GHASH_BLOCK_SIZE])
248c417e704SEric Biggers {
249c417e704SEric Biggers struct ghash_ctx ctx;
250c417e704SEric Biggers
251c417e704SEric Biggers ghash_init(&ctx, key);
252c417e704SEric Biggers ghash_update(&ctx, data, len);
253c417e704SEric Biggers ghash_final(&ctx, out);
254c417e704SEric Biggers }
255c417e704SEric Biggers
256c417e704SEric Biggers /**
2573d176751SEric Biggers * polyval() - Compute a POLYVAL value
2583d176751SEric Biggers * @key: The prepared key
2593d176751SEric Biggers * @data: The message data
2603d176751SEric Biggers * @len: The data length in bytes. Doesn't need to be block-aligned.
2613d176751SEric Biggers * @out: The output value
2623d176751SEric Biggers *
2633d176751SEric Biggers * Context: Any context.
2643d176751SEric Biggers */
polyval(const struct polyval_key * key,const u8 * data,size_t len,u8 out[POLYVAL_BLOCK_SIZE])2653d176751SEric Biggers static inline void polyval(const struct polyval_key *key,
2663d176751SEric Biggers const u8 *data, size_t len,
2673d176751SEric Biggers u8 out[POLYVAL_BLOCK_SIZE])
2683d176751SEric Biggers {
2693d176751SEric Biggers struct polyval_ctx ctx;
2703d176751SEric Biggers
2713d176751SEric Biggers polyval_init(&ctx, key);
2723d176751SEric Biggers polyval_update(&ctx, data, len);
2733d176751SEric Biggers polyval_final(&ctx, out);
2743d176751SEric Biggers }
2753d176751SEric Biggers
27661f66c52SEric Biggers #endif /* _CRYPTO_GF128HASH_H */
277