161f66c52SEric Biggers /* SPDX-License-Identifier: GPL-2.0-or-later */ 261f66c52SEric Biggers /* 361f66c52SEric Biggers * GF(2^128) polynomial hashing: GHASH and POLYVAL 461f66c52SEric Biggers * 561f66c52SEric Biggers * Copyright 2025 Google LLC 661f66c52SEric Biggers */ 761f66c52SEric Biggers 861f66c52SEric Biggers #ifndef _CRYPTO_GF128HASH_H 961f66c52SEric Biggers #define _CRYPTO_GF128HASH_H 1061f66c52SEric Biggers 1161f66c52SEric Biggers #include <linux/string.h> 1261f66c52SEric Biggers #include <linux/types.h> 1361f66c52SEric Biggers 14c417e704SEric Biggers #define GHASH_BLOCK_SIZE 16 15c417e704SEric Biggers #define GHASH_DIGEST_SIZE 16 1661f66c52SEric Biggers #define POLYVAL_BLOCK_SIZE 16 1761f66c52SEric Biggers #define POLYVAL_DIGEST_SIZE 16 1861f66c52SEric Biggers 1961f66c52SEric Biggers /** 2061f66c52SEric Biggers * struct polyval_elem - An element of the POLYVAL finite field 2161f66c52SEric Biggers * @bytes: View of the element as a byte array (unioned with @lo and @hi) 2261f66c52SEric Biggers * @lo: The low 64 terms of the element's polynomial 2361f66c52SEric Biggers * @hi: The high 64 terms of the element's polynomial 2461f66c52SEric Biggers * 2561f66c52SEric Biggers * This represents an element of the finite field GF(2^128), using the POLYVAL 2661f66c52SEric Biggers * convention: little-endian byte order and natural bit order. 2761f66c52SEric Biggers */ 2861f66c52SEric Biggers struct polyval_elem { 2961f66c52SEric Biggers union { 3061f66c52SEric Biggers u8 bytes[POLYVAL_BLOCK_SIZE]; 3161f66c52SEric Biggers struct { 3261f66c52SEric Biggers __le64 lo; 3361f66c52SEric Biggers __le64 hi; 3461f66c52SEric Biggers }; 3561f66c52SEric Biggers }; 3661f66c52SEric Biggers }; 3761f66c52SEric Biggers 3861f66c52SEric Biggers /** 39c417e704SEric Biggers * struct ghash_key - Prepared key for GHASH 40c417e704SEric Biggers * 41c417e704SEric Biggers * Use ghash_preparekey() to initialize this. 42c417e704SEric Biggers */ 43c417e704SEric Biggers struct ghash_key { 4473f315c1SEric Biggers #if defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && defined(CONFIG_PPC64) 4573f315c1SEric Biggers /** @htable: GHASH key format used by the POWER8 assembly code */ 4673f315c1SEric Biggers u64 htable[4][2]; 47*efd1d2c8SEric Biggers #elif defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && \ 48*efd1d2c8SEric Biggers (defined(CONFIG_RISCV) || defined(CONFIG_S390)) 49af413d71SEric Biggers /** @h_raw: The hash key H, in GHASH format */ 50af413d71SEric Biggers u8 h_raw[GHASH_BLOCK_SIZE]; 5173f315c1SEric Biggers #endif 52c417e704SEric Biggers /** @h: The hash key H, in POLYVAL format */ 53c417e704SEric Biggers struct polyval_elem h; 54c417e704SEric Biggers }; 55c417e704SEric Biggers 56c417e704SEric Biggers /** 5761f66c52SEric Biggers * struct polyval_key - Prepared key for POLYVAL 5861f66c52SEric Biggers * 5961f66c52SEric Biggers * This may contain just the raw key H, or it may contain precomputed key 6061f66c52SEric Biggers * powers, depending on the platform's POLYVAL implementation. Use 6161f66c52SEric Biggers * polyval_preparekey() to initialize this. 6261f66c52SEric Biggers * 6361f66c52SEric Biggers * By H^i we mean H^(i-1) * H * x^-128, with base case H^1 = H. I.e. the 6461f66c52SEric Biggers * exponentiation repeats the POLYVAL dot operation, with its "extra" x^-128. 6561f66c52SEric Biggers */ 6661f66c52SEric Biggers struct polyval_key { 67b3b6e8f9SEric Biggers #if defined(CONFIG_CRYPTO_LIB_GF128HASH_ARCH) && \ 68b3b6e8f9SEric Biggers (defined(CONFIG_ARM64) || defined(CONFIG_X86)) 6961f66c52SEric Biggers /** @h_powers: Powers of the hash key H^8 through H^1 */ 7061f66c52SEric Biggers struct polyval_elem h_powers[8]; 7161f66c52SEric Biggers #else 7261f66c52SEric Biggers /** @h: The hash key H */ 7361f66c52SEric Biggers struct polyval_elem h; 74b3b6e8f9SEric Biggers #endif 7561f66c52SEric Biggers }; 7661f66c52SEric Biggers 7761f66c52SEric Biggers /** 78c417e704SEric Biggers * struct ghash_ctx - Context for computing a GHASH value 79c417e704SEric Biggers * @key: Pointer to the prepared GHASH key. The user of the API is 80c417e704SEric Biggers * responsible for ensuring that the key lives as long as the context. 81c417e704SEric Biggers * @acc: The accumulator. It is stored in POLYVAL format rather than GHASH 82c417e704SEric Biggers * format, since most implementations want it in POLYVAL format. 83c417e704SEric Biggers * @partial: Number of data bytes processed so far modulo GHASH_BLOCK_SIZE 84c417e704SEric Biggers */ 85c417e704SEric Biggers struct ghash_ctx { 86c417e704SEric Biggers const struct ghash_key *key; 87c417e704SEric Biggers struct polyval_elem acc; 88c417e704SEric Biggers size_t partial; 89c417e704SEric Biggers }; 90c417e704SEric Biggers 91c417e704SEric Biggers /** 9261f66c52SEric Biggers * struct polyval_ctx - Context for computing a POLYVAL value 9361f66c52SEric Biggers * @key: Pointer to the prepared POLYVAL key. The user of the API is 9461f66c52SEric Biggers * responsible for ensuring that the key lives as long as the context. 9561f66c52SEric Biggers * @acc: The accumulator 9661f66c52SEric Biggers * @partial: Number of data bytes processed so far modulo POLYVAL_BLOCK_SIZE 9761f66c52SEric Biggers */ 9861f66c52SEric Biggers struct polyval_ctx { 9961f66c52SEric Biggers const struct polyval_key *key; 10061f66c52SEric Biggers struct polyval_elem acc; 10161f66c52SEric Biggers size_t partial; 10261f66c52SEric Biggers }; 10361f66c52SEric Biggers 10461f66c52SEric Biggers /** 105c417e704SEric Biggers * ghash_preparekey() - Prepare a GHASH key 106c417e704SEric Biggers * @key: (output) The key structure to initialize 107c417e704SEric Biggers * @raw_key: The raw hash key 108c417e704SEric Biggers * 109c417e704SEric Biggers * Initialize a GHASH key structure from a raw key. 110c417e704SEric Biggers * 111c417e704SEric Biggers * Context: Any context. 112c417e704SEric Biggers */ 113c417e704SEric Biggers void ghash_preparekey(struct ghash_key *key, 114c417e704SEric Biggers const u8 raw_key[GHASH_BLOCK_SIZE]); 115c417e704SEric Biggers 116c417e704SEric Biggers /** 11761f66c52SEric Biggers * polyval_preparekey() - Prepare a POLYVAL key 11861f66c52SEric Biggers * @key: (output) The key structure to initialize 11961f66c52SEric Biggers * @raw_key: The raw hash key 12061f66c52SEric Biggers * 12161f66c52SEric Biggers * Initialize a POLYVAL key structure from a raw key. This may be a simple 12261f66c52SEric Biggers * copy, or it may involve precomputing powers of the key, depending on the 12361f66c52SEric Biggers * platform's POLYVAL implementation. 12461f66c52SEric Biggers * 12561f66c52SEric Biggers * Context: Any context. 12661f66c52SEric Biggers */ 12761f66c52SEric Biggers void polyval_preparekey(struct polyval_key *key, 12861f66c52SEric Biggers const u8 raw_key[POLYVAL_BLOCK_SIZE]); 12961f66c52SEric Biggers 13061f66c52SEric Biggers /** 131c417e704SEric Biggers * ghash_init() - Initialize a GHASH context for a new message 132c417e704SEric Biggers * @ctx: The context to initialize 133c417e704SEric Biggers * @key: The key to use. Note that a pointer to the key is saved in the 134c417e704SEric Biggers * context, so the key must live at least as long as the context. 135c417e704SEric Biggers */ 136c417e704SEric Biggers static inline void ghash_init(struct ghash_ctx *ctx, 137c417e704SEric Biggers const struct ghash_key *key) 138c417e704SEric Biggers { 139c417e704SEric Biggers *ctx = (struct ghash_ctx){ .key = key }; 140c417e704SEric Biggers } 141c417e704SEric Biggers 142c417e704SEric Biggers /** 14361f66c52SEric Biggers * polyval_init() - Initialize a POLYVAL context for a new message 14461f66c52SEric Biggers * @ctx: The context to initialize 14561f66c52SEric Biggers * @key: The key to use. Note that a pointer to the key is saved in the 14661f66c52SEric Biggers * context, so the key must live at least as long as the context. 14761f66c52SEric Biggers */ 14861f66c52SEric Biggers static inline void polyval_init(struct polyval_ctx *ctx, 14961f66c52SEric Biggers const struct polyval_key *key) 15061f66c52SEric Biggers { 15161f66c52SEric Biggers *ctx = (struct polyval_ctx){ .key = key }; 15261f66c52SEric Biggers } 15361f66c52SEric Biggers 15461f66c52SEric Biggers /** 15561f66c52SEric Biggers * polyval_import_blkaligned() - Import a POLYVAL accumulator value 15661f66c52SEric Biggers * @ctx: The context to initialize 15761f66c52SEric Biggers * @key: The key to import. Note that a pointer to the key is saved in the 15861f66c52SEric Biggers * context, so the key must live at least as long as the context. 15961f66c52SEric Biggers * @acc: The accumulator value to import. 16061f66c52SEric Biggers * 16161f66c52SEric Biggers * This imports an accumulator that was saved by polyval_export_blkaligned(). 16261f66c52SEric Biggers * The same key must be used. 16361f66c52SEric Biggers */ 16461f66c52SEric Biggers static inline void 16561f66c52SEric Biggers polyval_import_blkaligned(struct polyval_ctx *ctx, 16661f66c52SEric Biggers const struct polyval_key *key, 16761f66c52SEric Biggers const struct polyval_elem *acc) 16861f66c52SEric Biggers { 16961f66c52SEric Biggers *ctx = (struct polyval_ctx){ .key = key, .acc = *acc }; 17061f66c52SEric Biggers } 17161f66c52SEric Biggers 17261f66c52SEric Biggers /** 17361f66c52SEric Biggers * polyval_export_blkaligned() - Export a POLYVAL accumulator value 17461f66c52SEric Biggers * @ctx: The context to export the accumulator value from 17561f66c52SEric Biggers * @acc: (output) The exported accumulator value 17661f66c52SEric Biggers * 17761f66c52SEric Biggers * This exports the accumulator from a POLYVAL context. The number of data 17861f66c52SEric Biggers * bytes processed so far must be a multiple of POLYVAL_BLOCK_SIZE. 17961f66c52SEric Biggers */ 18061f66c52SEric Biggers static inline void polyval_export_blkaligned(const struct polyval_ctx *ctx, 18161f66c52SEric Biggers struct polyval_elem *acc) 18261f66c52SEric Biggers { 18361f66c52SEric Biggers *acc = ctx->acc; 18461f66c52SEric Biggers } 18561f66c52SEric Biggers 18661f66c52SEric Biggers /** 187c417e704SEric Biggers * ghash_update() - Update a GHASH context with message data 188c417e704SEric Biggers * @ctx: The context to update; must have been initialized 189c417e704SEric Biggers * @data: The message data 190c417e704SEric Biggers * @len: The data length in bytes. Doesn't need to be block-aligned. 191c417e704SEric Biggers * 192c417e704SEric Biggers * This can be called any number of times. 193c417e704SEric Biggers * 194c417e704SEric Biggers * Context: Any context. 195c417e704SEric Biggers */ 196c417e704SEric Biggers void ghash_update(struct ghash_ctx *ctx, const u8 *data, size_t len); 197c417e704SEric Biggers 198c417e704SEric Biggers /** 19961f66c52SEric Biggers * polyval_update() - Update a POLYVAL context with message data 20061f66c52SEric Biggers * @ctx: The context to update; must have been initialized 20161f66c52SEric Biggers * @data: The message data 20261f66c52SEric Biggers * @len: The data length in bytes. Doesn't need to be block-aligned. 20361f66c52SEric Biggers * 20461f66c52SEric Biggers * This can be called any number of times. 20561f66c52SEric Biggers * 20661f66c52SEric Biggers * Context: Any context. 20761f66c52SEric Biggers */ 20861f66c52SEric Biggers void polyval_update(struct polyval_ctx *ctx, const u8 *data, size_t len); 20961f66c52SEric Biggers 21061f66c52SEric Biggers /** 211c417e704SEric Biggers * ghash_final() - Finish computing a GHASH value 212c417e704SEric Biggers * @ctx: The context to finalize 213c417e704SEric Biggers * @out: The output value 214c417e704SEric Biggers * 215c417e704SEric Biggers * If the total data length isn't a multiple of GHASH_BLOCK_SIZE, then the 216c417e704SEric Biggers * final block is automatically zero-padded. 217c417e704SEric Biggers * 218c417e704SEric Biggers * After finishing, this zeroizes @ctx. So the caller does not need to do it. 219c417e704SEric Biggers * 220c417e704SEric Biggers * Context: Any context. 221c417e704SEric Biggers */ 222c417e704SEric Biggers void ghash_final(struct ghash_ctx *ctx, u8 out[GHASH_BLOCK_SIZE]); 223c417e704SEric Biggers 224c417e704SEric Biggers /** 22561f66c52SEric Biggers * polyval_final() - Finish computing a POLYVAL value 22661f66c52SEric Biggers * @ctx: The context to finalize 22761f66c52SEric Biggers * @out: The output value 22861f66c52SEric Biggers * 22961f66c52SEric Biggers * If the total data length isn't a multiple of POLYVAL_BLOCK_SIZE, then the 23061f66c52SEric Biggers * final block is automatically zero-padded. 23161f66c52SEric Biggers * 23261f66c52SEric Biggers * After finishing, this zeroizes @ctx. So the caller does not need to do it. 23361f66c52SEric Biggers * 23461f66c52SEric Biggers * Context: Any context. 23561f66c52SEric Biggers */ 23661f66c52SEric Biggers void polyval_final(struct polyval_ctx *ctx, u8 out[POLYVAL_BLOCK_SIZE]); 23761f66c52SEric Biggers 23861f66c52SEric Biggers /** 239c417e704SEric Biggers * ghash() - Compute a GHASH value 240c417e704SEric Biggers * @key: The prepared key 241c417e704SEric Biggers * @data: The message data 242c417e704SEric Biggers * @len: The data length in bytes. Doesn't need to be block-aligned. 243c417e704SEric Biggers * @out: The output value 244c417e704SEric Biggers * 245c417e704SEric Biggers * Context: Any context. 246c417e704SEric Biggers */ 247c417e704SEric Biggers static inline void ghash(const struct ghash_key *key, const u8 *data, 248c417e704SEric Biggers size_t len, u8 out[GHASH_BLOCK_SIZE]) 249c417e704SEric Biggers { 250c417e704SEric Biggers struct ghash_ctx ctx; 251c417e704SEric Biggers 252c417e704SEric Biggers ghash_init(&ctx, key); 253c417e704SEric Biggers ghash_update(&ctx, data, len); 254c417e704SEric Biggers ghash_final(&ctx, out); 255c417e704SEric Biggers } 256c417e704SEric Biggers 257c417e704SEric Biggers /** 25861f66c52SEric Biggers * polyval() - Compute a POLYVAL value 25961f66c52SEric Biggers * @key: The prepared key 26061f66c52SEric Biggers * @data: The message data 26161f66c52SEric Biggers * @len: The data length in bytes. Doesn't need to be block-aligned. 26261f66c52SEric Biggers * @out: The output value 26361f66c52SEric Biggers * 26461f66c52SEric Biggers * Context: Any context. 26561f66c52SEric Biggers */ 26661f66c52SEric Biggers static inline void polyval(const struct polyval_key *key, 26761f66c52SEric Biggers const u8 *data, size_t len, 26861f66c52SEric Biggers u8 out[POLYVAL_BLOCK_SIZE]) 26961f66c52SEric Biggers { 27061f66c52SEric Biggers struct polyval_ctx ctx; 27161f66c52SEric Biggers 27261f66c52SEric Biggers polyval_init(&ctx, key); 27361f66c52SEric Biggers polyval_update(&ctx, data, len); 27461f66c52SEric Biggers polyval_final(&ctx, out); 27561f66c52SEric Biggers } 27661f66c52SEric Biggers 27761f66c52SEric Biggers #endif /* _CRYPTO_GF128HASH_H */ 278