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.
This commit is contained in:
Stephen Heumann 2023-12-10 15:09:57 -06:00
parent 5a986a996f
commit 191a27af86
3 changed files with 58 additions and 8 deletions

View File

@ -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);
}

View File

@ -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");
}

22
md5.h
View File

@ -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);