summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@kernel.org>2026-03-19 09:17:04 +0300
committerEric Biggers <ebiggers@kernel.org>2026-03-23 23:15:13 +0300
commitc417e7045b70345f59643fb2db67b0e7fbd7fbd0 (patch)
tree1685779a09103dad4fccb193a1e26ed8d391f93a /include
parentb3b6e8f9b38911e9b30a5abe845541ade0797327 (diff)
downloadlinux-c417e7045b70345f59643fb2db67b0e7fbd7fbd0.tar.xz
lib/crypto: gf128hash: Add GHASH support
Add GHASH support to the gf128hash module. This will replace the GHASH support in the crypto_shash API. It will be used by the "gcm" template and by the AES-GCM library (when an arch-optimized implementation of the full AES-GCM is unavailable). This consists of a simple API that mirrors the existing POLYVAL API, a generic implementation of that API based on the existing efficient and side-channel-resistant polyval_mul_generic(), and the framework for architecture-optimized implementations of the GHASH functions. The GHASH accumulator is stored in POLYVAL format rather than GHASH format, since this is what most modern GHASH implementations actually need. The few implementations that expect the accumulator in GHASH format will just convert the accumulator to/from GHASH format temporarily. (Supporting architecture-specific accumulator formats would be possible, but doesn't seem worth the complexity.) However, architecture-specific formats of struct ghash_key will be supported, since a variety of formats will be needed there anyway. The default format is just the key in POLYVAL format. Acked-by: Ard Biesheuvel <ardb@kernel.org> Link: https://lore.kernel.org/r/20260319061723.1140720-4-ebiggers@kernel.org Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Diffstat (limited to 'include')
-rw-r--r--include/crypto/gf128hash.h95
1 files changed, 95 insertions, 0 deletions
diff --git a/include/crypto/gf128hash.h b/include/crypto/gf128hash.h
index 1052041e3499..5090fbaa87f8 100644
--- a/include/crypto/gf128hash.h
+++ b/include/crypto/gf128hash.h
@@ -11,6 +11,8 @@
#include <linux/string.h>
#include <linux/types.h>
+#define GHASH_BLOCK_SIZE 16
+#define GHASH_DIGEST_SIZE 16
#define POLYVAL_BLOCK_SIZE 16
#define POLYVAL_DIGEST_SIZE 16
@@ -34,6 +36,16 @@ struct polyval_elem {
};
/**
+ * struct ghash_key - Prepared key for GHASH
+ *
+ * Use ghash_preparekey() to initialize this.
+ */
+struct ghash_key {
+ /** @h: The hash key H, in POLYVAL format */
+ struct polyval_elem h;
+};
+
+/**
* struct polyval_key - Prepared key for POLYVAL
*
* This may contain just the raw key H, or it may contain precomputed key
@@ -55,6 +67,20 @@ struct polyval_key {
};
/**
+ * struct ghash_ctx - Context for computing a GHASH value
+ * @key: Pointer to the prepared GHASH key. The user of the API is
+ * responsible for ensuring that the key lives as long as the context.
+ * @acc: The accumulator. It is stored in POLYVAL format rather than GHASH
+ * format, since most implementations want it in POLYVAL format.
+ * @partial: Number of data bytes processed so far modulo GHASH_BLOCK_SIZE
+ */
+struct ghash_ctx {
+ const struct ghash_key *key;
+ struct polyval_elem acc;
+ size_t partial;
+};
+
+/**
* struct polyval_ctx - Context for computing a POLYVAL value
* @key: Pointer to the prepared POLYVAL key. The user of the API is
* responsible for ensuring that the key lives as long as the context.
@@ -68,6 +94,18 @@ struct polyval_ctx {
};
/**
+ * ghash_preparekey() - Prepare a GHASH key
+ * @key: (output) The key structure to initialize
+ * @raw_key: The raw hash key
+ *
+ * Initialize a GHASH key structure from a raw key.
+ *
+ * Context: Any context.
+ */
+void ghash_preparekey(struct ghash_key *key,
+ const u8 raw_key[GHASH_BLOCK_SIZE]);
+
+/**
* polyval_preparekey() - Prepare a POLYVAL key
* @key: (output) The key structure to initialize
* @raw_key: The raw hash key
@@ -82,6 +120,18 @@ void polyval_preparekey(struct polyval_key *key,
const u8 raw_key[POLYVAL_BLOCK_SIZE]);
/**
+ * ghash_init() - Initialize a GHASH context for a new message
+ * @ctx: The context to initialize
+ * @key: The key to use. Note that a pointer to the key is saved in the
+ * context, so the key must live at least as long as the context.
+ */
+static inline void ghash_init(struct ghash_ctx *ctx,
+ const struct ghash_key *key)
+{
+ *ctx = (struct ghash_ctx){ .key = key };
+}
+
+/**
* polyval_init() - Initialize a POLYVAL context for a new message
* @ctx: The context to initialize
* @key: The key to use. Note that a pointer to the key is saved in the
@@ -126,6 +176,18 @@ static inline void polyval_export_blkaligned(const struct polyval_ctx *ctx,
}
/**
+ * ghash_update() - Update a GHASH context with message data
+ * @ctx: The context to update; must have been initialized
+ * @data: The message data
+ * @len: The data length in bytes. Doesn't need to be block-aligned.
+ *
+ * This can be called any number of times.
+ *
+ * Context: Any context.
+ */
+void ghash_update(struct ghash_ctx *ctx, const u8 *data, size_t len);
+
+/**
* polyval_update() - Update a POLYVAL context with message data
* @ctx: The context to update; must have been initialized
* @data: The message data
@@ -138,6 +200,20 @@ static inline void polyval_export_blkaligned(const struct polyval_ctx *ctx,
void polyval_update(struct polyval_ctx *ctx, const u8 *data, size_t len);
/**
+ * ghash_final() - Finish computing a GHASH value
+ * @ctx: The context to finalize
+ * @out: The output value
+ *
+ * If the total data length isn't a multiple of GHASH_BLOCK_SIZE, then the
+ * final block is automatically zero-padded.
+ *
+ * After finishing, this zeroizes @ctx. So the caller does not need to do it.
+ *
+ * Context: Any context.
+ */
+void ghash_final(struct ghash_ctx *ctx, u8 out[GHASH_BLOCK_SIZE]);
+
+/**
* polyval_final() - Finish computing a POLYVAL value
* @ctx: The context to finalize
* @out: The output value
@@ -152,6 +228,25 @@ void polyval_update(struct polyval_ctx *ctx, const u8 *data, size_t len);
void polyval_final(struct polyval_ctx *ctx, u8 out[POLYVAL_BLOCK_SIZE]);
/**
+ * ghash() - Compute a GHASH value
+ * @key: The prepared key
+ * @data: The message data
+ * @len: The data length in bytes. Doesn't need to be block-aligned.
+ * @out: The output value
+ *
+ * Context: Any context.
+ */
+static inline void ghash(const struct ghash_key *key, const u8 *data,
+ size_t len, u8 out[GHASH_BLOCK_SIZE])
+{
+ struct ghash_ctx ctx;
+
+ ghash_init(&ctx, key);
+ ghash_update(&ctx, data, len);
+ ghash_final(&ctx, out);
+}
+
+/**
* polyval() - Compute a POLYVAL value
* @key: The prepared key
* @data: The message data