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