1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * POLYVAL library API 4 * 5 * Copyright 2025 Google LLC 6 */ 7 8 #ifndef _CRYPTO_POLYVAL_H 9 #define _CRYPTO_POLYVAL_H 10 11 #include <linux/string.h> 12 #include <linux/types.h> 13 14 #define POLYVAL_BLOCK_SIZE 16 15 #define POLYVAL_DIGEST_SIZE 16 16 17 /** 18 * struct polyval_elem - An element of the POLYVAL finite field 19 * @bytes: View of the element as a byte array (unioned with @lo and @hi) 20 * @lo: The low 64 terms of the element's polynomial 21 * @hi: The high 64 terms of the element's polynomial 22 * 23 * This represents an element of the finite field GF(2^128), using the POLYVAL 24 * convention: little-endian byte order and natural bit order. 25 */ 26 struct polyval_elem { 27 union { 28 u8 bytes[POLYVAL_BLOCK_SIZE]; 29 struct { 30 __le64 lo; 31 __le64 hi; 32 }; 33 }; 34 }; 35 36 /** 37 * struct polyval_key - Prepared key for POLYVAL 38 * 39 * This may contain just the raw key H, or it may contain precomputed key 40 * powers, depending on the platform's POLYVAL implementation. Use 41 * polyval_preparekey() to initialize this. 42 * 43 * By H^i we mean H^(i-1) * H * x^-128, with base case H^1 = H. I.e. the 44 * exponentiation repeats the POLYVAL dot operation, with its "extra" x^-128. 45 */ 46 struct polyval_key { 47 #ifdef CONFIG_CRYPTO_LIB_POLYVAL_ARCH 48 #ifdef CONFIG_ARM64 49 /** @h_powers: Powers of the hash key H^8 through H^1 */ 50 struct polyval_elem h_powers[8]; 51 #else 52 #error "Unhandled arch" 53 #endif 54 #else /* CONFIG_CRYPTO_LIB_POLYVAL_ARCH */ 55 /** @h: The hash key H */ 56 struct polyval_elem h; 57 #endif /* !CONFIG_CRYPTO_LIB_POLYVAL_ARCH */ 58 }; 59 60 /** 61 * struct polyval_ctx - Context for computing a POLYVAL value 62 * @key: Pointer to the prepared POLYVAL key. The user of the API is 63 * responsible for ensuring that the key lives as long as the context. 64 * @acc: The accumulator 65 * @partial: Number of data bytes processed so far modulo POLYVAL_BLOCK_SIZE 66 */ 67 struct polyval_ctx { 68 const struct polyval_key *key; 69 struct polyval_elem acc; 70 size_t partial; 71 }; 72 73 /** 74 * polyval_preparekey() - Prepare a POLYVAL key 75 * @key: (output) The key structure to initialize 76 * @raw_key: The raw hash key 77 * 78 * Initialize a POLYVAL key structure from a raw key. This may be a simple 79 * copy, or it may involve precomputing powers of the key, depending on the 80 * platform's POLYVAL implementation. 81 * 82 * Context: Any context. 83 */ 84 #ifdef CONFIG_CRYPTO_LIB_POLYVAL_ARCH 85 void polyval_preparekey(struct polyval_key *key, 86 const u8 raw_key[POLYVAL_BLOCK_SIZE]); 87 88 #else 89 static inline void polyval_preparekey(struct polyval_key *key, 90 const u8 raw_key[POLYVAL_BLOCK_SIZE]) 91 { 92 /* Just a simple copy, so inline it. */ 93 memcpy(key->h.bytes, raw_key, POLYVAL_BLOCK_SIZE); 94 } 95 #endif 96 97 /** 98 * polyval_init() - Initialize a POLYVAL context for a new message 99 * @ctx: The context to initialize 100 * @key: The key to use. Note that a pointer to the key is saved in the 101 * context, so the key must live at least as long as the context. 102 */ 103 static inline void polyval_init(struct polyval_ctx *ctx, 104 const struct polyval_key *key) 105 { 106 *ctx = (struct polyval_ctx){ .key = key }; 107 } 108 109 /** 110 * polyval_import_blkaligned() - Import a POLYVAL accumulator value 111 * @ctx: The context to initialize 112 * @key: The key to import. Note that a pointer to the key is saved in the 113 * context, so the key must live at least as long as the context. 114 * @acc: The accumulator value to import. 115 * 116 * This imports an accumulator that was saved by polyval_export_blkaligned(). 117 * The same key must be used. 118 */ 119 static inline void 120 polyval_import_blkaligned(struct polyval_ctx *ctx, 121 const struct polyval_key *key, 122 const struct polyval_elem *acc) 123 { 124 *ctx = (struct polyval_ctx){ .key = key, .acc = *acc }; 125 } 126 127 /** 128 * polyval_export_blkaligned() - Export a POLYVAL accumulator value 129 * @ctx: The context to export the accumulator value from 130 * @acc: (output) The exported accumulator value 131 * 132 * This exports the accumulator from a POLYVAL context. The number of data 133 * bytes processed so far must be a multiple of POLYVAL_BLOCK_SIZE. 134 */ 135 static inline void polyval_export_blkaligned(const struct polyval_ctx *ctx, 136 struct polyval_elem *acc) 137 { 138 *acc = ctx->acc; 139 } 140 141 /** 142 * polyval_update() - Update a POLYVAL context with message data 143 * @ctx: The context to update; must have been initialized 144 * @data: The message data 145 * @len: The data length in bytes. Doesn't need to be block-aligned. 146 * 147 * This can be called any number of times. 148 * 149 * Context: Any context. 150 */ 151 void polyval_update(struct polyval_ctx *ctx, const u8 *data, size_t len); 152 153 /** 154 * polyval_final() - Finish computing a POLYVAL value 155 * @ctx: The context to finalize 156 * @out: The output value 157 * 158 * If the total data length isn't a multiple of POLYVAL_BLOCK_SIZE, then the 159 * final block is automatically zero-padded. 160 * 161 * After finishing, this zeroizes @ctx. So the caller does not need to do it. 162 * 163 * Context: Any context. 164 */ 165 void polyval_final(struct polyval_ctx *ctx, u8 out[POLYVAL_BLOCK_SIZE]); 166 167 /** 168 * polyval() - Compute a POLYVAL value 169 * @key: The prepared key 170 * @data: The message data 171 * @len: The data length in bytes. Doesn't need to be block-aligned. 172 * @out: The output value 173 * 174 * Context: Any context. 175 */ 176 static inline void polyval(const struct polyval_key *key, 177 const u8 *data, size_t len, 178 u8 out[POLYVAL_BLOCK_SIZE]) 179 { 180 struct polyval_ctx ctx; 181 182 polyval_init(&ctx, key); 183 polyval_update(&ctx, data, len); 184 polyval_final(&ctx, out); 185 } 186 187 #endif /* _CRYPTO_POLYVAL_H */ 188