From 191a27af865335ebccaf5b8a0ed3622e0d0ed406 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sun, 10 Dec 2023 15:09:57 -0600 Subject: [PATCH] Update HMAC-MD5 code to support processing a message in multiple parts. This is implemented in the common HMAC code and can apply to the other hash algorithms as well, but the header and tests are currently only implemented for HMAC-MD5. --- hmacimpl.h | 31 +++++++++++++++++++++++++++++-- hmactest.c | 13 +++++++++++-- md5.h | 22 ++++++++++++++++++---- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/hmacimpl.h b/hmacimpl.h index 3d9fdee..d1c2c93 100644 --- a/hmacimpl.h +++ b/hmacimpl.h @@ -31,15 +31,18 @@ #define hash_finalize concat(HASH_ALG,_finalize) #define hmac_init concat3(hmac_,HASH_ALG,_init) +#define hmac_update concat3(hmac_,HASH_ALG,_update) +#define hmac_finalize concat3(hmac_,HASH_ALG,_finalize) #define hmac_compute concat3(hmac_,HASH_ALG,_compute) #define hmac_context concat3(hmac_,HASH_ALG,_context) +#define BLOCK_SIZE sizeof(context->u[0].ctx.block) +#define HASH_SIZE sizeof(context->u[0].ctx.hash) + void hmac_init(struct hmac_context *context, const unsigned char *key, unsigned long key_length) { -#define BLOCK_SIZE sizeof(context->u[0].ctx.block) -#define HASH_SIZE sizeof(context->u[0].ctx.hash) unsigned i; @@ -67,6 +70,30 @@ void hmac_init(struct hmac_context *context, // Save outer hash context following initial block as context->u[1].ctx hash_init(&context->u[1].ctx); hash_update(&context->u[1].ctx, context->u[0].k, BLOCK_SIZE); + + // initialize context for use with hmac_update + context->u[0].ctx = context->u[2].ctx; +} + + +void hmac_update(struct hmac_context *context, + const unsigned char *message_part, + unsigned long part_length) +{ + hash_update(&context->u[0].ctx, message_part, part_length); +} + + +void hmac_finalize(struct hmac_context *context) +{ + // finalize inner hash + hash_finalize(&context->u[0].ctx); + memcpy(context->inner_hash, context->u[0].ctx.hash, HASH_SIZE); + + // Compute outer hash + context->u[0].ctx = context->u[1].ctx; + hash_update(&context->u[0].ctx, context->inner_hash, HASH_SIZE); + hash_finalize(&context->u[0].ctx); } diff --git a/hmactest.c b/hmactest.c index d733837..577b26d 100644 --- a/hmactest.c +++ b/hmactest.c @@ -48,7 +48,6 @@ int main(void) { printf("%02x", hmac_sha256_context->u[0].ctx.hash[i]); } printf("\n"); - hmac_sha1_context = (struct hmac_sha1_context *)*context_hndl; hmac_sha1_init(hmac_sha1_context, key, sizeof(key)-1); @@ -60,7 +59,6 @@ int main(void) { } printf("\n"); - hmac_md5_context = (struct hmac_md5_context *)*context_hndl; hmac_md5_init(hmac_md5_context, key, sizeof(key)-1); hmac_md5_compute(hmac_md5_context, msg, sizeof(msg)-1); @@ -81,4 +79,15 @@ int main(void) { printf("%02x", hmac_md4_context->u[0].ctx.hash[i]); } printf("\n"); + + hmac_md5_init(hmac_md5_context, key, sizeof(key)-1); + hmac_md5_update(hmac_md5_context, "T", 1); + hmac_md5_update(hmac_md5_context, msg+1, sizeof(msg)-2); + hmac_md5_finalize(hmac_md5_context); + + printf("HMAC-MD5 (incremental calculation): "); + for (int i = 0; i < sizeof(hmac_md5_context->u[0].ctx.hash); i++) { + printf("%02x", hmac_md5_context->u[0].ctx.hash[i]); + } + printf("\n"); } diff --git a/md5.h b/md5.h index 3d40b16..282184d 100644 --- a/md5.h +++ b/md5.h @@ -60,18 +60,32 @@ void md5_processblock(struct md5_context *context); /* * Initialize a context for HMAC-MD5 computation with a specified key. - * This must be called before any calls to hmac_md5_compute. After - * initialization, the context can be used to compute the HMAC for any - * number of messages. + * This must be called before any other HMAC calls. After initialization, + * the context can be used with either hmac_md5_update/hmac_md5_finalize + * or hmac_md5_compute, but they should not be mixed. */ void hmac_md5_init(struct hmac_md5_context *context, const unsigned char *key, unsigned long key_length); /* - * Compute the HMAC-MD5 of a message, using an already-initialized context. + * Update an HMAC-MD5 context based on the specified data. + */ +void hmac_md5_update(struct hmac_md5_context *context, + const unsigned char *message_part, + unsigned long part_length); + +/* + * Finish HMAC-MD5 processing and generate the final HMAC. * The result will be in context->u[0].ctx.hash. */ +void hmac_md5_finalize(struct hmac_md5_context *context); + +/* + * Compute the HMAC-MD5 of a message as a single operation. + * The result will be in context->u[0].ctx.hash. + * The context can be reused for multiple hmac_md5_compute operations. + */ void hmac_md5_compute(struct hmac_md5_context *context, const unsigned char *message, unsigned long message_length);