diff options
| author | Eric Biggers <ebiggers@kernel.org> | 2025-07-11 14:58:43 -0700 |
|---|---|---|
| committer | Eric Biggers <ebiggers@kernel.org> | 2025-07-14 08:20:37 -0700 |
| commit | 7941ad696506917fa6228f44be2df0c2f0909a62 (patch) | |
| tree | 615fc21f7dea8b8ea5b975bc522fa1f72950c513 | |
| parent | 6e07c5e166597de1d7943ecf2539cad18c0e2ce1 (diff) | |
lib/crypto: sha2: Add hmac_sha*_init_usingrawkey()
While the HMAC library functions support both incremental and one-shot
computation and both prepared and raw keys, the combination of raw key
+ incremental was missing. It turns out that several potential users of
the HMAC library functions (tpm2-sessions.c, smb2transport.c,
trusted_tpm1.c) want exactly that.
Therefore, add the missing functions hmac_sha*_init_usingrawkey().
Implement them in an optimized way that directly initializes the HMAC
context without a separate key preparation step.
Reimplement the one-shot raw key functions hmac_sha*_usingrawkey() on
top of the new functions, which makes them a bit more efficient.
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20250711215844.41715-1-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
| -rw-r--r-- | include/crypto/sha2.h | 60 | ||||
| -rw-r--r-- | lib/crypto/sha256.c | 53 | ||||
| -rw-r--r-- | lib/crypto/sha512.c | 55 |
3 files changed, 134 insertions, 34 deletions
diff --git a/include/crypto/sha2.h b/include/crypto/sha2.h index e0a08f6addd0..15e461e568cc 100644 --- a/include/crypto/sha2.h +++ b/include/crypto/sha2.h @@ -248,6 +248,21 @@ static inline void hmac_sha224_init(struct hmac_sha224_ctx *ctx, } /** + * hmac_sha224_init_usingrawkey() - Initialize an HMAC-SHA224 context for a new + * message, using a raw key + * @ctx: (output) the HMAC context to initialize + * @raw_key: the raw HMAC-SHA224 key + * @raw_key_len: the key length in bytes. All key lengths are supported. + * + * If you don't need incremental computation, consider hmac_sha224_usingrawkey() + * instead. + * + * Context: Any context. + */ +void hmac_sha224_init_usingrawkey(struct hmac_sha224_ctx *ctx, + const u8 *raw_key, size_t raw_key_len); + +/** * hmac_sha224_update() - Update an HMAC-SHA224 context with message data * @ctx: the HMAC context to update; must have been initialized * @data: the message data @@ -406,6 +421,21 @@ static inline void hmac_sha256_init(struct hmac_sha256_ctx *ctx, } /** + * hmac_sha256_init_usingrawkey() - Initialize an HMAC-SHA256 context for a new + * message, using a raw key + * @ctx: (output) the HMAC context to initialize + * @raw_key: the raw HMAC-SHA256 key + * @raw_key_len: the key length in bytes. All key lengths are supported. + * + * If you don't need incremental computation, consider hmac_sha256_usingrawkey() + * instead. + * + * Context: Any context. + */ +void hmac_sha256_init_usingrawkey(struct hmac_sha256_ctx *ctx, + const u8 *raw_key, size_t raw_key_len); + +/** * hmac_sha256_update() - Update an HMAC-SHA256 context with message data * @ctx: the HMAC context to update; must have been initialized * @data: the message data @@ -598,6 +628,21 @@ static inline void hmac_sha384_init(struct hmac_sha384_ctx *ctx, } /** + * hmac_sha384_init_usingrawkey() - Initialize an HMAC-SHA384 context for a new + * message, using a raw key + * @ctx: (output) the HMAC context to initialize + * @raw_key: the raw HMAC-SHA384 key + * @raw_key_len: the key length in bytes. All key lengths are supported. + * + * If you don't need incremental computation, consider hmac_sha384_usingrawkey() + * instead. + * + * Context: Any context. + */ +void hmac_sha384_init_usingrawkey(struct hmac_sha384_ctx *ctx, + const u8 *raw_key, size_t raw_key_len); + +/** * hmac_sha384_update() - Update an HMAC-SHA384 context with message data * @ctx: the HMAC context to update; must have been initialized * @data: the message data @@ -756,6 +801,21 @@ static inline void hmac_sha512_init(struct hmac_sha512_ctx *ctx, } /** + * hmac_sha512_init_usingrawkey() - Initialize an HMAC-SHA512 context for a new + * message, using a raw key + * @ctx: (output) the HMAC context to initialize + * @raw_key: the raw HMAC-SHA512 key + * @raw_key_len: the key length in bytes. All key lengths are supported. + * + * If you don't need incremental computation, consider hmac_sha512_usingrawkey() + * instead. + * + * Context: Any context. + */ +void hmac_sha512_init_usingrawkey(struct hmac_sha512_ctx *ctx, + const u8 *raw_key, size_t raw_key_len); + +/** * hmac_sha512_update() - Update an HMAC-SHA512 context with message data * @ctx: the HMAC context to update; must have been initialized * @data: the message data diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c index 808438d4f427..8fa15165d23e 100644 --- a/lib/crypto/sha256.c +++ b/lib/crypto/sha256.c @@ -263,7 +263,8 @@ EXPORT_SYMBOL(sha256); /* pre-boot environment (as indicated by __DISABLE_EXPORTS) doesn't need HMAC */ #ifndef __DISABLE_EXPORTS -static void __hmac_sha256_preparekey(struct __hmac_sha256_key *key, +static void __hmac_sha256_preparekey(struct sha256_block_state *istate, + struct sha256_block_state *ostate, const u8 *raw_key, size_t raw_key_len, const struct sha256_block_state *iv) { @@ -283,14 +284,14 @@ static void __hmac_sha256_preparekey(struct __hmac_sha256_key *key, for (size_t i = 0; i < ARRAY_SIZE(derived_key.w); i++) derived_key.w[i] ^= REPEAT_BYTE(HMAC_IPAD_VALUE); - key->istate = *iv; - sha256_blocks(&key->istate, derived_key.b, 1); + *istate = *iv; + sha256_blocks(istate, derived_key.b, 1); for (size_t i = 0; i < ARRAY_SIZE(derived_key.w); i++) derived_key.w[i] ^= REPEAT_BYTE(HMAC_OPAD_VALUE ^ HMAC_IPAD_VALUE); - key->ostate = *iv; - sha256_blocks(&key->ostate, derived_key.b, 1); + *ostate = *iv; + sha256_blocks(ostate, derived_key.b, 1); memzero_explicit(&derived_key, sizeof(derived_key)); } @@ -298,14 +299,16 @@ static void __hmac_sha256_preparekey(struct __hmac_sha256_key *key, void hmac_sha224_preparekey(struct hmac_sha224_key *key, const u8 *raw_key, size_t raw_key_len) { - __hmac_sha256_preparekey(&key->key, raw_key, raw_key_len, &sha224_iv); + __hmac_sha256_preparekey(&key->key.istate, &key->key.ostate, + raw_key, raw_key_len, &sha224_iv); } EXPORT_SYMBOL_GPL(hmac_sha224_preparekey); void hmac_sha256_preparekey(struct hmac_sha256_key *key, const u8 *raw_key, size_t raw_key_len) { - __hmac_sha256_preparekey(&key->key, raw_key, raw_key_len, &sha256_iv); + __hmac_sha256_preparekey(&key->key.istate, &key->key.ostate, + raw_key, raw_key_len, &sha256_iv); } EXPORT_SYMBOL_GPL(hmac_sha256_preparekey); @@ -317,6 +320,24 @@ void __hmac_sha256_init(struct __hmac_sha256_ctx *ctx, } EXPORT_SYMBOL_GPL(__hmac_sha256_init); +void hmac_sha224_init_usingrawkey(struct hmac_sha224_ctx *ctx, + const u8 *raw_key, size_t raw_key_len) +{ + __hmac_sha256_preparekey(&ctx->ctx.sha_ctx.state, &ctx->ctx.ostate, + raw_key, raw_key_len, &sha224_iv); + ctx->ctx.sha_ctx.bytecount = SHA256_BLOCK_SIZE; +} +EXPORT_SYMBOL_GPL(hmac_sha224_init_usingrawkey); + +void hmac_sha256_init_usingrawkey(struct hmac_sha256_ctx *ctx, + const u8 *raw_key, size_t raw_key_len) +{ + __hmac_sha256_preparekey(&ctx->ctx.sha_ctx.state, &ctx->ctx.ostate, + raw_key, raw_key_len, &sha256_iv); + ctx->ctx.sha_ctx.bytecount = SHA256_BLOCK_SIZE; +} +EXPORT_SYMBOL_GPL(hmac_sha256_init_usingrawkey); + static void __hmac_sha256_final(struct __hmac_sha256_ctx *ctx, u8 *out, size_t digest_size) { @@ -376,12 +397,11 @@ void hmac_sha224_usingrawkey(const u8 *raw_key, size_t raw_key_len, const u8 *data, size_t data_len, u8 out[SHA224_DIGEST_SIZE]) { - struct hmac_sha224_key key; - - hmac_sha224_preparekey(&key, raw_key, raw_key_len); - hmac_sha224(&key, data, data_len, out); + struct hmac_sha224_ctx ctx; - memzero_explicit(&key, sizeof(key)); + hmac_sha224_init_usingrawkey(&ctx, raw_key, raw_key_len); + hmac_sha224_update(&ctx, data, data_len); + hmac_sha224_final(&ctx, out); } EXPORT_SYMBOL_GPL(hmac_sha224_usingrawkey); @@ -389,12 +409,11 @@ void hmac_sha256_usingrawkey(const u8 *raw_key, size_t raw_key_len, const u8 *data, size_t data_len, u8 out[SHA256_DIGEST_SIZE]) { - struct hmac_sha256_key key; - - hmac_sha256_preparekey(&key, raw_key, raw_key_len); - hmac_sha256(&key, data, data_len, out); + struct hmac_sha256_ctx ctx; - memzero_explicit(&key, sizeof(key)); + hmac_sha256_init_usingrawkey(&ctx, raw_key, raw_key_len); + hmac_sha256_update(&ctx, data, data_len); + hmac_sha256_final(&ctx, out); } EXPORT_SYMBOL_GPL(hmac_sha256_usingrawkey); #endif /* !__DISABLE_EXPORTS */ diff --git a/lib/crypto/sha512.c b/lib/crypto/sha512.c index d514721491ca..d8062188be98 100644 --- a/lib/crypto/sha512.c +++ b/lib/crypto/sha512.c @@ -249,7 +249,8 @@ void sha512(const u8 *data, size_t len, u8 out[SHA512_DIGEST_SIZE]) } EXPORT_SYMBOL_GPL(sha512); -static void __hmac_sha512_preparekey(struct __hmac_sha512_key *key, +static void __hmac_sha512_preparekey(struct sha512_block_state *istate, + struct sha512_block_state *ostate, const u8 *raw_key, size_t raw_key_len, const struct sha512_block_state *iv) { @@ -269,14 +270,14 @@ static void __hmac_sha512_preparekey(struct __hmac_sha512_key *key, for (size_t i = 0; i < ARRAY_SIZE(derived_key.w); i++) derived_key.w[i] ^= REPEAT_BYTE(HMAC_IPAD_VALUE); - key->istate = *iv; - sha512_blocks(&key->istate, derived_key.b, 1); + *istate = *iv; + sha512_blocks(istate, derived_key.b, 1); for (size_t i = 0; i < ARRAY_SIZE(derived_key.w); i++) derived_key.w[i] ^= REPEAT_BYTE(HMAC_OPAD_VALUE ^ HMAC_IPAD_VALUE); - key->ostate = *iv; - sha512_blocks(&key->ostate, derived_key.b, 1); + *ostate = *iv; + sha512_blocks(ostate, derived_key.b, 1); memzero_explicit(&derived_key, sizeof(derived_key)); } @@ -284,14 +285,16 @@ static void __hmac_sha512_preparekey(struct __hmac_sha512_key *key, void hmac_sha384_preparekey(struct hmac_sha384_key *key, const u8 *raw_key, size_t raw_key_len) { - __hmac_sha512_preparekey(&key->key, raw_key, raw_key_len, &sha384_iv); + __hmac_sha512_preparekey(&key->key.istate, &key->key.ostate, + raw_key, raw_key_len, &sha384_iv); } EXPORT_SYMBOL_GPL(hmac_sha384_preparekey); void hmac_sha512_preparekey(struct hmac_sha512_key *key, const u8 *raw_key, size_t raw_key_len) { - __hmac_sha512_preparekey(&key->key, raw_key, raw_key_len, &sha512_iv); + __hmac_sha512_preparekey(&key->key.istate, &key->key.ostate, + raw_key, raw_key_len, &sha512_iv); } EXPORT_SYMBOL_GPL(hmac_sha512_preparekey); @@ -303,6 +306,26 @@ void __hmac_sha512_init(struct __hmac_sha512_ctx *ctx, } EXPORT_SYMBOL_GPL(__hmac_sha512_init); +void hmac_sha384_init_usingrawkey(struct hmac_sha384_ctx *ctx, + const u8 *raw_key, size_t raw_key_len) +{ + __hmac_sha512_preparekey(&ctx->ctx.sha_ctx.state, &ctx->ctx.ostate, + raw_key, raw_key_len, &sha384_iv); + ctx->ctx.sha_ctx.bytecount_lo = SHA512_BLOCK_SIZE; + ctx->ctx.sha_ctx.bytecount_hi = 0; +} +EXPORT_SYMBOL_GPL(hmac_sha384_init_usingrawkey); + +void hmac_sha512_init_usingrawkey(struct hmac_sha512_ctx *ctx, + const u8 *raw_key, size_t raw_key_len) +{ + __hmac_sha512_preparekey(&ctx->ctx.sha_ctx.state, &ctx->ctx.ostate, + raw_key, raw_key_len, &sha512_iv); + ctx->ctx.sha_ctx.bytecount_lo = SHA512_BLOCK_SIZE; + ctx->ctx.sha_ctx.bytecount_hi = 0; +} +EXPORT_SYMBOL_GPL(hmac_sha512_init_usingrawkey); + static void __hmac_sha512_final(struct __hmac_sha512_ctx *ctx, u8 *out, size_t digest_size) { @@ -362,12 +385,11 @@ void hmac_sha384_usingrawkey(const u8 *raw_key, size_t raw_key_len, const u8 *data, size_t data_len, u8 out[SHA384_DIGEST_SIZE]) { - struct hmac_sha384_key key; - - hmac_sha384_preparekey(&key, raw_key, raw_key_len); - hmac_sha384(&key, data, data_len, out); + struct hmac_sha384_ctx ctx; - memzero_explicit(&key, sizeof(key)); + hmac_sha384_init_usingrawkey(&ctx, raw_key, raw_key_len); + hmac_sha384_update(&ctx, data, data_len); + hmac_sha384_final(&ctx, out); } EXPORT_SYMBOL_GPL(hmac_sha384_usingrawkey); @@ -375,12 +397,11 @@ void hmac_sha512_usingrawkey(const u8 *raw_key, size_t raw_key_len, const u8 *data, size_t data_len, u8 out[SHA512_DIGEST_SIZE]) { - struct hmac_sha512_key key; - - hmac_sha512_preparekey(&key, raw_key, raw_key_len); - hmac_sha512(&key, data, data_len, out); + struct hmac_sha512_ctx ctx; - memzero_explicit(&key, sizeof(key)); + hmac_sha512_init_usingrawkey(&ctx, raw_key, raw_key_len); + hmac_sha512_update(&ctx, data, data_len); + hmac_sha512_final(&ctx, out); } EXPORT_SYMBOL_GPL(hmac_sha512_usingrawkey); |
