]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Allow for the construction of fixed-size HMAC keys
authorMichael Brown <mcb30@ipxe.org>
Mon, 29 Jun 2026 15:37:53 +0000 (16:37 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 29 Jun 2026 15:43:12 +0000 (16:43 +0100)
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 <mcb30@ipxe.org>
src/crypto/hmac.c
src/include/ipxe/hmac.h
src/tests/hmac_test.c

index ed4cefaad7f811f3cfdcced478422cffd19d7414..7be2c695065ac3b348ea2baab5ea7e1503975980 100644 (file)
@@ -48,29 +48,46 @@ FILE_SECBOOT ( PERMITTED );
 #include <ipxe/hmac.h>
 
 /**
- * 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
  *
index 12312c5409ec73676bf1e9c7a184aeb449e4a284..0ffecb27830bfce8ffa73dbd909ca34ee0e3117f 100644 (file)
@@ -11,6 +11,12 @@ FILE_SECBOOT ( PERMITTED );
 
 #include <ipxe/crypto.h>
 
+/** 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 );
 
index 5267999e420ee3347fce0b9fc687e72415ebcc3c..bf66e95e0361e078b509c986a7615868a38deb05 100644 (file)
@@ -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 );
 }