Added SILC Server library.
[silc.git] / lib / silccrypt / silcpkcs.c
index 6ce2f9fa389670e4c9991ee72267c4f418e8749a..240456ff481380d89647ee664654bb9700b4d430 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 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
@@ -18,7 +18,7 @@
 */
 /* $Id$ */
 
-#include "silcincludes.h"
+#include "silc.h"
 
 #include "rsa.h"
 
@@ -40,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;
@@ -75,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;
@@ -105,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;
@@ -139,7 +143,7 @@ bool silc_pkcs_unregister(SilcPKCSObject *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;
@@ -151,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;
@@ -172,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;
 
@@ -182,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;
     }
   }
@@ -191,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;
       }
@@ -222,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;
@@ -289,10 +295,10 @@ 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)
 {
-  bool ret = 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;
@@ -368,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);
@@ -376,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);
@@ -384,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);
@@ -392,7 +398,7 @@ bool silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
 
 /* Verifies signature */
 
-bool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
+SilcBool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
                      SilcUInt32 signature_len, unsigned char *data,
                      SilcUInt32 data_len)
 {
@@ -402,11 +408,11 @@ bool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
 
 /* 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;
 
@@ -424,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,
+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;
 
@@ -743,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;
@@ -800,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);
@@ -811,7 +817,7 @@ bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
      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);
@@ -870,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)
 {
@@ -912,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;
@@ -987,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;
@@ -1009,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;
   }
@@ -1022,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);
@@ -1033,7 +1039,7 @@ bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
      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;
@@ -1058,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)
@@ -1091,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;
@@ -1104,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,
@@ -1120,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,
@@ -1131,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,
@@ -1218,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);
@@ -1240,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:
@@ -1262,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);
@@ -1279,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,
@@ -1287,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,
@@ -1301,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;
@@ -1361,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,