Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 276 lines 8.1 kB view raw
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 */ 27struct 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 */ 42struct 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 */ 65struct 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 */ 84struct 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 */ 97struct 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 */ 112void 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 */ 126void 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 */ 135static 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 */ 147static 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 */ 163static inline void 164polyval_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 */ 179static 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 */ 195void 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 */ 207void 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 */ 221void 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 */ 235void 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 */ 246static 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 */ 265static 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 */