xref: /linux/include/crypto/gf128hash.h (revision c417e7045b70345f59643fb2db67b0e7fbd7fbd0)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * GF(2^128) polynomial hashing: GHASH and POLYVAL
4  *
5  * Copyright 2025 Google LLC
6  */
7 
8 #ifndef _CRYPTO_GF128HASH_H
9 #define _CRYPTO_GF128HASH_H
10 
11 #include <linux/string.h>
12 #include <linux/types.h>
13 
14 #define GHASH_BLOCK_SIZE	16
15 #define GHASH_DIGEST_SIZE	16
16 #define POLYVAL_BLOCK_SIZE	16
17 #define POLYVAL_DIGEST_SIZE	16
18 
19 /**
20  * struct polyval_elem - An element of the POLYVAL finite field
21  * @bytes: View of the element as a byte array (unioned with @lo and @hi)
22  * @lo: The low 64 terms of the element's polynomial
23  * @hi: The high 64 terms of the element's polynomial
24  *
25  * This represents an element of the finite field GF(2^128), using the POLYVAL
26  * convention: little-endian byte order and natural bit order.
27  */
28 struct polyval_elem {
29 	union {
30 		u8 bytes[POLYVAL_BLOCK_SIZE];
31 		struct {
32 			__le64 lo;
33 			__le64 hi;
34 		};
35 	};
36 };
37 
38 /**
39  * struct ghash_key - Prepared key for GHASH
40  *
41  * Use ghash_preparekey() to initialize this.
42  */
43 struct ghash_key {
44 	/** @h: The hash key H, in POLYVAL format */
45 	struct polyval_elem h;
46 };
47 
48 /**
49  * struct polyval_key - Prepared key for POLYVAL
50  *
51  * This may contain just the raw key H, or it may contain precomputed key
52  * powers, depending on the platform's POLYVAL implementation.  Use
53  * polyval_preparekey() to initialize this.
54  *
55  * By H^i we mean H^(i-1) * H * x^-128, with base case H^1 = H.  I.e. the
56  * exponentiation repeats the POLYVAL dot operation, with its "extra" x^-128.
57  */
58 struct polyval_key {
59 #if defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && \
60 	(defined(CONFIG_ARM64) || defined(CONFIG_X86))
61 	/** @h_powers: Powers of the hash key H^8 through H^1 */
62 	struct polyval_elem h_powers[8];
63 #else
64 	/** @h: The hash key H */
65 	struct polyval_elem h;
66 #endif
67 };
68 
69 /**
70  * struct ghash_ctx - Context for computing a GHASH value
71  * @key: Pointer to the prepared GHASH key.  The user of the API is
72  *	 responsible for ensuring that the key lives as long as the context.
73  * @acc: The accumulator.  It is stored in POLYVAL format rather than GHASH
74  *	 format, since most implementations want it in POLYVAL format.
75  * @partial: Number of data bytes processed so far modulo GHASH_BLOCK_SIZE
76  */
77 struct ghash_ctx {
78 	const struct ghash_key *key;
79 	struct polyval_elem acc;
80 	size_t partial;
81 };
82 
83 /**
84  * struct polyval_ctx - Context for computing a POLYVAL value
85  * @key: Pointer to the prepared POLYVAL key.  The user of the API is
86  *	 responsible for ensuring that the key lives as long as the context.
87  * @acc: The accumulator
88  * @partial: Number of data bytes processed so far modulo POLYVAL_BLOCK_SIZE
89  */
90 struct polyval_ctx {
91 	const struct polyval_key *key;
92 	struct polyval_elem acc;
93 	size_t partial;
94 };
95 
96 /**
97  * ghash_preparekey() - Prepare a GHASH key
98  * @key: (output) The key structure to initialize
99  * @raw_key: The raw hash key
100  *
101  * Initialize a GHASH key structure from a raw key.
102  *
103  * Context: Any context.
104  */
105 void ghash_preparekey(struct ghash_key *key,
106 		      const u8 raw_key[GHASH_BLOCK_SIZE]);
107 
108 /**
109  * polyval_preparekey() - Prepare a POLYVAL key
110  * @key: (output) The key structure to initialize
111  * @raw_key: The raw hash key
112  *
113  * Initialize a POLYVAL key structure from a raw key.  This may be a simple
114  * copy, or it may involve precomputing powers of the key, depending on the
115  * platform's POLYVAL implementation.
116  *
117  * Context: Any context.
118  */
119 void polyval_preparekey(struct polyval_key *key,
120 			const u8 raw_key[POLYVAL_BLOCK_SIZE]);
121 
122 /**
123  * ghash_init() - Initialize a GHASH context for a new message
124  * @ctx: The context to initialize
125  * @key: The key to use.  Note that a pointer to the key is saved in the
126  *	 context, so the key must live at least as long as the context.
127  */
128 static inline void ghash_init(struct ghash_ctx *ctx,
129 			      const struct ghash_key *key)
130 {
131 	*ctx = (struct ghash_ctx){ .key = key };
132 }
133 
134 /**
135  * polyval_init() - Initialize a POLYVAL context for a new message
136  * @ctx: The context to initialize
137  * @key: The key to use.  Note that a pointer to the key is saved in the
138  *	 context, so the key must live at least as long as the context.
139  */
140 static inline void polyval_init(struct polyval_ctx *ctx,
141 				const struct polyval_key *key)
142 {
143 	*ctx = (struct polyval_ctx){ .key = key };
144 }
145 
146 /**
147  * polyval_import_blkaligned() - Import a POLYVAL accumulator value
148  * @ctx: The context to initialize
149  * @key: The key to import.  Note that a pointer to the key is saved in the
150  *	 context, so the key must live at least as long as the context.
151  * @acc: The accumulator value to import.
152  *
153  * This imports an accumulator that was saved by polyval_export_blkaligned().
154  * The same key must be used.
155  */
156 static inline void
157 polyval_import_blkaligned(struct polyval_ctx *ctx,
158 			  const struct polyval_key *key,
159 			  const struct polyval_elem *acc)
160 {
161 	*ctx = (struct polyval_ctx){ .key = key, .acc = *acc };
162 }
163 
164 /**
165  * polyval_export_blkaligned() - Export a POLYVAL accumulator value
166  * @ctx: The context to export the accumulator value from
167  * @acc: (output) The exported accumulator value
168  *
169  * This exports the accumulator from a POLYVAL context.  The number of data
170  * bytes processed so far must be a multiple of POLYVAL_BLOCK_SIZE.
171  */
172 static inline void polyval_export_blkaligned(const struct polyval_ctx *ctx,
173 					     struct polyval_elem *acc)
174 {
175 	*acc = ctx->acc;
176 }
177 
178 /**
179  * ghash_update() - Update a GHASH context with message data
180  * @ctx: The context to update; must have been initialized
181  * @data: The message data
182  * @len: The data length in bytes.  Doesn't need to be block-aligned.
183  *
184  * This can be called any number of times.
185  *
186  * Context: Any context.
187  */
188 void ghash_update(struct ghash_ctx *ctx, const u8 *data, size_t len);
189 
190 /**
191  * polyval_update() - Update a POLYVAL context with message data
192  * @ctx: The context to update; must have been initialized
193  * @data: The message data
194  * @len: The data length in bytes.  Doesn't need to be block-aligned.
195  *
196  * This can be called any number of times.
197  *
198  * Context: Any context.
199  */
200 void polyval_update(struct polyval_ctx *ctx, const u8 *data, size_t len);
201 
202 /**
203  * ghash_final() - Finish computing a GHASH value
204  * @ctx: The context to finalize
205  * @out: The output value
206  *
207  * If the total data length isn't a multiple of GHASH_BLOCK_SIZE, then the
208  * final block is automatically zero-padded.
209  *
210  * After finishing, this zeroizes @ctx.  So the caller does not need to do it.
211  *
212  * Context: Any context.
213  */
214 void ghash_final(struct ghash_ctx *ctx, u8 out[GHASH_BLOCK_SIZE]);
215 
216 /**
217  * polyval_final() - Finish computing a POLYVAL value
218  * @ctx: The context to finalize
219  * @out: The output value
220  *
221  * If the total data length isn't a multiple of POLYVAL_BLOCK_SIZE, then the
222  * final block is automatically zero-padded.
223  *
224  * After finishing, this zeroizes @ctx.  So the caller does not need to do it.
225  *
226  * Context: Any context.
227  */
228 void polyval_final(struct polyval_ctx *ctx, u8 out[POLYVAL_BLOCK_SIZE]);
229 
230 /**
231  * ghash() - Compute a GHASH value
232  * @key: The prepared key
233  * @data: The message data
234  * @len: The data length in bytes.  Doesn't need to be block-aligned.
235  * @out: The output value
236  *
237  * Context: Any context.
238  */
239 static inline void ghash(const struct ghash_key *key, const u8 *data,
240 			 size_t len, u8 out[GHASH_BLOCK_SIZE])
241 {
242 	struct ghash_ctx ctx;
243 
244 	ghash_init(&ctx, key);
245 	ghash_update(&ctx, data, len);
246 	ghash_final(&ctx, out);
247 }
248 
249 /**
250  * polyval() - Compute a POLYVAL value
251  * @key: The prepared key
252  * @data: The message data
253  * @len: The data length in bytes.  Doesn't need to be block-aligned.
254  * @out: The output value
255  *
256  * Context: Any context.
257  */
258 static inline void polyval(const struct polyval_key *key,
259 			   const u8 *data, size_t len,
260 			   u8 out[POLYVAL_BLOCK_SIZE])
261 {
262 	struct polyval_ctx ctx;
263 
264 	polyval_init(&ctx, key);
265 	polyval_update(&ctx, data, len);
266 	polyval_final(&ctx, out);
267 }
268 
269 #endif /* _CRYPTO_GF128HASH_H */
270