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