SEC: add HMAC implementation.
authorrasky <rasky@38d2e660-2303-0410-9eaa-f027e97ec537>
Fri, 24 Sep 2010 13:56:42 +0000 (13:56 +0000)
committerrasky <rasky@38d2e660-2303-0410-9eaa-f027e97ec537>
Fri, 24 Sep 2010 13:56:42 +0000 (13:56 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4302 38d2e660-2303-0410-9eaa-f027e97ec537

bertos/sec/mac/hmac.c [new file with mode: 0644]
bertos/sec/mac/hmac.h [new file with mode: 0644]
bertos/sec/mac/hmac_test.c [new file with mode: 0644]

diff --git a/bertos/sec/mac/hmac.c b/bertos/sec/mac/hmac.c
new file mode 100644 (file)
index 0000000..1616ec4
--- /dev/null
@@ -0,0 +1,105 @@
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction.  Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License.  This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
+ *
+ * -->
+ *
+ * \brief HMAC implementation
+ * \author Giovanni Bajo <rasky@develer.com>
+ * 
+ */
+
+#include "hmac.h"
+#include <sec/util.h>
+#include <string.h>
+
+
+static void HMAC_set_key(Mac *m, const uint8_t *key, size_t key_len)
+{
+       HMAC_Context *ctx = (HMAC_Context *)m;
+
+       memset(ctx->key, 0, ctx->m.key_len);
+       if (key_len <= ctx->m.key_len)
+               memcpy(ctx->key, key, key_len);         
+       else
+       {
+               hash_begin(ctx->h);
+               hash_update(ctx->h, key, key_len);
+               memcpy(ctx->key, hash_final(ctx->h), hash_digest_len(ctx->h));
+       }
+       
+       xor_block_const(ctx->key, ctx->key, 0x5C, ctx->m.key_len);
+}
+
+static void HMAC_begin(Mac *m)
+{
+       HMAC_Context *ctx = (HMAC_Context *)m;
+       int klen = ctx->m.key_len;
+       
+       xor_block_const(ctx->key, ctx->key, 0x36^0x5C, klen);
+       hash_begin(ctx->h);
+       hash_update(ctx->h, ctx->key, klen);
+}
+
+static void HMAC_update(Mac *m, const uint8_t *data, size_t len)
+{
+       HMAC_Context *ctx = (HMAC_Context *)m;
+       hash_update(ctx->h, data, len);
+}
+
+static uint8_t *HMAC_final(Mac *m)
+{
+       HMAC_Context *ctx = (HMAC_Context *)m;
+       int hlen = hash_digest_len(ctx->h);
+
+       uint8_t temp[hlen];
+       memcpy(temp, hash_final(ctx->h), hlen);
+       
+       xor_block_const(ctx->key, ctx->key, 0x5C^0x36, ctx->m.key_len);
+       hash_begin(ctx->h);
+       hash_update(ctx->h, ctx->key, ctx->m.key_len);
+       hash_update(ctx->h, temp, hlen);
+       
+       PURGE(temp);
+       return hash_final(ctx->h);
+}
+
+/*********************************************************************/
+
+void HMAC_init(HMAC_Context *ctx, Hash *h)
+{
+       ctx->h = h;
+       ctx->m.key_len = hash_block_len(h);
+       ctx->m.digest_len = hash_digest_len(h);
+       ctx->m.set_key = HMAC_set_key;
+       ctx->m.begin = HMAC_begin;
+       ctx->m.update = HMAC_update;
+       ctx->m.final = HMAC_final;      
+       ASSERT(sizeof(ctx->key) >= ctx->m.key_len);
+}
diff --git a/bertos/sec/mac/hmac.h b/bertos/sec/mac/hmac.h
new file mode 100644 (file)
index 0000000..c22a695
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction.  Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License.  This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
+ *
+ * -->
+ *
+ * \brief HMAC (RFC 2104) implementation
+ * \author Giovanni Bajo <rasky@develer.com>
+ * 
+ */
+
+#ifndef SEC_MAC_HMAC_H
+#define SEC_MAC_HMAC_H
+
+#include <sec/mac.h>
+#include <sec/hash.h>
+
+typedef struct HMAC_Context
+{
+       Mac m;
+       Hash *h;        
+       uint8_t key[64];
+} HMAC_Context;
+
+void HMAC_init(HMAC_Context* hmac, Hash *h);
+
+int HMAC_testSetup(void);
+int HMAC_testRun(void);
+int HMAC_testTearDown(void);
+
+#endif /* SEC_MAC_HMAC_H */
diff --git a/bertos/sec/mac/hmac_test.c b/bertos/sec/mac/hmac_test.c
new file mode 100644 (file)
index 0000000..8b16096
--- /dev/null
@@ -0,0 +1,192 @@
+
+#include <sec/mac/hmac.h>
+#include <cfg/test.h>
+#include <cfg/debug.h>
+#include <sec/hash/sha1.h>
+#include <sec/hash/md5.h>
+#include <string.h>
+
+int HMAC_testSetup(void)
+{
+       kdbg_init();
+       return 0;
+}
+
+int HMAC_testTearDown(void)
+{
+       return 0;
+}
+
+struct Test_HMAC
+{
+       const char *key;
+       size_t key_len;
+       const char *data;
+       size_t data_len;
+       const char *digest;
+};
+
+const struct Test_HMAC tests_hmac_md5[] =
+{
+       { 
+               "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 16,
+               "Hi There", 8,
+               "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d",
+       },
+       {
+               "Jefe", 4, 
+               "what do ya want for nothing?", 28,
+               "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38",
+       },
+       {
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 16,
+               "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+               "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+               "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+               "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+               "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", 50,
+               "\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6",
+       },
+       {
+               "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+               "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25,
+               "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+               "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+               "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+               "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+               "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", 50,
+               "\x69\x7e\xaf\x0a\xca\x3a\x3a\xea\x3a\x75\x16\x47\x46\xff\xaa\x79",
+       },
+       {
+               "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 16,
+               "Test With Truncation", 20,
+               "\x56\x46\x1e\xf2\x34\x2e\xdc\x00\xf9\xba\xb9\x95\x69\x0e\xfd\x4c",
+       },
+       {
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80,
+               "Test Using Larger Than Block-Size Key - Hash Key First", 54,
+               "\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f\x0b\x62\xe6\xce\x61\xb9\xd0\xcd",
+       },
+       {
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80,
+               "Test Using Larger Than Block-Size Key and Larger Than One "
+               "Block-Size Data", 73,
+               "\x6f\x63\x0f\xad\x67\xcd\xa0\xee\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e",
+       }
+};
+
+const struct Test_HMAC tests_hmac_sha1[] =
+{
+       {
+               "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20,
+               "Hi There", 8,
+               "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00",
+       },
+       {
+               "Jefe", 4,
+               "what do ya want for nothing?", 28,
+               "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79",
+       },      
+       {
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 20,
+               "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+               "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+               "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+               "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+               "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", 50,
+               "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3",
+       },
+       {
+               "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25,
+               "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+               "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+               "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+               "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+               "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", 50,
+               "\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda",
+       },
+       {
+               "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 20,
+               "Test With Truncation", 20,
+               "\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04",
+       },
+       {
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80,
+               "Test Using Larger Than Block-Size Key - Hash Key First", 54,
+               "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12",
+       },
+       {
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+               "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80,
+               "Test Using Larger Than Block-Size Key and Larger "
+        "Than One Block-Size Data", 73,
+        "\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91",
+   },
+};
+
+static void algo_run_tests(HMAC_Context *hmac, const struct Test_HMAC *t, int count)
+{
+       for (int i=0; i<count; ++i, ++t)
+       {
+               mac_set_key(&hmac->m, (const uint8_t*)t->key, t->key_len);
+               mac_begin(&hmac->m);
+               mac_update(&hmac->m, (const uint8_t*)t->data, t->data_len);
+               ASSERT(memcmp(mac_final(&hmac->m), t->digest, mac_digest_len(&hmac->m)) == 0);
+       }
+}
+
+int HMAC_testRun(void)
+{
+       if (1)
+       {
+               MD5_Context md5;
+               MD5_init(&md5);
+
+               HMAC_Context hmac;
+               HMAC_init(&hmac, &md5.h);
+
+               algo_run_tests(&hmac, tests_hmac_md5, countof(tests_hmac_md5));
+       }
+
+       if (1)
+       {
+               SHA1_Context sha1;
+               SHA1_init(&sha1);
+
+               HMAC_Context hmac;
+               HMAC_init(&hmac, &sha1.h);
+
+               algo_run_tests(&hmac, tests_hmac_sha1, countof(tests_hmac_sha1));
+       }
+       
+       return 0;
+}
+
+TEST_MAIN(HMAC);