silc_buffer_format reallocates automatically now.
[crypto.git] / lib / silccore / silcmessage.c
index d46a4148ad66472f3d5c5633e4246cf7d046b52f..67be2e1476cc650c31a864085f36794d85bbcd58 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2005 Pekka Riikonen
+  Copyright (C) 1997 - 2006 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -20,7 +20,7 @@
    private messages. */
 /* $Id$ */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcmessage.h"
 
 /******************************************************************************
@@ -59,13 +59,13 @@ struct SilcMessagePayloadStruct {
 
 /* Decrypts the Message Payload. The `data' is the actual Message Payload */
 
-bool silc_message_payload_decrypt(unsigned char *data,
+SilcBool silc_message_payload_decrypt(unsigned char *data,
                                  size_t data_len,
-                                 bool private_message,
-                                 bool static_key,
+                                 SilcBool private_message,
+                                 SilcBool static_key,
                                  SilcCipher cipher,
                                  SilcHmac hmac,
-                                 bool check_mac)
+                                 SilcBool check_mac)
 {
   SilcUInt32 mac_len, iv_len = 0, block_len;
   SilcUInt16 len, totlen, dlen;
@@ -148,8 +148,8 @@ bool silc_message_payload_decrypt(unsigned char *data,
 SilcMessagePayload
 silc_message_payload_parse(unsigned char *payload,
                           SilcUInt32 payload_len,
-                          bool private_message,
-                          bool static_key,
+                          SilcBool private_message,
+                          SilcBool static_key,
                           SilcCipher cipher,
                           SilcHmac hmac)
 {
@@ -229,7 +229,7 @@ silc_message_payload_parse(unsigned char *payload,
    Payload encoding routines but application may call this too if needed.
    The `true_len' is the data length which is used to create MAC out of. */
 
-bool silc_message_payload_encrypt(unsigned char *data,
+SilcBool silc_message_payload_encrypt(unsigned char *data,
                                  SilcUInt32 data_len,
                                  SilcUInt32 true_len,
                                  unsigned char *iv,
@@ -263,8 +263,8 @@ bool silc_message_payload_encrypt(unsigned char *data,
 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
                                       const unsigned char *data,
                                       SilcUInt32 data_len,
-                                      bool generate_iv,
-                                      bool private_message,
+                                      SilcBool generate_iv,
+                                      SilcBool private_message,
                                       SilcCipher cipher,
                                       SilcHmac hmac,
                                       SilcRng rng,
@@ -335,10 +335,12 @@ SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
 
   /* Sign the message if wanted */
   if (flags & SILC_MESSAGE_FLAG_SIGNED && private_key && hash) {
-    sig = silc_message_signed_payload_encode(buffer->data, silc_buffer_len(buffer),
+    sig = silc_message_signed_payload_encode(buffer->data,
+                                            silc_buffer_len(buffer),
                                             public_key, private_key, hash);
     if (sig) {
-      buffer = silc_buffer_realloc(buffer, silc_buffer_truelen(buffer) + silc_buffer_len(sig));
+      buffer = silc_buffer_realloc(buffer, silc_buffer_truelen(buffer) +
+                                  silc_buffer_len(sig));
       if (buffer) {
        silc_buffer_pull(buffer, 6 + data_len + pad_len);
        silc_buffer_pull_tail(buffer, silc_buffer_len(sig));
@@ -349,14 +351,14 @@ SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
   }
 
   /* Put IV */
-  silc_buffer_pull(buffer, 6 + data_len + pad_len + (sig ? silc_buffer_len(sig) : 0));
+  silc_buffer_pull(buffer, 6 + data_len + pad_len +
+                  (sig ? silc_buffer_len(sig) : 0));
   silc_buffer_pull_tail(buffer, iv_len);
   silc_buffer_format(buffer,
                     SILC_STR_UI_XNSTRING(iv, iv_len),
                     SILC_STR_END);
-  silc_buffer_push(buffer, 6 + data_len + pad_len + (sig ? silc_buffer_len(sig) : 0));
-
-  SILC_LOG_HEXDUMP(("foo"), buffer->data, silc_buffer_len(buffer));
+  silc_buffer_push(buffer, 6 + data_len + pad_len +
+                  (sig ? silc_buffer_len(sig) : 0));
 
   /* Now encrypt the Message Payload and compute MAC */
   if (cipher) {
@@ -370,7 +372,8 @@ SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
       return NULL;
     }
   }
-  silc_buffer_pull_tail(buffer, silc_buffer_truelen(buffer) - silc_buffer_len(buffer));
+  silc_buffer_pull_tail(buffer, silc_buffer_truelen(buffer) -
+                       silc_buffer_len(buffer));
 
   silc_buffer_free(sig);
   return buffer;
@@ -543,7 +546,6 @@ silc_message_signed_payload_encode(const unsigned char *message_payload,
                                   SilcHash hash)
 {
   SilcBuffer buffer, sign;
-  SilcPKCS pkcs;
   unsigned char auth_data[2048 + 1];
   SilcUInt32 auth_len;
   unsigned char *pk = NULL;
@@ -553,11 +555,12 @@ silc_message_signed_payload_encode(const unsigned char *message_payload,
   if (!message_payload || !message_payload_len || !private_key || !hash)
     return NULL;
 
-  if (public_key)
+  if (public_key) {
     pk = silc_pkcs_public_key_encode(public_key, &pk_len);
-
-  /* Now we support only SILC style public key */
-  pk_type = SILC_SKE_PK_TYPE_SILC;
+    if (!pk)
+      return NULL;
+  }
+  pk_type = silc_pkcs_get_type(public_key);
 
   /* Encode the data to be signed */
   sign = silc_message_signed_encode_data(message_payload,
@@ -570,24 +573,12 @@ silc_message_signed_payload_encode(const unsigned char *message_payload,
 
   /* Sign the buffer */
 
-  /* Allocate PKCS object */
-  if (!silc_pkcs_alloc(private_key->name, &pkcs)) {
-    SILC_LOG_ERROR(("Could not allocated PKCS"));
-    silc_buffer_clear(sign);
-    silc_buffer_free(sign);
-    silc_free(pk);
-    return NULL;
-  }
-  silc_pkcs_private_key_set(pkcs, private_key);
-
   /* Compute the hash and the signature. */
-  if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
-      !silc_pkcs_sign_with_hash(pkcs, hash, sign->data, silc_buffer_len(sign), auth_data,
-                               &auth_len)) {
+  if (!silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign),
+                     auth_data, sizeof(auth_data) - 1, &auth_len, hash)) {
     SILC_LOG_ERROR(("Could not compute signature"));
     silc_buffer_clear(sign);
     silc_buffer_free(sign);
-    silc_pkcs_free(pkcs);
     silc_free(pk);
     return NULL;
   }
@@ -598,7 +589,6 @@ silc_message_signed_payload_encode(const unsigned char *message_payload,
   if (!buffer) {
     silc_buffer_clear(sign);
     silc_buffer_free(sign);
-    silc_pkcs_free(pkcs);
     memset(auth_data, 0, sizeof(auth_data));
     silc_free(pk);
     return NULL;
@@ -627,7 +617,6 @@ silc_message_signed_payload_encode(const unsigned char *message_payload,
   SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer));
 
   memset(auth_data, 0, sizeof(auth_data));
-  silc_pkcs_free(pkcs);
   silc_buffer_clear(sign);
   silc_buffer_free(sign);
   silc_free(pk);
@@ -654,46 +643,36 @@ int silc_message_signed_verify(SilcMessageSignedPayload sig,
 {
   int ret = SILC_AUTH_FAILED;
   SilcBuffer sign;
-  SilcPKCS pkcs;
-  SilcBuffer tmp;
+  SilcBufferStruct tmp;
 
   if (!sig || !remote_public_key || !hash)
     return ret;
 
   /* Generate the signature verification data, the Message Payload */
-  tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len);
-  silc_buffer_format(tmp,
+  memset(&tmp, 0, sizeof(tmp));
+  silc_buffer_format(&tmp,
                     SILC_STR_UI_SHORT(message->flags),
                     SILC_STR_UI_SHORT(message->data_len),
                     SILC_STR_UI_XNSTRING(message->data, message->data_len),
                     SILC_STR_UI_SHORT(message->pad_len),
                     SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
                     SILC_STR_END);
-  sign = silc_message_signed_encode_data(tmp->data, silc_buffer_len(tmp),
+  sign = silc_message_signed_encode_data(tmp.data, silc_buffer_len(&tmp),
                                         sig->pk_data, sig->pk_len,
                                         sig->pk_type);
-  silc_buffer_clear(tmp);
-  silc_buffer_free(tmp);
+  silc_buffer_clear(&tmp);
+  silc_free(silc_buffer_steal(&tmp, NULL));
 
   if (!sign)
     return ret;
 
-  /* Allocate PKCS object */
-  if (!silc_pkcs_alloc(remote_public_key->name, &pkcs)) {
-    silc_buffer_clear(sign);
-    silc_buffer_free(sign);
-    return ret;
-  }
-  silc_pkcs_public_key_set(pkcs, remote_public_key);
-
   /* Verify the authentication data */
-  if (!silc_pkcs_verify_with_hash(pkcs, hash, sig->sign_data,
-                                 sig->sign_len,
-                                 sign->data, silc_buffer_len(sign))) {
+  if (!silc_pkcs_verify(remote_public_key, sig->sign_data,
+                       sig->sign_len,
+                       sign->data, silc_buffer_len(sign), hash)) {
 
     silc_buffer_clear(sign);
     silc_buffer_free(sign);
-    silc_pkcs_free(pkcs);
     SILC_LOG_DEBUG(("Signature verification failed"));
     return ret;
   }
@@ -702,7 +681,6 @@ int silc_message_signed_verify(SilcMessageSignedPayload sig,
 
   silc_buffer_clear(sign);
   silc_buffer_free(sign);
-  silc_pkcs_free(pkcs);
 
   SILC_LOG_DEBUG(("Signature verification successful"));
 
@@ -713,13 +691,16 @@ int silc_message_signed_verify(SilcMessageSignedPayload sig,
 
 SilcPublicKey
 silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
-                                  unsigned char **pk_data,
+                                  const unsigned char **pk_data,
                                   SilcUInt32 *pk_data_len)
 {
   SilcPublicKey pk;
 
-  if (!sig->pk_data || !silc_pkcs_public_key_decode(sig->pk_data,
-                                                   sig->pk_len, &pk))
+  if (!sig->pk_data)
+    return NULL;
+
+  if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
+                                 sig->pk_len, &pk))
     return NULL;
 
   if (pk_data)