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