Error checkings for signature computation.
[silc.git] / lib / silcske / silcske.c
index 1eb290032f5114e789a97cc47d85dfc98f63949f..6535f55d4d9d1c54d12701b357edcc3895c56ef6 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 - 2002 Pekka Riikonen
+  Copyright (C) 2000 - 2002 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,6 +81,7 @@ void silc_ske_free(SilcSKE ske)
       silc_ske_payload_ke_free(ske->ke1_payload);
     if (ske->ke2_payload)
       silc_ske_payload_ke_free(ske->ke2_payload);
+    silc_free(ske->remote_version);
 
     /* Free rest */
     if (ske->prop) {
@@ -381,7 +382,7 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
 
   /* Compute signature data if we are doing mutual authentication */
   if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
-    unsigned char hash[32], sign[1024];
+    unsigned char hash[32], sign[2048];
     SilcUInt32 hash_len, sign_len;
 
     SILC_LOG_DEBUG(("We are doing mutual authentication"));
@@ -396,7 +397,16 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
     /* Sign the hash value */
     silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv, 
                                   private_key->prv_len);
-    silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
+    if (silc_pkcs_get_key_len(ske->prop->pkcs) > sizeof(sign) - 1 ||
+       !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
+      silc_mp_uninit(x);
+      silc_free(x);
+      silc_mp_uninit(&payload->x);
+      silc_free(payload->pk_data);
+      silc_free(payload);
+      ske->status = status;
+      return status;
+    }
     payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
     memcpy(payload->sign_data, sign, sign_len);
     memset(sign, 0, sizeof(sign));
@@ -985,7 +995,7 @@ SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
   SilcSKEStatus status = SILC_SKE_STATUS_OK;
   SilcBuffer payload_buf;
   SilcMPInt *KEY;
-  unsigned char hash[32], sign[1024], *pk;
+  unsigned char hash[32], sign[2048], *pk;
   SilcUInt32 hash_len, sign_len, pk_len;
 
   SILC_LOG_DEBUG(("Start"));
@@ -1028,7 +1038,9 @@ SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
     /* Sign the hash value */
     silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv, 
                                   private_key->prv_len);
-    silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
+    if (silc_pkcs_get_key_len(ske->prop->pkcs) > sizeof(sign) - 1 ||
+       !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len))
+      goto err;
     ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
     memcpy(ske->ke2_payload->sign_data, sign, sign_len);
     memset(sign, 0, sizeof(sign));
@@ -1100,6 +1112,9 @@ SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
 
   SILC_LOG_DEBUG(("Start"));
 
+  if (status > SILC_SKE_STATUS_INVALID_COOKIE)
+    status = SILC_SKE_STATUS_BAD_PAYLOAD;
+
   packet = silc_buffer_alloc(4);
   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
   silc_buffer_format(packet,
@@ -1213,6 +1228,8 @@ silc_ske_select_security_properties(SilcSKE ske,
     }
   }
 
+  ske->remote_version = silc_memdup(rp->version, rp->version_len);
+
   /* Flags are returned unchanged. */
   payload->flags = rp->flags;
 
@@ -1607,18 +1624,20 @@ static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
     KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
     
     /* Format the buffer used to compute the hash value */
-    /* XXX Backward support for 0.6.1 */
-    if (ske->backward_version == 1) {
-      SILC_LOG_DEBUG(("*********** Using old KE payload"));
-      buf = silc_buffer_alloc(ske->start_payload_copy->len + 
-                             ske->ke2_payload->pk_len + e_len + 
-                             f_len + KEY_len);
-      silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+    buf = silc_buffer_alloc(ske->start_payload_copy->len + 
+                           ske->ke2_payload->pk_len + 
+                           ske->ke1_payload->pk_len + 
+                           e_len + f_len + KEY_len);
+    silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
 
+    /* Initiator is not required to send its public key */
+    if (!ske->ke1_payload->pk_data) {
       ret = 
        silc_buffer_format(buf,
-                          SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
-                                               ske->start_payload_copy->len),
+                          SILC_STR_UI_XNSTRING(ske->start_payload_copy->
+                                               data,
+                                               ske->start_payload_copy->
+                                               len),
                           SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data, 
                                                ske->ke2_payload->pk_len),
                           SILC_STR_UI_XNSTRING(e, e_len),
@@ -1626,43 +1645,20 @@ static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
                           SILC_STR_UI_XNSTRING(KEY, KEY_len),
                           SILC_STR_END);
     } else {
-      /* Initiator is not required to send its public key */
-      SILC_LOG_DEBUG(("*********** Using new KE payload"));
-      buf = silc_buffer_alloc(ske->start_payload_copy->len + 
-                             ske->ke2_payload->pk_len + 
-                             ske->ke1_payload->pk_len + 
-                             e_len + f_len + KEY_len);
-      silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
-
-      if (!ske->ke1_payload->pk_data) {
-       ret = 
-         silc_buffer_format(buf,
-                            SILC_STR_UI_XNSTRING(ske->start_payload_copy->
-                                                 data,
-                                                 ske->start_payload_copy->
-                                                 len),
-                            SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data, 
-                                                 ske->ke2_payload->pk_len),
-                            SILC_STR_UI_XNSTRING(e, e_len),
-                            SILC_STR_UI_XNSTRING(f, f_len),
-                            SILC_STR_UI_XNSTRING(KEY, KEY_len),
-                            SILC_STR_END);
-      } else {
-       ret = 
-         silc_buffer_format(buf,
-                            SILC_STR_UI_XNSTRING(ske->start_payload_copy->
-                                                 data,
-                                                 ske->start_payload_copy->
-                                                 len),
-                            SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data, 
-                                                 ske->ke2_payload->pk_len),
-                            SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data, 
-                                                 ske->ke1_payload->pk_len),
-                            SILC_STR_UI_XNSTRING(e, e_len),
-                            SILC_STR_UI_XNSTRING(f, f_len),
-                            SILC_STR_UI_XNSTRING(KEY, KEY_len),
-                            SILC_STR_END);
-      }
+      ret = 
+       silc_buffer_format(buf,
+                          SILC_STR_UI_XNSTRING(ske->start_payload_copy->
+                                               data,
+                                               ske->start_payload_copy->
+                                               len),
+                          SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data, 
+                                               ske->ke2_payload->pk_len),
+                          SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data, 
+                                               ske->ke1_payload->pk_len),
+                          SILC_STR_UI_XNSTRING(e, e_len),
+                          SILC_STR_UI_XNSTRING(f, f_len),
+                          SILC_STR_UI_XNSTRING(KEY, KEY_len),
+                          SILC_STR_END);
     }
     if (ret == -1) {
       silc_buffer_free(buf);
@@ -1710,7 +1706,7 @@ static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
 
   /* Make the hash */
   silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
-  *return_hash_len = ske->prop->hash->hash->hash_len;
+  *return_hash_len = silc_hash_len(ske->prop->hash);
 
   if (initiator == FALSE) {
     SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
@@ -2014,3 +2010,20 @@ const char *silc_ske_map_status(SilcSKEStatus status)
 
   return "";
 }
+
+/* Parses remote host's version string. */
+
+bool silc_ske_parse_version(SilcSKE ske, 
+                           SilcUInt32 *protocol_version,
+                           char **protocol_version_string,
+                           SilcUInt32 *software_version, 
+                           char **software_version_string,
+                           char **vendor_version)
+{
+  return silc_parse_version_string(ske->remote_version,
+                                  protocol_version, 
+                                  protocol_version_string, 
+                                  software_version,
+                                  software_version_string,
+                                  vendor_version);
+}