From: Pekka Riikonen Date: Sun, 8 Jul 2007 17:33:06 +0000 (+0000) Subject: Rewrote crypto library init/uninit. Added silc_crypto_init X-Git-Tag: 1.2.beta1~202 X-Git-Url: http://git.silcnet.org/gitweb/?a=commitdiff_plain;h=abfab56ac76372f17c2e509b2e2fdd4675ec7764;p=crypto.git Rewrote crypto library init/uninit. Added silc_crypto_init and silc_crypto_uninit, and silc_crypto_stack. Changed SILC PKCS API asynchronous so that accelerators can be used, and added SilcStack support to many routines. Rewrote PKCS, cipher, hash and HMAC registering/unregistering. silc_xxx_register_default does not call silc_xxx_register anymore. User can enforece the order of algorithms by calling silc_xxx_register in the order they want. Changed silc_rng_get_rn_data to non-allocating. --- diff --git a/lib/silccrypt/Makefile.ad b/lib/silccrypt/Makefile.ad index 19031662..4b0a4268 100644 --- a/lib/silccrypt/Makefile.ad +++ b/lib/silccrypt/Makefile.ad @@ -39,6 +39,7 @@ libsilccrypt_la_SOURCES = \ sha256.c \ twofish.c \ blowfish.c \ + silccrypto.c \ silccipher.c \ silchash.c \ silchmac.c \ @@ -58,10 +59,12 @@ CFLAGS = $(LTFLAGS) @SILC_CRYPTO_CFLAGS@ #ifdef SILC_DIST_TOOLKIT include_HEADERS = \ + silccrypto.h \ silccipher.h \ silchash.h \ silchmac.h \ silcpkcs.h \ + silcpkcs_i.h \ silcrng.h \ silcpkcs1.h \ silcpk.h diff --git a/lib/silccrypt/silccipher.c b/lib/silccrypt/silccipher.c index f7f64600..729d54ec 100644 --- a/lib/silccrypt/silccipher.c +++ b/lib/silccrypt/silccipher.c @@ -66,10 +66,7 @@ const SilcCipherObject silc_default_ciphers[] = { NULL, NULL, 0, 0, 0, 0 } }; -/* Register a new cipher into SILC. This is used at the initialization of - the SILC. This function allocates a new object for the cipher to be - registered. Therefore, if memory has been allocated for the object sent - as argument it has to be free'd after this function returns succesfully. */ +/* Register new cipher */ SilcBool silc_cipher_register(const SilcCipherObject *cipher) { @@ -82,7 +79,7 @@ SilcBool silc_cipher_register(const SilcCipherObject *cipher) if (silc_cipher_list) { SilcCipherObject *entry; silc_dlist_start(silc_cipher_list); - while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) { + while ((entry = silc_dlist_get(silc_cipher_list))) { if (!strcmp(entry->name, cipher->name)) return FALSE; } @@ -115,7 +112,7 @@ SilcBool silc_cipher_register(const SilcCipherObject *cipher) return TRUE; } -/* Unregister a cipher from the SILC. */ +/* Unregister a cipher */ SilcBool silc_cipher_unregister(SilcCipherObject *cipher) { @@ -128,7 +125,7 @@ SilcBool silc_cipher_unregister(SilcCipherObject *cipher) return FALSE; silc_dlist_start(silc_cipher_list); - while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) { + while ((entry = silc_dlist_get(silc_cipher_list))) { if (cipher == SILC_ALL_CIPHERS || entry == cipher) { silc_dlist_del(silc_cipher_list, entry); silc_free(entry->name); @@ -147,22 +144,16 @@ SilcBool silc_cipher_unregister(SilcCipherObject *cipher) return FALSE; } -/* Function that registers all the default ciphers (all builtin ciphers). - The application may use this to register the default ciphers if specific - ciphers in any specific order is not wanted. */ +/* Register default ciphers */ SilcBool silc_cipher_register_default(void) { -#ifndef SILC_SYMBIAN - int i; - - for (i = 0; silc_default_ciphers[i].name; i++) - silc_cipher_register(&(silc_default_ciphers[i])); - -#endif /* SILC_SYMBIAN */ + /* We use builtin ciphers */ return TRUE; } +/* Unregister all ciphers */ + SilcBool silc_cipher_unregister_all(void) { #ifndef SILC_SYMBIAN @@ -172,7 +163,7 @@ SilcBool silc_cipher_unregister_all(void) return FALSE; silc_dlist_start(silc_cipher_list); - while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) { + while ((entry = silc_dlist_get(silc_cipher_list))) { silc_cipher_unregister(entry); if (!silc_cipher_list) break; @@ -189,21 +180,23 @@ SilcBool silc_cipher_unregister_all(void) SilcBool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher) { SilcCipherObject *entry = NULL; + int i; SILC_LOG_DEBUG(("Allocating new cipher object")); #ifndef SILC_SYMBIAN + /* First check registered list of ciphers */ if (silc_cipher_list) { silc_dlist_start(silc_cipher_list); - while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) { + while ((entry = silc_dlist_get(silc_cipher_list))) { if (!strcmp(entry->name, name)) break; } } -#else - { - /* On EPOC which don't have globals we check our constant cipher list. */ - int i; +#endif /* SILC_SYMBIAN */ + + if (!entry) { + /* Check builtin list of ciphers */ for (i = 0; silc_default_ciphers[i].name; i++) { if (!strcmp(silc_default_ciphers[i].name, name)) { entry = (SilcCipherObject *)&(silc_default_ciphers[i]); @@ -211,7 +204,6 @@ SilcBool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher) } } } -#endif /* SILC_SYMBIAN */ if (entry) { *new_cipher = silc_calloc(1, sizeof(**new_cipher)); @@ -223,6 +215,7 @@ SilcBool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher) silc_free(*new_cipher); return FALSE; } + return TRUE; } @@ -243,24 +236,25 @@ void silc_cipher_free(SilcCipher cipher) SilcBool silc_cipher_is_supported(const unsigned char *name) { -#ifndef SILC_SYMBIAN SilcCipherObject *entry; + int i; +#ifndef SILC_SYMBIAN + /* First check registered list of ciphers */ if (silc_cipher_list) { silc_dlist_start(silc_cipher_list); - while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) { + while ((entry = silc_dlist_get(silc_cipher_list))) { if (!strcmp(entry->name, name)) return TRUE; } } -#else - { - int i; - for (i = 0; silc_default_ciphers[i].name; i++) - if (!strcmp(silc_default_ciphers[i].name, name)) - return TRUE; - } #endif /* SILC_SYMBIAN */ + + /* Check builtin list of ciphers */ + for (i = 0; silc_default_ciphers[i].name; i++) + if (!strcmp(silc_default_ciphers[i].name, name)) + return TRUE; + return FALSE; } @@ -268,14 +262,14 @@ SilcBool silc_cipher_is_supported(const unsigned char *name) char *silc_cipher_get_supported(void) { - SilcCipherObject *entry; + SilcCipherObject *entry, *entry2; char *list = NULL; - int len = 0; + int i, len = 0; #ifndef SILC_SYMBIAN if (silc_cipher_list) { silc_dlist_start(silc_cipher_list); - while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) { + while ((entry = silc_dlist_get(silc_cipher_list))) { len += strlen(entry->name); list = silc_realloc(list, len + 1); @@ -285,21 +279,29 @@ char *silc_cipher_get_supported(void) len++; } } -#else - { - int i; - for (i = 0; silc_default_ciphers[i].name; i++) { - entry = (SilcCipherObject *)&(silc_default_ciphers[i]); - len += strlen(entry->name); - list = silc_realloc(list, len + 1); +#endif /* SILC_SYMBIAN */ - memcpy(list + (len - strlen(entry->name)), - entry->name, strlen(entry->name)); - memcpy(list + len, ",", 1); - len++; + for (i = 0; silc_default_ciphers[i].name; i++) { + entry = (SilcCipherObject *)&(silc_default_ciphers[i]); + + if (silc_cipher_list) { + silc_dlist_start(silc_cipher_list); + while ((entry2 = silc_dlist_get(silc_cipher_list))) { + 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++; } -#endif /* SILC_SYMBIAN */ list[len - 1] = 0; diff --git a/lib/silccrypt/silccrypto.c b/lib/silccrypt/silccrypto.c new file mode 100644 index 00000000..c4ac5ded --- /dev/null +++ b/lib/silccrypt/silccrypto.c @@ -0,0 +1,96 @@ +/* + + silccrypto.c + + Author: Pekka Riikonen + + Copyright (C) 2007 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 "silc.h" + +#ifndef SILC_SYMBIAN +SilcStack crypto_stack = NULL; /* Crypto Toolkit's global stack */ +#endif /* SILC_SYMBIAN */ + +/* Init crypto */ + +SilcBool silc_crypto_init(SilcStack stack) +{ + SILC_LOG_DEBUG(("Initializing crypto")); + +#ifndef SILC_SYMBIAN + /* Stack allocation is allowed to fail */ + crypto_stack = silc_stack_alloc(0, stack); +#endif /* SILC_SYMBIAN */ + + /* Init crypto library */ + if (!silc_cipher_register_default()) { + SILC_LOG_ERROR(("Error registering ciphers")); + goto err; + } + if (!silc_hash_register_default()) { + SILC_LOG_ERROR(("Error registering hash functions")); + goto err; + } + if (!silc_hmac_register_default()) { + SILC_LOG_ERROR(("Error registering hash HMACs")); + goto err; + } + if (!silc_pkcs_register_default()) { + SILC_LOG_ERROR(("Error registering hash PKCSs")); + goto err; + } + +#ifdef SILC_DIST_ACC + /* Initialize accelerator library */ +#endif /* SILC_DIST_ACC */ + + return TRUE; + + err: + silc_crypto_uninit(); + return FALSE; +} + +/* Uninit crypto */ + +void silc_crypto_uninit(void) +{ + SILC_LOG_DEBUG(("Uninitializing crypto")); + +#ifdef SILC_DIST_ACC + /* Uninit accelerator library */ +#endif /* SILC_DIST_ACC */ + + /* Uninit crypto library */ + silc_pkcs_unregister_all(); + silc_hmac_unregister_all(); + silc_hash_unregister_all(); + silc_cipher_unregister_all(); + +#ifndef SILC_SYMBIAN + silc_stack_free(crypto_stack); +#endif /* SILC_SYMBIAN */ +} + +/* Return stack */ + +SilcStack silc_crypto_stack(void) +{ +#ifndef SILC_SYMBIAN + return crypto_stack; +#else + return NULL; +#endif /* SILC_SYMBIAN */ +} diff --git a/lib/silccrypt/silccrypto.h b/lib/silccrypt/silccrypto.h new file mode 100644 index 00000000..4d99ecab --- /dev/null +++ b/lib/silccrypt/silccrypto.h @@ -0,0 +1,118 @@ +/* + + silccrypto.h + + Author: Pekka Riikonen + + Copyright (C) 2007 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. + +*/ + +/****h* silccrypt/SILC Crypto Toolkit API + * + * DESCRIPTION + * + * This interface is used to initialize and uninitialize the SILC Crypto + * Toolkit. SILC Crypto Toolkit is initialized by calling the + * 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 + * 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 + * in desired order. + * + * A global SilcStack, a memory pool, can be associated with the Crypto + * Toolkit. If it is set in initialization, all routines in the Crypto + * Toolkit will use that stack as its memory source. Some interfaces and + * libraries in the SILC Crypto Toolkit support also providing the SilcStack + * as an additional argument, in which case a different stack from the global + * one can be used. + * + ***/ + +#ifndef SILCCRYPTO_H +#define SILCCRYPTO_H + +/****f* silccrypt/SilcCryptoAPI/silc_crypto_init + * + * SYNOPSIS + * + * SilcBool silc_crypto_init(SilcStack stack); + * + * DESCRIPTION + * + * Initialize SILC Crypto Toolkit. This must be called once for every + * process. It initializes all libraries and registers builtin algorithms + * to the crypto library. If user wants to change the order of the + * registered algorithms, user can re-register them with their + * corresponding registering functions in the wanted order. + * + * If `stack' is non-NULL, it will be used by all libraries as their main + * source for memory. A child stack is created from the `stack'. When + * silc_crypto_uninit is called the allocated memory is returned back to + * `stack' and the caller must then free `stack'. + * + * Returns FALSE if the initialization failed. If this happens the + * SILC Crypto Toolkit cannot be used. + * + ***/ +SilcBool silc_crypto_init(SilcStack stack); + +/****f* silccrypt/SilcCryptoAPI/silc_crypto_uninit + * + * SYNOPSIS + * + * void silc_crypto_uninit(void); + * + * DESCRIPTION + * + * Uninitializes the SILC Crypto Toolkit. This should be called at the + * of the process before it is exited. + * + ***/ +void silc_crypto_uninit(void); + +/****f* silccrypt/SilcCryptoAPI/silc_crypto_stack + * + * SYNOPSIS + * + * SilcStack silc_crypto_stack(void); + * + * DESCRIPTION + * + * Returns the SILC Crypto Toolkit's global stack, the memory pool. + * Returns NULL if the stack does not exist. + * + * A common way to use this is to allocate a child stack from the + * returned stack. That operation is thread-safe, usually does not + * allocate any memory and is very fast. Another way to use the stack + * is to push it when memory is needed and then pop it when it is not + * needed anymore. Note however, that is not thread-safe if the stack + * is used in multi-threaded environment. + * + * EXAMPLE + * + * SilcStack stack; + * + * // Get child stack from global crypto stack + * stack = silc_stack_alloc(0, silc_crypto_stack()); + * ... + * + * // Return memory back to the global crypto stack + * silc_stack_free(stack); + * + ***/ +SilcStack silc_crypto_stack(void); + +#endif /* SILCCRYPTO_H */ diff --git a/lib/silccrypt/silchash.c b/lib/silccrypt/silchash.c index 59cdf7f9..b67d43f2 100644 --- a/lib/silccrypt/silchash.c +++ b/lib/silccrypt/silchash.c @@ -51,8 +51,7 @@ const SilcHashObject silc_default_hash[] = { NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL } }; -/* Registers a new hash function into the SILC. This function is used at - the initialization of the SILC. */ +/* Registers a new hash function */ SilcBool silc_hash_register(const SilcHashObject *hash) { @@ -101,7 +100,7 @@ SilcBool silc_hash_register(const SilcHashObject *hash) return TRUE; } -/* Unregister a hash function from the SILC. */ +/* Unregister a hash function */ SilcBool silc_hash_unregister(SilcHashObject *hash) { @@ -134,22 +133,16 @@ SilcBool silc_hash_unregister(SilcHashObject *hash) return FALSE; } -/* Function that registers all the default hash funcs (all builtin ones). - The application may use this to register the default hash funcs if - specific hash funcs in any specific order is not wanted. */ +/* Register default hash functions */ SilcBool silc_hash_register_default(void) { -#ifndef SILC_SYMBIAN - int i; - - for (i = 0; silc_default_hash[i].name; i++) - silc_hash_register(&(silc_default_hash[i])); - -#endif /* SILC_SYMBIAN */ + /* We use builtin hash functions */ return TRUE; } +/* Unregister all hash functions */ + SilcBool silc_hash_unregister_all(void) { #ifndef SILC_SYMBIAN @@ -174,10 +167,12 @@ SilcBool silc_hash_unregister_all(void) SilcBool silc_hash_alloc(const unsigned char *name, SilcHash *new_hash) { SilcHashObject *entry = NULL; + int i; SILC_LOG_DEBUG(("Allocating new hash %s", name)); #ifndef SILC_SYMBIAN + /* Check list of registered hash functions */ if (silc_hash_list) { silc_dlist_start(silc_hash_list); while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) { @@ -185,10 +180,10 @@ SilcBool silc_hash_alloc(const unsigned char *name, SilcHash *new_hash) break; } } -#else - { - /* On EPOC which don't have globals we check our constant hash list. */ - int i; +#endif /* SILC_SYMBIAN */ + + if (!entry) { + /* Check builtin hash function list */ for (i = 0; silc_default_hash[i].name; i++) { if (!strcmp(silc_default_hash[i].name, name)) { entry = (SilcHashObject *)&(silc_default_hash[i]); @@ -196,7 +191,6 @@ SilcBool silc_hash_alloc(const unsigned char *name, SilcHash *new_hash) } } } -#endif /* SILC_SYMBIAN */ if (entry) { *new_hash = silc_calloc(1, sizeof(**new_hash)); @@ -219,10 +213,12 @@ SilcBool silc_hash_alloc(const unsigned char *name, SilcHash *new_hash) SilcBool silc_hash_alloc_by_oid(const char *oid, SilcHash *new_hash) { SilcHashObject *entry = NULL; + int i; SILC_LOG_DEBUG(("Allocating new hash %s", oid)); #ifndef SILC_SYMBIAN + /* Check list of registered hash functions */ if (silc_hash_list) { silc_dlist_start(silc_hash_list); while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) { @@ -230,10 +226,10 @@ SilcBool silc_hash_alloc_by_oid(const char *oid, SilcHash *new_hash) break; } } -#else - { - /* On EPOC which don't have globals we check our constant hash list. */ - int i; +#endif /* SILC_SYMBIAN */ + + if (!entry) { + /* Check builtin hash function list */ for (i = 0; silc_default_hash[i].oid; i++) { if (!strcmp(silc_default_hash[i].oid, oid)) { entry = (SilcHashObject *)&(silc_default_hash[i]); @@ -241,7 +237,6 @@ SilcBool silc_hash_alloc_by_oid(const char *oid, SilcHash *new_hash) } } } -#endif /* SILC_SYMBIAN */ if (entry) { *new_hash = silc_calloc(1, sizeof(**new_hash)); @@ -301,9 +296,10 @@ const char *silc_hash_get_oid(SilcHash hash) SilcBool silc_hash_is_supported(const unsigned char *name) { -#ifndef SILC_SYMBIAN SilcHashObject *entry; + int i; +#ifndef SILC_SYMBIAN if (silc_hash_list) { silc_dlist_start(silc_hash_list); while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) { @@ -311,14 +307,12 @@ SilcBool silc_hash_is_supported(const unsigned char *name) return TRUE; } } -#else - { - int i; - for (i = 0; silc_default_hash[i].name; i++) - if (!strcmp(silc_default_hash[i].name, name)) - return TRUE; - } #endif /* SILC_SYMBIAN */ + + for (i = 0; silc_default_hash[i].name; i++) + if (!strcmp(silc_default_hash[i].name, name)) + return TRUE; + return FALSE; } @@ -326,9 +320,9 @@ SilcBool silc_hash_is_supported(const unsigned char *name) char *silc_hash_get_supported(void) { - SilcHashObject *entry; + SilcHashObject *entry, *entry2; char *list = NULL; - int len = 0; + int i, len = 0; #ifndef SILC_SYMBIAN if (silc_hash_list) { @@ -343,21 +337,29 @@ char *silc_hash_get_supported(void) len++; } } -#else - { - int i; - for (i = 0; silc_default_hash[i].name; i++) { - entry = (SilcHashObject *)&(silc_default_hash[i]); - len += strlen(entry->name); - list = silc_realloc(list, len + 1); +#endif /* SILC_SYMBIAN */ - memcpy(list + (len - strlen(entry->name)), - entry->name, strlen(entry->name)); - memcpy(list + len, ",", 1); - len++; + for (i = 0; silc_default_hash[i].name; i++) { + entry = (SilcHashObject *)&(silc_default_hash[i]); + + if (silc_hash_list) { + silc_dlist_start(silc_hash_list); + while ((entry2 = silc_dlist_get(silc_hash_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++; } -#endif /* SILC_SYMBIAN */ list[len - 1] = 0; diff --git a/lib/silccrypt/silchmac.c b/lib/silccrypt/silchmac.c index 1e9380db..a343429d 100644 --- a/lib/silccrypt/silchmac.c +++ b/lib/silccrypt/silchmac.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1999 - 2006 Pekka Riikonen + Copyright (C) 1999 - 2007 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 @@ -81,8 +81,7 @@ static void silc_hmac_init_internal(SilcHmac hmac, unsigned char *key, } } -/* Registers a new HMAC into the SILC. This function is used at the - initialization of the SILC. */ +/* Registers a new HMAC */ SilcBool silc_hmac_register(const SilcHmacObject *hmac) { @@ -116,7 +115,7 @@ SilcBool silc_hmac_register(const SilcHmacObject *hmac) return TRUE; } -/* Unregister a HMAC from the SILC. */ +/* Unregister a HMAC */ SilcBool silc_hmac_unregister(SilcHmacObject *hmac) { @@ -148,22 +147,16 @@ SilcBool silc_hmac_unregister(SilcHmacObject *hmac) return FALSE; } -/* Function that registers all the default hmacs (all builtin ones). - The application may use this to register the default hmacs if - specific hmacs in any specific order is not wanted. */ +/* Register default HMACs */ SilcBool silc_hmac_register_default(void) { -#ifndef SILC_SYMBIAN - int i; - - for (i = 0; silc_default_hmacs[i].name; i++) - silc_hmac_register(&(silc_default_hmacs[i])); - -#endif /* SILC_SYMBIAN */ + /* We use builtin HMACs */ return TRUE; } +/* Unregister all HMACs */ + SilcBool silc_hmac_unregister_all(void) { #ifndef SILC_SYMBIAN @@ -189,6 +182,9 @@ SilcBool silc_hmac_unregister_all(void) 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 */ @@ -219,8 +215,8 @@ SilcBool silc_hmac_alloc(const char *name, SilcHash hash, SilcHmac *new_hmac) (*new_hmac)->hash = hash; #ifndef SILC_SYMBIAN + /* Check registered list of HMACs */ 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, name)) { @@ -229,10 +225,10 @@ SilcBool silc_hmac_alloc(const char *name, SilcHash hash, SilcHmac *new_hmac) } } } -#else - { - /* On EPOC which don't have globals we check our constant hash list. */ - int i; +#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]); @@ -240,7 +236,6 @@ SilcBool silc_hmac_alloc(const char *name, SilcHash hash, SilcHmac *new_hmac) } } } -#endif /* SILC_SYMBIAN */ silc_free(*new_hmac); *new_hmac = NULL; @@ -289,12 +284,13 @@ const char *silc_hmac_get_name(SilcHmac hmac) SilcBool silc_hmac_is_supported(const char *name) { -#ifndef SILC_SYMBIAN 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) { @@ -302,14 +298,12 @@ SilcBool silc_hmac_is_supported(const char *name) return TRUE; } } -#else - { - int i; - for (i = 0; silc_default_hmacs[i].name; i++) - if (!strcmp(silc_default_hmacs[i].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; } @@ -317,9 +311,9 @@ SilcBool silc_hmac_is_supported(const char *name) char *silc_hmac_get_supported() { - SilcHmacObject *entry; + SilcHmacObject *entry, *entry2; char *list = NULL; - int len = 0; + int len = 0, i; #ifndef SILC_SYMBIAN if (silc_hmac_list) { @@ -334,21 +328,30 @@ char *silc_hmac_get_supported() len++; } } -#else - { - int i; - for (i = 0; silc_default_hmacs[i].name; i++) { - entry = (SilcHmacObject *)&(silc_default_hmacs[i]); - len += strlen(entry->name); - list = silc_realloc(list, len + 1); +#endif /* SILC_SYMBIAN */ - memcpy(list + (len - strlen(entry->name)), - entry->name, strlen(entry->name)); - memcpy(list + len, ",", 1); - len++; + + 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++; } -#endif /* SILC_SYMBIAN */ list[len - 1] = 0; diff --git a/lib/silccrypt/silcpk.c b/lib/silccrypt/silcpk.c index 618d1b61..b383db8c 100644 --- a/lib/silccrypt/silcpk.c +++ b/lib/silccrypt/silcpk.c @@ -100,7 +100,7 @@ SilcBool silc_pkcs_silc_generate_key(const char *algorithm, (*ret_private_key)->private_key = privkey; /* Generate the algorithm key pair */ - if (!alg->generate_key(bits_key_len, rng, &pubkey->public_key, + if (!alg->generate_key(alg, bits_key_len, rng, &pubkey->public_key, &privkey->private_key)) { silc_free(pubkey); silc_free(privkey); @@ -196,7 +196,8 @@ SilcBool silc_pkcs_silc_decode_identifier(const char *identifier, arguments is NULL those are not encoded into the identifier string. Protocol says that at least username and host must be provided. */ -char *silc_pkcs_silc_encode_identifier(char *username, char *host, +char *silc_pkcs_silc_encode_identifier(SilcStack stack, + char *username, char *host, char *realname, char *email, char *org, char *country, char *version) @@ -212,66 +213,66 @@ char *silc_pkcs_silc_encode_identifier(char *username, char *host, memset(&buf, 0, sizeof(buf)); if (username) - silc_buffer_format(&buf, - SILC_STR_ADVANCE, - SILC_STR_UI32_STRING("UN="), - SILC_STR_UI32_STRING(username), - SILC_STR_END); + silc_buffer_sformat(stack, &buf, + SILC_STR_ADVANCE, + SILC_STR_UI32_STRING("UN="), + SILC_STR_UI32_STRING(username), + SILC_STR_END); if (host) - silc_buffer_format(&buf, - SILC_STR_ADVANCE, - SILC_STR_UI32_STRING(", "), - SILC_STR_UI32_STRING("HN="), - SILC_STR_UI32_STRING(host), - SILC_STR_END); + silc_buffer_sformat(stack, &buf, + SILC_STR_ADVANCE, + SILC_STR_UI32_STRING(", "), + SILC_STR_UI32_STRING("HN="), + SILC_STR_UI32_STRING(host), + SILC_STR_END); if (realname) - silc_buffer_format(&buf, - SILC_STR_ADVANCE, - SILC_STR_UI32_STRING(", "), - SILC_STR_UI32_STRING("RN="), - SILC_STR_UI32_STRING(realname), - SILC_STR_END); + silc_buffer_sformat(stack, &buf, + SILC_STR_ADVANCE, + SILC_STR_UI32_STRING(", "), + SILC_STR_UI32_STRING("RN="), + SILC_STR_UI32_STRING(realname), + SILC_STR_END); if (email) - silc_buffer_format(&buf, - SILC_STR_ADVANCE, - SILC_STR_UI32_STRING(", "), - SILC_STR_UI32_STRING("E="), - SILC_STR_UI32_STRING(email), - SILC_STR_END); + silc_buffer_sformat(stack, &buf, + SILC_STR_ADVANCE, + SILC_STR_UI32_STRING(", "), + SILC_STR_UI32_STRING("E="), + SILC_STR_UI32_STRING(email), + SILC_STR_END); if (org) - silc_buffer_format(&buf, - SILC_STR_ADVANCE, - SILC_STR_UI32_STRING(", "), - SILC_STR_UI32_STRING("O="), - SILC_STR_UI32_STRING(org), - SILC_STR_END); + silc_buffer_sformat(stack, &buf, + SILC_STR_ADVANCE, + SILC_STR_UI32_STRING(", "), + SILC_STR_UI32_STRING("O="), + SILC_STR_UI32_STRING(org), + SILC_STR_END); if (country) - silc_buffer_format(&buf, - SILC_STR_ADVANCE, - SILC_STR_UI32_STRING(", "), - SILC_STR_UI32_STRING("C="), - SILC_STR_UI32_STRING(country), - SILC_STR_END); + silc_buffer_sformat(stack, &buf, + SILC_STR_ADVANCE, + SILC_STR_UI32_STRING(", "), + SILC_STR_UI32_STRING("C="), + SILC_STR_UI32_STRING(country), + SILC_STR_END); if (version) { if (strlen(version) > 1 || !isdigit(version[0])) { - silc_buffer_purge(&buf); + silc_buffer_spurge(stack, &buf); return NULL; } - silc_buffer_format(&buf, - SILC_STR_ADVANCE, - SILC_STR_UI32_STRING(", "), - SILC_STR_UI32_STRING("V="), - SILC_STR_UI32_STRING(version), - SILC_STR_END); + silc_buffer_sformat(stack, &buf, + SILC_STR_ADVANCE, + SILC_STR_UI32_STRING(", "), + SILC_STR_UI32_STRING("V="), + SILC_STR_UI32_STRING(version), + SILC_STR_END); } - silc_buffer_format(&buf, SILC_STR_UI_CHAR(0), SILC_STR_END); + silc_buffer_sformat(stack, &buf, SILC_STR_UI_CHAR(0), SILC_STR_END); identifier = silc_buffer_steal(&buf, NULL); return identifier; @@ -299,7 +300,9 @@ int silc_pkcs_silc_public_key_version(SilcPublicKey public_key) /* Returns PKCS algorithm context */ -const SilcPKCSAlgorithm *silc_pkcs_silc_get_algorithm(void *public_key) +const SilcPKCSAlgorithm * +silc_pkcs_silc_get_algorithm(const struct SilcPKCSObjectStruct *pkcs, + void *public_key) { SilcSILCPublicKey silc_pubkey = public_key; return silc_pubkey->pkcs; @@ -307,10 +310,12 @@ const SilcPKCSAlgorithm *silc_pkcs_silc_get_algorithm(void *public_key) /* Imports SILC protocol style public key from SILC public key file */ -SilcBool silc_pkcs_silc_import_public_key_file(unsigned char *filedata, - SilcUInt32 filedata_len, - SilcPKCSFileEncoding encoding, - void **ret_public_key) +SilcBool +silc_pkcs_silc_import_public_key_file(const struct SilcPKCSObjectStruct *pkcs, + unsigned char *filedata, + SilcUInt32 filedata_len, + SilcPKCSFileEncoding encoding, + void **ret_public_key) { SilcUInt32 i, len; unsigned char *data = NULL; @@ -342,14 +347,14 @@ SilcBool silc_pkcs_silc_import_public_key_file(unsigned char *filedata, break; case SILC_PKCS_FILE_BASE64: - data = silc_base64_decode(filedata, filedata_len, &filedata_len); + data = silc_base64_decode(NULL, filedata, filedata_len, &filedata_len); if (!data) return FALSE; filedata = data; break; } - ret = silc_pkcs_silc_import_public_key(filedata, filedata_len, + ret = silc_pkcs_silc_import_public_key(pkcs, filedata, filedata_len, ret_public_key); silc_free(data); @@ -358,11 +363,12 @@ SilcBool silc_pkcs_silc_import_public_key_file(unsigned char *filedata, /* Imports SILC protocol style public key */ -int silc_pkcs_silc_import_public_key(unsigned char *key, +int silc_pkcs_silc_import_public_key(const struct SilcPKCSObjectStruct *pkcs, + void *key, SilcUInt32 key_len, void **ret_public_key) { - const SilcPKCSAlgorithm *pkcs; + const SilcPKCSAlgorithm *alg; SilcBufferStruct buf, alg_key; SilcSILCPublicKey silc_pubkey = NULL; SilcAsn1 asn1 = NULL; @@ -442,16 +448,16 @@ int silc_pkcs_silc_import_public_key(unsigned char *key, if (!silc_pubkey->identifier.version || atoi(silc_pubkey->identifier.version) <= 1) { /* Version 1 */ - pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid"); + alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid"); } else { /* Version 2 and newer */ - pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1"); + alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1"); } - if (!pkcs) { + if (!alg) { SILC_LOG_DEBUG(("Unsupported PKCS algorithm: rsa")); goto err; } - silc_pubkey->pkcs = pkcs; + silc_pubkey->pkcs = alg; if (keydata_len < 4) goto err; @@ -497,8 +503,8 @@ int silc_pkcs_silc_import_public_key(unsigned char *key, } /* Import PKCS algorithm public key */ - if (!pkcs->import_public_key(alg_key.data, silc_buffer_len(&alg_key), - &silc_pubkey->public_key)) + if (!alg->import_public_key(alg, alg_key.data, silc_buffer_len(&alg_key), + &silc_pubkey->public_key)) goto err; silc_free(pkcs_name); @@ -521,7 +527,9 @@ int silc_pkcs_silc_import_public_key(unsigned char *key, /* Exports public key as SILC protocol style public key file */ unsigned char * -silc_pkcs_silc_export_public_key_file(void *public_key, +silc_pkcs_silc_export_public_key_file(const struct SilcPKCSObjectStruct *pkcs, + SilcStack stack, + void *public_key, SilcPKCSFileEncoding encoding, SilcUInt32 *ret_len) { @@ -532,7 +540,7 @@ silc_pkcs_silc_export_public_key_file(void *public_key, SILC_LOG_DEBUG(("Encoding SILC public key file")); /* Export key */ - key = silc_pkcs_silc_export_public_key(public_key, &key_len); + key = silc_pkcs_silc_export_public_key(pkcs, stack, public_key, &key_len); if (!key) return NULL; @@ -541,48 +549,51 @@ silc_pkcs_silc_export_public_key_file(void *public_key, break; case SILC_PKCS_FILE_BASE64: - data = silc_base64_encode_file(key, key_len); + data = silc_base64_encode_file(stack, key, key_len); if (!data) return NULL; - silc_free(key); + silc_sfree(stack, key); key = data; key_len = strlen(data); break; } /* Encode SILC public key file */ - buf = silc_buffer_alloc_size(key_len + - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) + - strlen(SILC_PKCS_PUBLIC_KEYFILE_END))); + buf = silc_buffer_salloc_size(stack, key_len + + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) + + strlen(SILC_PKCS_PUBLIC_KEYFILE_END))); if (!buf) { - silc_free(key); + silc_sfree(stack, key); return NULL; } - if (silc_buffer_format(buf, - SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN), - SILC_STR_UI_XNSTRING(key, key_len), - SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END), - SILC_STR_END) < 0) { - silc_buffer_free(buf); - silc_free(key); + if (silc_buffer_sformat(stack, buf, + SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN), + SILC_STR_UI_XNSTRING(key, key_len), + SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END), + SILC_STR_END) < 0) { + silc_buffer_sfree(stack, buf); + silc_sfree(stack, key); return NULL; } - silc_free(key); + silc_sfree(stack, key); key = silc_buffer_steal(buf, ret_len); - silc_buffer_free(buf); + silc_buffer_sfree(stack, buf); return key; } /* Exports public key as SILC protocol style public key */ -unsigned char *silc_pkcs_silc_export_public_key(void *public_key, - SilcUInt32 *ret_len) +unsigned char * +silc_pkcs_silc_export_public_key(const struct SilcPKCSObjectStruct *pkcs, + SilcStack stack, + void *public_key, + SilcUInt32 *ret_len) { SilcSILCPublicKey silc_pubkey = public_key; - const SilcPKCSAlgorithm *pkcs = silc_pubkey->pkcs; + const SilcPKCSAlgorithm *alg = silc_pubkey->pkcs; SilcBufferStruct alg_key; SilcBuffer buf = NULL; SilcAsn1 asn1 = NULL; @@ -593,8 +604,8 @@ unsigned char *silc_pkcs_silc_export_public_key(void *public_key, SILC_LOG_DEBUG(("Encoding SILC public key")); /* Export PKCS algorithm public key */ - if (pkcs->export_public_key) - pk = pkcs->export_public_key(silc_pubkey->public_key, &pk_len); + if (alg->export_public_key) + pk = alg->export_public_key(alg, stack, silc_pubkey->public_key, &pk_len); if (!pk) { SILC_LOG_ERROR(("Error exporting PKCS algorithm key")); return NULL; @@ -603,7 +614,8 @@ unsigned char *silc_pkcs_silc_export_public_key(void *public_key, /* Encode identifier */ identifier = - silc_pkcs_silc_encode_identifier(silc_pubkey->identifier.username, + silc_pkcs_silc_encode_identifier(stack, + silc_pubkey->identifier.username, silc_pubkey->identifier.host, silc_pubkey->identifier.realname, silc_pubkey->identifier.email, @@ -615,11 +627,11 @@ unsigned char *silc_pkcs_silc_export_public_key(void *public_key, goto err; } - asn1 = silc_asn1_alloc(NULL); + asn1 = silc_asn1_alloc(stack); if (!asn1) goto err; - if (!strcmp(pkcs->name, "rsa")) { + if (!strcmp(alg->name, "rsa")) { /* Parse the PKCS #1 public key */ SilcMPInt n, e; SilcUInt32 n_len, e_len; @@ -642,7 +654,7 @@ unsigned char *silc_pkcs_silc_export_public_key(void *public_key, if (!nb) goto err; key_len = e_len + 4 + n_len + 4; - key = silc_calloc(key_len, sizeof(*key)); + key = silc_scalloc(stack, key_len, sizeof(*key)); if (!key) goto err; @@ -657,45 +669,44 @@ unsigned char *silc_pkcs_silc_export_public_key(void *public_key, silc_free(nb); silc_free(eb); - } else if (!strcmp(pkcs->name, "dsa")) { + } else if (!strcmp(alg->name, "dsa")) { SILC_NOT_IMPLEMENTED("SILC DSA Public Key"); goto err; } else { - SILC_LOG_ERROR(("Unsupported PKCS algorithm: %s", pkcs->name)); + SILC_LOG_ERROR(("Unsupported PKCS algorithm: %s", alg->name)); goto err; } /* Encode SILC Public Key */ - totlen = 2 + strlen(pkcs->name) + 2 + strlen(identifier) + key_len; - buf = silc_buffer_alloc_size(totlen + 4); + totlen = 2 + strlen(alg->name) + 2 + strlen(identifier) + key_len; + buf = silc_buffer_salloc_size(stack, totlen + 4); if (!buf) goto err; - if (silc_buffer_format(buf, - SILC_STR_UI_INT(totlen), - SILC_STR_UI_SHORT(strlen(pkcs->name)), - SILC_STR_UI32_STRING(pkcs->name), - SILC_STR_UI_SHORT(strlen(identifier)), - SILC_STR_UI32_STRING(identifier), - SILC_STR_UI_XNSTRING(key, key_len), - SILC_STR_END) < 0) + if (silc_buffer_sformat(stack, buf, + SILC_STR_UI_INT(totlen), + SILC_STR_UI_SHORT(strlen(alg->name)), + SILC_STR_UI32_STRING(alg->name), + SILC_STR_UI_SHORT(strlen(identifier)), + SILC_STR_UI32_STRING(identifier), + SILC_STR_UI_XNSTRING(key, key_len), + SILC_STR_END) < 0) goto err; ret = silc_buffer_steal(buf, ret_len); - silc_buffer_free(buf); - silc_free(key); - silc_free(identifier); - silc_buffer_purge(&alg_key); + silc_buffer_sfree(stack, buf); + silc_sfree(stack, key); + silc_sfree(stack, identifier); + silc_buffer_spurge(stack, &alg_key); silc_asn1_free(asn1); return ret; err: - silc_free(identifier); - silc_free(pk); - silc_free(key); - if (buf) - silc_buffer_free(buf); + silc_sfree(stack, identifier); + silc_sfree(stack, pk); + silc_sfree(stack, key); + silc_buffer_sfree(stack, buf); if (asn1) silc_asn1_free(asn1); return NULL; @@ -703,15 +714,19 @@ unsigned char *silc_pkcs_silc_export_public_key(void *public_key, /* Return key length */ -SilcUInt32 silc_pkcs_silc_public_key_bitlen(void *public_key) +SilcUInt32 +silc_pkcs_silc_public_key_bitlen(const struct SilcPKCSObjectStruct *pkcs, + void *public_key) { SilcSILCPublicKey silc_pubkey = public_key; - return silc_pubkey->pkcs->public_key_bitlen(silc_pubkey->public_key); + return silc_pubkey->pkcs->public_key_bitlen(silc_pubkey->pkcs, + silc_pubkey->public_key); } /* Copy public key */ -void *silc_pkcs_silc_public_key_copy(void *public_key) +void *silc_pkcs_silc_public_key_copy(const struct SilcPKCSObjectStruct *pkcs, + void *public_key) { SilcSILCPublicKey silc_pubkey = public_key, new_pubkey; SilcPublicKeyIdentifier ident = &silc_pubkey->identifier; @@ -722,7 +737,8 @@ void *silc_pkcs_silc_public_key_copy(void *public_key) new_pubkey->pkcs = silc_pubkey->pkcs; new_pubkey->public_key = - silc_pubkey->pkcs->public_key_copy(silc_pubkey->public_key); + silc_pubkey->pkcs->public_key_copy(silc_pubkey->pkcs, + silc_pubkey->public_key); if (!new_pubkey->public_key) { silc_free(new_pubkey); return NULL; @@ -755,7 +771,9 @@ void *silc_pkcs_silc_public_key_copy(void *public_key) /* Compares public keys */ -SilcBool silc_pkcs_silc_public_key_compare(void *key1, void *key2) +SilcBool +silc_pkcs_silc_public_key_compare(const struct SilcPKCSObjectStruct *pkcs, + void *key1, void *key2) { SilcSILCPublicKey k1 = key1, k2 = key2; @@ -804,16 +822,18 @@ SilcBool silc_pkcs_silc_public_key_compare(void *key1, void *key2) strcmp(k1->identifier.version, k2->identifier.version))) return FALSE; - return k1->pkcs->public_key_compare(k1->public_key, k2->public_key); + return k1->pkcs->public_key_compare(k1->pkcs, k1->public_key, k2->public_key); } /* Frees public key */ -void silc_pkcs_silc_public_key_free(void *public_key) +void silc_pkcs_silc_public_key_free(const struct SilcPKCSObjectStruct *pkcs, + void *public_key) { SilcSILCPublicKey silc_pubkey = public_key; - silc_pubkey->pkcs->public_key_free(silc_pubkey->public_key); + silc_pubkey->pkcs->public_key_free(silc_pubkey->pkcs, + silc_pubkey->public_key); silc_free(silc_pubkey->identifier.username); silc_free(silc_pubkey->identifier.host); @@ -833,12 +853,14 @@ void silc_pkcs_silc_public_key_free(void *public_key) /* Imports SILC implementation style private key file */ -SilcBool silc_pkcs_silc_import_private_key_file(unsigned char *filedata, - SilcUInt32 filedata_len, - const char *passphrase, - SilcUInt32 passphrase_len, - SilcPKCSFileEncoding encoding, - void **ret_private_key) +SilcBool +silc_pkcs_silc_import_private_key_file(const struct SilcPKCSObjectStruct *pkcs, + unsigned char *filedata, + SilcUInt32 filedata_len, + const char *passphrase, + SilcUInt32 passphrase_len, + SilcPKCSFileEncoding encoding, + void **ret_private_key) { SilcCipher aes; SilcHash sha1; @@ -872,7 +894,7 @@ SilcBool silc_pkcs_silc_import_private_key_file(unsigned char *filedata, break; case SILC_PKCS_FILE_BASE64: - data = silc_base64_decode(filedata, filedata_len, &len); + data = silc_base64_decode(NULL, filedata, filedata_len, &len); if (!data) return FALSE; filedata = data; @@ -970,7 +992,7 @@ SilcBool silc_pkcs_silc_import_private_key_file(unsigned char *filedata, silc_cipher_free(aes); /* Import the private key */ - ret = silc_pkcs_silc_import_private_key(filedata, len, ret_private_key); + ret = silc_pkcs_silc_import_private_key(pkcs, filedata, len, ret_private_key); silc_free(data); @@ -983,12 +1005,13 @@ SilcBool silc_pkcs_silc_import_private_key_file(unsigned char *filedata, /* Imports SILC implementation style private key */ -int silc_pkcs_silc_import_private_key(unsigned char *key, +int silc_pkcs_silc_import_private_key(const struct SilcPKCSObjectStruct *pkcs, + void *key, SilcUInt32 key_len, void **ret_private_key) { SilcBufferStruct buf; - const SilcPKCSAlgorithm *pkcs; + const SilcPKCSAlgorithm *alg; SilcBufferStruct alg_key; SilcSILCPrivateKey silc_privkey = NULL; SilcAsn1 asn1 = NULL; @@ -1002,7 +1025,7 @@ int silc_pkcs_silc_import_private_key(unsigned char *key, if (!ret_private_key) return 0; - silc_buffer_set(&buf, key, key_len); + silc_buffer_set(&buf, (unsigned char *)key, key_len); /* Get algorithm name and identifier */ ret = @@ -1072,16 +1095,16 @@ int silc_pkcs_silc_import_private_key(unsigned char *key, versions. */ if (ver == 0 || ver == SILC_PRIVATE_KEY_VERSION_1) { /* Version 0 and 1 */ - pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid"); + alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid"); } else { /* Version 2 and newer */ - pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1"); + alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1"); } - if (!pkcs) { + if (!alg) { SILC_LOG_DEBUG(("Unsupported PKCS algorithm")); goto err; } - silc_privkey->pkcs = pkcs; + silc_privkey->pkcs = alg; SILC_LOG_DEBUG(("Private key version %s", (ver == SILC_PRIVATE_KEY_VERSION_1 ? "1" : @@ -1263,8 +1286,8 @@ int silc_pkcs_silc_import_private_key(unsigned char *key, } /* Import PKCS algorithm private key */ - if (!pkcs->import_private_key(alg_key.data, silc_buffer_len(&alg_key), - &silc_privkey->private_key)) + if (!alg->import_private_key(alg, alg_key.data, silc_buffer_len(&alg_key), + &silc_privkey->private_key)) goto err; silc_free(pkcs_name); @@ -1286,7 +1309,9 @@ int silc_pkcs_silc_import_private_key(unsigned char *key, /* Exports private key as SILC implementation style private key file */ unsigned char * -silc_pkcs_silc_export_private_key_file(void *private_key, +silc_pkcs_silc_export_private_key_file(const struct SilcPKCSObjectStruct *pkcs, + SilcStack stack, + void *private_key, const char *passphrase, SilcUInt32 passphrase_len, SilcPKCSFileEncoding encoding, @@ -1305,7 +1330,7 @@ silc_pkcs_silc_export_private_key_file(void *private_key, SILC_LOG_DEBUG(("Encoding SILC private key file")); /* Export the private key */ - key = silc_pkcs_silc_export_private_key(private_key, &key_len); + key = silc_pkcs_silc_export_private_key(pkcs, stack, private_key, &key_len); if (!key) return NULL; @@ -1315,19 +1340,20 @@ silc_pkcs_silc_export_private_key_file(void *private_key, /* Allocate the AES cipher */ if (!silc_cipher_alloc("aes-256-cbc", &aes)) { SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered")); - silc_free(key); + silc_sfree(stack, key); return NULL; } blocklen = silc_cipher_get_block_len(aes); if (blocklen * 2 > sizeof(tmp)) { silc_cipher_free(aes); - silc_free(key); + silc_sfree(stack, key); return NULL; } /* Allocate SHA1 hash */ if (!silc_hash_alloc("sha1", &sha1)) { SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered")); + silc_sfree(stack, key); silc_cipher_free(aes); return NULL; } @@ -1335,6 +1361,7 @@ silc_pkcs_silc_export_private_key_file(void *private_key, /* Allocate HMAC */ if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) { SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered")); + silc_sfree(stack, key); silc_hash_free(sha1); silc_cipher_free(aes); return NULL; @@ -1361,8 +1388,9 @@ silc_pkcs_silc_export_private_key_file(void *private_key, /* Allocate buffer for encryption */ len = silc_hmac_len(sha1hmac); padlen = 16 + (16 - ((key_len + 4) % blocklen)); - enc = silc_buffer_alloc_size(4 + 4 + key_len + padlen + len); + enc = silc_buffer_salloc_size(stack, 4 + 4 + key_len + padlen + len); if (!enc) { + silc_sfree(stack, key); silc_hmac_free(sha1hmac); silc_hash_free(sha1); silc_cipher_free(aes); @@ -1378,12 +1406,12 @@ silc_pkcs_silc_export_private_key_file(void *private_key, silc_buffer_pull(enc, 4); /* Encode the buffer */ - silc_buffer_format(enc, - SILC_STR_UI_INT(key_len), - SILC_STR_UI_XNSTRING(key, key_len), - SILC_STR_UI_XNSTRING(tmp, padlen), - SILC_STR_END); - silc_free(key); + silc_buffer_sformat(stack, enc, + SILC_STR_UI_INT(key_len), + SILC_STR_UI_XNSTRING(key, key_len), + SILC_STR_UI_XNSTRING(tmp, padlen), + SILC_STR_END); + silc_sfree(stack, key); /* Encrypt. */ silc_cipher_encrypt(aes, enc->data, enc->data, silc_buffer_len(enc) - len, @@ -1412,13 +1440,13 @@ silc_pkcs_silc_export_private_key_file(void *private_key, break; case SILC_PKCS_FILE_BASE64: - data = silc_base64_encode_file(enc->data, silc_buffer_len(enc)); + data = silc_base64_encode_file(stack, enc->data, silc_buffer_len(enc)); if (!data) { silc_buffer_clear(enc); - silc_buffer_free(enc); + silc_buffer_sfree(stack, enc); return NULL; } - silc_free(silc_buffer_steal(enc, NULL)); + silc_sfree(stack, silc_buffer_steal(enc, NULL)); silc_buffer_set(enc, data, strlen(data)); break; } @@ -1429,31 +1457,34 @@ silc_pkcs_silc_export_private_key_file(void *private_key, /* Encode the data and save to file */ len = key_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) + strlen(SILC_PKCS_PRIVATE_KEYFILE_END)); - buf = silc_buffer_alloc_size(len); + buf = silc_buffer_salloc_size(stack, len); if (!buf) { - silc_buffer_free(enc); + silc_buffer_sfree(stack, enc); return NULL; } - silc_buffer_format(buf, - SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN), - SILC_STR_UI_XNSTRING(key, key_len), - SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END), - SILC_STR_END); + silc_buffer_sformat(stack, buf, + SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN), + SILC_STR_UI_XNSTRING(key, key_len), + SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END), + SILC_STR_END); - silc_buffer_free(enc); + silc_buffer_sfree(stack, enc); data = silc_buffer_steal(buf, ret_len); - silc_buffer_free(buf); + silc_buffer_sfree(stack, buf); return data; } /* Exports private key as SILC implementation style private key */ -unsigned char *silc_pkcs_silc_export_private_key(void *private_key, - SilcUInt32 *ret_len) +unsigned char * +silc_pkcs_silc_export_private_key(const struct SilcPKCSObjectStruct *pkcs, + SilcStack stack, + void *private_key, + SilcUInt32 *ret_len) { SilcSILCPrivateKey silc_privkey = private_key; - const SilcPKCSAlgorithm *pkcs = silc_privkey->pkcs; + const SilcPKCSAlgorithm *alg = silc_privkey->pkcs; SilcBufferStruct alg_key; SilcBuffer buf = NULL; SilcAsn1 asn1 = NULL; @@ -1463,17 +1494,18 @@ unsigned char *silc_pkcs_silc_export_private_key(void *private_key, SILC_LOG_DEBUG(("Encoding SILC private key")); /* Export PKCS algorithm private key */ - if (pkcs->export_private_key) - prv = pkcs->export_private_key(silc_privkey->private_key, &prv_len); + if (alg->export_private_key) + prv = alg->export_private_key(alg, stack, + silc_privkey->private_key, &prv_len); if (!prv) return NULL; silc_buffer_set(&alg_key, prv, prv_len); - asn1 = silc_asn1_alloc(NULL); + asn1 = silc_asn1_alloc(stack); if (!asn1) goto err; - if (!strcmp(pkcs->name, "rsa")) { + if (!strcmp(alg->name, "rsa")) { /* Parse the PKCS #1 private key */ SilcMPInt n, e, d, dp, dq, qp, p, q; SilcUInt32 e_len, n_len, d_len, dp_len, dq_len, @@ -1506,32 +1538,32 @@ unsigned char *silc_pkcs_silc_export_private_key(void *private_key, len = 4 + e_len + 4 + n_len + 4 + d_len + 4+ dp_len + 4 + dq_len + 4 + qp_len + 4 + p_len + 4 + q_len + 4; - buf = silc_buffer_alloc_size(len); + buf = silc_buffer_salloc_size(stack, len); if (!buf) goto err; - if (silc_buffer_format(buf, - SILC_STR_UI_INT(SILC_PRIVATE_KEY_VERSION_1), - SILC_STR_UI_INT(e_len), - SILC_STR_UI_XNSTRING(eb, e_len), - SILC_STR_UI_INT(n_len), - SILC_STR_UI_XNSTRING(nb, n_len), - SILC_STR_UI_INT(d_len), - SILC_STR_UI_XNSTRING(db, d_len), - SILC_STR_UI_INT(dp_len), - SILC_STR_UI_XNSTRING(dpb, dp_len), - SILC_STR_UI_INT(dq_len), - SILC_STR_UI_XNSTRING(dqb, dq_len), - SILC_STR_UI_INT(qp_len), - SILC_STR_UI_XNSTRING(qpb, qp_len), - SILC_STR_UI_INT(p_len), - SILC_STR_UI_XNSTRING(pb, p_len), - SILC_STR_UI_INT(q_len), - SILC_STR_UI_XNSTRING(qb, q_len), - SILC_STR_END) < 0) + if (silc_buffer_sformat(stack, buf, + SILC_STR_UI_INT(SILC_PRIVATE_KEY_VERSION_1), + SILC_STR_UI_INT(e_len), + SILC_STR_UI_XNSTRING(eb, e_len), + SILC_STR_UI_INT(n_len), + SILC_STR_UI_XNSTRING(nb, n_len), + SILC_STR_UI_INT(d_len), + SILC_STR_UI_XNSTRING(db, d_len), + SILC_STR_UI_INT(dp_len), + SILC_STR_UI_XNSTRING(dpb, dp_len), + SILC_STR_UI_INT(dq_len), + SILC_STR_UI_XNSTRING(dqb, dq_len), + SILC_STR_UI_INT(qp_len), + SILC_STR_UI_XNSTRING(qpb, qp_len), + SILC_STR_UI_INT(p_len), + SILC_STR_UI_XNSTRING(pb, p_len), + SILC_STR_UI_INT(q_len), + SILC_STR_UI_XNSTRING(qb, q_len), + SILC_STR_END) < 0) goto err; key = silc_buffer_steal(buf, &key_len); - silc_buffer_free(buf); + silc_buffer_sfree(stack, buf); silc_free(nb); silc_free(eb); silc_free(db); @@ -1541,7 +1573,7 @@ unsigned char *silc_pkcs_silc_export_private_key(void *private_key, silc_free(pb); silc_free(qb); - } else if (!strcmp(pkcs->name, "dsa")) { + } else if (!strcmp(alg->name, "dsa")) { SILC_NOT_IMPLEMENTED("SILC DSA Private Key"); goto err; @@ -1551,49 +1583,52 @@ unsigned char *silc_pkcs_silc_export_private_key(void *private_key, } /* Encode SILC private key */ - totlen = 2 + strlen(pkcs->name) + key_len; - buf = silc_buffer_alloc_size(totlen); + totlen = 2 + strlen(alg->name) + key_len; + buf = silc_buffer_salloc_size(stack, totlen); if (!buf) goto err; - if (silc_buffer_format(buf, - SILC_STR_UI_SHORT(strlen(pkcs->name)), - SILC_STR_UI32_STRING(pkcs->name), - SILC_STR_UI_XNSTRING(key, key_len), - SILC_STR_END) < 0) + if (silc_buffer_sformat(stack, buf, + SILC_STR_UI_SHORT(strlen(alg->name)), + SILC_STR_UI32_STRING(alg->name), + SILC_STR_UI_XNSTRING(key, key_len), + SILC_STR_END) < 0) goto err; ret = silc_buffer_steal(buf, ret_len); - silc_buffer_free(buf); - silc_free(prv); - silc_free(key); + silc_buffer_sfree(stack, buf); + silc_sfree(stack, prv); + silc_sfree(stack, key); silc_asn1_free(asn1); return ret; err: - silc_free(prv); - silc_free(key); - if (buf) - silc_buffer_free(buf); + silc_sfree(stack, prv); + silc_sfree(stack, key); + silc_buffer_sfree(stack, buf); return NULL; } /* Return key length */ -SilcUInt32 silc_pkcs_silc_private_key_bitlen(void *private_key) +SilcUInt32 +silc_pkcs_silc_private_key_bitlen(const struct SilcPKCSObjectStruct *pkcs, + void *private_key) { SilcSILCPrivateKey silc_privkey = private_key; - return silc_privkey->pkcs->private_key_bitlen(silc_privkey->private_key); + return silc_privkey->pkcs->private_key_bitlen(silc_privkey->pkcs, + silc_privkey->private_key); } /* Frees private key */ -void silc_pkcs_silc_private_key_free(void *private_key) +void silc_pkcs_silc_private_key_free(const struct SilcPKCSObjectStruct *pkcs, + void *private_key) { SilcSILCPrivateKey silc_privkey = private_key; - silc_privkey->pkcs->private_key_free(silc_privkey->private_key); - + silc_privkey->pkcs->private_key_free(silc_privkey->pkcs, + silc_privkey->private_key); silc_free(silc_privkey); } @@ -1602,80 +1637,98 @@ void silc_pkcs_silc_private_key_free(void *private_key) /* Encrypts as specified in SILC protocol specification */ -SilcBool silc_pkcs_silc_encrypt(void *public_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *dst, - SilcUInt32 dst_size, - SilcUInt32 *ret_dst_len, - SilcRng rng) +SilcAsyncOperation +silc_pkcs_silc_encrypt(const struct SilcPKCSObjectStruct *pkcs, + void *public_key, + unsigned char *src, + SilcUInt32 src_len, + SilcRng rng, + SilcPKCSEncryptCb encrypt_cb, + void *context) { SilcSILCPublicKey silc_pubkey = public_key; - if (!silc_pubkey->pkcs->encrypt) - return FALSE; + if (!silc_pubkey->pkcs->encrypt) { + encrypt_cb(FALSE, NULL, 0, context); + return NULL; + } - return silc_pubkey->pkcs->encrypt(silc_pubkey->public_key, - src, src_len, - dst, dst_size, ret_dst_len, rng); + return silc_pubkey->pkcs->encrypt(silc_pubkey->pkcs, + silc_pubkey->public_key, + src, src_len, rng, encrypt_cb, context); } /* Decrypts as specified in SILC protocol specification */ -SilcBool silc_pkcs_silc_decrypt(void *private_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *dst, - SilcUInt32 dst_size, - SilcUInt32 *ret_dst_len) +SilcAsyncOperation +silc_pkcs_silc_decrypt(const struct SilcPKCSObjectStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcPKCSDecryptCb decrypt_cb, + void *context) { SilcSILCPrivateKey silc_privkey = private_key; - if (!silc_privkey->pkcs->decrypt) - return FALSE; + if (!silc_privkey->pkcs->decrypt) { + decrypt_cb(FALSE, NULL, 0, context); + return NULL; + } - return silc_privkey->pkcs->decrypt(silc_privkey->private_key, - src, src_len, - dst, dst_size, ret_dst_len); + return silc_privkey->pkcs->decrypt(silc_privkey->pkcs, + silc_privkey->private_key, + src, src_len, decrypt_cb, context); } /* Signs as specified in SILC protocol specification */ -SilcBool silc_pkcs_silc_sign(void *private_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *signature, - SilcUInt32 signature_size, - SilcUInt32 *ret_signature_len, - SilcBool compute_hash, - SilcHash hash) +SilcAsyncOperation +silc_pkcs_silc_sign(const struct SilcPKCSObjectStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcBool compute_hash, + SilcHash hash, + SilcPKCSSignCb sign_cb, + void *context) { SilcSILCPrivateKey silc_privkey = private_key; - if (!silc_privkey->pkcs->sign) - return FALSE; + if (!silc_privkey->pkcs->sign) { + sign_cb(FALSE, NULL, 0, context); + return NULL; + } - return silc_privkey->pkcs->sign(silc_privkey->private_key, + return silc_privkey->pkcs->sign(silc_privkey->pkcs, + silc_privkey->private_key, src, src_len, - signature, signature_size, - ret_signature_len, compute_hash, hash); + compute_hash, hash, + sign_cb, context); } /* Verifies as specified in SILC protocol specification */ -SilcBool silc_pkcs_silc_verify(void *public_key, - unsigned char *signature, - SilcUInt32 signature_len, - unsigned char *data, - SilcUInt32 data_len, - SilcHash hash) +SilcAsyncOperation +silc_pkcs_silc_verify(const struct SilcPKCSObjectStruct *pkcs, + void *public_key, + unsigned char *signature, + SilcUInt32 signature_len, + unsigned char *data, + SilcUInt32 data_len, + SilcHash hash, + SilcPKCSVerifyCb verify_cb, + void *context) { SilcSILCPublicKey silc_pubkey = public_key; - if (!silc_pubkey->pkcs->verify) - return FALSE; + if (!silc_pubkey->pkcs->verify) { + verify_cb(FALSE, context); + return NULL; + } - return silc_pubkey->pkcs->verify(silc_pubkey->public_key, + return silc_pubkey->pkcs->verify(silc_pubkey->pkcs, + silc_pubkey->public_key, signature, signature_len, - data, data_len, hash); + data, data_len, hash, + verify_cb, context); } diff --git a/lib/silccrypt/silcpk.h b/lib/silccrypt/silcpk.h index f62c628c..181bfa6f 100644 --- a/lib/silccrypt/silcpk.h +++ b/lib/silccrypt/silcpk.h @@ -142,8 +142,11 @@ SilcBool silc_pkcs_silc_generate_key(const char *algorithm, * Protocol says that at least username and host must be provided. * Caller must free the returned identifier string. * + * If `stack' is non-NULL the returned string is allocated from `stack'. + * ***/ -char *silc_pkcs_silc_encode_identifier(char *username, char *host, +char *silc_pkcs_silc_encode_identifier(SilcStack stack, + char *username, char *host, char *realname, char *email, char *org, char *country, char *version); diff --git a/lib/silccrypt/silcpk_i.h b/lib/silccrypt/silcpk_i.h index e0275610..48bfb465 100644 --- a/lib/silccrypt/silcpk_i.h +++ b/lib/silccrypt/silcpk_i.h @@ -26,70 +26,104 @@ #define SILC_PKCS_PRIVATE_KEYFILE_BEGIN "-----BEGIN SILC PRIVATE KEY-----\n" #define SILC_PKCS_PRIVATE_KEYFILE_END "\n-----END SILC PRIVATE KEY-----\n" -const SilcPKCSAlgorithm *silc_pkcs_silc_get_algorithm(void *public_key); -SilcBool silc_pkcs_silc_import_public_key_file(unsigned char *filedata, - SilcUInt32 filedata_len, - SilcPKCSFileEncoding encoding, - void **ret_public_key); -int silc_pkcs_silc_import_public_key(unsigned char *key, +const SilcPKCSAlgorithm * +silc_pkcs_silc_get_algorithm(const struct SilcPKCSObjectStruct *pkcs, + void *public_key); +SilcBool +silc_pkcs_silc_import_public_key_file(const struct SilcPKCSObjectStruct *pkcs, + unsigned char *filedata, + SilcUInt32 filedata_len, + SilcPKCSFileEncoding encoding, + void **ret_public_key); +int silc_pkcs_silc_import_public_key(const struct SilcPKCSObjectStruct *pkcs, + void *key, SilcUInt32 key_len, void **ret_public_key); unsigned char * -silc_pkcs_silc_export_public_key_file(void *public_key, +silc_pkcs_silc_export_public_key_file(const struct SilcPKCSObjectStruct *pkcs, + SilcStack stack, + void *public_key, SilcPKCSFileEncoding encoding, SilcUInt32 *ret_len); -unsigned char *silc_pkcs_silc_export_public_key(void *public_key, - SilcUInt32 *ret_len); -SilcUInt32 silc_pkcs_silc_public_key_bitlen(void *public_key); -void *silc_pkcs_silc_public_key_copy(void *public_key); -SilcBool silc_pkcs_silc_public_key_compare(void *key1, void *key2); -void silc_pkcs_silc_public_key_free(void *public_key); -SilcBool silc_pkcs_silc_import_private_key_file(unsigned char *filedata, - SilcUInt32 filedata_len, - const char *passphrase, - SilcUInt32 passphrase_len, - SilcPKCSFileEncoding encoding, - void **ret_private_key); -int silc_pkcs_silc_import_private_key(unsigned char *key, +unsigned char * +silc_pkcs_silc_export_public_key(const struct SilcPKCSObjectStruct *pkcs, + SilcStack stack, + void *public_key, + SilcUInt32 *ret_len); +SilcUInt32 +silc_pkcs_silc_public_key_bitlen(const struct SilcPKCSObjectStruct *pkcs, + void *public_key); +void *silc_pkcs_silc_public_key_copy(const struct SilcPKCSObjectStruct *pkcs, + void *public_key); +SilcBool +silc_pkcs_silc_public_key_compare(const struct SilcPKCSObjectStruct *pkcs, + void *key1, void *key2); +void silc_pkcs_silc_public_key_free(const struct SilcPKCSObjectStruct *pkcs, + void *public_key); +SilcBool +silc_pkcs_silc_import_private_key_file(const struct SilcPKCSObjectStruct *pkcs, + unsigned char *filedata, + SilcUInt32 filedata_len, + const char *passphrase, + SilcUInt32 passphrase_len, + SilcPKCSFileEncoding encoding, + void **ret_private_key); +int silc_pkcs_silc_import_private_key(const struct SilcPKCSObjectStruct *pkcs, + void *key, SilcUInt32 key_len, void **ret_private_key); unsigned char * -silc_pkcs_silc_export_private_key_file(void *private_key, +silc_pkcs_silc_export_private_key_file(const struct SilcPKCSObjectStruct *pkcs, + SilcStack stack, + void *private_key, const char *passphrase, SilcUInt32 passphrase_len, SilcPKCSFileEncoding encoding, SilcRng rng, SilcUInt32 *ret_len); -unsigned char *silc_pkcs_silc_export_private_key(void *private_key, - SilcUInt32 *ret_len); -SilcUInt32 silc_pkcs_silc_private_key_bitlen(void *private_key); -void silc_pkcs_silc_private_key_free(void *private_key); -SilcBool silc_pkcs_silc_encrypt(void *public_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *dst, - SilcUInt32 dst_size, - SilcUInt32 *ret_dst_len, - SilcRng rng); -SilcBool silc_pkcs_silc_decrypt(void *private_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *dst, - SilcUInt32 dst_size, - SilcUInt32 *ret_dst_len); -SilcBool silc_pkcs_silc_sign(void *private_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *signature, - SilcUInt32 signature_size, - SilcUInt32 *ret_signature_len, - SilcBool compute_hash, - SilcHash hash); -SilcBool silc_pkcs_silc_verify(void *public_key, - unsigned char *signature, - SilcUInt32 signature_len, - unsigned char *data, - SilcUInt32 data_len, - SilcHash hash); +unsigned char * +silc_pkcs_silc_export_private_key(const struct SilcPKCSObjectStruct *pkcs, + SilcStack stack, + void *private_key, + SilcUInt32 *ret_len); +SilcUInt32 +silc_pkcs_silc_private_key_bitlen(const struct SilcPKCSObjectStruct *pkcs, + void *private_key); +void silc_pkcs_silc_private_key_free(const struct SilcPKCSObjectStruct *pkcs, + void *private_key); +SilcAsyncOperation +silc_pkcs_silc_encrypt(const struct SilcPKCSObjectStruct *pkcs, + void *public_key, + unsigned char *src, + SilcUInt32 src_len, + SilcRng rng, + SilcPKCSEncryptCb encrypt_cb, + void *context); +SilcAsyncOperation +silc_pkcs_silc_decrypt(const struct SilcPKCSObjectStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcPKCSDecryptCb decrypt_cb, + void *context); +SilcAsyncOperation +silc_pkcs_silc_sign(const struct SilcPKCSObjectStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcBool compute_hash, + SilcHash hash, + SilcPKCSSignCb sign_cb, + void *context); +SilcAsyncOperation +silc_pkcs_silc_verify(const struct SilcPKCSObjectStruct *pkcs, + void *public_key, + unsigned char *signature, + SilcUInt32 signature_len, + unsigned char *data, + SilcUInt32 data_len, + SilcHash hash, + SilcPKCSVerifyCb verify_cb, + void *context); #endif /* SILCPK_I_H */ diff --git a/lib/silccrypt/silcpkcs.c b/lib/silccrypt/silcpkcs.c index 7c07cfea..f537b880 100644 --- a/lib/silccrypt/silcpkcs.c +++ b/lib/silccrypt/silcpkcs.c @@ -121,7 +121,7 @@ const SilcPKCSAlgorithm silc_default_pkcs_alg[] = } }; -/* Register a new PKCS into SILC. */ +/* Register a new PKCS */ SilcBool silc_pkcs_register(const SilcPKCSObject *pkcs) { @@ -154,7 +154,7 @@ SilcBool silc_pkcs_register(const SilcPKCSObject *pkcs) return TRUE; } -/* Unregister a PKCS from the SILC. */ +/* Unregister a PKCS */ SilcBool silc_pkcs_unregister(SilcPKCSObject *pkcs) { @@ -271,19 +271,12 @@ SilcBool silc_pkcs_algorithm_unregister(SilcPKCSAlgorithm *pkcs) SilcBool silc_pkcs_register_default(void) { -#ifndef SILC_SYMBIAN - int i; - - for (i = 0; silc_default_pkcs[i].type; i++) - silc_pkcs_register(&(silc_default_pkcs[i])); - - for (i = 0; silc_default_pkcs_alg[i].name; i++) - silc_pkcs_algorithm_register(&(silc_default_pkcs_alg[i])); - -#endif /* SILC_SYMBIAN */ + /* We use builtin PKCS and algorithms */ return TRUE; } +/* Unregister all PKCS and algorithms */ + SilcBool silc_pkcs_unregister_all(void) { #ifndef SILC_SYMBIAN @@ -316,9 +309,9 @@ SilcBool silc_pkcs_unregister_all(void) char *silc_pkcs_get_supported(void) { - SilcPKCSAlgorithm *entry; + SilcPKCSAlgorithm *entry, *entry2; char *list = NULL; - int len = 0; + int i, len = 0; #ifndef SILC_SYMBIAN if (silc_pkcs_alg_list) { @@ -335,23 +328,31 @@ char *silc_pkcs_get_supported(void) len++; } } -#else - { - int i; - for (i = 0; silc_default_pkcs_alg[i].name; i++) { - entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]); - len += strlen(entry->name); - list = silc_realloc(list, len + 1); - if (!list) - return NULL; +#endif /* SILC_SYMBIAN */ - memcpy(list + (len - strlen(entry->name)), - entry->name, strlen(entry->name)); - memcpy(list + len, ",", 1); - len++; + for (i = 0; silc_default_pkcs_alg[i].name; i++) { + entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]); + + if (silc_pkcs_alg_list) { + silc_dlist_start(silc_pkcs_alg_list); + while ((entry2 = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) { + if (!strcmp(entry2->name, entry->name)) + break; + } + if (entry2) + continue; } + + len += strlen(entry->name); + list = silc_realloc(list, len + 1); + if (!list) + return NULL; + + memcpy(list + (len - strlen(entry->name)), + entry->name, strlen(entry->name)); + memcpy(list + len, ",", 1); + len++; } -#endif /* SILC_SYMBIAN */ list[len - 1] = 0; @@ -363,6 +364,7 @@ char *silc_pkcs_get_supported(void) const SilcPKCSObject *silc_pkcs_find_pkcs(SilcPKCSType type) { SilcPKCSObject *entry; + int i; #ifndef SILC_SYMBIAN if (silc_pkcs_list) { @@ -372,17 +374,14 @@ const SilcPKCSObject *silc_pkcs_find_pkcs(SilcPKCSType type) return (const SilcPKCSObject *)entry; } } -#else - { - int i; - for (i = 0; silc_default_pkcs[i].type; i++) { - entry = (SilcPKCSObject *)&(silc_default_pkcs[i]); - if (entry->type == type) - return (const SilcPKCSObject *)entry; - } - } #endif /* SILC_SYMBIAN */ + for (i = 0; silc_default_pkcs[i].type; i++) { + entry = (SilcPKCSObject *)&(silc_default_pkcs[i]); + if (entry->type == type) + return (const SilcPKCSObject *)entry; + } + return NULL; } @@ -392,6 +391,7 @@ const SilcPKCSAlgorithm *silc_pkcs_find_algorithm(const char *algorithm, const char *scheme) { SilcPKCSAlgorithm *entry; + int i; #ifndef SILC_SYMBIAN if (silc_pkcs_alg_list) { @@ -402,18 +402,15 @@ const SilcPKCSAlgorithm *silc_pkcs_find_algorithm(const char *algorithm, return (const SilcPKCSAlgorithm *)entry; } } -#else - { - int i; - for (i = 0; silc_default_pkcs_alg[i].name; i++) { - entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]); - if (!strcmp(entry->name, algorithm) && - (!scheme || !entry->scheme || !strcmp(entry->scheme, scheme))) - return (const SilcPKCSAlgorithm *)entry; - } - } #endif /* SILC_SYMBIAN */ + for (i = 0; silc_default_pkcs_alg[i].name; i++) { + entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]); + if (!strcmp(entry->name, algorithm) && + (!scheme || !entry->scheme || !strcmp(entry->scheme, scheme))) + return (const SilcPKCSAlgorithm *)entry; + } + return NULL; } @@ -430,7 +427,8 @@ const SilcPKCSObject *silc_pkcs_get_pkcs(void *key) const SilcPKCSAlgorithm *silc_pkcs_get_algorithm(void *key) { SilcPublicKey public_key = key; - return public_key->pkcs->get_algorithm(public_key->public_key); + return public_key->pkcs->get_algorithm(public_key->pkcs, + public_key->public_key); } /* Return algorithm name */ @@ -474,7 +472,7 @@ SilcBool silc_pkcs_public_key_alloc(SilcPKCSType type, } /* Import the PKCS public key */ - if (!pkcs->import_public_key(key, key_len, &public_key->public_key)) { + if (!pkcs->import_public_key(pkcs, key, key_len, &public_key->public_key)) { silc_free(public_key); return FALSE; } @@ -488,24 +486,26 @@ SilcBool silc_pkcs_public_key_alloc(SilcPKCSType type, void silc_pkcs_public_key_free(SilcPublicKey public_key) { - public_key->pkcs->public_key_free(public_key->public_key); + public_key->pkcs->public_key_free(public_key->pkcs, public_key->public_key); silc_free(public_key); } /* Exports public key */ -unsigned char *silc_pkcs_public_key_encode(SilcPublicKey public_key, +unsigned char *silc_pkcs_public_key_encode(SilcStack stack, + SilcPublicKey public_key, SilcUInt32 *ret_len) { - return public_key->pkcs->export_public_key(public_key->public_key, - ret_len); + return public_key->pkcs->export_public_key(public_key->pkcs, stack, + public_key->public_key, ret_len); } /* Return key length */ SilcUInt32 silc_pkcs_public_key_get_len(SilcPublicKey public_key) { - return public_key->pkcs->public_key_bitlen(public_key->public_key); + return public_key->pkcs->public_key_bitlen(public_key->pkcs, + public_key->public_key); } /* Returns internal PKCS public key context */ @@ -543,7 +543,8 @@ SilcBool silc_pkcs_private_key_alloc(SilcPKCSType type, } /* Import the PKCS private key */ - if (!pkcs->import_private_key(key, key_len, &private_key->private_key)) { + if (!pkcs->import_private_key(pkcs, key, key_len, + &private_key->private_key)) { silc_free(private_key); return FALSE; } @@ -557,61 +558,74 @@ SilcBool silc_pkcs_private_key_alloc(SilcPKCSType type, SilcUInt32 silc_pkcs_private_key_get_len(SilcPrivateKey private_key) { - return private_key->pkcs->private_key_bitlen(private_key->private_key); + return private_key->pkcs->private_key_bitlen(private_key->pkcs, + private_key->private_key); } /* Frees the private key */ void silc_pkcs_private_key_free(SilcPrivateKey private_key) { - private_key->pkcs->private_key_free(private_key->private_key); + private_key->pkcs->private_key_free(private_key->pkcs, + private_key->private_key); silc_free(private_key); } /* Encrypts */ -SilcBool silc_pkcs_encrypt(SilcPublicKey public_key, - unsigned char *src, SilcUInt32 src_len, - unsigned char *dst, SilcUInt32 dst_size, - SilcUInt32 *dst_len, SilcRng rng) +SilcAsyncOperation silc_pkcs_encrypt(SilcPublicKey public_key, + unsigned char *src, SilcUInt32 src_len, + SilcRng rng, + SilcPKCSEncryptCb encrypt_cb, + void *context) { - return public_key->pkcs->encrypt(public_key->public_key, src, src_len, - dst, dst_size, dst_len, rng); + return public_key->pkcs->encrypt(public_key->pkcs, + public_key->public_key, src, src_len, + rng, encrypt_cb, context); } /* Decrypts */ -SilcBool silc_pkcs_decrypt(SilcPrivateKey private_key, - unsigned char *src, SilcUInt32 src_len, - unsigned char *dst, SilcUInt32 dst_size, - SilcUInt32 *dst_len) +SilcAsyncOperation silc_pkcs_decrypt(SilcPrivateKey private_key, + unsigned char *src, SilcUInt32 src_len, + SilcPKCSDecryptCb decrypt_cb, + void *context) { - return private_key->pkcs->decrypt(private_key->private_key, src, src_len, - dst, dst_size, dst_len); + return private_key->pkcs->decrypt(private_key->pkcs, + private_key->private_key, src, src_len, + decrypt_cb, context); } /* Generates signature */ -SilcBool silc_pkcs_sign(SilcPrivateKey private_key, - unsigned char *src, SilcUInt32 src_len, - unsigned char *dst, SilcUInt32 dst_size, - SilcUInt32 *dst_len, SilcBool compute_hash, - SilcHash hash) -{ - return private_key->pkcs->sign(private_key->private_key, src, src_len, - dst, dst_size, dst_len, compute_hash, hash); +SilcAsyncOperation silc_pkcs_sign(SilcPrivateKey private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcBool compute_hash, + SilcHash hash, + SilcPKCSSignCb sign_cb, + void *context) +{ + return private_key->pkcs->sign(private_key->pkcs, + private_key->private_key, src, src_len, + compute_hash, hash, sign_cb, context); } /* Verifies signature */ -SilcBool silc_pkcs_verify(SilcPublicKey public_key, - unsigned char *signature, - SilcUInt32 signature_len, - unsigned char *data, - SilcUInt32 data_len, SilcHash hash) -{ - return public_key->pkcs->verify(public_key->public_key, signature, - signature_len, data, data_len, hash); +SilcAsyncOperation silc_pkcs_verify(SilcPublicKey public_key, + unsigned char *signature, + SilcUInt32 signature_len, + unsigned char *data, + SilcUInt32 data_len, + SilcHash hash, + SilcPKCSVerifyCb verify_cb, + void *context) +{ + return public_key->pkcs->verify(public_key->pkcs, + public_key->public_key, signature, + signature_len, data, data_len, hash, + verify_cb, context); } /* Compares two public keys and returns TRUE if they are same key, and @@ -622,7 +636,8 @@ SilcBool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2) if (key1->pkcs->type != key2->pkcs->type) return FALSE; - return key1->pkcs->public_key_compare(key1->public_key, key2->public_key); + return key1->pkcs->public_key_compare(key1->pkcs, + key1->public_key, key2->public_key); } /* Copies the public key indicated by `public_key' and returns new allocated @@ -635,7 +650,8 @@ SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key) return NULL; key->pkcs = public_key->pkcs; - key->public_key = public_key->pkcs->public_key_copy(public_key->public_key); + key->public_key = public_key->pkcs->public_key_copy(public_key->pkcs, + public_key->public_key); if (!key->public_key) { silc_free(key); return NULL; @@ -676,14 +692,16 @@ SilcBool silc_pkcs_load_public_key(const char *filename, if (!public_key->pkcs) continue; - if (public_key->pkcs->import_public_key_file(data, data_len, + if (public_key->pkcs->import_public_key_file(public_key->pkcs, + data, data_len, SILC_PKCS_FILE_BASE64, &public_key->public_key)) { silc_free(data); return TRUE; } - if (public_key->pkcs->import_public_key_file(data, data_len, + if (public_key->pkcs->import_public_key_file(public_key->pkcs, + data, data_len, SILC_PKCS_FILE_BIN, &public_key->public_key)) { silc_free(data); @@ -705,20 +723,29 @@ SilcBool silc_pkcs_save_public_key(const char *filename, { unsigned char *data; SilcUInt32 data_len; + SilcStack stack; + + stack = silc_stack_alloc(2048, silc_crypto_stack()); /* Export the public key file */ - data = public_key->pkcs->export_public_key_file(public_key->public_key, + data = public_key->pkcs->export_public_key_file(public_key->pkcs, + stack, + public_key->public_key, encoding, &data_len); - if (!data) + if (!data) { + silc_stack_free(stack); return FALSE; + } /* Write to file */ if (silc_file_writefile(filename, data, data_len)) { - silc_free(data); + silc_sfree(stack, data); + silc_stack_free(stack); return FALSE; } - silc_free(data); + silc_sfree(stack, data); + silc_stack_free(stack); return TRUE; } @@ -757,6 +784,7 @@ SilcBool silc_pkcs_load_private_key(const char *filename, continue; if (private_key->pkcs->import_private_key_file( + private_key->pkcs, data, data_len, passphrase, passphrase_len, @@ -767,6 +795,7 @@ SilcBool silc_pkcs_load_private_key(const char *filename, } if (private_key->pkcs->import_private_key_file( + private_key->pkcs, data, data_len, passphrase, passphrase_len, @@ -794,21 +823,65 @@ SilcBool silc_pkcs_save_private_key(const char *filename, { unsigned char *data; SilcUInt32 data_len; + SilcStack stack; + + stack = silc_stack_alloc(2048, silc_crypto_stack()); /* Export the private key file */ - data = private_key->pkcs->export_private_key_file(private_key->private_key, + data = private_key->pkcs->export_private_key_file(private_key->pkcs, stack, + private_key->private_key, passphrase, passphrase_len, encoding, rng, &data_len); - if (!data) + if (!data) { + silc_stack_free(stack); return FALSE; + } /* Write to file */ if (silc_file_writefile(filename, data, data_len)) { - silc_free(data); + silc_sfree(stack, data); + silc_stack_free(stack); return FALSE; } - silc_free(data); + silc_sfree(stack, data); + silc_stack_free(stack); return TRUE; } + +/* Hash public key of any type. */ + +SilcUInt32 silc_hash_public_key(void *key, void *user_context) +{ + SilcPublicKey public_key = key; + unsigned char *pk; + SilcUInt32 pk_len; + SilcUInt32 hash = 0; + SilcStack stack = NULL; + + if (silc_crypto_stack()) + stack = silc_stack_alloc(2048, silc_crypto_stack()); + + pk = silc_pkcs_public_key_encode(stack, public_key, &pk_len); + if (!pk) { + silc_stack_free(stack); + return hash; + } + + hash = silc_hash_data(pk, SILC_32_TO_PTR(pk_len)); + + silc_sfree(stack, pk); + silc_stack_free(stack); + + return hash; +} + +/* Compares two SILC Public keys. It may be used as SilcHashTable + comparison function. */ + +SilcBool silc_hash_public_key_compare(void *key1, void *key2, + void *user_context) +{ + return silc_pkcs_public_key_compare(key1, key2); +} diff --git a/lib/silccrypt/silcpkcs.h b/lib/silccrypt/silcpkcs.h index 42e47264..13488c72 100644 --- a/lib/silccrypt/silcpkcs.h +++ b/lib/silccrypt/silcpkcs.h @@ -32,6 +32,7 @@ #define SILCPKCS_H /* Forward declarations */ +typedef struct SilcPKCSAlgorithmStruct SilcPKCSAlgorithm; typedef struct SilcPKCSObjectStruct SilcPKCSObject; /****d* silccrypt/SilcPKCSAPI/SilcPKCSType @@ -112,182 +113,89 @@ typedef enum { } SilcPKCSFileEncoding; /***/ -/* The PKCS Algorithm object to represent any PKCS algorithm. */ -typedef struct { - /* Algorithm name and scheme */ - char *name; - char *scheme; - - /* Supported hash functions, comma separated list */ - char *hash; - - /* Generate new key pair. Returns PKCS algorithm specific public key - and private key contexts. */ - SilcBool (*generate_key)(SilcUInt32 keylen, - SilcRng rng, - void **ret_public_key, - void **ret_private_key); - - /* Public key routines. */ - int (*import_public_key)(unsigned char *key, - SilcUInt32 key_len, - void **ret_public_key); - unsigned char *(*export_public_key)(void *public_key, - SilcUInt32 *ret_len); - SilcUInt32 (*public_key_bitlen)(void *public_key); - void *(*public_key_copy)(void *public_key); - SilcBool (*public_key_compare)(void *key1, void *key2); - void (*public_key_free)(void *public_key); - - /* Private key routines */ - int (*import_private_key)(unsigned char *key, - SilcUInt32 key_len, - void **ret_private_key); - unsigned char *(*export_private_key)(void *private_key, - SilcUInt32 *ret_len); - SilcUInt32 (*private_key_bitlen)(void *public_key); - void (*private_key_free)(void *private_key); - - /* Encrypt and decrypt operations */ - SilcBool (*encrypt)(void *public_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *dst, - SilcUInt32 dst_size, - SilcUInt32 *ret_dst_len, - SilcRng rng); - SilcBool (*decrypt)(void *private_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *dst, - SilcUInt32 dst_size, - SilcUInt32 *ret_dst_len); - - /* Signature and verification operations */ - SilcBool (*sign)(void *private_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *signature, - SilcUInt32 signature_size, - SilcUInt32 *ret_signature_len, - SilcBool compute_hash, - SilcHash hash); - SilcBool (*verify)(void *public_key, - unsigned char *signature, - SilcUInt32 signature_len, - unsigned char *data, - SilcUInt32 data_len, - SilcHash hash); -} SilcPKCSAlgorithm; - -/* The PKCS (Public Key Cryptosystem) object to represent any PKCS. */ -struct SilcPKCSObjectStruct { - /* PKCS type */ - SilcPKCSType type; - - /* Public key routines */ - - /* Returns PKCS algorithm context from public key */ - const SilcPKCSAlgorithm *(*get_algorithm)(void *public_key); - - /* Imports from public key file */ - SilcBool (*import_public_key_file)(unsigned char *filedata, - SilcUInt32 filedata_len, - SilcPKCSFileEncoding encoding, - void **ret_public_key); - - /* Imports from public key binary data. Returns the amount of bytes - imported from `key' or 0 on error. */ - int (*import_public_key)(unsigned char *key, - SilcUInt32 key_len, - void **ret_public_key); - - /* Exports public key to file */ - unsigned char *(*export_public_key_file)(void *public_key, - SilcPKCSFileEncoding encoding, - SilcUInt32 *ret_len); +/****f* silccrypt/SilcPKCSAPI/SilcPKCSEncryptCb + * + * SYNOPSIS + * + * typedef void (*SilcPKCSEncryptCb)(SilcBool success, + * const unsigned char *encrypted, + * SilcUInt32 encrypted_len, + * void *context); + * + * DESCRIPTION + * + * Encryption callback. This callback is given as argument to the + * silc_pkcs_encrypt and the encrypted data is delivered to the caller + * in this callback. The `encrypted' is the encrypted data. If the + * `success' is FALSE the encryption operation failed. + * + ***/ +typedef void (*SilcPKCSEncryptCb)(SilcBool success, + const unsigned char *encrypted, + SilcUInt32 encrypted_len, + void *context); + +/****f* silccrypt/SilcPKCSAPI/SilcPKCSDecryptCb + * + * SYNOPSIS + * + * typedef void (*SilcPKCSDecryptCb)(SilcBool success, + * const unsigned char *decrypted, + * SilcUInt32 decrypted_len, + * void *context); + * + * DESCRIPTION + * + * Decryption callback. This callback is given as argument to the + * silc_pkcs_decrypt and the decrypted data is delivered to the caller + * in this callback. The `decrypted' is the decrypted data. If the + * `success' is FALSE the decryption operation failed. + * + ***/ +typedef void (*SilcPKCSDecryptCb)(SilcBool success, + const unsigned char *decrypted, + SilcUInt32 decrypted_len, + void *context); - /* Export public key as binary data */ - unsigned char *(*export_public_key)(void *public_key, - SilcUInt32 *ret_len); - - /* Returns key length in bits */ - SilcUInt32 (*public_key_bitlen)(void *public_key); - - /* Copy public key */ - void *(*public_key_copy)(void *public_key); - - /* Compares public keys */ - SilcBool (*public_key_compare)(void *key1, void *key2); - - /* Free public key */ - void (*public_key_free)(void *public_key); - - /* Private key routines */ - - /* Imports from private key file */ - SilcBool (*import_private_key_file)(unsigned char *filedata, - SilcUInt32 filedata_len, - const char *passphrase, - SilcUInt32 passphrase_len, - SilcPKCSFileEncoding encoding, - void **ret_private_key); - - /* Imports from private key binary data. Returns the amount of bytes - imported from `key' or 0 on error. */ - int (*import_private_key)(unsigned char *key, - SilcUInt32 key_len, - void **ret_private_key); - - /* Exports private key to file */ - unsigned char *(*export_private_key_file)(void *private_key, - const char *passphrase, - SilcUInt32 passphrase_len, - SilcPKCSFileEncoding encoding, - SilcRng rng, - SilcUInt32 *ret_len); - - /* Export private key as binary data */ - unsigned char *(*export_private_key)(void *private_key, - SilcUInt32 *ret_len); - - /* Returns key length in bits */ - SilcUInt32 (*private_key_bitlen)(void *private_key); - - /* Free private key */ - void (*private_key_free)(void *private_key); - - /* Encrypt and decrypt operations */ - SilcBool (*encrypt)(void *public_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *dst, - SilcUInt32 dst_size, - SilcUInt32 *ret_dst_len, - SilcRng rng); - SilcBool (*decrypt)(void *private_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *dst, - SilcUInt32 dst_size, - SilcUInt32 *ret_dst_len); - - /* Signature and verification operations */ - SilcBool (*sign)(void *private_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *signature, - SilcUInt32 signature_size, - SilcUInt32 *ret_signature_len, - SilcBool compute_hash, - SilcHash hash); - SilcBool (*verify)(void *public_key, - unsigned char *signature, - SilcUInt32 signature_len, - unsigned char *data, - SilcUInt32 data_len, - SilcHash hash); -}; +/****f* silccrypt/SilcPKCSAPI/SilcPKCSSignCb + * + * SYNOPSIS + * + * typedef void (*SilcPKCSSignCb)(SilcBool success, + * const unsigned char *signature, + * SilcUInt32 signature_len, + * void *context); + * + * DESCRIPTION + * + * Signature callback. This callback is given as argument to the + * silc_pkcs_sign and the digitally signed data is delivered to the caller + * in this callback. The `signature' is the signature data. If the + * `success' is FALSE the signature operation failed. + * + ***/ +typedef void (*SilcPKCSSignCb)(SilcBool success, + const unsigned char *signature, + SilcUInt32 signature_len, + void *context); + +/****f* silccrypt/SilcPKCSAPI/SilcPKCSVerifyCb + * + * SYNOPSIS + * + * typedef void (*SilcPKCSVerifyCb)(SilcBool success, void *context); + * + * DESCRIPTION + * + * Verification callback. This callback is given as argument to the + * silc_pkcs_verify and the result of the signature verification is + * deliver to the caller in this callback. If the `success' is FALSE + * the signature verification failed. + * + ***/ +typedef void (*SilcPKCSVerifyCb)(SilcBool success, void *context); + +#include "silcpkcs_i.h" /* Marks for all PKCS in. This can be used in silc_pkcs_unregister to unregister all PKCS at once. */ @@ -340,7 +248,7 @@ SilcBool silc_pkcs_unregister(SilcPKCSObject *pkcs); * * DESCRIPTION * - * Registers a new PKCS Algorithm into crypto library. This function + * Registers a new PKCS Algorithm into crypto library. This function * is used at the initialization of an application. All registered PKCS * algorithms should be unregistered with silc_pkcs_unregister. * @@ -543,7 +451,8 @@ void silc_pkcs_public_key_free(SilcPublicKey public_key); * * SYNOPSIS * - * unsigned char *silc_pkcs_public_key_encode(SilcPublicKey public_key, + * unsigned char *silc_pkcs_public_key_encode(SilcStack stack, + * SilcPublicKey public_key, * SilcUInt32 *ret_len); * * DESCRIPTION @@ -551,8 +460,13 @@ void silc_pkcs_public_key_free(SilcPublicKey public_key); * Encodes the `public_key' into a binary format and returns it. Returns * NULL on error. Caller must free the returned buffer. * + * If the `stack' is non-NULL the returned buffer is allocated from the + * `stack'. This call will consume `stack' so caller should push the stack + * before calling and then later pop it. + * ***/ -unsigned char *silc_pkcs_public_key_encode(SilcPublicKey public_key, +unsigned char *silc_pkcs_public_key_encode(SilcStack stack, + SilcPublicKey public_key, SilcUInt32 *ret_len); /****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_get_len @@ -648,88 +562,111 @@ void silc_pkcs_private_key_free(SilcPrivateKey private_key); * * SYNOPSIS * - * SilcBool silc_pkcs_encrypt(SilcPublicKey public_key, - * unsigned char *src, SilcUInt32 src_len, - * unsigned char *dst, SilcUInt32 dst_size, - * SilcUInt32 *dst_len); + * SilcAsyncOperation silc_pkcs_encrypt(SilcPublicKey public_key, + * unsigned char *src, + * SilcUInt32 src_len, SilcRng rng, + * SilcPKCSEncryptCb encrypt_cb, + * void *context); * * DESCRIPTION * - * Encrypts with the public key. Returns FALSE on error. + * Encrypts with the public key. The `encrypt_cb' will be called to + * deliver the encrypted data. The encryption operation may be asynchronous + * if the `public_key' is accelerated public key. If this returns NULL + * the asynchronous operation cannot be controlled. * ***/ -SilcBool silc_pkcs_encrypt(SilcPublicKey public_key, - unsigned char *src, SilcUInt32 src_len, - unsigned char *dst, SilcUInt32 dst_size, - SilcUInt32 *dst_len, SilcRng rng); +SilcAsyncOperation silc_pkcs_encrypt(SilcPublicKey public_key, + unsigned char *src, + SilcUInt32 src_len, SilcRng rng, + SilcPKCSEncryptCb encrypt_cb, + void *context); /****f* silccrypt/SilcPKCSAPI/silc_pkcs_decrypt * * SYNOPSIS * - * SilcBool silc_pkcs_decrypt(SilcPrivateKey private_key, - * unsigned char *src, SilcUInt32 src_len, - * unsigned char *dst, SilcUInt32 dst_size, - * SilcUInt32 *dst_len); + * SilcAsyncOperation silc_pkcs_decrypt(SilcPrivateKey private_key, + * unsigned char *src, + * SilcUInt32 src_len, + * SilcPKCSDecryptCb decrypt_cb, + * void *context); * * DESCRIPTION * - * Decrypts with the private key. Returns FALSE on error. + * Decrypts with the private key. The `decrypt_cb' will be called to + * deliver the decrypted data. The decryption operation may be asynchronous + * if the `private_key' is accelerated private key. If this returns NULL + * the asynchronous operation cannot be controlled. * ***/ -SilcBool silc_pkcs_decrypt(SilcPrivateKey private_key, - unsigned char *src, SilcUInt32 src_len, - unsigned char *dst, SilcUInt32 dst_size, - SilcUInt32 *dst_len); +SilcAsyncOperation silc_pkcs_decrypt(SilcPrivateKey private_key, + unsigned char *src, SilcUInt32 src_len, + SilcPKCSDecryptCb decrypt_cb, + void *context); /****f* silccrypt/SilcPKCSAPI/silc_pkcs_sign * * SYNOPSIS * - * SilcBool silc_pkcs_sign(SilcPrivateKey private_key, - * unsigned char *src, SilcUInt32 src_len, - * unsigned char *dst, SilcUInt32 dst_size, - * SilcUInt32 *dst_len, SilcBool compute_hash, - * SilcHash hash); + * SilcAsyncOperation silc_pkcs_sign(SilcPrivateKey private_key, + * unsigned char *src, + * SilcUInt32 src_len, + * SilcBool compute_hash, + * SilcHash hash, + * SilcPKCSSignCb sign_cb, + * void *context); * * DESCRIPTION * - * Generates signature with the private key. Returns FALSE on error. - * If `compute_hash' is TRUE the `hash' will be used to compute a - * digest over the `src'. The `hash' must always be valid. + * Computes signature with the private key. The `sign_cb' will be called + * to deliver the signature data. If `compute_hash' is TRUE the `hash' + * will be used to compute a message digest over the `src'. The `hash' + * must always be valid. The signature operation may be asynchronous if + * the `private_key' is accelerated private key. If this returns NULL the + * asynchronous operation cannot be controlled. * ***/ -SilcBool silc_pkcs_sign(SilcPrivateKey private_key, - unsigned char *src, SilcUInt32 src_len, - unsigned char *dst, SilcUInt32 dst_size, - SilcUInt32 *dst_len, SilcBool compute_hash, - SilcHash hash); +SilcAsyncOperation silc_pkcs_sign(SilcPrivateKey private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcBool compute_hash, + SilcHash hash, + SilcPKCSSignCb sign_cb, + void *context); /****f* silccrypt/SilcPKCSAPI/silc_pkcs_verify * * SYNOPSIS * - * SilcBool silc_pkcs_verify(SilcPublicKey public_key, - * unsigned char *signature, - * SilcUInt32 signature_len, - * unsigned char *data, - * SilcUInt32 data_len, SilcHash hash); + * SilcAsyncOperation silc_pkcs_verify(SilcPublicKey public_key, + * unsigned char *signature, + * SilcUInt32 signature_len, + * unsigned char *data, + * SilcUInt32 data_len, + * SilcHash hash, + * SilcPKCSVerifyCb verify_cb, + * void *context); * * DESCRIPTION * - * Verifies signature. Returns FALSE on error. The 'signature' is - * verified against the 'data'. If the `hash' is non-NULL then the `data' - * will hashed before verification. If the `hash' is NULL, then the - * hash algorithm to be used is retrieved from the signature. If it - * isn't present in the signature the verification is done as is without - * hashing. + * Verifies signature. The `verify_cb' will be called to deliver the + * result of the verification process. The 'signature' is verified against + * the 'data'. If the `hash' is non-NULL then the `data' will hashed + * before verification. If the `hash' is NULL, then the hash algorithm + * to be used is retrieved from the signature. If it isn't present in the + * signature the verification is done as is without hashing. If this + * returns NULL the asynchronous operation cannot be controlled. * ***/ -SilcBool silc_pkcs_verify(SilcPublicKey public_key, - unsigned char *signature, - SilcUInt32 signature_len, - unsigned char *data, - SilcUInt32 data_len, SilcHash hash); +SilcAsyncOperation silc_pkcs_verify(SilcPublicKey public_key, + unsigned char *signature, + SilcUInt32 signature_len, + unsigned char *data, + SilcUInt32 data_len, + SilcHash hash, + SilcPKCSVerifyCb verify_cb, + void *context); /****f* silccrypt/SilcPKCSAPI/silc_pkcs_load_public_key * @@ -811,4 +748,34 @@ SilcBool silc_pkcs_save_private_key(const char *filename, SilcPKCSFileEncoding encoding, SilcRng rng); +/****f* silccrypt/SilcPKCSAPI/silc_hash_public_key + * + * SYNOPSIS + * + * SilcUInt32 silc_hash_public_key(void *key, void *user_context); + * + * DESCRIPTION + * + * An utility function for hashing public key for SilcHashTable. Give + * this as argument as the hash function for SilcHashTable. + * + ***/ +SilcUInt32 silc_hash_public_key(void *key, void *user_context); + +/****f* silccrypt/SilcPKCSAPI/silc_hash_public_key_compare + * + * SYNOPSIS + * + * SilcBool silc_hash_public_key_compare(void *key1, void *key2, + * void *user_context); + * + * DESCRIPTION + * + * An utility function for comparing public keys for SilcHashTable. Give + * this as argument as the compare function for SilcHashTable. + * + ***/ +SilcBool silc_hash_public_key_compare(void *key1, void *key2, + void *user_context); + #endif /* !SILCPKCS_H */ diff --git a/lib/silccrypt/silcpkcs1.c b/lib/silccrypt/silcpkcs1.c index 2124d2e3..b4ea51ca 100644 --- a/lib/silccrypt/silcpkcs1.c +++ b/lib/silccrypt/silcpkcs1.c @@ -169,7 +169,8 @@ SilcBool silc_pkcs1_decode(SilcPkcs1BlockType bt, /* Generates RSA key pair. */ -SilcBool silc_pkcs1_generate_key(SilcUInt32 keylen, +SilcBool silc_pkcs1_generate_key(const struct SilcPKCSAlgorithmStruct *pkcs, + SilcUInt32 keylen, SilcRng rng, void **ret_public_key, void **ret_private_key) @@ -216,7 +217,8 @@ SilcBool silc_pkcs1_generate_key(SilcUInt32 keylen, /* Import PKCS #1 compliant public key */ -int silc_pkcs1_import_public_key(unsigned char *key, +int silc_pkcs1_import_public_key(const struct SilcPKCSAlgorithmStruct *pkcs, + void *key, SilcUInt32 key_len, void **ret_public_key) { @@ -261,15 +263,18 @@ int silc_pkcs1_import_public_key(unsigned char *key, /* Export PKCS #1 compliant public key */ -unsigned char *silc_pkcs1_export_public_key(void *public_key, - SilcUInt32 *ret_len) +unsigned char * +silc_pkcs1_export_public_key(const struct SilcPKCSAlgorithmStruct *pkcs, + SilcStack stack, + void *public_key, + SilcUInt32 *ret_len) { RsaPublicKey *key = public_key; SilcAsn1 asn1 = NULL; SilcBufferStruct alg_key; unsigned char *ret; - asn1 = silc_asn1_alloc(NULL); + asn1 = silc_asn1_alloc(stack); if (!asn1) goto err; @@ -296,7 +301,9 @@ unsigned char *silc_pkcs1_export_public_key(void *public_key, /* Returns key length */ -SilcUInt32 silc_pkcs1_public_key_bitlen(void *public_key) +SilcUInt32 +silc_pkcs1_public_key_bitlen(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key) { RsaPublicKey *key = public_key; return key->bits; @@ -304,7 +311,8 @@ SilcUInt32 silc_pkcs1_public_key_bitlen(void *public_key) /* Copy public key */ -void *silc_pkcs1_public_key_copy(void *public_key) +void *silc_pkcs1_public_key_copy(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key) { RsaPublicKey *key = public_key, *new_key; @@ -323,7 +331,9 @@ void *silc_pkcs1_public_key_copy(void *public_key) /* Compare public keys */ -SilcBool silc_pkcs1_public_key_compare(void *key1, void *key2) +SilcBool +silc_pkcs1_public_key_compare(const struct SilcPKCSAlgorithmStruct *pkcs, + void *key1, void *key2) { RsaPublicKey *k1 = key1, *k2 = key2; @@ -339,7 +349,8 @@ SilcBool silc_pkcs1_public_key_compare(void *key1, void *key2) /* Frees public key */ -void silc_pkcs1_public_key_free(void *public_key) +void silc_pkcs1_public_key_free(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key) { RsaPublicKey *key = public_key; @@ -350,7 +361,8 @@ void silc_pkcs1_public_key_free(void *public_key) /* Import PKCS #1 compliant private key */ -int silc_pkcs1_import_private_key(unsigned char *key, +int silc_pkcs1_import_private_key(const struct SilcPKCSAlgorithmStruct *pkcs, + void *key, SilcUInt32 key_len, void **ret_private_key) { @@ -406,15 +418,18 @@ int silc_pkcs1_import_private_key(unsigned char *key, /* Export PKCS #1 compliant private key */ -unsigned char *silc_pkcs1_export_private_key(void *private_key, - SilcUInt32 *ret_len) +unsigned char * +silc_pkcs1_export_private_key(const struct SilcPKCSAlgorithmStruct *pkcs, + SilcStack stack, + void *private_key, + SilcUInt32 *ret_len) { RsaPrivateKey *key = private_key; SilcAsn1 asn1; SilcBufferStruct alg_key; unsigned char *ret; - asn1 = silc_asn1_alloc(NULL); + asn1 = silc_asn1_alloc(stack); if (!asn1) return FALSE; @@ -447,7 +462,9 @@ unsigned char *silc_pkcs1_export_private_key(void *private_key, /* Returns key length */ -SilcUInt32 silc_pkcs1_private_key_bitlen(void *private_key) +SilcUInt32 +silc_pkcs1_private_key_bitlen(const struct SilcPKCSAlgorithmStruct *pkcs, + void *private_key) { RsaPrivateKey *key = private_key; return key->bits; @@ -455,7 +472,8 @@ SilcUInt32 silc_pkcs1_private_key_bitlen(void *private_key) /* Frees private key */ -void silc_pkcs1_private_key_free(void *private_key) +void silc_pkcs1_private_key_free(const struct SilcPKCSAlgorithmStruct *pkcs, + void *private_key) { RsaPrivateKey *key = private_key; @@ -472,32 +490,38 @@ void silc_pkcs1_private_key_free(void *private_key) /* PKCS #1 RSA routines */ -SilcBool silc_pkcs1_encrypt(void *public_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *dst, - SilcUInt32 dst_size, - SilcUInt32 *ret_dst_len, - SilcRng rng) +SilcAsyncOperation +silc_pkcs1_encrypt(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key, + unsigned char *src, + SilcUInt32 src_len, + SilcRng rng, + SilcPKCSEncryptCb encrypt_cb, + void *context) { RsaPublicKey *key = public_key; SilcMPInt mp_tmp; SilcMPInt mp_dst; unsigned char padded[2048 + 1]; SilcUInt32 len = (key->bits + 7) / 8; + SilcStack stack; - if (sizeof(padded) < len) - return FALSE; - if (dst_size < len) - return FALSE; + if (sizeof(padded) < len) { + encrypt_cb(FALSE, NULL, 0, context); + return NULL; + } /* Pad data */ if (!silc_pkcs1_encode(SILC_PKCS1_BT_PUB, src, src_len, - padded, len, rng)) - return FALSE; + padded, len, rng)) { + encrypt_cb(FALSE, NULL, 0, context); + return NULL; + } + + stack = silc_stack_alloc(2048, silc_crypto_stack()); - silc_mp_init(&mp_tmp); - silc_mp_init(&mp_dst); + silc_mp_sinit(stack, &mp_tmp); + silc_mp_sinit(stack, &mp_dst); /* Data to MP */ silc_mp_bin2mp(padded, len, &mp_tmp); @@ -506,34 +530,43 @@ SilcBool silc_pkcs1_encrypt(void *public_key, silc_rsa_public_operation(key, &mp_tmp, &mp_dst); /* MP to data */ - silc_mp_mp2bin_noalloc(&mp_dst, dst, len); - *ret_dst_len = len; + silc_mp_mp2bin_noalloc(&mp_dst, padded, len); + + /* Deliver result */ + encrypt_cb(TRUE, padded, len, context); memset(padded, 0, sizeof(padded)); - silc_mp_uninit(&mp_tmp); - silc_mp_uninit(&mp_dst); + silc_mp_suninit(stack, &mp_tmp); + silc_mp_suninit(stack, &mp_dst); + silc_stack_free(stack); - return TRUE; + return NULL; } -SilcBool silc_pkcs1_decrypt(void *private_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *dst, - SilcUInt32 dst_size, - SilcUInt32 *ret_dst_len) +SilcAsyncOperation +silc_pkcs1_decrypt(const struct SilcPKCSAlgorithmStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcPKCSDecryptCb decrypt_cb, + void *context) { RsaPrivateKey *key = private_key; SilcMPInt mp_tmp; SilcMPInt mp_dst; unsigned char *padded, unpadded[2048 + 1]; - SilcUInt32 padded_len; + SilcUInt32 padded_len, dst_len; + SilcStack stack; - if (dst_size < (key->bits + 7) / 8) - return FALSE; + if (sizeof(unpadded) < (key->bits + 7) / 8) { + decrypt_cb(FALSE, NULL, 0, context); + return NULL; + } + + stack = silc_stack_alloc(2048, silc_crypto_stack()); - silc_mp_init(&mp_tmp); - silc_mp_init(&mp_dst); + silc_mp_sinit(stack, &mp_tmp); + silc_mp_sinit(stack, &mp_dst); /* Data to MP */ silc_mp_bin2mp(src, src_len, &mp_tmp); @@ -546,36 +579,39 @@ SilcBool silc_pkcs1_decrypt(void *private_key, /* Unpad data */ if (!silc_pkcs1_decode(SILC_PKCS1_BT_PUB, padded, padded_len, - unpadded, sizeof(unpadded), ret_dst_len)) { + unpadded, sizeof(unpadded), &dst_len)) { memset(padded, 0, padded_len); silc_free(padded); - silc_mp_uninit(&mp_tmp); - silc_mp_uninit(&mp_dst); - return FALSE; + silc_mp_suninit(stack, &mp_tmp); + silc_mp_suninit(stack, &mp_dst); + decrypt_cb(FALSE, NULL, 0, context); + return NULL; } - /* Copy to destination */ - memcpy(dst, unpadded, *ret_dst_len); + /* Deliver result */ + decrypt_cb(TRUE, unpadded, dst_len, context); memset(padded, 0, padded_len); memset(unpadded, 0, sizeof(unpadded)); silc_free(padded); - silc_mp_uninit(&mp_tmp); - silc_mp_uninit(&mp_dst); + silc_mp_suninit(stack, &mp_tmp); + silc_mp_suninit(stack, &mp_dst); + silc_stack_free(stack); - return TRUE; + return NULL; } /* PKCS #1 sign with appendix, hash OID included in the signature */ -SilcBool silc_pkcs1_sign(void *private_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *signature, - SilcUInt32 signature_size, - SilcUInt32 *ret_signature_len, - SilcBool compute_hash, - SilcHash hash) +SilcAsyncOperation +silc_pkcs1_sign(const struct SilcPKCSAlgorithmStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcBool compute_hash, + SilcHash hash, + SilcPKCSSignCb sign_cb, + void *context) { RsaPrivateKey *key = private_key; unsigned char padded[2048 + 1], hashr[SILC_HASH_MAXLEN]; @@ -584,22 +620,30 @@ SilcBool silc_pkcs1_sign(void *private_key, SilcBufferStruct di; SilcUInt32 len = (key->bits + 7) / 8; const char *oid; + SilcStack stack; SilcAsn1 asn1; SILC_LOG_DEBUG(("Sign")); - if (sizeof(padded) < len) - return FALSE; - if (signature_size < len) - return FALSE; + if (sizeof(padded) < len) { + sign_cb(FALSE, NULL, 0, context); + return NULL; + } oid = silc_hash_get_oid(hash); - if (!oid) - return FALSE; + if (!oid) { + sign_cb(FALSE, NULL, 0, context); + return NULL; + } - asn1 = silc_asn1_alloc(NULL); - if (!asn1) - return FALSE; + stack = silc_stack_alloc(2048, silc_crypto_stack()); + + asn1 = silc_asn1_alloc(stack); + if (!asn1) { + silc_stack_free(stack); + sign_cb(FALSE, NULL, 0, context); + return NULL; + } /* Compute hash */ if (compute_hash) { @@ -614,12 +658,14 @@ SilcBool silc_pkcs1_sign(void *private_key, SILC_ASN1_SEQUENCE, SILC_ASN1_SEQUENCE, SILC_ASN1_OID(oid), - SILC_ASN1_NULL, + SILC_ASN1_NULL(TRUE), SILC_ASN1_END, SILC_ASN1_OCTET_STRING(src, src_len), SILC_ASN1_END, SILC_ASN1_END)) { silc_asn1_free(asn1); - return FALSE; + silc_stack_free(stack); + sign_cb(FALSE, NULL, 0, context); + return NULL; } SILC_LOG_HEXDUMP(("DigestInfo"), silc_buffer_data(&di), silc_buffer_len(&di)); @@ -628,11 +674,13 @@ SilcBool silc_pkcs1_sign(void *private_key, if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, silc_buffer_data(&di), silc_buffer_len(&di), padded, len, NULL)) { silc_asn1_free(asn1); - return FALSE; + silc_stack_free(stack); + sign_cb(FALSE, NULL, 0, context); + return NULL; } - silc_mp_init(&mp_tmp); - silc_mp_init(&mp_dst); + silc_mp_sinit(stack, &mp_tmp); + silc_mp_sinit(stack, &mp_dst); /* Data to MP */ silc_mp_bin2mp(padded, len, &mp_tmp); @@ -641,27 +689,34 @@ SilcBool silc_pkcs1_sign(void *private_key, silc_rsa_private_operation(key, &mp_tmp, &mp_dst); /* MP to data */ - silc_mp_mp2bin_noalloc(&mp_dst, signature, len); - *ret_signature_len = len; + silc_mp_mp2bin_noalloc(&mp_dst, padded, len); + + /* Deliver result */ + sign_cb(TRUE, padded, len, context); memset(padded, 0, sizeof(padded)); - silc_mp_uninit(&mp_tmp); - silc_mp_uninit(&mp_dst); if (compute_hash) memset(hashr, 0, sizeof(hashr)); + silc_mp_suninit(stack, &mp_tmp); + silc_mp_suninit(stack, &mp_dst); silc_asn1_free(asn1); + silc_stack_free(stack); - return TRUE; + return NULL; } /* PKCS #1 verification with appendix. */ -SilcBool silc_pkcs1_verify(void *public_key, - unsigned char *signature, - SilcUInt32 signature_len, - unsigned char *data, - SilcUInt32 data_len, - SilcHash hash) +SilcAsyncOperation +silc_pkcs1_verify(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key, + unsigned char *signature, + SilcUInt32 signature_len, + unsigned char *data, + SilcUInt32 data_len, + SilcHash hash, + SilcPKCSVerifyCb verify_cb, + void *context) { RsaPublicKey *key = public_key; SilcBool ret = FALSE; @@ -670,18 +725,24 @@ SilcBool silc_pkcs1_verify(void *public_key, unsigned char *verify, unpadded[2048 + 1], hashr[SILC_HASH_MAXLEN]; SilcUInt32 verify_len, len = (key->bits + 7) / 8; SilcBufferStruct di, ldi; + SilcBool has_null = TRUE; SilcHash ihash = NULL; - SilcAsn1 asn1 = NULL; + SilcStack stack; + SilcAsn1 asn1; char *oid; SILC_LOG_DEBUG(("Verify signature")); - asn1 = silc_asn1_alloc(NULL); - if (!asn1) - return FALSE; + stack = silc_stack_alloc(2048, silc_crypto_stack()); - silc_mp_init(&mp_tmp2); - silc_mp_init(&mp_dst); + asn1 = silc_asn1_alloc(stack); + if (!asn1) { + verify_cb(FALSE, context); + return NULL; + } + + silc_mp_sinit(stack, &mp_tmp2); + silc_mp_sinit(stack, &mp_dst); /* Format the signature into MP int */ silc_mp_bin2mp(signature, signature_len, &mp_tmp2); @@ -700,12 +761,16 @@ SilcBool silc_pkcs1_verify(void *public_key, /* If hash isn't given, allocate the one given in digest info */ if (!hash) { + has_null = FALSE; + /* Decode digest info */ if (!silc_asn1_decode(asn1, &di, SILC_ASN1_OPTS(SILC_ASN1_ACCUMUL), SILC_ASN1_SEQUENCE, SILC_ASN1_SEQUENCE, SILC_ASN1_OID(&oid), + SILC_ASN1_NULL_T(SILC_ASN1_OPTIONAL, + SILC_ASN1_TAG_NULL, &has_null), SILC_ASN1_END, SILC_ASN1_END, SILC_ASN1_END)) goto err; @@ -730,7 +795,7 @@ SilcBool silc_pkcs1_verify(void *public_key, SILC_ASN1_SEQUENCE, SILC_ASN1_SEQUENCE, SILC_ASN1_OID(oid), - SILC_ASN1_NULL, + SILC_ASN1_NULL(has_null), SILC_ASN1_END, SILC_ASN1_OCTET_STRING(data, data_len), SILC_ASN1_END, SILC_ASN1_END)) @@ -747,53 +812,62 @@ SilcBool silc_pkcs1_verify(void *public_key, silc_buffer_len(&ldi))) ret = TRUE; + /* Deliver result */ + verify_cb(ret, context); + memset(verify, 0, verify_len); memset(unpadded, 0, sizeof(unpadded)); silc_free(verify); - silc_mp_uninit(&mp_tmp2); - silc_mp_uninit(&mp_dst); + silc_mp_suninit(stack, &mp_tmp2); + silc_mp_suninit(stack, &mp_dst); if (hash) memset(hashr, 0, sizeof(hashr)); if (ihash) silc_hash_free(ihash); silc_asn1_free(asn1); + silc_stack_free(stack); - return ret; + return NULL; err: memset(verify, 0, verify_len); silc_free(verify); - silc_mp_uninit(&mp_tmp2); - silc_mp_uninit(&mp_dst); + silc_mp_suninit(stack, &mp_tmp2); + silc_mp_suninit(stack, &mp_dst); if (ihash) silc_hash_free(ihash); silc_asn1_free(asn1); - return FALSE; + silc_stack_free(stack); + + verify_cb(FALSE, context); + return NULL; } /* PKCS #1 sign without hash oid */ -SilcBool silc_pkcs1_sign_no_oid(void *private_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *signature, - SilcUInt32 signature_size, - SilcUInt32 *ret_signature_len, - SilcBool compute_hash, - SilcHash hash) +SilcAsyncOperation +silc_pkcs1_sign_no_oid(const struct SilcPKCSAlgorithmStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcBool compute_hash, + SilcHash hash, + SilcPKCSSignCb sign_cb, + void *context) { RsaPrivateKey *key = private_key; SilcMPInt mp_tmp; SilcMPInt mp_dst; unsigned char padded[2048 + 1], hashr[SILC_HASH_MAXLEN]; SilcUInt32 len = (key->bits + 7) / 8; + SilcStack stack; SILC_LOG_DEBUG(("Sign")); - if (sizeof(padded) < len) - return FALSE; - if (signature_size < len) - return FALSE; + if (sizeof(padded) < len) { + sign_cb(FALSE, NULL, 0, context); + return NULL; + } /* Compute hash if requested */ if (compute_hash) { @@ -804,11 +878,15 @@ SilcBool silc_pkcs1_sign_no_oid(void *private_key, /* Pad data */ if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, src, src_len, - padded, len, NULL)) - return FALSE; + padded, len, NULL)) { + sign_cb(FALSE, NULL, 0, context); + return NULL; + } + + stack = silc_stack_alloc(2048, silc_crypto_stack()); - silc_mp_init(&mp_tmp); - silc_mp_init(&mp_dst); + silc_mp_sinit(stack, &mp_tmp); + silc_mp_sinit(stack, &mp_dst); /* Data to MP */ silc_mp_bin2mp(padded, len, &mp_tmp); @@ -817,26 +895,33 @@ SilcBool silc_pkcs1_sign_no_oid(void *private_key, silc_rsa_private_operation(key, &mp_tmp, &mp_dst); /* MP to data */ - silc_mp_mp2bin_noalloc(&mp_dst, signature, len); - *ret_signature_len = len; + silc_mp_mp2bin_noalloc(&mp_dst, padded, len); + + /* Deliver result */ + sign_cb(TRUE, padded, len, context); memset(padded, 0, sizeof(padded)); - silc_mp_uninit(&mp_tmp); - silc_mp_uninit(&mp_dst); if (compute_hash) memset(hashr, 0, sizeof(hashr)); + silc_mp_suninit(stack, &mp_tmp); + silc_mp_suninit(stack, &mp_dst); + silc_stack_free(stack); - return TRUE; + return NULL; } /* PKCS #1 verify without hash oid */ -SilcBool silc_pkcs1_verify_no_oid(void *public_key, - unsigned char *signature, - SilcUInt32 signature_len, - unsigned char *data, - SilcUInt32 data_len, - SilcHash hash) +SilcAsyncOperation +silc_pkcs1_verify_no_oid(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key, + unsigned char *signature, + SilcUInt32 signature_len, + unsigned char *data, + SilcUInt32 data_len, + SilcHash hash, + SilcPKCSVerifyCb verify_cb, + void *context) { RsaPublicKey *key = public_key; SilcBool ret = FALSE; @@ -844,11 +929,14 @@ SilcBool silc_pkcs1_verify_no_oid(void *public_key, SilcMPInt mp_dst; unsigned char *verify, unpadded[2048 + 1], hashr[SILC_HASH_MAXLEN]; SilcUInt32 verify_len, len = (key->bits + 7) / 8; + SilcStack stack; SILC_LOG_DEBUG(("Verify signature")); - silc_mp_init(&mp_tmp2); - silc_mp_init(&mp_dst); + stack = silc_stack_alloc(2048, silc_crypto_stack()); + + silc_mp_sinit(stack, &mp_tmp2); + silc_mp_sinit(stack, &mp_dst); /* Format the signature into MP int */ silc_mp_bin2mp(signature, signature_len, &mp_tmp2); @@ -864,9 +952,11 @@ SilcBool silc_pkcs1_verify_no_oid(void *public_key, unpadded, sizeof(unpadded), &len)) { memset(verify, 0, verify_len); silc_free(verify); - silc_mp_uninit(&mp_tmp2); - silc_mp_uninit(&mp_dst); - return FALSE; + silc_mp_suninit(stack, &mp_tmp2); + silc_mp_suninit(stack, &mp_dst); + silc_stack_free(stack); + verify_cb(FALSE, context); + return NULL; } /* Hash data if requested */ @@ -880,13 +970,17 @@ SilcBool silc_pkcs1_verify_no_oid(void *public_key, if (len == data_len && !memcmp(data, unpadded, len)) ret = TRUE; + /* Deliver result */ + verify_cb(ret, context); + memset(verify, 0, verify_len); memset(unpadded, 0, sizeof(unpadded)); - silc_free(verify); - silc_mp_uninit(&mp_tmp2); - silc_mp_uninit(&mp_dst); if (hash) memset(hashr, 0, sizeof(hashr)); + silc_free(verify); + silc_mp_suninit(stack, &mp_tmp2); + silc_mp_suninit(stack, &mp_dst); + silc_stack_free(stack); - return ret; + return NULL; } diff --git a/lib/silccrypt/silcpkcs1_i.h b/lib/silccrypt/silcpkcs1_i.h index fd5ecb4f..ac74848f 100644 --- a/lib/silccrypt/silcpkcs1_i.h +++ b/lib/silccrypt/silcpkcs1_i.h @@ -20,66 +20,94 @@ #ifndef SILCPKCS1_I_H #define SILCPKCS1_I_H -SilcBool silc_pkcs1_generate_key(SilcUInt32 keylen, +SilcBool silc_pkcs1_generate_key(const struct SilcPKCSAlgorithmStruct *pkcs, + SilcUInt32 keylen, SilcRng rng, void **ret_public_key, void **ret_private_key); -int silc_pkcs1_import_public_key(unsigned char *key, +int silc_pkcs1_import_public_key(const struct SilcPKCSAlgorithmStruct *pkcs, + void *key, SilcUInt32 key_len, void **ret_public_key); -unsigned char *silc_pkcs1_export_public_key(void *public_key, - SilcUInt32 *ret_len); -SilcUInt32 silc_pkcs1_public_key_bitlen(void *public_key); -void *silc_pkcs1_public_key_copy(void *public_key); -SilcBool silc_pkcs1_public_key_compare(void *key1, void *key2); -void silc_pkcs1_public_key_free(void *public_key); -int silc_pkcs1_import_private_key(unsigned char *key, +unsigned char * +silc_pkcs1_export_public_key(const struct SilcPKCSAlgorithmStruct *pkcs, + SilcStack stack, + void *public_key, + SilcUInt32 *ret_len); +SilcUInt32 +silc_pkcs1_public_key_bitlen(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key); +void *silc_pkcs1_public_key_copy(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key); +SilcBool +silc_pkcs1_public_key_compare(const struct SilcPKCSAlgorithmStruct *pkcs, + void *key1, void *key2); +void silc_pkcs1_public_key_free(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key); +int silc_pkcs1_import_private_key(const struct SilcPKCSAlgorithmStruct *pkcs, + void *key, SilcUInt32 key_len, void **ret_private_key); -unsigned char *silc_pkcs1_export_private_key(void *private_key, - SilcUInt32 *ret_len); -SilcUInt32 silc_pkcs1_private_key_bitlen(void *private_key); -void silc_pkcs1_private_key_free(void *private_key); -SilcBool silc_pkcs1_encrypt(void *public_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *dst, - SilcUInt32 dst_size, - SilcUInt32 *ret_dst_len, - SilcRng rng); -SilcBool silc_pkcs1_decrypt(void *private_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *dst, - SilcUInt32 dst_size, - SilcUInt32 *ret_dst_len); -SilcBool silc_pkcs1_sign(void *private_key, - unsigned char *src, - SilcUInt32 src_len, +unsigned char * +silc_pkcs1_export_private_key(const struct SilcPKCSAlgorithmStruct *pkcs, + SilcStack stack, + void *private_key, + SilcUInt32 *ret_len); +SilcUInt32 +silc_pkcs1_private_key_bitlen(const struct SilcPKCSAlgorithmStruct *pkcs, + void *private_key); +void silc_pkcs1_private_key_free(const struct SilcPKCSAlgorithmStruct *pkcs, + void *private_key); +SilcAsyncOperation +silc_pkcs1_encrypt(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key, + unsigned char *src, + SilcUInt32 src_len, + SilcRng rng, + SilcPKCSEncryptCb encrypt_cb, + void *context); +SilcAsyncOperation +silc_pkcs1_decrypt(const struct SilcPKCSAlgorithmStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcPKCSDecryptCb decrypt_cb, + void *context); +SilcAsyncOperation silc_pkcs1_sign(const struct SilcPKCSAlgorithmStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcBool compute_hash, + SilcHash hash, + SilcPKCSSignCb sign_cb, + void *context); +SilcAsyncOperation silc_pkcs1_verify(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key, + unsigned char *signature, + SilcUInt32 signature_len, + unsigned char *data, + SilcUInt32 data_len, + SilcHash hash, + SilcPKCSVerifyCb verify_cb, + void *context); +SilcAsyncOperation +silc_pkcs1_sign_no_oid(const struct SilcPKCSAlgorithmStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcBool compute_hash, + SilcHash hash, + SilcPKCSSignCb sign_cb, + void *context); +SilcAsyncOperation +silc_pkcs1_verify_no_oid(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key, unsigned char *signature, - SilcUInt32 signature_size, - SilcUInt32 *ret_signature_len, - SilcBool compute_hash, - SilcHash hash); -SilcBool silc_pkcs1_verify(void *public_key, - unsigned char *signature, - SilcUInt32 signature_len, - unsigned char *data, - SilcUInt32 data_len, - SilcHash hash); -SilcBool silc_pkcs1_sign_no_oid(void *private_key, - unsigned char *src, - SilcUInt32 src_len, - unsigned char *signature, - SilcUInt32 signature_size, - SilcUInt32 *ret_signature_len, - SilcBool compute_hash, - SilcHash hash); -SilcBool silc_pkcs1_verify_no_oid(void *public_key, - unsigned char *signature, - SilcUInt32 signature_len, - unsigned char *data, - SilcUInt32 data_len, - SilcHash hash); + SilcUInt32 signature_len, + unsigned char *data, + SilcUInt32 data_len, + SilcHash hash, + SilcPKCSVerifyCb verify_cb, + void *context); #endif /* SILCPKCS1_I_H */ diff --git a/lib/silccrypt/silcpkcs_i.h b/lib/silccrypt/silcpkcs_i.h new file mode 100644 index 00000000..7eb80ae4 --- /dev/null +++ b/lib/silccrypt/silcpkcs_i.h @@ -0,0 +1,275 @@ +/* + + silcpkcs_i.h + + Author: Pekka Riikonen + + Copyright (C) 1997 - 2007 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 SILCPKCS_I_H +#define SILCPKCS_I_H + +#ifndef SILCPKCS_H +#error "Do not include this header directly" +#endif + +/* The PKCS Algorithm object to represent any PKCS algorithm. This context + implements the PKCS algorithm, such as RSA, DSA, etc. */ +struct SilcPKCSAlgorithmStruct { + /* Algorithm name and scheme */ + char *name; /* Eg. rsa, dsa, etc. */ + char *scheme; /* Eg. pkcs1, openpgp, etc. */ + + /* Supported hash functions, comma separated list */ + char *hash; + + /* Generate new key pair. Returns PKCS algorithm specific public key + and private key contexts. */ + SilcBool (*generate_key)(const struct SilcPKCSAlgorithmStruct *pkcs, + SilcUInt32 keylen, + SilcRng rng, + void **ret_public_key, + void **ret_private_key); + + /* Public key routines. */ + + /* Import/create new public key. Returns the length of the data that was + imported from `key' or 0 on error. Returns the PKCS algorithm specific + public key to `ret_public_key'. */ + int (*import_public_key)(const struct SilcPKCSAlgorithmStruct *pkcs, + void *key, SilcUInt32 key_len, + void **ret_public_key); + + /* Export/encode public key. Returns the encoded public key buffer that + the caller must free. */ + unsigned char * + (*export_public_key)(const struct SilcPKCSAlgorithmStruct *pkcs, + SilcStack stack, + void *public_key, + SilcUInt32 *ret_len); + + /* Returns the bit length of public key */ + SilcUInt32 (*public_key_bitlen)(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key); + + /* Duplicated public key */ + void *(*public_key_copy)(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key); + + /* Compares two public keys. Returns TRUE if they are identical. */ + SilcBool (*public_key_compare)(const struct SilcPKCSAlgorithmStruct *pkcs, + void *key1, void *key2); + + /* Free public key */ + void (*public_key_free)(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key); + + /* Private key routines. */ + + /* Import/create new private key. Returns the length of the data that was + imported from `key' or 0 on error. Returns the PKCS algorithm specific + private key to `ret_private_key'. */ + int (*import_private_key)(const struct SilcPKCSAlgorithmStruct *pkcs, + void *key, + SilcUInt32 key_len, + void **ret_private_key); + + /* Export/encode private key. Returns the encoded private key buffer that + the caller must free. */ + unsigned char * + (*export_private_key)(const struct SilcPKCSAlgorithmStruct *pkcs, + SilcStack stack, + void *private_key, + SilcUInt32 *ret_len); + + /* Returns the bi length of private key */ + SilcUInt32 (*private_key_bitlen)(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key); + + /* Free private key */ + void (*private_key_free)(const struct SilcPKCSAlgorithmStruct *pkcs, + void *private_key); + + /* Encrypt and decrypt operations */ + SilcAsyncOperation (*encrypt)(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key, + unsigned char *src, + SilcUInt32 src_len, + SilcRng rng, + SilcPKCSEncryptCb encrypt_cb, + void *context); + SilcAsyncOperation (*decrypt)(const struct SilcPKCSAlgorithmStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcPKCSDecryptCb decrypt_cb, + void *context); + + /* Signature and verification operations */ + SilcAsyncOperation (*sign)(const struct SilcPKCSAlgorithmStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcBool compute_hash, + SilcHash hash, + SilcPKCSSignCb sign_cb, + void *context); + SilcAsyncOperation (*verify)(const struct SilcPKCSAlgorithmStruct *pkcs, + void *public_key, + unsigned char *signature, + SilcUInt32 signature_len, + unsigned char *data, + SilcUInt32 data_len, + SilcHash hash, + SilcPKCSVerifyCb verify_cb, + void *context); +}; + +/* The PKCS (Public Key Cryptosystem) object to represent any PKCS. This + context implements the PKCS, such as SILC public keys, X.509 certificates, + OpenPGP certificates, etc. under a common API. */ +struct SilcPKCSObjectStruct { + /* PKCS type */ + SilcPKCSType type; + + /* Public key routines */ + + /* Returns PKCS algorithm context from public key */ + const SilcPKCSAlgorithm * + (*get_algorithm)(const struct SilcPKCSObjectStruct *pkcs, + void *public_key); + + /* Imports from public key file */ + SilcBool (*import_public_key_file)(const struct SilcPKCSObjectStruct *pkcs, + unsigned char *filedata, + SilcUInt32 filedata_len, + SilcPKCSFileEncoding encoding, + void **ret_public_key); + + /* Imports from public key binary data. Returns the amount of bytes + imported from `key' or 0 on error. */ + int (*import_public_key)(const struct SilcPKCSObjectStruct *pkcs, + void *key, + SilcUInt32 key_len, + void **ret_public_key); + + /* Exports public key to file */ + unsigned char * + (*export_public_key_file)(const struct SilcPKCSObjectStruct *pkcs, + SilcStack stack, + void *public_key, + SilcPKCSFileEncoding encoding, + SilcUInt32 *ret_len); + + /* Export public key as binary data */ + unsigned char *(*export_public_key)(const struct SilcPKCSObjectStruct *pkcs, + SilcStack stack, + void *public_key, + SilcUInt32 *ret_len); + + /* Returns key length in bits */ + SilcUInt32 (*public_key_bitlen)(const struct SilcPKCSObjectStruct *pkcs, + void *public_key); + + /* Copy public key */ + void *(*public_key_copy)(const struct SilcPKCSObjectStruct *pkcs, + void *public_key); + + /* Compares public keys */ + SilcBool (*public_key_compare)(const struct SilcPKCSObjectStruct *pkcs, + void *key1, void *key2); + + /* Free public key */ + void (*public_key_free)(const struct SilcPKCSObjectStruct *pkcs, + void *public_key); + + /* Private key routines */ + + /* Imports from private key file */ + SilcBool (*import_private_key_file)(const struct SilcPKCSObjectStruct *pkcs, + unsigned char *filedata, + SilcUInt32 filedata_len, + const char *passphrase, + SilcUInt32 passphrase_len, + SilcPKCSFileEncoding encoding, + void **ret_private_key); + + /* Imports from private key binary data. Returns the amount of bytes + imported from `key' or 0 on error. */ + int (*import_private_key)(const struct SilcPKCSObjectStruct *pkcs, + void *key, + SilcUInt32 key_len, + void **ret_private_key); + + /* Exports private key to file */ + unsigned char * + (*export_private_key_file)(const struct SilcPKCSObjectStruct *pkcs, + SilcStack stack, + void *private_key, + const char *passphrase, + SilcUInt32 passphrase_len, + SilcPKCSFileEncoding encoding, + SilcRng rng, + SilcUInt32 *ret_len); + + /* Export private key as binary data */ + unsigned char *(*export_private_key)(const struct SilcPKCSObjectStruct *pkcs, + SilcStack stack, + void *private_key, + SilcUInt32 *ret_len); + + /* Returns key length in bits */ + SilcUInt32 (*private_key_bitlen)(const struct SilcPKCSObjectStruct *pkcs, + void *private_key); + + /* Free private key */ + void (*private_key_free)(const struct SilcPKCSObjectStruct *pkcs, + void *private_key); + + /* Encrypt and decrypt operations */ + SilcAsyncOperation (*encrypt)(const struct SilcPKCSObjectStruct *pkcs, + void *public_key, + unsigned char *src, + SilcUInt32 src_len, + SilcRng rng, + SilcPKCSEncryptCb encrypt_cb, + void *context); + SilcAsyncOperation (*decrypt)(const struct SilcPKCSObjectStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcPKCSDecryptCb decrypt_cb, + void *context); + + /* Signature and verification operations */ + SilcAsyncOperation (*sign)(const struct SilcPKCSObjectStruct *pkcs, + void *private_key, + unsigned char *src, + SilcUInt32 src_len, + SilcBool compute_hash, + SilcHash hash, + SilcPKCSSignCb sign_cb, + void *context); + SilcAsyncOperation (*verify)(const struct SilcPKCSObjectStruct *pkcs, + void *public_key, + unsigned char *signature, + SilcUInt32 signature_len, + unsigned char *data, + SilcUInt32 data_len, + SilcHash hash, + SilcPKCSVerifyCb verify_cb, + void *context); +}; + +#endif /* SILCPKCS_I_H */ diff --git a/lib/silccrypt/silcrng.c b/lib/silccrypt/silcrng.c index 668a64ea..ab680bf0 100644 --- a/lib/silccrypt/silcrng.c +++ b/lib/silccrypt/silcrng.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2003 Pekka Riikonen + Copyright (C) 1997 - 2007 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 @@ -311,7 +311,7 @@ static void silc_rng_get_soft_noise(SilcRng rng) silc_rng_xor(rng, (r.ru_nvcsw ^ r.ru_nivcsw), pos++); #endif /* SILC_SYMBIAN */ #endif /* HAVE_GETRUSAGE */ - + #ifdef SILC_RNG_DEBUG SILC_LOG_HEXDUMP(("pool"), rng->pool, sizeof(rng->pool)); #endif @@ -623,17 +623,18 @@ unsigned char *silc_rng_get_rn_string(SilcRng rng, SilcUInt32 len) /* Returns non-zero random number binary data. */ -unsigned char *silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len) +SilcBool silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len, unsigned char *buf, + SilcUInt32 buf_size) { int i; - unsigned char *data; - data = silc_calloc(len + 1, sizeof(*data)); + if (len > buf_size) + return FALSE; for (i = 0; i < len; i++) - data[i] = silc_rng_get_byte(rng); + buf[i] = silc_rng_get_byte(rng); - return data; + return TRUE; } /* Global RNG. This is global RNG that application can initialize so @@ -701,9 +702,11 @@ unsigned char *silc_rng_global_get_rn_string(SilcUInt32 len) return global_rng ? silc_rng_get_rn_string(global_rng, len) : NULL; } -unsigned char *silc_rng_global_get_rn_data(SilcUInt32 len) +SilcBool silc_rng_global_get_rn_data(SilcRng rng, SilcUInt32 len, + unsigned char *buf, SilcUInt32 buf_size) { - return global_rng ? silc_rng_get_rn_data(global_rng, len) : NULL; + return global_rng ? silc_rng_get_rn_data(global_rng, len, buf, + buf_size) : FALSE; } void silc_rng_global_add_noise(unsigned char *buffer, SilcUInt32 len) diff --git a/lib/silccrypt/silcrng.h b/lib/silccrypt/silcrng.h index b4deeb8d..bf32fd8f 100644 --- a/lib/silccrypt/silcrng.h +++ b/lib/silccrypt/silcrng.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2003 Pekka Riikonen + Copyright (C) 1997 - 2007 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 @@ -184,16 +184,18 @@ unsigned char *silc_rng_get_rn_string(SilcRng rng, SilcUInt32 len); * * SYNOPSIS * - * unsigned char *silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len); + * SilcBool silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len, + * unsigned char *buf, SilcUInt32 buf_size); * * DESCRIPTION * - * Returns random binary data of the length of `len' bytes. The - * caller must free returned data buffer. It is guaranteed the data - * buffer does not include any zero (0x00) bytes. + * Returns random binary data of the length of `len' bytes to the `buf' + * of maximum size of `buf_size'. It is guaranteed the data buffer does + * not include any zero (0x00) bytes. * ***/ -unsigned char *silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len); +SilcBool silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len, + unsigned char *buf, SilcUInt32 buf_size); /****f* silccrypt/SilcRNGAPI/silc_rng_add_noise * @@ -329,16 +331,19 @@ unsigned char *silc_rng_global_get_rn_string(SilcUInt32 len); * * SYNOPSIS * - * unsigned char *silc_rng_global_get_rn_data(SilcUInt32 len); + * SilcBool silc_rng_global_get_rn_data(SilcRng rng, SilcUInt32 len, + * unsigned char *buf, + * SilcUInt32 buf_size); * * DESCRIPTION * - * Returns random binary data of the length of `len' bytes. The - * caller must free returned data buffer. It is guaranteed the data - * buffer does not include any zero (0x00) bytes. + * Returns random binary data of the length of `len' bytes to the `buf' + * of maximum size of `buf_size'. It is guaranteed the data buffer does + * not include any zero (0x00) bytes. * ***/ -unsigned char *silc_rng_global_get_rn_data(SilcUInt32 len); +SilcBool silc_rng_global_get_rn_data(SilcRng rng, SilcUInt32 len, + unsigned char *buf, SilcUInt32 buf_size); /****f* silccrypt/SilcRNGAPI/silc_rng_global_add_noise *