Added SILC Server library.
[silc.git] / lib / silccrypt / silcpkcs.c
index 83a16d005e4bb6073164dfbc77d171d21c95e274..240456ff481380d89647ee664654bb9700b4d430 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcpkcs.c 
+  silcpkcs.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2005 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
 */
 /* $Id$ */
 
-#include "silcincludes.h"
+#include "silc.h"
 
 #include "rsa.h"
-#include "pkcs1.h"
 
 /* The main SILC PKCS structure. */
 struct SilcPKCSStruct {
@@ -41,30 +40,32 @@ SilcDList silc_pkcs_list = NULL;
 /* Static list of PKCS for silc_pkcs_register_default(). */
 const SilcPKCSObject silc_default_pkcs[] =
 {
-  /* RSA with PKCS #1 (Uses directly routines from Raw RSA operations) */
-  { "rsa", 
+  /* RSA with PKCS #1 for SILC PKCS */
+  { "rsa", SILC_PKCS_SILC,
     silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
     silc_rsa_get_private_key, silc_rsa_set_public_key,
     silc_rsa_set_private_key, silc_rsa_context_len,
     silc_pkcs1_encrypt, silc_pkcs1_decrypt,
     silc_pkcs1_sign, silc_pkcs1_verify },
 
-  /* Raw RSA operations */
-  { "rsa-raw", 
+  /* RSASSA-PKCS1-V1_5 for SSH2 PKCS */
+/*
+  { "rsa", SILC_PKCS_SSH2,
     silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
     silc_rsa_get_private_key, silc_rsa_set_public_key,
     silc_rsa_set_private_key, silc_rsa_context_len,
-    silc_rsa_encrypt, silc_rsa_decrypt,
-    silc_rsa_sign, silc_rsa_verify },
+    silc_pkcs1_encrypt, silc_pkcs1_decrypt,
+    silc_pkcs1_sign, silc_pkcs1_verify },
+*/
 
-  { NULL, NULL, NULL, NULL, NULL,
+  { NULL, 0, NULL, NULL, NULL, NULL,
     NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
 /* Register a new PKCS into SILC. This is used at the initialization of
    the SILC. */
 
-bool silc_pkcs_register(const SilcPKCSObject *pkcs)
+SilcBool silc_pkcs_register(const SilcPKCSObject *pkcs)
 {
 #ifndef SILC_EPOC
   SilcPKCSObject *new;
@@ -76,13 +77,15 @@ bool silc_pkcs_register(const SilcPKCSObject *pkcs)
     SilcPKCSObject *entry;
     silc_dlist_start(silc_pkcs_list);
     while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
-      if (!strcmp(entry->name, pkcs->name))
+      if (!strcmp(entry->name, pkcs->name) &&
+         entry->type == pkcs->type)
         return FALSE;
     }
   }
 
   new = silc_calloc(1, sizeof(*new));
   new->name = strdup(pkcs->name);
+  new->type = pkcs->type;
   new->init = pkcs->init;
   new->clear_keys = pkcs->clear_keys;
   new->get_public_key = pkcs->get_public_key;
@@ -106,7 +109,7 @@ bool silc_pkcs_register(const SilcPKCSObject *pkcs)
 
 /* Unregister a PKCS from the SILC. */
 
-bool silc_pkcs_unregister(SilcPKCSObject *pkcs)
+SilcBool silc_pkcs_unregister(SilcPKCSObject *pkcs)
 {
 #ifndef SILC_EPOC
   SilcPKCSObject *entry;
@@ -136,11 +139,11 @@ bool silc_pkcs_unregister(SilcPKCSObject *pkcs)
   return FALSE;
 }
 
-/* Function that registers all the default PKCS (all builtin PKCS). 
+/* Function that registers all the default PKCS (all builtin PKCS).
    The application may use this to register the default PKCS if specific
    PKCS in any specific order is not wanted. */
 
-bool silc_pkcs_register_default(void)
+SilcBool silc_pkcs_register_default(void)
 {
 #ifndef SILC_EPOC
   int i;
@@ -152,7 +155,7 @@ bool silc_pkcs_register_default(void)
   return TRUE;
 }
 
-bool silc_pkcs_unregister_all(void)
+SilcBool silc_pkcs_unregister_all(void)
 {
 #ifndef SILC_EPOC
   SilcPKCSObject *entry;
@@ -173,7 +176,8 @@ bool silc_pkcs_unregister_all(void)
 /* Allocates a new SilcPKCS object. The new allocated object is returned
    to the 'new_pkcs' argument. */
 
-bool silc_pkcs_alloc(const unsigned char *name, SilcPKCS *new_pkcs)
+SilcBool silc_pkcs_alloc(const unsigned char *name, SilcPKCSType type,
+                        SilcPKCS *new_pkcs)
 {
   SilcPKCSObject *entry = NULL;
 
@@ -183,7 +187,7 @@ bool silc_pkcs_alloc(const unsigned char *name, SilcPKCS *new_pkcs)
   if (silc_pkcs_list) {
     silc_dlist_start(silc_pkcs_list);
     while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
-      if (!strcmp(entry->name, name))
+      if (!strcmp(entry->name, name) && entry->type == type)
        break;
     }
   }
@@ -192,7 +196,8 @@ bool silc_pkcs_alloc(const unsigned char *name, SilcPKCS *new_pkcs)
     /* On EPOC which don't have globals we check our constant hash list. */
     int i;
     for (i = 0; silc_default_pkcs[i].name; i++) {
-      if (!strcmp(silc_default_pkcs[i].name, name)) {
+      if (!strcmp(silc_default_pkcs[i].name, name) &&
+         silc_default_pkcs[i].type == type) {
        entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
        break;
       }
@@ -223,7 +228,7 @@ void silc_pkcs_free(SilcPKCS pkcs)
 
 /* Return TRUE if PKCS algorithm `name' is supported. */
 
-bool silc_pkcs_is_supported(const unsigned char *name)
+SilcBool silc_pkcs_is_supported(const unsigned char *name)
 {
 #ifndef SILC_EPOC
   SilcPKCSObject *entry;
@@ -260,8 +265,8 @@ char *silc_pkcs_get_supported(void)
     while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
       len += strlen(entry->name);
       list = silc_realloc(list, len + 1);
-      
-      memcpy(list + (len - strlen(entry->name)), 
+
+      memcpy(list + (len - strlen(entry->name)),
             entry->name, strlen(entry->name));
       memcpy(list + len, ",", 1);
       len++;
@@ -274,8 +279,8 @@ char *silc_pkcs_get_supported(void)
       entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
       len += strlen(entry->name);
       list = silc_realloc(list, len + 1);
-      
-      memcpy(list + (len - strlen(entry->name)), 
+
+      memcpy(list + (len - strlen(entry->name)),
             entry->name, strlen(entry->name));
       memcpy(list + len, ",", 1);
       len++;
@@ -290,10 +295,13 @@ char *silc_pkcs_get_supported(void)
 
 /* Generate new key pair into the `pkcs' context. */
 
-bool silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
-                           SilcRng rng)
+SilcBool silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
+                               SilcRng rng)
 {
-  return pkcs->pkcs->init(pkcs->context, bits_key_len, rng);
+  SilcBool ret = pkcs->pkcs->init(pkcs->context, bits_key_len, rng);
+  if (ret)
+    pkcs->key_len = bits_key_len;
+  return ret;
 }
 
 /* Returns the length of the key */
@@ -326,7 +334,7 @@ unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, SilcUInt32 *len)
 
 SilcUInt32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
 {
-  pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk, 
+  pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
                                             public_key->pk_len);
   return pkcs->key_len;
 }
@@ -345,7 +353,7 @@ SilcUInt32 silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
 SilcUInt32 silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
 {
   SilcUInt32 key_len;
-  key_len = pkcs->pkcs->set_private_key(pkcs->context, private_key->prv, 
+  key_len = pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
                                        private_key->prv_len);
   if (!pkcs->key_len)
     pkcs->key_len = key_len;
@@ -366,7 +374,7 @@ SilcUInt32 silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
 
 /* Encrypts */
 
-bool silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
+SilcBool silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
                       unsigned char *dst, SilcUInt32 *dst_len)
 {
   return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
@@ -374,7 +382,7 @@ bool silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
 
 /* Decrypts */
 
-bool silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
+SilcBool silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
                       unsigned char *dst, SilcUInt32 *dst_len)
 {
   return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
@@ -382,7 +390,7 @@ bool silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
 
 /* Generates signature */
 
-bool silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
+SilcBool silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
                    unsigned char *dst, SilcUInt32 *dst_len)
 {
   return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
@@ -390,21 +398,21 @@ bool silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
 
 /* Verifies signature */
 
-bool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature, 
-                     SilcUInt32 signature_len, unsigned char *data, 
+SilcBool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
+                     SilcUInt32 signature_len, unsigned char *data,
                      SilcUInt32 data_len)
 {
-  return pkcs->pkcs->verify(pkcs->context, signature, signature_len, 
+  return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
                            data, data_len);
 }
 
 /* Generates signature with hash. The hash is signed. */
 
-bool silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
+SilcBool silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
                              unsigned char *src, SilcUInt32 src_len,
                              unsigned char *dst, SilcUInt32 *dst_len)
 {
-  unsigned char hashr[32];
+  unsigned char hashr[SILC_HASH_MAXLEN];
   SilcUInt32 hash_len;
   int ret;
 
@@ -422,13 +430,13 @@ bool silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
 /* Verifies signature with hash. The `data' is hashed and verified against
    the `signature'. */
 
-bool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash, 
-                               unsigned char *signature, 
-                               SilcUInt32 signature_len, 
-                               unsigned char *data, 
+SilcBool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
+                               unsigned char *signature,
+                               SilcUInt32 signature_len,
+                               unsigned char *data,
                                SilcUInt32 data_len)
 {
-  unsigned char hashr[32];
+  unsigned char hashr[SILC_HASH_MAXLEN];
   SilcUInt32 hash_len;
   int ret;
 
@@ -437,14 +445,14 @@ bool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
 
   SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
 
-  ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len, 
+  ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
                           hashr, hash_len);
   memset(hashr, 0, sizeof(hashr));
 
   return ret;
 }
 
-/* Encodes and returns SILC public key identifier. If some of the 
+/* Encodes and returns SILC public key identifier. If some of the
    arguments is NULL those are not encoded into the identifier string.
    Protocol says that at least username and host must be provided. */
 
@@ -464,7 +472,7 @@ char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
        (email    ? strlen(email)    : 0) +
        (org      ? strlen(org)      : 0) +
        (country  ? strlen(country)  : 0);
-  
+
   if (len < 3)
     return NULL;
 
@@ -478,9 +486,9 @@ char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
                       SILC_STR_UI32_STRING(username),
                       SILC_STR_END);
     silc_buffer_pull(buf, 3 + strlen(username));
-    tlen = 3 + strlen(username); 
+    tlen = 3 + strlen(username);
   }
-    
+
   if (host) {
     silc_buffer_format(buf,
                       SILC_STR_UI32_STRING(", "),
@@ -488,7 +496,7 @@ char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
                       SILC_STR_UI32_STRING(host),
                       SILC_STR_END);
     silc_buffer_pull(buf, 5 + strlen(host));
-    tlen += 5 + strlen(host); 
+    tlen += 5 + strlen(host);
   }
 
   if (realname) {
@@ -498,7 +506,7 @@ char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
                       SILC_STR_UI32_STRING(realname),
                       SILC_STR_END);
     silc_buffer_pull(buf, 5 + strlen(realname));
-    tlen += 5 + strlen(realname); 
+    tlen += 5 + strlen(realname);
   }
 
   if (email) {
@@ -508,7 +516,7 @@ char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
                       SILC_STR_UI32_STRING(email),
                       SILC_STR_END);
     silc_buffer_pull(buf, 4 + strlen(email));
-    tlen += 4 + strlen(email); 
+    tlen += 4 + strlen(email);
   }
 
   if (org) {
@@ -518,7 +526,7 @@ char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
                       SILC_STR_UI32_STRING(org),
                       SILC_STR_END);
     silc_buffer_pull(buf, 4 + strlen(org));
-    tlen += 4 + strlen(org); 
+    tlen += 4 + strlen(org);
   }
 
   if (country) {
@@ -528,7 +536,7 @@ char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
                       SILC_STR_UI32_STRING(country),
                       SILC_STR_END);
     silc_buffer_pull(buf, 4 + strlen(country));
-    tlen += 4 + strlen(country); 
+    tlen += 4 + strlen(country);
   }
 
   silc_buffer_push(buf, buf->data - buf->head);
@@ -553,16 +561,33 @@ SilcPublicKeyIdentifier silc_pkcs_decode_identifier(char *identifier)
   cp = identifier;
   while (cp) {
     len = strcspn(cp, ",");
+    if (len < 1) {
+      cp = NULL;
+      break;
+    }
     if (len - 1 >= 0 && cp[len - 1] == '\\') {
       while (cp) {
+       if (len + 1 > strlen(cp)) {
+         cp = NULL;
+         break;
+       }
        cp += len + 1;
        len = strcspn(cp, ",") + len;
+       if (len < 1) {
+         cp = NULL;
+         break;
+       }
        if (len - 1 >= 0 && cp[len - 1] != '\\')
          break;
       }
     }
 
+    if (!cp)
+      break;
+
     item = silc_calloc(len + 1, sizeof(char));
+    if (len > strlen(cp))
+      break;
     memcpy(item, cp, len);
 
     if (strstr(item, "UN="))
@@ -577,13 +602,13 @@ SilcPublicKeyIdentifier silc_pkcs_decode_identifier(char *identifier)
       ident->org = strdup(item + strcspn(cp, "=") + 1);
     else if (strstr(item, "C="))
       ident->country = strdup(item + strcspn(cp, "=") + 1);
-    
+
     cp += len;
-    if (strlen(cp) == 0)
+    if (strlen(cp) < 1)
       cp = NULL;
     else
       cp += 1;
-    
+
     if (item)
       silc_free(item);
   }
@@ -608,9 +633,9 @@ void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier)
 /* Allocates SILC style public key formed from sent arguments. All data
    is duplicated. */
 
-SilcPublicKey silc_pkcs_public_key_alloc(const char *name, 
+SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
                                         const char *identifier,
-                                        const unsigned char *pk, 
+                                        const unsigned char *pk,
                                         SilcUInt32 pk_len)
 {
   SilcPublicKey public_key;
@@ -619,9 +644,8 @@ SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
   public_key = silc_calloc(1, sizeof(*public_key));
   public_key->name = strdup(name);
   public_key->pk_len = pk_len;
-  public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
+  public_key->pk = silc_memdup(pk, pk_len);
   public_key->pk_type = SILC_SKE_PK_TYPE_SILC;
-  memcpy(public_key->pk, pk, pk_len);
 
   if (!silc_utf8_valid(identifier, strlen(identifier))) {
     int len = silc_utf8_encoded_len(identifier, strlen(identifier), 0);
@@ -661,8 +685,7 @@ SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
   private_key = silc_calloc(1, sizeof(*private_key));
   private_key->name = strdup(name);
   private_key->prv_len = prv_len;
-  private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
-  memcpy(private_key->prv, prv, prv_len);
+  private_key->prv = silc_memdup(prv, prv_len);
 
   return private_key;
 }
@@ -673,7 +696,10 @@ void silc_pkcs_private_key_free(SilcPrivateKey private_key)
 {
   if (private_key) {
     silc_free(private_key->name);
-    silc_free(private_key->prv);
+    if (private_key->prv) {
+      memset(private_key->prv, 0, private_key->prv_len);
+      silc_free(private_key->prv);
+    }
     silc_free(private_key);
   }
 }
@@ -684,33 +710,17 @@ void silc_pkcs_private_key_free(SilcPrivateKey private_key)
 unsigned char *
 silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
 {
-  SilcBuffer buf;
-  unsigned char *ret;
-
-  buf = silc_buffer_alloc_size(public_key->len + 4);
-  if (!buf)
-    return NULL;
-
-  silc_buffer_format(buf,
-                    SILC_STR_UI_INT(public_key->len),
-                    SILC_STR_UI_SHORT(strlen(public_key->name)),
-                    SILC_STR_UI32_STRING(public_key->name),
-                    SILC_STR_UI_SHORT(strlen(public_key->identifier)),
-                    SILC_STR_UI32_STRING(public_key->identifier),
-                    SILC_STR_UI_XNSTRING(public_key->pk, 
-                                         public_key->pk_len),
-                    SILC_STR_END);
-
-  ret = silc_buffer_steal(buf, len);
-  silc_buffer_free(buf);
-  return ret;
+  return silc_pkcs_public_key_data_encode(public_key->pk,
+                                         public_key->pk_len,
+                                         public_key->name,
+                                         public_key->identifier, len);
 }
 
 /* Encodes SILC style public key. Returns the encoded data. */
 
 unsigned char *
 silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
-                                char *pkcs, char *identifier, 
+                                char *pkcs, char *identifier,
                                 SilcUInt32 *len)
 {
   SilcBuffer buf;
@@ -739,7 +749,7 @@ silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
 /* Decodes SILC style public key. Returns TRUE if the decoding was
    successful. Allocates new public key as well. */
 
-bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
+SilcBool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
                                 SilcPublicKey *public_key)
 {
   SilcBufferStruct buf;
@@ -776,7 +786,7 @@ bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
   if (ret == -1)
     goto err;
 
-  if (pkcs_len < 1 || identifier_len < 3 || 
+  if (pkcs_len < 1 || identifier_len < 3 ||
       pkcs_len + identifier_len > totlen)
     goto err;
 
@@ -796,7 +806,7 @@ bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
 
   /* Get key data. We assume that rest of the buffer is key data. */
   silc_buffer_pull(&buf, 2 + pkcs_len + 2 + identifier_len);
-  key_len = buf.len;
+  key_len = silc_buffer_len(&buf);
   ret = silc_buffer_unformat(&buf,
                             SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
                             SILC_STR_END);
@@ -804,15 +814,15 @@ bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
     goto err;
 
   /* Try to set the key. If this fails the key must be malformed. This
-     code assumes that the PKCS routine checks the format of the key. 
+     code assumes that the PKCS routine checks the format of the key.
      (check only if PKCS are registered) */
   if (SILC_PKCS_LIST) {
-    silc_pkcs_alloc(pkcs_name, &alg);
+    silc_pkcs_alloc(pkcs_name, SILC_PKCS_SILC, &alg);
     if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
       goto err;
     silc_pkcs_free(alg);
   }
-  
+
   if (public_key) {
     *public_key = silc_calloc(1, sizeof(**public_key));
     (*public_key)->len = totlen;
@@ -866,7 +876,7 @@ SilcBuffer silc_pkcs_public_key_payload_encode(SilcPublicKey public_key)
 /* Decode Public Key Payload and decodes the public key inside it to
    to `payload'. */
 
-bool silc_pkcs_public_key_payload_decode(unsigned char *data,
+SilcBool silc_pkcs_public_key_payload_decode(unsigned char *data,
                                         SilcUInt32 data_len,
                                         SilcPublicKey *public_key)
 {
@@ -908,7 +918,7 @@ bool silc_pkcs_public_key_payload_decode(unsigned char *data,
 /* Compares two public keys and returns TRUE if they are same key, and
    FALSE if they are not same. */
 
-bool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
+SilcBool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
 {
   if (key1 == key2)
     return TRUE;
@@ -949,25 +959,9 @@ SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
 unsigned char *
 silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
 {
-  SilcBuffer buf;
-  unsigned char *ret;
-  SilcUInt32 totlen;
-
-  totlen = 2 + strlen(private_key->name) + private_key->prv_len;
-  buf = silc_buffer_alloc_size(totlen);
-  if (!buf)
-    return NULL;
-
-  silc_buffer_format(buf,
-                    SILC_STR_UI_SHORT(strlen(private_key->name)),
-                    SILC_STR_UI32_STRING(private_key->name),
-                    SILC_STR_UI_XNSTRING(private_key->prv, 
-                                         private_key->prv_len),
-                    SILC_STR_END);
-
-  ret = silc_buffer_steal(buf, len);
-  silc_buffer_free(buf);
-  return ret;
+  return silc_pkcs_private_key_data_encode(private_key->prv,
+                                          private_key->prv_len,
+                                          private_key->name, len);
 }
 
 /* Encodes SILC private key. Returns the encoded data. */
@@ -999,7 +993,7 @@ silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
 /* Decodes SILC style private key. Returns TRUE if the decoding was
    successful. Allocates new private key as well. */
 
-bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
+SilcBool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
                                  SilcPrivateKey *private_key)
 {
   SilcBufferStruct buf;
@@ -1012,7 +1006,7 @@ bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
   silc_buffer_set(&buf, data, data_len);
 
   /* Get algorithm name and identifier */
-  ret = 
+  ret =
     silc_buffer_unformat(&buf,
                         SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
                         SILC_STR_END);
@@ -1021,7 +1015,7 @@ bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
     goto err;
   }
 
-  if (pkcs_len < 1 || pkcs_len > buf.truelen) {
+  if (pkcs_len < 1 || pkcs_len > silc_buffer_truelen(&buf)) {
     SILC_LOG_DEBUG(("Malformed private key buffer"));
     goto err;
   }
@@ -1034,7 +1028,7 @@ bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
 
   /* Get key data. We assume that rest of the buffer is key data. */
   silc_buffer_pull(&buf, 2 + pkcs_len);
-  key_len = buf.len;
+  key_len = silc_buffer_len(&buf);
   ret = silc_buffer_unformat(&buf,
                             SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
                             SILC_STR_END);
@@ -1042,17 +1036,17 @@ bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
     goto err;
 
   /* Try to set the key. If this fails the key must be malformed. This
-     code assumes that the PKCS routine checks the format of the key. 
+     code assumes that the PKCS routine checks the format of the key.
      (check only if PKCS are registered) */
   if (SILC_PKCS_LIST) {
-    silc_pkcs_alloc(pkcs_name, &alg);
+    silc_pkcs_alloc(pkcs_name, SILC_PKCS_SILC, &alg);
     if (!alg->pkcs->set_private_key(alg->context, key_data, key_len)) {
       SILC_LOG_DEBUG(("Could not set private key data"));
       goto err;
     }
     silc_pkcs_free(alg);
   }
-  
+
   if (private_key) {
     *private_key = silc_calloc(1, sizeof(**private_key));
     (*private_key)->name = pkcs_name;
@@ -1070,7 +1064,7 @@ bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
 
 /* Internal routine to save public key */
 
-static bool silc_pkcs_save_public_key_internal(const char *filename,
+static SilcBool silc_pkcs_save_public_key_internal(const char *filename,
                                               unsigned char *data,
                                               SilcUInt32 data_len,
                                               SilcUInt32 encoding)
@@ -1103,7 +1097,7 @@ static bool silc_pkcs_save_public_key_internal(const char *filename,
                     SILC_STR_END);
 
   /* Save into file */
-  if (silc_file_writefile(filename, buf->data, buf->len)) {
+  if (silc_file_writefile(filename, buf->data, silc_buffer_len(buf))) {
     silc_free(tmp);
     silc_buffer_free(buf);
     return FALSE;
@@ -1116,12 +1110,12 @@ static bool silc_pkcs_save_public_key_internal(const char *filename,
 
 /* Saves public key into file */
 
-bool silc_pkcs_save_public_key(const char *filename, SilcPublicKey public_key,
+SilcBool silc_pkcs_save_public_key(const char *filename, SilcPublicKey public_key,
                               SilcUInt32 encoding)
 {
   unsigned char *data;
   SilcUInt32 data_len;
-  bool ret;
+  SilcBool ret;
 
   data = silc_pkcs_public_key_encode(public_key, &data_len);
   ret = silc_pkcs_save_public_key_internal(filename, data, data_len,
@@ -1132,7 +1126,7 @@ bool silc_pkcs_save_public_key(const char *filename, SilcPublicKey public_key,
 
 /* Saves public key into file */
 
-bool silc_pkcs_save_public_key_data(const char *filename, unsigned char *data,
+SilcBool silc_pkcs_save_public_key_data(const char *filename, unsigned char *data,
                                    SilcUInt32 data_len, SilcUInt32 encoding)
 {
   return silc_pkcs_save_public_key_internal(filename, data, data_len,
@@ -1143,7 +1137,7 @@ bool silc_pkcs_save_public_key_data(const char *filename, unsigned char *data,
 
 /* Internal routine to save private key. */
 
-static bool silc_pkcs_save_private_key_internal(const char *filename,
+static SilcBool silc_pkcs_save_private_key_internal(const char *filename,
                                                unsigned char *data,
                                                SilcUInt32 data_len,
                                                unsigned char *key,
@@ -1186,7 +1180,7 @@ static bool silc_pkcs_save_private_key_internal(const char *filename,
   }
 
   /* Derive the encryption key from the provided key material.  The key
-     is 256 bits length, and derived by taking hash of the data, then 
+     is 256 bits length, and derived by taking hash of the data, then
      re-hashing the data and the previous digest, and using the first and
      second digest as the key. */
   silc_hash_init(sha1);
@@ -1230,14 +1224,14 @@ static bool silc_pkcs_save_private_key_internal(const char *filename,
                     SILC_STR_END);
 
   /* Encrypt. */
-  silc_cipher_encrypt(aes, enc->data, enc->data, enc->len - len,
+  silc_cipher_encrypt(aes, enc->data, enc->data, silc_buffer_len(enc) - len,
                      silc_cipher_get_iv(aes));
 
   silc_buffer_push(enc, 4);
 
   /* Compute HMAC over the encrypted data and append the MAC to data.
      The key is the first digest of the original key material. */
-  data_len = enc->len - len;
+  data_len = silc_buffer_len(enc) - len;
   silc_hmac_init_with_key(sha1hmac, keymat, 16);
   silc_hmac_update(sha1hmac, enc->data, data_len);
   silc_buffer_pull(enc, data_len);
@@ -1252,7 +1246,7 @@ static bool silc_pkcs_save_private_key_internal(const char *filename,
   silc_cipher_free(aes);
 
   data = enc->data;
-  data_len = enc->len;
+  data_len = silc_buffer_len(enc);
 
   switch (encoding) {
   case SILC_PKCS_FILE_BIN:
@@ -1274,7 +1268,8 @@ static bool silc_pkcs_save_private_key_internal(const char *filename,
                     SILC_STR_END);
 
   /* Save into a file */
-  if (silc_file_writefile_mode(filename, buf->data, buf->len, 0600)) {
+  if (silc_file_writefile_mode(filename, buf->data,
+                              silc_buffer_len(buf), 0600)) {
     silc_buffer_clear(buf);
     silc_buffer_free(buf);
     silc_buffer_clear(enc);
@@ -1291,7 +1286,7 @@ static bool silc_pkcs_save_private_key_internal(const char *filename,
 
 /* Saves private key into file. */
 
-bool silc_pkcs_save_private_key(const char *filename,
+SilcBool silc_pkcs_save_private_key(const char *filename,
                                SilcPrivateKey private_key,
                                unsigned char *passphrase,
                                SilcUInt32 passphrase_len,
@@ -1299,7 +1294,7 @@ bool silc_pkcs_save_private_key(const char *filename,
 {
   unsigned char *data;
   SilcUInt32 data_len;
-  bool ret;
+  SilcBool ret;
 
   data = silc_pkcs_private_key_encode(private_key, &data_len);
   ret = silc_pkcs_save_private_key_internal(filename, data, data_len,
@@ -1313,7 +1308,7 @@ bool silc_pkcs_save_private_key(const char *filename,
 /* Loads public key from file and allocates new public key. Returns TRUE
    if loading was successful. */
 
-bool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
+SilcBool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
                               SilcUInt32 encoding)
 {
   unsigned char *cp, *old, *data, byte;
@@ -1322,7 +1317,7 @@ bool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
   SILC_LOG_DEBUG(("Loading public key `%s' with %s encoding", filename,
                  encoding == SILC_PKCS_FILE_PEM ? "Base64" :
                  encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
-  
+
   old = data = silc_file_readfile(filename, &data_len);
   if (!data)
     return FALSE;
@@ -1353,7 +1348,7 @@ bool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
       data = silc_pem_decode(data, len, &len);
       memset(old, 0, data_len);
       silc_free(old);
-      old = data; 
+      old = data;
       data_len = len;
       break;
     }
@@ -1373,7 +1368,7 @@ bool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
 /* Load private key from file and allocates new private key. Returns TRUE
    if loading was successful. */
 
-bool silc_pkcs_load_private_key(const char *filename,
+SilcBool silc_pkcs_load_private_key(const char *filename,
                                SilcPrivateKey *private_key,
                                unsigned char *passphrase,
                                SilcUInt32 passphrase_len,
@@ -1390,7 +1385,7 @@ bool silc_pkcs_load_private_key(const char *filename,
   SILC_LOG_DEBUG(("Loading private key `%s' with %s encoding", filename,
                  encoding == SILC_PKCS_FILE_PEM ? "Base64" :
                  encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
-  
+
   old = data = silc_file_readfile(filename, &data_len);
   if (!data)
     return FALSE;
@@ -1481,7 +1476,7 @@ bool silc_pkcs_load_private_key(const char *filename,
   }
 
   /* Derive the decryption key from the provided key material.  The key
-     is 256 bits length, and derived by taking hash of the data, then 
+     is 256 bits length, and derived by taking hash of the data, then
      re-hashing the data and the previous digest, and using the first and
      second digest as the key. */
   silc_hash_init(sha1);