Rewrote crypto library init/uninit. Added silc_crypto_init
authorPekka Riikonen <priikone@silcnet.org>
Sun, 8 Jul 2007 17:33:06 +0000 (17:33 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 8 Jul 2007 17:33:06 +0000 (17:33 +0000)
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.

16 files changed:
lib/silccrypt/Makefile.ad
lib/silccrypt/silccipher.c
lib/silccrypt/silccrypto.c [new file with mode: 0644]
lib/silccrypt/silccrypto.h [new file with mode: 0644]
lib/silccrypt/silchash.c
lib/silccrypt/silchmac.c
lib/silccrypt/silcpk.c
lib/silccrypt/silcpk.h
lib/silccrypt/silcpk_i.h
lib/silccrypt/silcpkcs.c
lib/silccrypt/silcpkcs.h
lib/silccrypt/silcpkcs1.c
lib/silccrypt/silcpkcs1_i.h
lib/silccrypt/silcpkcs_i.h [new file with mode: 0644]
lib/silccrypt/silcrng.c
lib/silccrypt/silcrng.h

index 190316627fa63646a9576df3de0a28c0819eb316..4b0a4268396853dc326ac8549b0410fcb5eec047 100644 (file)
@@ -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
index f7f64600b34633fc788f756d59dfffab5061f143..729d54ecc1e279097f3c6a49c7000cb4f1373ddf 100644 (file)
@@ -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 (file)
index 0000000..c4ac5de
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+
+  silccrypto.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  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 (file)
index 0000000..4d99eca
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+
+  silccrypto.h
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  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 */
index 59cdf7f94eb88d07efc93792a791f3f79e3a516a..b67d43f273af28bfe89c9b2e831c12a0381b7328 100644 (file)
@@ -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;
 
index 1e9380dbfd1e9a57c1bd26ccca21fcbaab823972..a343429dd3d582c8947c20e7bbfa7fe401ba92f2 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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;
 
index 618d1b61bd45788d6a1cd6b2f6e80ebb3a43dbb4..b383db8c19637a2efb0a90f89068f9d645d31250 100644 (file)
@@ -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);
 }
index f62c628c9f0cc4d7b9967d05138c77451bf31e6b..181bfa6fafe778022c8e5cb94a26e23357b32900 100644 (file)
@@ -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);
index e027561001d0604825e47c4fe46f45c08ac1ddc1..48bfb465dda5d3cdf36bd2ba03503ee2bea6b2e4 100644 (file)
 #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 */
index 7c07cfeacee66c20aee069ea046910f610014241..f537b880c1c2ebf01dfaef2570b99df347f81f3c 100644 (file)
@@ -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);
+}
index 42e47264203e30932bfbe4feda882696ddaf0563..13488c72ee2cfd30eec8ee3d29be7b4b35fb3be3 100644 (file)
@@ -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 */
index 2124d2e326bb0fcf9f4c7b506b229ca812aed75a..b4ea51ca0e65790c02eab907b513e910132a4bfe 100644 (file)
@@ -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;
 }
index fd5ecb4fd91822c115d23cbe406938441b555420..ac74848f86002bcc070450235ecdba359bf01ffc 100644 (file)
 #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 (file)
index 0000000..7eb80ae
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+
+  silcpkcs_i.h
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  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 */
index 668a64ea24e73bb9051f09e362676c85c2cf7672..ab680bf04c929389a8d38ed558d1c92c6bfede9c 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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)
index b4deeb8d2eba4867c3208ba48ac96cab0ecb3f27..bf32fd8fcac2e9d9802613331b7559f03e86e49c 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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
  *