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