--- /dev/null
+/**
+ * \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);
+}
--- /dev/null
+/**
+ * \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 */
--- /dev/null
+
+#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);