From: Pavel TvrdĂ­k Date: Wed, 13 May 2015 09:14:11 +0000 (+0200) Subject: Add HMAC-MD5 library and tests X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=40d323e150531392e64cf8529fb09e7d5dd6d543;p=thirdparty%2Fbird.git Add HMAC-MD5 library and tests --- diff --git a/lib/md5.c b/lib/md5.c index e00f92a46..882ed7a13 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -247,3 +247,64 @@ void md5_transform(u32 buf[4], u32 const in[16]) buf[2] += c; buf[3] += d; } + +/** + * MD5-HMAC + */ + +static void +md5_hash_buffer(byte *outbuf, const byte *buffer, size_t length) +{ + md5_context hd_tmp; + + md5_init(&hd_tmp); + md5_update(&hd_tmp, buffer, length); + memcpy(outbuf, md5_final(&hd_tmp), MD5_SIZE); +} + +void +md5_hmac_init(md5_hmac_context *ctx, const byte *key, size_t keylen) +{ + byte keybuf[MD5_BLOCK_SIZE], buf[MD5_BLOCK_SIZE]; + + // Hash the key if necessary + if (keylen <= MD5_BLOCK_SIZE) + { + memcpy(keybuf, key, keylen); + bzero(keybuf + keylen, MD5_BLOCK_SIZE - keylen); + } + else + { + md5_hash_buffer(keybuf, key, keylen); + bzero(keybuf + MD5_SIZE, MD5_BLOCK_SIZE - MD5_SIZE); + } + + // Initialize the inner digest + md5_init(&ctx->ictx); + int i; + for (i = 0; i < MD5_BLOCK_SIZE; i++) + buf[i] = keybuf[i] ^ 0x36; + md5_update(&ctx->ictx, buf, MD5_BLOCK_SIZE); + + // Initialize the outer digest + md5_init(&ctx->octx); + for (i = 0; i < MD5_BLOCK_SIZE; i++) + buf[i] = keybuf[i] ^ 0x5c; + md5_update(&ctx->octx, buf, MD5_BLOCK_SIZE); +} + +void md5_hmac_update(md5_hmac_context *ctx, const byte *buf, size_t buflen) +{ + // Just update the inner digest + md5_update(&ctx->ictx, buf, buflen); +} + +byte *md5_hmac_final(md5_hmac_context *ctx) +{ + // Finish the inner digest + byte *isha = md5_final(&ctx->ictx); + + // Finish the outer digest + md5_update(&ctx->octx, isha, MD5_SIZE); + return md5_final(&ctx->octx); +} diff --git a/lib/md5.h b/lib/md5.h index ef3ebdfc5..8ace29cbd 100644 --- a/lib/md5.h +++ b/lib/md5.h @@ -28,5 +28,17 @@ byte *md5_final(md5_context *context); void md5_transform(u32 buf[4], u32 const in[16]); +/** + * HMAC-MD5 + */ +typedef struct +{ + md5_context ictx; + md5_context octx; +} md5_hmac_context; + +void md5_hmac_init(md5_hmac_context *ctx, const byte *key, size_t keylen); +void md5_hmac_update(md5_hmac_context *ctx, const byte *buf, size_t buflen); +byte *md5_hmac_final(md5_hmac_context *ctx); #endif /* _BIRD_MD5_H_ */ diff --git a/lib/md5_test.c b/lib/md5_test.c index 83ce5000f..e3baed157 100644 --- a/lib/md5_test.c +++ b/lib/md5_test.c @@ -69,12 +69,154 @@ t_md5(void) return BT_SUCCESS; } +#define HMAC_BUFFER_SIZE 80 +struct hmac_data_in { + byte key[HMAC_BUFFER_SIZE]; + uint key_len; + byte data[HMAC_BUFFER_SIZE]; + uint data_len; +}; + +static void +get_md5_hmac(const struct hmac_data_in in, char (*out_hash)[MD5_HEX_SIZE]) +{ + md5_hmac_context ctx; + md5_hmac_init(&ctx, in.key, in.key_len); + md5_hmac_update(&ctx, in.data, in.data_len); + byte *hash_byte = md5_hmac_final(&ctx); + + int i; + for (i = 0; i < MD5_SIZE; i++) + sprintf(*out_hash + i*2, "%02x", hash_byte[i]); +} + +static int +t_md5_hmac(void) +{ + struct in_out { + struct hmac_data_in in; + char out[MD5_HEX_SIZE]; + } in_out[] = { + { + .in = { + .key = { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, + .key_len = 16, + .data = "Hi There", + .data_len = 8, + }, + .out = "9294727a3638bb1c13f48ef8158bfc9d", + }, + { + .in = { + .key = "Jefe", + .key_len = 4, + .data = "what do ya want for nothing?", + .data_len = 28, + }, + .out = "750c783e6ab0b503eaa86e310a5db738", + }, + { + .in = { + .key = { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + }, + .key_len = 16, + .data = { + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + }, + .data_len = 50, + }, + .out = "56be34521d144c88dbb8c733f0e8b3f6", + }, + { + .in = { + .key = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, + }, + .key_len = 25, + .data = { + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + }, + .data_len = 50, + }, + .out = "697eaf0aca3a3aea3a75164746ffaa79", + }, + { + .in = { + .key = { + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + }, + .key_len = 16, + .data = "Test With Truncation", + .data_len = 20, + }, + .out = "56461ef2342edc00f9bab995690efd4c", + }, + { + .in = { + .key = { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + }, + .key_len = 80, + .data = "Test Using Larger Than Block-Size Key - Hash Key First", + .data_len = 54, + }, + .out = "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd", + }, + { + .in = { + .key = { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + }, + .key_len = 80, + .data = "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", + .data_len = 73, + }, + .out = "6f630fad67cda0ee1fb1f562db3aa53e", + }, + }; + + bt_assert_fn_in_out(get_md5_hmac, in_out, NULL, "'%s'"); + + return BT_SUCCESS; +} + int main(int argc, char *argv[]) { bt_init(argc, argv); - bt_test_suite(t_md5, "Test Suite by RFC 1321"); + bt_test_suite(t_md5, "Test Suite by RFC 1321"); + bt_test_suite(t_md5_hmac, "Test Suite by RFC 2202"); return bt_end(); }