From: Michael Brown Date: Mon, 29 Jun 2026 15:37:53 +0000 (+0100) Subject: [crypto] Allow for the construction of fixed-size HMAC keys X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bbd7821bd42da5456ee068a471ef73d525ea26a1;p=thirdparty%2Fipxe.git [crypto] Allow for the construction of fixed-size HMAC keys An HMAC key can always be reduced to the block size of the underlying digest algorithm. Provide hmac_key() that can be used to perform this reduction, and hmac_init_key() as a way to initialise an HMAC digest operation from a previously reduced key. Signed-off-by: Michael Brown --- diff --git a/src/crypto/hmac.c b/src/crypto/hmac.c index ed4cefaad..7be2c6950 100644 --- a/src/crypto/hmac.c +++ b/src/crypto/hmac.c @@ -48,29 +48,46 @@ FILE_SECBOOT ( PERMITTED ); #include /** - * Initialise HMAC + * Construct HMAC reduced key * * @v digest Digest algorithm to use * @v ctx HMAC context - * @v key Key - * @v key_len Length of key + * @v secret Secret key + * @v len Length of secret key + * @v key HMAC reduced key to fill in */ -void hmac_init ( struct digest_algorithm *digest, void *ctx, const void *key, - size_t key_len ) { +void hmac_key ( struct digest_algorithm *digest, void *ctx, const void *secret, + size_t len, void *key ) { hmac_context_t ( digest ) *hctx = ctx; - unsigned int i; + hmac_key_t ( digest ) *hkey = key; - /* Construct input pad */ - memset ( hctx->pad, 0, sizeof ( hctx->pad ) ); - if ( key_len <= sizeof ( hctx->pad ) ) { - memcpy ( hctx->pad, key, key_len ); + /* Reduce key (if applicable) and zero-pad to block size */ + memset ( hkey->pad, 0, sizeof ( hkey->pad ) ); + if ( len <= sizeof ( hkey->pad ) ) { + memcpy ( hkey->pad, secret, len ); } else { digest_init ( digest, hctx->ctx ); - digest_update ( digest, hctx->ctx, key, key_len ); - digest_final ( digest, hctx->ctx, hctx->pad ); + digest_update ( digest, hctx->ctx, secret, len ); + digest_final ( digest, hctx->ctx, hkey->pad ); } - for ( i = 0 ; i < sizeof ( hctx->pad ) ; i++ ) { - hctx->pad[i] ^= 0x36; +} + +/** + * Initialise HMAC from reduced key + * + * @v digest Digest algorithm + * @v ctx HMAC context + * @v hkey HMAC key + */ +void hmac_init_key ( struct digest_algorithm *digest, void *ctx, + const void *key ) { + hmac_context_t ( digest ) *hctx = ctx; + const hmac_key_t ( digest ) *hkey = key; + unsigned int i; + + /* Construct input pad */ + for ( i = 0 ; i < sizeof ( hkey->pad ) ; i++ ) { + hctx->pad[i] = ( hkey->pad[i] ^ 0x36 ); } /* Start inner hash */ @@ -78,6 +95,25 @@ void hmac_init ( struct digest_algorithm *digest, void *ctx, const void *key, digest_update ( digest, hctx->ctx, hctx->pad, sizeof ( hctx->pad ) ); } +/** + * Initialise HMAC + * + * @v digest Digest algorithm to use + * @v ctx HMAC context + * @v secret Secret key + * @v len Length of secret key + */ +void hmac_init ( struct digest_algorithm *digest, void *ctx, + const void *secret, size_t len ) { + hmac_context_t ( digest ) *hctx = ctx; + + /* Construct reduced key (in input pad) */ + hmac_key ( digest, hctx->ctx, secret, len, hctx->pad ); + + /* Initialise HMAC */ + hmac_init_key ( digest, hctx->ctx, hctx->pad ); +} + /** * Finalise HMAC * diff --git a/src/include/ipxe/hmac.h b/src/include/ipxe/hmac.h index 12312c540..0ffecb278 100644 --- a/src/include/ipxe/hmac.h +++ b/src/include/ipxe/hmac.h @@ -11,6 +11,12 @@ FILE_SECBOOT ( PERMITTED ); #include +/** HMAC reduced key type */ +#define hmac_key_t( digest ) struct { \ + /** HMAC input/output padding */ \ + uint8_t pad[ digest->blocksize ]; \ + } __attribute__ (( packed )) + /** HMAC context type */ #define hmac_context_t( digest ) struct { \ /** Digest context */ \ @@ -19,6 +25,19 @@ FILE_SECBOOT ( PERMITTED ); uint8_t pad[ digest->blocksize ]; \ } __attribute__ (( packed )) +/** + * Calculate HMAC reduced key size + * + * @v digest Digest algorithm to use + * @ret len HMAC key pad size + */ +static inline __attribute__ (( always_inline )) size_t +hmac_keysize ( struct digest_algorithm *digest ) { + hmac_key_t ( digest ) *hkey; + + return sizeof ( hkey->pad ); +} + /** * Calculate HMAC context size * @@ -47,8 +66,12 @@ static inline void hmac_update ( struct digest_algorithm *digest, void *ctx, digest_update ( digest, hctx->ctx, data, len ); } +extern void hmac_key ( struct digest_algorithm *digest, void *ctx, + const void *secret, size_t len, void *key ); +extern void hmac_init_key ( struct digest_algorithm *digest, void *ctx, + const void *key ); extern void hmac_init ( struct digest_algorithm *digest, void *ctx, - const void *key, size_t key_len ); + const void *secret, size_t len ); extern void hmac_final ( struct digest_algorithm *digest, void *ctx, void *hmac ); diff --git a/src/tests/hmac_test.c b/src/tests/hmac_test.c index 5267999e4..bf66e95e0 100644 --- a/src/tests/hmac_test.c +++ b/src/tests/hmac_test.c @@ -101,11 +101,13 @@ static void hmac_okx ( struct hmac_test *test, const char *file, unsigned int line ) { struct digest_algorithm *digest = test->digest; uint8_t ctx[ hmac_ctxsize ( digest ) ]; + uint8_t key[ hmac_keysize ( digest ) ]; uint8_t hmac[digest->digestsize]; /* Sanity checks */ okx ( sizeof ( ctx ) == ( digest->ctxsize + digest->blocksize ), file, line ); + okx ( sizeof ( key ) == digest->blocksize, file, line ); okx ( test->expected_len == digest->digestsize, file, line ); /* Calculate HMAC */ @@ -118,8 +120,18 @@ static void hmac_okx ( struct hmac_test *test, const char *file, hmac_final ( digest, ctx, hmac ); DBGC ( test, "HMAC-%s result:\n", digest->name ); DBGC_HDA ( test, 0, hmac, sizeof ( hmac ) ); + okx ( memcmp ( hmac, test->expected, test->expected_len ) == 0, + file, line ); - /* Compare against expected result */ + /* Calculate HMAC using reduced key */ + hmac_key ( digest, ctx, test->key, test->key_len, key ); + DBGC ( test, "HMAC-%s key:\n", digest->name ); + DBGC_HDA ( test, 0, key, sizeof ( key ) ); + hmac_init_key ( digest, ctx, key ); + hmac_update ( digest, ctx, test->data, test->data_len ); + hmac_final ( digest, ctx, hmac ); + DBGC ( test, "HMAC-%s result:\n", digest->name ); + DBGC_HDA ( test, 0, hmac, sizeof ( hmac ) ); okx ( memcmp ( hmac, test->expected, test->expected_len ) == 0, file, line ); }