From 8cbd4e2524c7e45c506bd00779d05f6608a81f66 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Wed, 5 Mar 2008 20:50:57 +0200 Subject: [PATCH] Added SILC MAC API, removed the SILC HMAC API. Internally the code is still the old HMAC implementation. When we later add new MACs the internals of the MAC API must be rewritten to support other MACs. --- lib/silccrypt/Makefile.ad | 4 +- lib/silccrypt/silccrypto.c | 4 +- lib/silccrypt/silccrypto.h.in | 4 +- lib/silccrypt/silchmac.c | 483 --------------------------------- lib/silccrypt/silchmac.h | 447 ------------------------------- lib/silccrypt/silcmac.c | 484 ++++++++++++++++++++++++++++++++++ lib/silccrypt/silcmac.h | 484 ++++++++++++++++++++++++++++++++++ lib/silccrypt/silcpk.c | 32 +-- 8 files changed, 990 insertions(+), 952 deletions(-) delete mode 100644 lib/silccrypt/silchmac.c delete mode 100644 lib/silccrypt/silchmac.h create mode 100644 lib/silccrypt/silcmac.c create mode 100644 lib/silccrypt/silcmac.h diff --git a/lib/silccrypt/Makefile.ad b/lib/silccrypt/Makefile.ad index a6204ef7..afa77f57 100644 --- a/lib/silccrypt/Makefile.ad +++ b/lib/silccrypt/Makefile.ad @@ -47,7 +47,7 @@ libsilccrypt_la_SOURCES = \ silccrypto.c \ silccipher.c \ silchash.c \ - silchmac.c \ + silcmac.c \ silcrng.c \ silcpkcs.c \ silcpkcs1.c \ @@ -60,7 +60,7 @@ include_HEADERS = \ silccipher.h \ silccipher_i.h \ silchash.h \ - silchmac.h \ + silcmac.h \ silcpkcs.h \ silcpkcs_i.h \ silcrng.h \ diff --git a/lib/silccrypt/silccrypto.c b/lib/silccrypt/silccrypto.c index 8d729443..e383c82d 100644 --- a/lib/silccrypt/silccrypto.c +++ b/lib/silccrypt/silccrypto.c @@ -43,7 +43,7 @@ SilcBool silc_crypto_init(SilcStack stack) SILC_LOG_ERROR(("Error registering hash functions")); goto err; } - if (!silc_hmac_register_default()) { + if (!silc_mac_register_default()) { SILC_LOG_ERROR(("Error registering hash HMACs")); goto err; } @@ -75,7 +75,7 @@ void silc_crypto_uninit(void) /* Uninit crypto library */ silc_pkcs_unregister_all(); - silc_hmac_unregister_all(); + silc_mac_unregister_all(); silc_hash_unregister_all(); silc_cipher_unregister_all(); diff --git a/lib/silccrypt/silccrypto.h.in b/lib/silccrypt/silccrypto.h.in index 8a130115..f7aa3b5f 100644 --- a/lib/silccrypt/silccrypto.h.in +++ b/lib/silccrypt/silccrypto.h.in @@ -26,7 +26,7 @@ * silc_crypto_init function. It needs to be called only once per-process * but must be called before any crypto functions are used. * - * In initialization all builtin ciphers, hash functions, HMACs, PKCSs + * In initialization all builtin ciphers, hash functions, MACs, PKCSs * and other algorithms will be registered to the crypto library. If user * wants to register new algorithms or change the order of the automatically * registered algorithms, user can do this by re-registering the algorithms @@ -89,7 +89,7 @@ extern "C" { #include #include #include -#include +#include #include #include #include diff --git a/lib/silccrypt/silchmac.c b/lib/silccrypt/silchmac.c deleted file mode 100644 index 12cdb560..00000000 --- a/lib/silccrypt/silchmac.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - - silchmac.c - - Author: Pekka Riikonen - - Copyright (C) 1999 - 2008 Pekka Riikonen - - This program 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; version 2 of the License. - - 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. - -*/ - -#include "silccrypto.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; - - SILC_LOG_DEBUG(("Unregistering HMAC")); - - if (!silc_hmac_list) - return FALSE; - - silc_dlist_start(silc_hmac_list); - while ((entry = silc_dlist_get(silc_hmac_list)) != SILC_LIST_END) { - if (hmac == SILC_ALL_HMACS || entry == hmac) { - silc_dlist_del(silc_hmac_list, entry); - silc_free(entry->name); - silc_free(entry); - - if (silc_dlist_count(silc_hmac_list) == 0) { - silc_dlist_uninit(silc_hmac_list); - silc_hmac_list = NULL; - } - - return TRUE; - } - } - -#endif /* SILC_SYMBIAN */ - return FALSE; -} - -/* Register default HMACs */ - -SilcBool silc_hmac_register_default(void) -{ - /* We use builtin HMACs */ - return TRUE; -} - -/* Unregister all HMACs */ - -SilcBool silc_hmac_unregister_all(void) -{ -#ifndef SILC_SYMBIAN - SilcHmacObject *entry; - - if (!silc_hmac_list) - return FALSE; - - silc_dlist_start(silc_hmac_list); - while ((entry = silc_dlist_get(silc_hmac_list)) != SILC_LIST_END) { - silc_hmac_unregister(entry); - if (!silc_hmac_list) - break; - } -#endif /* SILC_SYMBIAN */ - return TRUE; -} - -/* Allocates a new SilcHmac object of name of `name'. The `hash' may - be provided as argument. If provided it is used as the hash function - of the HMAC. If it is NULL then the hash function is allocated and - the name of the hash algorithm is derived from the `name'. */ - -SilcBool silc_hmac_alloc(const char *name, SilcHash hash, SilcHmac *new_hmac) -{ - SilcHmacObject *entry = NULL; - int i; - - SILC_LOG_DEBUG(("Allocating new HMAC")); - - /* Allocate the new object */ - *new_hmac = silc_calloc(1, sizeof(**new_hmac)); - if (!(*new_hmac)) - return FALSE; - - if (!hash) { - char *tmp = strdup(name), *hname; - - hname = tmp; - if (strchr(hname, '-')) - hname = strchr(hname, '-') + 1; - if (strchr(hname, '-')) - *strchr(hname, '-') = '\0'; - - if (!silc_hash_alloc(hname, &hash)) { - silc_free(tmp); - silc_free(*new_hmac); - *new_hmac = NULL; - return FALSE; - } - - (*new_hmac)->allocated_hash = TRUE; - silc_free(tmp); - } - - (*new_hmac)->hash = hash; - -#ifndef SILC_SYMBIAN - /* Check registered list of HMACs */ - if (silc_hmac_list) { - silc_dlist_start(silc_hmac_list); - while ((entry = silc_dlist_get(silc_hmac_list)) != SILC_LIST_END) { - if (!strcmp(entry->name, name)) { - (*new_hmac)->hmac = entry; - return TRUE; - } - } - } -#endif /* SILC_SYMBIAN */ - - if (!entry) { - /* Check builtin list of HMACs */ - for (i = 0; silc_default_hmacs[i].name; i++) { - if (!strcmp(silc_default_hmacs[i].name, name)) { - (*new_hmac)->hmac = (SilcHmacObject *)&(silc_default_hmacs[i]); - return TRUE; - } - } - } - - silc_free(*new_hmac); - *new_hmac = NULL; - return FALSE; -} - -/* Free's the SilcHmac object. */ - -void silc_hmac_free(SilcHmac hmac) -{ - if (hmac) { - if (hmac->allocated_hash) - silc_hash_free(hmac->hash); - - if (hmac->key) { - memset(hmac->key, 0, hmac->key_len); - silc_free(hmac->key); - } - - silc_free(hmac); - } -} - -/* Returns the length of the MAC that the HMAC will produce. */ - -SilcUInt32 silc_hmac_len(SilcHmac hmac) -{ - return hmac->hmac->len; -} - -/* Get hash context */ - -SilcHash silc_hmac_get_hash(SilcHmac hmac) -{ - return hmac->hash; -} - -/* Return name of hmac */ - -const char *silc_hmac_get_name(SilcHmac hmac) -{ - return hmac->hmac->name; -} - -/* Returns TRUE if HMAC `name' is supported. */ - -SilcBool silc_hmac_is_supported(const char *name) -{ - SilcHmacObject *entry; - int i; - - if (!name) - return FALSE; - -#ifndef SILC_SYMBIAN - if (silc_hmac_list) { - silc_dlist_start(silc_hmac_list); - while ((entry = silc_dlist_get(silc_hmac_list)) != SILC_LIST_END) { - if (!strcmp(entry->name, name)) - return TRUE; - } - } -#endif /* SILC_SYMBIAN */ - - for (i = 0; silc_default_hmacs[i].name; i++) - if (!strcmp(silc_default_hmacs[i].name, name)) - return TRUE; - - return FALSE; -} - -/* Returns comma separated list of supported HMACs. */ - -char *silc_hmac_get_supported() -{ - SilcHmacObject *entry, *entry2; - char *list = NULL; - int len = 0, i; - -#ifndef SILC_SYMBIAN - if (silc_hmac_list) { - silc_dlist_start(silc_hmac_list); - while ((entry = silc_dlist_get(silc_hmac_list)) != SILC_LIST_END) { - len += strlen(entry->name); - list = silc_realloc(list, len + 1); - - memcpy(list + (len - strlen(entry->name)), - entry->name, strlen(entry->name)); - memcpy(list + len, ",", 1); - len++; - } - } -#endif /* SILC_SYMBIAN */ - - - for (i = 0; silc_default_hmacs[i].name; i++) { - entry = (SilcHmacObject *)&(silc_default_hmacs[i]); - - if (silc_hmac_list) { - silc_dlist_start(silc_hmac_list); - while ((entry2 = silc_dlist_get(silc_hmac_list)) != SILC_LIST_END) { - if (!strcmp(entry2->name, entry->name)) - break; - } - if (entry2) - continue; - } - - len += strlen(entry->name); - list = silc_realloc(list, len + 1); - - memcpy(list + (len - strlen(entry->name)), - entry->name, strlen(entry->name)); - memcpy(list + len, ",", 1); - len++; - } - - list[len - 1] = 0; - - return list; -} - -/* Sets the HMAC key used in the HMAC creation */ - -void silc_hmac_set_key(SilcHmac hmac, const unsigned char *key, - SilcUInt32 key_len) -{ - if (hmac->key) { - memset(hmac->key, 0, hmac->key_len); - silc_free(hmac->key); - } - hmac->key = silc_malloc(key_len); - if (!hmac->key) - return; - hmac->key_len = key_len; - memcpy(hmac->key, key, key_len); -} - -/* Return HMAC key */ - -const unsigned char *silc_hmac_get_key(SilcHmac hmac, SilcUInt32 *key_len) -{ - if (key_len) - *key_len = hmac->key_len; - return (const unsigned char *)hmac->key; -} - -/* Create the HMAC. This is thee make_hmac function pointer. This - uses the internal key set with silc_hmac_set_key. */ - -void silc_hmac_make(SilcHmac hmac, unsigned char *data, - SilcUInt32 data_len, unsigned char *return_hash, - SilcUInt32 *return_len) -{ - SILC_LOG_DEBUG(("Making HMAC for message")); - - silc_hmac_init(hmac); - silc_hmac_update(hmac, data, data_len); - silc_hmac_final(hmac, return_hash, return_len); -} - -/* Creates HMAC just as above except that this doesn't use the internal - key. The key is sent as argument to the function. */ - -void silc_hmac_make_with_key(SilcHmac hmac, unsigned char *data, - SilcUInt32 data_len, - unsigned char *key, SilcUInt32 key_len, - unsigned char *return_hash, - SilcUInt32 *return_len) -{ - SILC_LOG_DEBUG(("Making HMAC for message")); - - silc_hmac_init_with_key(hmac, key, key_len); - silc_hmac_update(hmac, data, data_len); - silc_hmac_final(hmac, return_hash, return_len); -} - -/* Creates the HMAC just as above except that the hash value is truncated - to the truncated_len sent as argument. NOTE: One should not truncate to - less than half of the length of original hash value. However, this - routine allows these dangerous truncations. */ - -void silc_hmac_make_truncated(SilcHmac hmac, unsigned char *data, - SilcUInt32 data_len, - SilcUInt32 truncated_len, - unsigned char *return_hash) -{ - unsigned char hvalue[SILC_HASH_MAXLEN]; - - SILC_LOG_DEBUG(("Making HMAC for message")); - - silc_hmac_init(hmac); - silc_hmac_update(hmac, data, data_len); - silc_hmac_final(hmac, return_hash, NULL); - memcpy(return_hash, hvalue, truncated_len); - memset(hvalue, 0, sizeof(hvalue)); -} - -/* Init HMAC for silc_hmac_update and silc_hmac_final. */ - -void silc_hmac_init(SilcHmac hmac) -{ - silc_hmac_init_with_key(hmac, hmac->key, hmac->key_len); -} - -/* Same as above but with specific key */ - -void silc_hmac_init_with_key(SilcHmac hmac, const unsigned char *key, - SilcUInt32 key_len) -{ - SilcHash hash = hmac->hash; - silc_hmac_init_internal(hmac, (unsigned char *)key, key_len); - silc_hash_init(hash); - silc_hash_update(hash, hmac->inner_pad, silc_hash_block_len(hash)); -} - -/* Add data to be used in the MAC computation. */ - -void silc_hmac_update(SilcHmac hmac, const unsigned char *data, - SilcUInt32 data_len) -{ - SilcHash hash = hmac->hash; - silc_hash_update(hash, data, data_len); -} - -/* Compute the final MAC. */ - -void silc_hmac_final(SilcHmac hmac, unsigned char *return_hash, - SilcUInt32 *return_len) -{ - SilcHash hash = hmac->hash; - unsigned char mac[SILC_HASH_MAXLEN]; - - silc_hash_final(hash, mac); - silc_hash_init(hash); - silc_hash_update(hash, hmac->outer_pad, silc_hash_block_len(hash)); - silc_hash_update(hash, mac, silc_hash_len(hash)); - silc_hash_final(hash, mac); - memcpy(return_hash, mac, hmac->hmac->len); - memset(mac, 0, sizeof(mac)); - - if (return_len) - *return_len = hmac->hmac->len; -} diff --git a/lib/silccrypt/silchmac.h b/lib/silccrypt/silchmac.h deleted file mode 100644 index 66d82349..00000000 --- a/lib/silccrypt/silchmac.h +++ /dev/null @@ -1,447 +0,0 @@ -/* - - silchmac.h - - Author: Pekka Riikonen - - Copyright (C) 1999 - 2006 Pekka Riikonen - - This program 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; version 2 of the License. - - 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. - -*/ - -#ifndef SILCHMAC_H -#define SILCHMAC_H - -/****h* silccrypt/SILC HMAC Interface - * - * DESCRIPTION - * - * This is the interface for HMAC, or the keyed hash values, that are - * used for packet and message authentication. These routines uses - * already implemented hash functions from the SilcHashAPI. These - * routines were created according to RFC 2104. - * - ***/ - -/****s* silccrypt/SilcHMACAPI/SilcHmac - * - * NAME - * - * typedef struct SilcHmacStruct *SilcHmac; - * - * DESCRIPTION - * - * This context is the actual HMAC context and is allocated - * by silc_hmac_alloc and given as argument usually to all - * silc_hmac_* functions. It is freed by the silc_hmac_free - * function. - * - ***/ -typedef struct SilcHmacStruct *SilcHmac; - -/****s* silccrypt/SilcHMACAPI/SilcHmacObject - * - * NAME - * - * typedef struct { ... } SilcHmacObject; - * - * DESCRIPTION - * - * This structure represents one HMAC. The HMAC's name and the - * MAC length is defined in the structure. This structure is - * then given as argument to the silc_hmac_register. That function - * is used to register all HMACs into SILC. They can be then - * allocated by the name found in this structure by calling the - * silc_hmac_alloc. - * - ***/ -typedef struct { - char *name; - SilcUInt32 len; -} SilcHmacObject; - -/* Marks for all hmacs. This can be used in silc_hmac_unregister - to unregister all hmacs at once. */ -#define SILC_ALL_HMACS ((SilcHmacObject *)1) - -/* Default hmacs for silc_hmac_register_default(). */ -extern DLLAPI const SilcHmacObject silc_default_hmacs[]; - -/* Default HMAC in the SILC protocol */ -#define SILC_DEFAULT_HMAC "hmac-sha1-96" - -/* Prototypes */ - -/****f* silccrypt/SilcHMACAPI/silc_hmac_register - * - * SYNOPSIS - * - * SilcBool silc_hmac_register(const SilcHmacObject *hmac); - * - * DESCRIPTION - * - * Registers a new HMAC into the SILC. This function is used at the - * initialization of the SILC. All registered HMACs should be - * unregistered with silc_hmac_unregister. The `hmac' includes the - * name of the HMAC and the length of the MAC. Usually this - * function is not called directly. Instead, application can call - * the silc_hmac_register_default to register all default HMACs - * that are builtin the sources. Returns FALSE on error. - * - ***/ -SilcBool silc_hmac_register(const SilcHmacObject *hmac); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_unregister - * - * SYNOPSIS - * - * SilcBool silc_hmac_unregister(SilcHmacObject *hmac); - * - * DESCRIPTION - * - * Unregister a HMAC from SILC by the HMAC structure `hmac'. This - * should be called for all registered HMAC's. Returns FALSE on - * error. - * - ***/ -SilcBool silc_hmac_unregister(SilcHmacObject *hmac); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_register_default - * - * SYNOPSIS - * - * SilcBool silc_hmac_register_default(void); - * - * DESCRIPTION - * - * Registers all default HMACs into the SILC. These are the HMACs - * that are builtin in the sources. See the list of default HMACs - * in the silchmac.c source file. The application may use this - * to register default HMACs if specific HMAC in any specific order - * is not wanted (application's configuration usually may decide - * the order of the registration, in which case this should not be - * used). - * - ***/ -SilcBool silc_hmac_register_default(void); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_unregister_all - * - * SYNOPSIS - * - * SilcBool silc_hmac_unregister_all(void); - * - * DESCRIPTION - * - * Unregisters all registered HMACs. - * - ***/ -SilcBool silc_hmac_unregister_all(void); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_alloc - * - * SYNOPSIS - * - * SilcBool silc_hmac_alloc(const char *name, SilcHash hash, - * SilcHmac *new_hmac); - * - * DESCRIPTION - * - * Allocates a new SilcHmac object of name of `name'. The `hash' may - * be provided as argument. If provided it is used as the hash function - * of the HMAC. If it is NULL then the hash function is allocated and - * the name of the hash algorithm is derived from the `name'. Returns - * FALSE if such HMAC does not exist. - * - ***/ -SilcBool silc_hmac_alloc(const char *name, SilcHash hash, SilcHmac *new_hmac); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_free - * - * SYNOPSIS - * - * void silc_hmac_free(SilcHmac hmac); - * - * DESCRIPTION - * - * Frees the allocated HMAC context. The key that may have been set - * with the silc_hmac_set_key is also destroyed. - * - ***/ -void silc_hmac_free(SilcHmac hmac); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_is_supported - * - * SYNOPSIS - * - * SilcBool silc_hmac_is_supported(const char *name); - * - * DESCRIPTION - * - * Returns TRUE if the HMAC indicated by the `name' exists. - * - ***/ -SilcBool silc_hmac_is_supported(const char *name); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_get_supported - * - * SYNOPSIS - * - * char *silc_hmac_get_supported(void); - * - * DESCRIPTION - * - * Returns comma (`,') separated list of registered HMACs. This is - * used for example when sending supported HMAC list during the SILC - * Key Exchange protocol (SKE). The caller must free the returned - * pointer. - * - ***/ -char *silc_hmac_get_supported(void); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_len - * - * SYNOPSIS - * - * SilcUInt32 silc_hmac_len(SilcHmac hmac); - * - * DESCRIPTION - * - * Returns the length of the MAC that the HMAC will produce. - * - ***/ -SilcUInt32 silc_hmac_len(SilcHmac hmac); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_get_hash - * - * SYNOPSIS - * - * SilcHash silc_hmac_get_hash(SilcHmac hmac); - * - * DESCRIPTION - * - * Returns the SilcHash context that has been associated with the - * HMAC context. The caller must not free the returned context. - * - ***/ -SilcHash silc_hmac_get_hash(SilcHmac hmac); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_get_name - * - * SYNOPSIS - * - * const char *silc_hmac_get_name(SilcHmac hmac); - * - * DESCRIPTION - * - * Returns the name of the HMAC context. - * - ***/ -const char *silc_hmac_get_name(SilcHmac hmac); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_set_key - * - * SYNOPSIS - * - * void silc_hmac_set_key(SilcHmac hmac, const unsigned char *key, - * SilcUInt32 key_len); - * - * DESCRIPTION - * - * Sets the key to be used in the HMAC operation. This must be set - * before calling silc_hmac_make or silc_hmac_final functions. If - * you do not want to set the key you can still produce a MAC by - * calling the silc_hmac_make_with_key where you give the key as - * argument. Usually application still wants to set the key. - * - ***/ -void silc_hmac_set_key(SilcHmac hmac, const unsigned char *key, - SilcUInt32 key_len); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_get_key - * - * SYNOPSIS - * - * const unsigned char * - * silc_hmac_get_key(SilcHmac hmac, SilcUInt32 *key_len); - * - * DESCRIPTION - * - * Returns the key data from the `hmac' set with silc_hamc_set_key. - * The caller must not free the returned pointer. - * - ***/ -const unsigned char *silc_hmac_get_key(SilcHmac hmac, SilcUInt32 *key_len); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_make - * - * SYNOPSIS - * - * void silc_hmac_make(SilcHmac hmac, unsigned char *data, - * SilcUInt32 data_len, unsigned char *return_hash, - * SilcUInt32 *return_len); - * - * DESCRIPTION - * - * Computes a MAC from a data buffer indicated by the `data' of the - * length of `data_len'. The returned MAC is copied into the - * `return_hash' pointer which must be at least the size of the - * value silc_hmac_len returns. The returned length is still - * returned to `return_len'. - * - ***/ -void silc_hmac_make(SilcHmac hmac, unsigned char *data, - SilcUInt32 data_len, unsigned char *return_hash, - SilcUInt32 *return_len); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_make_with_key - * - * SYNOPSIS - * - * void silc_hmac_make_with_key(SilcHmac hmac, unsigned char *data, - * SilcUInt32 data_len, - * unsigned char *key, SilcUInt32 key_len, - * unsigned char *return_hash, - * SilcUInt32 *return_len); - * - * DESCRIPTION - * - * Same as the silc_hmac_make but takes the key for the HMAC as - * argument. If this is used the key that may have been set by calling - * silc_hmac_set_key is ignored. - * - ***/ -void silc_hmac_make_with_key(SilcHmac hmac, unsigned char *data, - SilcUInt32 data_len, - unsigned char *key, SilcUInt32 key_len, - unsigned char *return_hash, - SilcUInt32 *return_len); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_make_truncated - * - * SYNOPSIS - * - * void silc_hmac_make_truncated(SilcHmac hmac, - * unsigned char *data, - * SilcUInt32 data_len, - * SilcUInt32 truncated_len, - * unsigned char *return_hash); - * - * DESCRIPTION - * - * Same as the silc_hmac_make except that the returned MAC is - * truncated to the length indicated by the `truncated_len'. Some - * special applications may need this function. The `return_hash' - * must be at least the size of `truncated_len'. - * - * NOTES - * - * For security reasons, one should not truncate to less than half - * of the length of the true MAC lenght. However, since this routine - * may be used to non-critical applications this allows these dangerous - * truncations. - * - ***/ -void silc_hmac_make_truncated(SilcHmac hmac, - unsigned char *data, - SilcUInt32 data_len, - SilcUInt32 truncated_len, - unsigned char *return_hash); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_init - * - * SYNOPSIS - * - * void silc_hmac_init(SilcHmac hmac); - * - * DESCRIPTION - * - * Sometimes calling the silc_hmac_make might not be the most - * optimal case of doing MACs. If you have a lot of different data - * that you need to put together for computing a MAC you may either - * put them into a buffer and compute the MAC from the buffer by - * calling the silc_hmac_make, or you can use the silc_hmac_init, - * silc_hmac_update and silc_hmac_final to do the MAC. This function - * prepares the allocated HMAC context for this kind of MAC - * computation. The caller must have been called the function - * silc_hmac_set_key before calling this function. To add the - * data to be used in the MAC computation call the silc_hmac_update - * function. - * - ***/ -void silc_hmac_init(SilcHmac hmac); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_init_with_key - * - * SYNOPSIS - * - * void silc_hmac_init_with_key(SilcHmac hmac, const unsigned char *key, - * SilcUInt32 key_len); - * - * DESCRIPTION - * - * Same as silc_hmac_init but initializes with specific key. The - * key that may have been set with silc_hmac_set_key is ignored. - * - ***/ -void silc_hmac_init_with_key(SilcHmac hmac, const unsigned char *key, - SilcUInt32 key_len); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_update - * - * SYNOPSIS - * - * void silc_hmac_update(SilcHmac hmac, const unsigned char *data, - * SilcUInt32 data_len); - * - * DESCRIPTION - * - * This function may be called to add data to be used in the MAC - * computation. This can be called multiple times to add data from - * many sources before actually performing the HMAC. Once you've - * added all the data you need you can call the silc_hmac_final to - * actually produce the MAC. - * - * EXAMPLE - * - * unsigned char mac[20]; - * SilcUInt32 mac_len; - * - * silc_hmac_init(hmac); - * silc_hmac_update(hmac, data, data_len); - * silc_hmac_update(hmac, more_data, more_data_len); - * silc_hmac_final(hmac, mac, &mac_len); - * - ***/ -void silc_hmac_update(SilcHmac hmac, const unsigned char *data, - SilcUInt32 data_len); - -/****f* silccrypt/SilcHMACAPI/silc_hmac_final - * - * SYNOPSIS - * - * void silc_hmac_final(SilcHmac hmac, unsigned char *return_hash, - * SilcUInt32 *return_len); - * - * DESCRIPTION - * - * This function is used to produce the final MAC from the data - * that has been added to the HMAC context by calling the - * silc_hmac_update function. The MAC is copied in to the - * `return_hash' pointer which must be at least the size that - * the silc_hmac_len returns. The length of the MAC is still - * returned into `return_len'. - * - ***/ -void silc_hmac_final(SilcHmac hmac, unsigned char *return_hash, - SilcUInt32 *return_len); - -#endif diff --git a/lib/silccrypt/silcmac.c b/lib/silccrypt/silcmac.c new file mode 100644 index 00000000..6a2a8b4b --- /dev/null +++ b/lib/silccrypt/silcmac.c @@ -0,0 +1,484 @@ +/* + + silcmac.c + + Author: Pekka Riikonen + + Copyright (C) 1999 - 2008 Pekka Riikonen + + This program 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; version 2 of the License. + + 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. + +*/ + +#include "silccrypto.h" + +/* MAC context */ +struct SilcMacStruct { + SilcMacObject *mac; + 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 MACs. */ +SilcDList silc_mac_list = NULL; +#endif /* SILC_SYMBIAN */ + +/* Default macs for silc_mac_register_default(). */ +const SilcMacObject silc_default_macs[] = +{ + { "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_mac_init_internal(SilcMac mac, unsigned char *key, + SilcUInt32 key_len) +{ + SilcHash hash = mac->hash; + SilcUInt32 block_len; + unsigned char hvalue[SILC_HASH_MAXLEN]; + int i; + + memset(mac->inner_pad, 0, sizeof(mac->inner_pad)); + memset(mac->outer_pad, 0, sizeof(mac->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(mac->inner_pad, key, key_len); + memcpy(mac->outer_pad, key, key_len); + + /* XOR the key with pads */ + for (i = 0; i < block_len; i++) { + mac->inner_pad[i] ^= 0x36; + mac->outer_pad[i] ^= 0x5c; + } +} + +/* Registers a new MAC */ + +SilcBool silc_mac_register(const SilcMacObject *mac) +{ +#ifndef SILC_SYMBIAN + SilcMacObject *new; + + SILC_LOG_DEBUG(("Registering new MAC `%s'", mac->name)); + + /* Check for existing */ + if (silc_mac_list) { + SilcMacObject *entry; + silc_dlist_start(silc_mac_list); + while ((entry = silc_dlist_get(silc_mac_list)) != SILC_LIST_END) { + if (!strcmp(entry->name, mac->name)) + return FALSE; + } + } + + new = silc_calloc(1, sizeof(*new)); + if (!new) + return FALSE; + new->name = strdup(mac->name); + new->len = mac->len; + + /* Add to list */ + if (silc_mac_list == NULL) + silc_mac_list = silc_dlist_init(); + silc_dlist_add(silc_mac_list, new); + +#endif /* SILC_SYMBIAN */ + return TRUE; +} + +/* Unregister a MAC */ + +SilcBool silc_mac_unregister(SilcMacObject *mac) +{ +#ifndef SILC_SYMBIAN + SilcMacObject *entry; + + SILC_LOG_DEBUG(("Unregistering MAC")); + + if (!silc_mac_list) + return FALSE; + + silc_dlist_start(silc_mac_list); + while ((entry = silc_dlist_get(silc_mac_list)) != SILC_LIST_END) { + if (mac == SILC_ALL_MACS || entry == mac) { + silc_dlist_del(silc_mac_list, entry); + silc_free(entry->name); + silc_free(entry); + + if (silc_dlist_count(silc_mac_list) == 0) { + silc_dlist_uninit(silc_mac_list); + silc_mac_list = NULL; + } + + return TRUE; + } + } + +#endif /* SILC_SYMBIAN */ + return FALSE; +} + +/* Register default MACs */ + +SilcBool silc_mac_register_default(void) +{ + /* We use builtin MACs */ + return TRUE; +} + +/* Unregister all MACs */ + +SilcBool silc_mac_unregister_all(void) +{ +#ifndef SILC_SYMBIAN + SilcMacObject *entry; + + if (!silc_mac_list) + return FALSE; + + silc_dlist_start(silc_mac_list); + while ((entry = silc_dlist_get(silc_mac_list)) != SILC_LIST_END) { + silc_mac_unregister(entry); + if (!silc_mac_list) + break; + } +#endif /* SILC_SYMBIAN */ + return TRUE; +} + +/* Allocates a new SilcMac object of name of `name'. The `hash' may + be provided as argument. If provided it is used as the hash function + of the MAC. If it is NULL then the hash function is allocated and + the name of the hash algorithm is derived from the `name'. */ + +SilcBool silc_mac_alloc(const char *name, SilcMac *new_mac) +{ + SilcMacObject *entry = NULL; + SilcHash hash = NULL; + int i; + + SILC_LOG_DEBUG(("Allocating new MAC")); + + /* Allocate the new object */ + *new_mac = silc_calloc(1, sizeof(**new_mac)); + if (!(*new_mac)) + return FALSE; + + if (!hash) { + char *tmp = strdup(name), *hname; + + hname = tmp; + if (strchr(hname, '-')) + hname = strchr(hname, '-') + 1; + if (strchr(hname, '-')) + *strchr(hname, '-') = '\0'; + + if (!silc_hash_alloc(hname, &hash)) { + silc_free(tmp); + silc_free(*new_mac); + *new_mac = NULL; + return FALSE; + } + + (*new_mac)->allocated_hash = TRUE; + silc_free(tmp); + } + + (*new_mac)->hash = hash; + +#ifndef SILC_SYMBIAN + /* Check registered list of MACs */ + if (silc_mac_list) { + silc_dlist_start(silc_mac_list); + while ((entry = silc_dlist_get(silc_mac_list)) != SILC_LIST_END) { + if (!strcmp(entry->name, name)) { + (*new_mac)->mac = entry; + return TRUE; + } + } + } +#endif /* SILC_SYMBIAN */ + + if (!entry) { + /* Check builtin list of MACs */ + for (i = 0; silc_default_macs[i].name; i++) { + if (!strcmp(silc_default_macs[i].name, name)) { + (*new_mac)->mac = (SilcMacObject *)&(silc_default_macs[i]); + return TRUE; + } + } + } + + silc_free(*new_mac); + *new_mac = NULL; + return FALSE; +} + +/* Free's the SilcMac object. */ + +void silc_mac_free(SilcMac mac) +{ + if (mac) { + if (mac->allocated_hash) + silc_hash_free(mac->hash); + + if (mac->key) { + memset(mac->key, 0, mac->key_len); + silc_free(mac->key); + } + + silc_free(mac); + } +} + +/* Returns the length of the MAC that the MAC will produce. */ + +SilcUInt32 silc_mac_len(SilcMac mac) +{ + return mac->mac->len; +} + +/* Get hash context */ + +SilcHash silc_mac_get_hash(SilcMac mac) +{ + return mac->hash; +} + +/* Return name of mac */ + +const char *silc_mac_get_name(SilcMac mac) +{ + return mac->mac->name; +} + +/* Returns TRUE if MAC `name' is supported. */ + +SilcBool silc_mac_is_supported(const char *name) +{ + SilcMacObject *entry; + int i; + + if (!name) + return FALSE; + +#ifndef SILC_SYMBIAN + if (silc_mac_list) { + silc_dlist_start(silc_mac_list); + while ((entry = silc_dlist_get(silc_mac_list)) != SILC_LIST_END) { + if (!strcmp(entry->name, name)) + return TRUE; + } + } +#endif /* SILC_SYMBIAN */ + + for (i = 0; silc_default_macs[i].name; i++) + if (!strcmp(silc_default_macs[i].name, name)) + return TRUE; + + return FALSE; +} + +/* Returns comma separated list of supported MACs. */ + +char *silc_mac_get_supported() +{ + SilcMacObject *entry, *entry2; + char *list = NULL; + int len = 0, i; + +#ifndef SILC_SYMBIAN + if (silc_mac_list) { + silc_dlist_start(silc_mac_list); + while ((entry = silc_dlist_get(silc_mac_list)) != SILC_LIST_END) { + len += strlen(entry->name); + list = silc_realloc(list, len + 1); + + memcpy(list + (len - strlen(entry->name)), + entry->name, strlen(entry->name)); + memcpy(list + len, ",", 1); + len++; + } + } +#endif /* SILC_SYMBIAN */ + + + for (i = 0; silc_default_macs[i].name; i++) { + entry = (SilcMacObject *)&(silc_default_macs[i]); + + if (silc_mac_list) { + silc_dlist_start(silc_mac_list); + while ((entry2 = silc_dlist_get(silc_mac_list)) != SILC_LIST_END) { + if (!strcmp(entry2->name, entry->name)) + break; + } + if (entry2) + continue; + } + + len += strlen(entry->name); + list = silc_realloc(list, len + 1); + + memcpy(list + (len - strlen(entry->name)), + entry->name, strlen(entry->name)); + memcpy(list + len, ",", 1); + len++; + } + + list[len - 1] = 0; + + return list; +} + +/* Sets the MAC key used in the MAC creation */ + +void silc_mac_set_key(SilcMac mac, const unsigned char *key, + SilcUInt32 key_len) +{ + if (mac->key) { + memset(mac->key, 0, mac->key_len); + silc_free(mac->key); + } + mac->key = silc_malloc(key_len); + if (!mac->key) + return; + mac->key_len = key_len; + memcpy(mac->key, key, key_len); +} + +/* Return MAC key */ + +const unsigned char *silc_mac_get_key(SilcMac mac, SilcUInt32 *key_len) +{ + if (key_len) + *key_len = mac->key_len; + return (const unsigned char *)mac->key; +} + +/* Create the MAC. This is thee make_mac function pointer. This + uses the internal key set with silc_mac_set_key. */ + +void silc_mac_make(SilcMac mac, unsigned char *data, + SilcUInt32 data_len, unsigned char *return_hash, + SilcUInt32 *return_len) +{ + SILC_LOG_DEBUG(("Making MAC for message")); + + silc_mac_init(mac); + silc_mac_update(mac, data, data_len); + silc_mac_final(mac, return_hash, return_len); +} + +/* Creates MAC just as above except that this doesn't use the internal + key. The key is sent as argument to the function. */ + +void silc_mac_make_with_key(SilcMac mac, unsigned char *data, + SilcUInt32 data_len, + unsigned char *key, SilcUInt32 key_len, + unsigned char *return_hash, + SilcUInt32 *return_len) +{ + SILC_LOG_DEBUG(("Making MAC for message")); + + silc_mac_init_with_key(mac, key, key_len); + silc_mac_update(mac, data, data_len); + silc_mac_final(mac, return_hash, return_len); +} + +/* Creates the MAC just as above except that the hash value is truncated + to the truncated_len sent as argument. NOTE: One should not truncate to + less than half of the length of original hash value. However, this + routine allows these dangerous truncations. */ + +void silc_mac_make_truncated(SilcMac mac, unsigned char *data, + SilcUInt32 data_len, + SilcUInt32 truncated_len, + unsigned char *return_hash) +{ + unsigned char hvalue[SILC_HASH_MAXLEN]; + + SILC_LOG_DEBUG(("Making MAC for message")); + + silc_mac_init(mac); + silc_mac_update(mac, data, data_len); + silc_mac_final(mac, return_hash, NULL); + memcpy(return_hash, hvalue, truncated_len); + memset(hvalue, 0, sizeof(hvalue)); +} + +/* Init MAC for silc_mac_update and silc_mac_final. */ + +void silc_mac_init(SilcMac mac) +{ + silc_mac_init_with_key(mac, mac->key, mac->key_len); +} + +/* Same as above but with specific key */ + +void silc_mac_init_with_key(SilcMac mac, const unsigned char *key, + SilcUInt32 key_len) +{ + SilcHash hash = mac->hash; + silc_mac_init_internal(mac, (unsigned char *)key, key_len); + silc_hash_init(hash); + silc_hash_update(hash, mac->inner_pad, silc_hash_block_len(hash)); +} + +/* Add data to be used in the MAC computation. */ + +void silc_mac_update(SilcMac mac, const unsigned char *data, + SilcUInt32 data_len) +{ + SilcHash hash = mac->hash; + silc_hash_update(hash, data, data_len); +} + +/* Compute the final MAC. */ + +void silc_mac_final(SilcMac mac, unsigned char *return_hash, + SilcUInt32 *return_len) +{ + SilcHash hash = mac->hash; + unsigned char digest[SILC_HASH_MAXLEN]; + + silc_hash_final(hash, digest); + silc_hash_init(hash); + silc_hash_update(hash, mac->outer_pad, silc_hash_block_len(hash)); + silc_hash_update(hash, digest, silc_hash_len(hash)); + silc_hash_final(hash, digest); + memcpy(return_hash, digest, mac->mac->len); + memset(digest, 0, sizeof(digest)); + + if (return_len) + *return_len = mac->mac->len; +} diff --git a/lib/silccrypt/silcmac.h b/lib/silccrypt/silcmac.h new file mode 100644 index 00000000..d04d8c10 --- /dev/null +++ b/lib/silccrypt/silcmac.h @@ -0,0 +1,484 @@ +/* + + silcmac.h + + Author: Pekka Riikonen + + Copyright (C) 1999 - 2008 Pekka Riikonen + + This program 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; version 2 of the License. + + 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. + +*/ + +#ifndef SILCMAC_H +#define SILCMAC_H + +/****h* silccrypt/SILC MAC Interface + * + * DESCRIPTION + * + * The Message Authentication Code interface for computing MAC values for + * authentication purposes. The MAC is usually used in combination with + * encryption to provide authentication. + * + ***/ + +/****s* silccrypt/SilcMac + * + * NAME + * + * typedef struct SilcMacStruct *SilcMac; + * + * DESCRIPTION + * + * This context is the actual MAC context and is allocated + * by silc_mac_alloc and given as argument usually to all + * silc_mac_* functions. It is freed by the silc_mac_free + * function. + * + ***/ +typedef struct SilcMacStruct *SilcMac; + +/****d* silccrypt/MACs + * + * NAME + * + * MAC Algorithms + * + * DESCRIPTION + * + * Supported MAC algorithm names. These names can be given as argument + * to silc_mac_alloc. + * + * SOURCE + */ + +/* HMAC with SHA-256, MAC truncated to 96 bits */ +#define SILC_MAC_HMAC_SHA256_96 "hmac-sha256-96" + +/* HMAC with SHA-512, MAC truncated to 96 bits */ +#define SILC_MAC_HMAC_SHA512_96 "hmac-sha512-96" + +/* HMAC with SHA-1, MAC truncated to 96 bits */ +#define SILC_MAC_HMAC_SHA1_96 "hmac-sha1-96" + +/* HMAC with MD5, MAC truncated to 96 bits */ +#define SILC_MAC_HMAC_MD5_96 "hmac-md5-96" + +/* HMAC with SHA-256 */ +#define SILC_MAC_HMAC_SHA256 "hmac-sha256" + +/* HMAC with SHA-512 */ +#define SILC_MAC_HMAC_SHA512 "hmac-sha512" + +/* HMAC with SHA-1 */ +#define SILC_MAC_HMAC_SHA1 "hmac-sha1" + +/* HMAC with MD5 */ +#define SILC_MAC_HMAC_MD5 "hmac-md5" +/***/ + +/* MAC implementation object */ +typedef struct { + char *name; + SilcUInt32 len; +} SilcMacObject; + +/* Marks for all MACs. This can be used in silc_mac_unregister + to unregister all MACs at once. */ +#define SILC_ALL_MACS ((SilcMacObject *)1) + +/* Default MACs for silc_mac_register_default(). */ +extern DLLAPI const SilcMacObject silc_default_macs[]; + +/* Prototypes */ + +/****f* silccrypt/silc_mac_register + * + * SYNOPSIS + * + * SilcBool silc_mac_register(const SilcMacObject *mac); + * + * DESCRIPTION + * + * Registers a new MAC into Crypto Toolkit. This function can be used + * at the initialization. All registered MACs should be unregistered + * with silc_mac_unregister. Returns FALSE on error. Usually this + * function is not needed. The default MAC algorithms are automatically + * registered. This can be used to change the order of the registered + * MAC algorithms by re-registering them in desired order, or add new + * algorithms. + * + ***/ +SilcBool silc_mac_register(const SilcMacObject *mac); + +/****f* silccrypt/silc_mac_unregister + * + * SYNOPSIS + * + * SilcBool silc_mac_unregister(SilcMacObject *mac); + * + * DESCRIPTION + * + * Unregister a MAC from SILC by the MAC structure `mac'. This + * should be called for all MACs registered with silc_mac_register. + * Returns FALSE on error. + * + ***/ +SilcBool silc_mac_unregister(SilcMacObject *mac); + +/****f* silccrypt/silc_mac_register_default + * + * SYNOPSIS + * + * SilcBool silc_mac_register_default(void); + * + * DESCRIPTION + * + * Registers all default MACs into the SILC. These are the MACs + * that are builtin in the sources. Application need not call this + * directly. By calling silc_crypto_init this function is called. + * + ***/ +SilcBool silc_mac_register_default(void); + +/****f* silccrypt/silc_mac_unregister_all + * + * SYNOPSIS + * + * SilcBool silc_mac_unregister_all(void); + * + * DESCRIPTION + * + * Unregisters all registered MACs. Application need not call this + * directly. By calling silc_crypto_uninit this function is called. + * + ***/ +SilcBool silc_mac_unregister_all(void); + +/****f* silccrypt/silc_mac_alloc + * + * SYNOPSIS + * + * SilcBool silc_mac_alloc(const char *name, SilcMac *new_mac); + * + * DESCRIPTION + * + * Allocates a new SilcMac object of name of `name'. Returns FALSE if + * such MAC does not exist. After the MAC is allocated a key must be + * set for it by calling silc_mac_set_key. + * + ***/ +SilcBool silc_mac_alloc(const char *name, SilcMac *new_mac); + +/****f* silccrypt/silc_mac_free + * + * SYNOPSIS + * + * void silc_mac_free(SilcMac mac); + * + * DESCRIPTION + * + * Frees the allocated MAC context. The key that may have been set + * with the silc_mac_set_key is also destroyed. + * + ***/ +void silc_mac_free(SilcMac mac); + +/****f* silccrypt/silc_mac_is_supported + * + * SYNOPSIS + * + * SilcBool silc_mac_is_supported(const char *name); + * + * DESCRIPTION + * + * Returns TRUE if the MAC indicated by the `name' exists. + * + ***/ +SilcBool silc_mac_is_supported(const char *name); + +/****f* silccrypt/silc_mac_get_supported + * + * SYNOPSIS + * + * char *silc_mac_get_supported(void); + * + * DESCRIPTION + * + * Returns comma (`,') separated list of registered MACs. The caller + * must free the returned pointer. + * + ***/ +char *silc_mac_get_supported(void); + +/****f* silccrypt/silc_mac_len + * + * SYNOPSIS + * + * SilcUInt32 silc_mac_len(SilcMac mac); + * + * DESCRIPTION + * + * Returns the length of the MAC that the MAC will produce. + * + ***/ +SilcUInt32 silc_mac_len(SilcMac mac); + +/****f* silccrypt/silc_mac_get_name + * + * SYNOPSIS + * + * const char *silc_mac_get_name(SilcMac mac); + * + * DESCRIPTION + * + * Returns the name of the MAC context. + * + ***/ +const char *silc_mac_get_name(SilcMac mac); + +/****f* silccrypt/silc_mac_get_hash + * + * SYNOPSIS + * + * SilcHash silc_mac_get_hash(SilcMac mac); + * + * DESCRIPTION + * + * Returns the SilcHash context that has been associated with the + * MAC context or NULL if the `mac' doesn't use hash function. In effect + * with HMACs this returns the underlaying hash function. The caller + * must not free the returned context. + * + ***/ +SilcHash silc_mac_get_hash(SilcMac hmac); + +/****f* silccrypt/silc_mac_set_key + * + * SYNOPSIS + * + * void silc_mac_set_key(SilcMac mac, const unsigned char *key, + * SilcUInt32 key_len); + * + * DESCRIPTION + * + * Sets the key to be used in the MAC operation. This must be set + * before calling silc_mac_make or silc_mac_final functions. If + * you do not want to set the key you can still produce a MAC by + * calling the silc_mac_make_with_key where you give the key as + * argument. Usually application still wants to set the key. + * + ***/ +void silc_mac_set_key(SilcMac mac, const unsigned char *key, + SilcUInt32 key_len); + +/****f* silccrypt/silc_mac_get_key + * + * SYNOPSIS + * + * const unsigned char * + * silc_mac_get_key(SilcMac mac, SilcUInt32 *key_len); + * + * DESCRIPTION + * + * Returns the key data from the `mac' set with silc_hamc_set_key. + * The caller must not free the returned pointer. + * + ***/ +const unsigned char *silc_mac_get_key(SilcMac mac, SilcUInt32 *key_len); + +/****f* silccrypt/silc_mac_make + * + * SYNOPSIS + * + * void silc_mac_make(SilcMac mac, unsigned char *data, + * SilcUInt32 data_len, unsigned char *return_hash, + * SilcUInt32 *return_len); + * + * DESCRIPTION + * + * Computes a MAC from a data buffer indicated by the `data' of the + * length of `data_len'. The returned MAC is copied into the + * `return_hash' pointer which must be at least the size of the + * value silc_mac_len returns. The returned length is still + * returned to `return_len'. + * + ***/ +void silc_mac_make(SilcMac mac, unsigned char *data, + SilcUInt32 data_len, unsigned char *return_hash, + SilcUInt32 *return_len); + +/****f* silccrypt/silc_mac_make_with_key + * + * SYNOPSIS + * + * void silc_mac_make_with_key(SilcMac mac, unsigned char *data, + * SilcUInt32 data_len, + * unsigned char *key, SilcUInt32 key_len, + * unsigned char *return_hash, + * SilcUInt32 *return_len); + * + * DESCRIPTION + * + * Same as the silc_mac_make but takes the key for the MAC as argument. + * If this is used the key that may have been set by calling + * silc_mac_set_key is ignored. + * + ***/ +void silc_mac_make_with_key(SilcMac mac, unsigned char *data, + SilcUInt32 data_len, + unsigned char *key, SilcUInt32 key_len, + unsigned char *return_hash, + SilcUInt32 *return_len); + +/****f* silccrypt/silc_mac_make_truncated + * + * SYNOPSIS + * + * void silc_mac_make_truncated(SilcMac mac, + * unsigned char *data, + * SilcUInt32 data_len, + * SilcUInt32 truncated_len, + * unsigned char *return_hash); + * + * DESCRIPTION + * + * Same as the silc_mac_make except that the returned MAC is + * truncated to the length indicated by the `truncated_len'. Some + * special applications may need this function. The `return_hash' + * must be at least the size of `truncated_len'. + * + * NOTES + * + * For security reasons, one should not truncate to less than half + * of the length of the true MAC lenght. However, since this routine + * may be used to non-critical applications this allows these dangerous + * truncations. + * + ***/ +void silc_mac_make_truncated(SilcMac mac, + unsigned char *data, + SilcUInt32 data_len, + SilcUInt32 truncated_len, + unsigned char *return_hash); + +/****f* silccrypt/silc_mac_init + * + * SYNOPSIS + * + * void silc_mac_init(SilcMac mac); + * + * DESCRIPTION + * + * Sometimes calling the silc_mac_make might not be the most + * optimal case of doing MACs. If you have a lot of different data + * that you need to put together for computing a MAC you may either + * put them into a buffer and compute the MAC from the buffer by + * calling the silc_mac_make, or you can use the silc_mac_init, + * silc_mac_update and silc_mac_final to do the MAC. This function + * prepares the allocated MAC context for this kind of MAC + * computation. The caller must have been called the function + * silc_mac_set_key before calling this function. To add the + * data to be used in the MAC computation call the silc_mac_update + * function. + * + ***/ +void silc_mac_init(SilcMac mac); + +/****f* silccrypt/silc_mac_init_with_key + * + * SYNOPSIS + * + * void silc_mac_init_with_key(SilcMac mac, const unsigned char *key, + * SilcUInt32 key_len); + * + * DESCRIPTION + * + * Same as silc_mac_init but initializes with specific key. The + * key that may have been set with silc_mac_set_key is ignored. + * + ***/ +void silc_mac_init_with_key(SilcMac mac, const unsigned char *key, + SilcUInt32 key_len); + +/****f* silccrypt/silc_mac_update + * + * SYNOPSIS + * + * void silc_mac_update(SilcMac mac, const unsigned char *data, + * SilcUInt32 data_len); + * + * DESCRIPTION + * + * This function may be called to add data to be used in the MAC + * computation. This can be called multiple times to add data from + * many sources before actually performing the MAC. Once you've + * added all the data you need you can call the silc_mac_final to + * actually produce the MAC. + * + * EXAMPLE + * + * unsigned char mac[20]; + * SilcUInt32 mac_len; + * + * silc_mac_init(mac); + * silc_mac_update(mac, data, data_len); + * silc_mac_update(mac, more_data, more_data_len); + * silc_mac_final(hac, mac, &mac_len); + * + ***/ +void silc_mac_update(SilcMac mac, const unsigned char *data, + SilcUInt32 data_len); + +/****f* silccrypt/silc_mac_final + * + * SYNOPSIS + * + * void silc_mac_final(SilcMac mac, unsigned char *return_hash, + * SilcUInt32 *return_len); + * + * DESCRIPTION + * + * This function is used to produce the final MAC from the data + * that has been added to the MAC context by calling the + * silc_mac_update function. The MAC is copied in to the + * `return_hash' pointer which must be at least the size that + * the silc_mac_len returns. The length of the MAC is still + * returned into `return_len'. + * + ***/ +void silc_mac_final(SilcMac mac, unsigned char *return_hash, + SilcUInt32 *return_len); + +/* Backwards support for old HMAC API */ +#define SilcHmac SilcMac +#define SilcHmacObject SilcMacObject +#define SILC_ALL_HMACS SILC_ALL_MACS +#define silc_default_hmacs silc_default_macs +#define silc_hmac_register silc_mac_register +#define silc_hmac_unregister silc_mac_unregister +#define silc_hmac_register_default silc_mac_register_default +#define silc_hmac_unregister_all silc_mac_unregister_all +#define silc_hmac_alloc(name, hash, new_hmac) silc_mac_alloc(name, new_hmac) +#define silc_hmac_free silc_mac_free +#define silc_hmac_is_supported silc_mac_is_supported +#define silc_hmac_get_supported silc_mac_get_supported +#define silc_hmac_len silc_mac_len +#define silc_hmac_get_hash silc_mac_get_hash +#define silc_hmac_get_name silc_mac_get_name +#define silc_hmac_set_key silc_mac_set_key +#define silc_hmac_get_key silc_mac_get_key +#define silc_hmac_make silc_mac_make +#define silc_hmac_init_with_key silc_mac_init_with_key +#define silc_hmac_update silc_mac_update +#define silc_hmac_final silc_mac_final + +#endif /* SILCMAC_H */ diff --git a/lib/silccrypt/silcpk.c b/lib/silccrypt/silcpk.c index b96cb3e9..708fb49a 100644 --- a/lib/silccrypt/silcpk.c +++ b/lib/silccrypt/silcpk.c @@ -903,7 +903,7 @@ SILC_PKCS_IMPORT_PRIVATE_KEY_FILE(silc_pkcs_silc_import_private_key_file) } /* Allocate HMAC */ - if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) { + if (!silc_mac_alloc("hmac-sha1-96", &sha1hmac)) { SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered")); silc_hash_free(sha1); silc_cipher_free(aes); @@ -926,15 +926,15 @@ SILC_PKCS_IMPORT_PRIVATE_KEY_FILE(silc_pkcs_silc_import_private_key_file) silc_cipher_set_key(aes, keymat, 256, FALSE); /* First, verify the MAC of the private key data */ - mac_len = silc_hmac_len(sha1hmac); - silc_hmac_init_with_key(sha1hmac, keymat, 16); - silc_hmac_update(sha1hmac, filedata, len - mac_len); - silc_hmac_final(sha1hmac, tmp, NULL); + mac_len = silc_mac_len(sha1hmac); + silc_mac_init_with_key(sha1hmac, keymat, 16); + silc_mac_update(sha1hmac, filedata, len - mac_len); + silc_mac_final(sha1hmac, tmp, NULL); if (memcmp(tmp, filedata + (len - mac_len), mac_len)) { SILC_LOG_DEBUG(("Integrity check for private key failed")); memset(keymat, 0, sizeof(keymat)); memset(tmp, 0, sizeof(tmp)); - silc_hmac_free(sha1hmac); + silc_mac_free(sha1hmac); silc_hash_free(sha1); silc_cipher_free(aes); return FALSE; @@ -949,7 +949,7 @@ SILC_PKCS_IMPORT_PRIVATE_KEY_FILE(silc_pkcs_silc_import_private_key_file) SILC_LOG_DEBUG(("Bad private key length in buffer!")); memset(keymat, 0, sizeof(keymat)); memset(tmp, 0, sizeof(tmp)); - silc_hmac_free(sha1hmac); + silc_mac_free(sha1hmac); silc_hash_free(sha1); silc_cipher_free(aes); return FALSE; @@ -960,7 +960,7 @@ SILC_PKCS_IMPORT_PRIVATE_KEY_FILE(silc_pkcs_silc_import_private_key_file) /* Cleanup */ memset(keymat, 0, sizeof(keymat)); memset(tmp, 0, sizeof(tmp)); - silc_hmac_free(sha1hmac); + silc_mac_free(sha1hmac); silc_hash_free(sha1); silc_cipher_free(aes); @@ -1322,7 +1322,7 @@ SILC_PKCS_EXPORT_PRIVATE_KEY_FILE(silc_pkcs_silc_export_private_key_file) } /* Allocate HMAC */ - if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) { + if (!silc_mac_alloc("hmac-sha1-96", &sha1hmac)) { SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered")); silc_sfree(stack, key); silc_hash_free(sha1); @@ -1349,12 +1349,12 @@ SILC_PKCS_EXPORT_PRIVATE_KEY_FILE(silc_pkcs_silc_export_private_key_file) block size of the cipher. */ /* Allocate buffer for encryption */ - len = silc_hmac_len(sha1hmac); + len = silc_mac_len(sha1hmac); padlen = 16 + (16 - ((key_len + 4) % blocklen)); enc = silc_buffer_salloc_size(stack, 4 + 4 + key_len + padlen + len); if (!enc) { silc_sfree(stack, key); - silc_hmac_free(sha1hmac); + silc_mac_free(sha1hmac); silc_hash_free(sha1); silc_cipher_free(aes); return FALSE; @@ -1385,16 +1385,16 @@ SILC_PKCS_EXPORT_PRIVATE_KEY_FILE(silc_pkcs_silc_export_private_key_file) /* Compute HMAC over the encrypted data and append the MAC to data. The key is the first digest of the original key material. */ key_len = silc_buffer_len(enc) - len; - silc_hmac_init_with_key(sha1hmac, keymat, 16); - silc_hmac_update(sha1hmac, enc->data, key_len); + silc_mac_init_with_key(sha1hmac, keymat, 16); + silc_mac_update(sha1hmac, enc->data, key_len); silc_buffer_pull(enc, key_len); - silc_hmac_final(sha1hmac, enc->data, NULL); + silc_mac_final(sha1hmac, enc->data, NULL); silc_buffer_push(enc, key_len); /* Cleanup */ memset(keymat, 0, sizeof(keymat)); memset(tmp, 0, sizeof(tmp)); - silc_hmac_free(sha1hmac); + silc_mac_free(sha1hmac); silc_hash_free(sha1); silc_cipher_free(aes); @@ -1655,6 +1655,6 @@ SILC_PKCS_VERIFY(silc_pkcs_silc_verify) return silc_pubkey->pkcs->verify(silc_pubkey->pkcs, silc_pubkey->public_key, signature, signature_len, - data, data_len, hash, rng, + data, data_len, hash != NULL, hash, rng, verify_cb, context); } -- 2.24.0