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