-/*
- * $Id$
- * $Log$
- * Revision 1.3 2000/07/14 09:12:24 priikone
- * Fixed bug in silc_hmac_make.
- *
- * Revision 1.2 2000/07/05 06:08:43 priikone
- * Global cosmetic change.
- *
- * Revision 1.1.1.1 2000/06/27 11:36:55 priikone
- * Imported from internal CVS/Added Log headers.
- *
- *
- */
-
-#include "silcincludes.h"
-
-/* Allocates a new SilcHmac object. First argument is the hash function
- object to tell the hmac which hash function should be used when creating
- HMAC's. The new SilcHmac object is returned to new_hmac argument. */
-
-int silc_hmac_alloc(SilcHash hash, SilcHmac *new_hmac)
-{
- SILC_LOG_DEBUG(("Allocating new hmac object"));
+/* $Id$ */
+
+#include "silc.h"
+
+/* HMAC context */
+struct SilcHmacStruct {
+ SilcHmacObject *hmac;
+ SilcHash hash;
+ unsigned char inner_pad[64];
+ unsigned char outer_pad[64];
+ unsigned char *key;
+ unsigned int key_len : 31;
+ unsigned int allocated_hash : 1; /* TRUE if the hash was allocated */
+};
+
+#ifndef SILC_SYMBIAN
+/* List of dynamically registered HMACs. */
+SilcDList silc_hmac_list = NULL;
+#endif /* SILC_SYMBIAN */
+
+/* Default hmacs for silc_hmac_register_default(). */
+const SilcHmacObject silc_default_hmacs[] =
+{
+ { "hmac-sha256-96", 12 },
+ { "hmac-sha512-96", 12 },
+ { "hmac-sha1-96", 12 },
+ { "hmac-md5-96", 12 },
+ { "hmac-sha256", 32 },
+ { "hmac-sha512", 64 },
+ { "hmac-sha1", 20 },
+ { "hmac-md5", 16 },
+
+ { NULL, 0 }
+};
+
+static void silc_hmac_init_internal(SilcHmac hmac, unsigned char *key,
+ SilcUInt32 key_len)
+{
+ SilcHash hash = hmac->hash;
+ SilcUInt32 block_len;
+ unsigned char hvalue[SILC_HASH_MAXLEN];
+ int i;
+
+ memset(hmac->inner_pad, 0, sizeof(hmac->inner_pad));
+ memset(hmac->outer_pad, 0, sizeof(hmac->outer_pad));
+
+ block_len = silc_hash_block_len(hash);
+
+ /* If the key length is more than block size of the hash function, the
+ key is hashed. */
+ if (key_len > block_len) {
+ silc_hash_make(hash, key, key_len, hvalue);
+ key = hvalue;
+ key_len = silc_hash_len(hash);
+ }
+
+ /* Copy the key into the pads */
+ memcpy(hmac->inner_pad, key, key_len);
+ memcpy(hmac->outer_pad, key, key_len);
+
+ /* XOR the key with pads */
+ for (i = 0; i < block_len; i++) {
+ hmac->inner_pad[i] ^= 0x36;
+ hmac->outer_pad[i] ^= 0x5c;
+ }
+}
+
+/* Registers a new HMAC */
+
+SilcBool silc_hmac_register(const SilcHmacObject *hmac)
+{
+#ifndef SILC_SYMBIAN
+ SilcHmacObject *new;
+
+ SILC_LOG_DEBUG(("Registering new HMAC `%s'", hmac->name));
+
+ /* Check for existing */
+ if (silc_hmac_list) {
+ SilcHmacObject *entry;
+ silc_dlist_start(silc_hmac_list);
+ while ((entry = silc_dlist_get(silc_hmac_list)) != SILC_LIST_END) {
+ if (!strcmp(entry->name, hmac->name))
+ return FALSE;
+ }
+ }
+
+ new = silc_calloc(1, sizeof(*new));
+ if (!new)
+ return FALSE;
+ new->name = strdup(hmac->name);
+ new->len = hmac->len;
+
+ /* Add to list */
+ if (silc_hmac_list == NULL)
+ silc_hmac_list = silc_dlist_init();
+ silc_dlist_add(silc_hmac_list, new);
+
+#endif /* SILC_SYMBIAN */
+ return TRUE;
+}
+
+/* Unregister a HMAC */
+
+SilcBool silc_hmac_unregister(SilcHmacObject *hmac)
+{
+#ifndef SILC_SYMBIAN
+ SilcHmacObject *entry;