]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Add HMAC-MD5 library and tests
authorPavel Tvrdík <pawel.tvrdik@gmail.cz>
Wed, 13 May 2015 09:14:11 +0000 (11:14 +0200)
committerPavel Tvrdík <pawel.tvrdik@gmail.cz>
Wed, 13 May 2015 09:18:10 +0000 (11:18 +0200)
lib/md5.c
lib/md5.h
lib/md5_test.c

index e00f92a4634f4384f7987784e0b4f372665ae614..882ed7a13452535e561be71d88a4288d0bda42dc 100644 (file)
--- 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);
+}
index ef3ebdfc5b546ef1966e6a729311de72afa4b70d..8ace29cbd17226f23f0db91647b7f8a0e3dd61ab 100644 (file)
--- 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_ */
index 83ce5000f9673ecb70aeb48498b4e8511c982f92..e3baed1572ec29365b685ec699f83dd0dd9fd087 100644 (file)
@@ -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();
 }