Added silc_ske_get_key_material.
authorPekka Riikonen <priikone@silcnet.org>
Thu, 7 Dec 2006 16:59:22 +0000 (16:59 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 7 Dec 2006 16:59:22 +0000 (16:59 +0000)
Error handling fixes.

lib/silcske/groups.c
lib/silcske/silcske.c
lib/silcske/silcske.h
lib/silcske/silcske_i.h

index 992779123a54c0f85663fa53b216738d02fd26cb..7f55aced89703d774c4b43b2729de6213b3100f9 100644 (file)
@@ -4,12 +4,12 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2001 Pekka Riikonen
+  Copyright (C) 2000 - 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
   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
@@ -24,7 +24,7 @@
 /* Fixed and public Diffie Hellman Groups defined by the SKE
    protocol. These are equivalent to the OAKLEY Key Determination
    protocol groups (taken from RFC 2412). */
-const struct SilcSKEDiffieHellmanGroupDefStruct silc_ske_groups[] = 
+const struct SilcSKEDiffieHellmanGroupDefStruct silc_ske_groups[] =
 {
   /* 1024 bits modulus (Mandatory group) */
   { 1, "diffie-hellman-group1",
@@ -98,7 +98,7 @@ SilcSKEStatus silc_ske_group_get_by_number(int number,
     silc_mp_set_str(&group->group, silc_ske_groups[i].group, 16);
     silc_mp_set_str(&group->group_order, silc_ske_groups[i].group_order, 16);
     silc_mp_set_str(&group->generator, silc_ske_groups[i].generator, 16);
-    
+
     *ret = group;
   }
 
@@ -134,7 +134,7 @@ SilcSKEStatus silc_ske_group_get_by_name(const char *name,
     silc_mp_set_str(&group->group, silc_ske_groups[i].group, 16);
     silc_mp_set_str(&group->group_order, silc_ske_groups[i].group_order, 16);
     silc_mp_set_str(&group->generator, silc_ske_groups[i].generator, 16);
-    
+
     *ret = group;
   }
 
@@ -163,7 +163,7 @@ char *silc_ske_get_supported_groups()
     len += strlen(silc_ske_groups[i].name);
     list = silc_realloc(list, len + 1);
 
-    memcpy(list + (len - strlen(silc_ske_groups[i].name)), 
+    memcpy(list + (len - strlen(silc_ske_groups[i].name)),
           silc_ske_groups[i].name, strlen(silc_ske_groups[i].name));
     memcpy(list + len, ",", 1);
     len++;
index d4ad07ab0e1de381c0e3c7aed01638e300fb3af3..dcd8aad49034b8f3c55a99cfbd7957dd34842005 100644 (file)
@@ -387,8 +387,7 @@ silc_ske_select_security_properties(SilcSKE ske,
   }
 
   /* Save selected cipher to security properties */
-  if (silc_cipher_alloc(payload->enc_alg_list,
-                       &(*prop)->cipher) == FALSE) {
+  if (silc_cipher_alloc(payload->enc_alg_list, &(*prop)->cipher) == FALSE) {
     silc_free(payload->ke_grp_list);
     silc_free(payload->pkcs_alg_list);
     silc_free(payload);
@@ -446,8 +445,7 @@ silc_ske_select_security_properties(SilcSKE ske,
   }
 
   /* Save selected hash algorithm to security properties */
-  if (silc_hash_alloc(ske->start_payload->hash_alg_list,
-                     &(*prop)->hash) == FALSE) {
+  if (silc_hash_alloc(payload->hash_alg_list, &(*prop)->hash) == FALSE) {
     silc_free(payload->ke_grp_list);
     silc_free(payload->pkcs_alg_list);
     silc_free(payload->enc_alg_list);
@@ -507,8 +505,7 @@ silc_ske_select_security_properties(SilcSKE ske,
   }
 
   /* Save selected HMACc to security properties */
-  if (silc_hmac_alloc(ske->start_payload->hmac_alg_list, NULL,
-                     &(*prop)->hmac) == FALSE) {
+  if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &(*prop)->hmac) == FALSE) {
     silc_free(payload->ke_grp_list);
     silc_free(payload->pkcs_alg_list);
     silc_free(payload->enc_alg_list);
@@ -812,9 +809,14 @@ SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule,
 
   SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
 
-  if (!rng || !schedule || !public_key)
+  if (!rng || !schedule)
     return NULL;
 
+  if (!public_key) {
+    SILC_LOG_ERROR(("Public key must be given to silc_ske_alloc"));
+    return NULL;
+  }
+
   ske = silc_calloc(1, sizeof(*ske));
   if (!ske)
     return NULL;
@@ -835,46 +837,52 @@ void silc_ske_free(SilcSKE ske)
 {
   SILC_LOG_DEBUG(("Freeing Key Exchange object"));
 
-  if (ske) {
-    /* Free start payload */
-    if (ske->start_payload)
-      silc_ske_payload_start_free(ske->start_payload);
-
-    /* Free KE payload */
-    if (ske->ke1_payload)
-      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) {
-      if (ske->prop->group)
-       silc_ske_group_free(ske->prop->group);
-      if (ske->prop->cipher)
-       silc_cipher_free(ske->prop->cipher);
-      if (ske->prop->hash)
-       silc_hash_free(ske->prop->hash);
-      if (ske->prop->hmac)
-       silc_hmac_free(ske->prop->hmac);
-      silc_free(ske->prop);
-    }
-    if (ske->start_payload_copy)
-      silc_buffer_free(ske->start_payload_copy);
-    if (ske->x) {
-      silc_mp_uninit(ske->x);
-      silc_free(ske->x);
-    }
-    if (ske->KEY) {
-      silc_mp_uninit(ske->KEY);
-      silc_free(ske->KEY);
-    }
-    silc_free(ske->hash);
-    silc_free(ske->callbacks);
+  if (!ske)
+    return;
+
+  if (ske->running) {
+    ske->freed = TRUE;
+    return;
+  }
 
-    memset(ske, 'F', sizeof(*ske));
-    silc_free(ske);
+  /* Free start payload */
+  if (ske->start_payload)
+    silc_ske_payload_start_free(ske->start_payload);
+
+  /* Free KE payload */
+  if (ske->ke1_payload)
+    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) {
+    if (ske->prop->group)
+      silc_ske_group_free(ske->prop->group);
+    if (ske->prop->cipher)
+      silc_cipher_free(ske->prop->cipher);
+    if (ske->prop->hash)
+      silc_hash_free(ske->prop->hash);
+    if (ske->prop->hmac)
+      silc_hmac_free(ske->prop->hmac);
+      silc_free(ske->prop);
+  }
+  if (ske->start_payload_copy)
+    silc_buffer_free(ske->start_payload_copy);
+  if (ske->x) {
+    silc_mp_uninit(ske->x);
+    silc_free(ske->x);
+  }
+  if (ske->KEY) {
+    silc_mp_uninit(ske->KEY);
+    silc_free(ske->KEY);
   }
+  silc_free(ske->hash);
+  silc_free(ske->callbacks);
+
+  memset(ske, 'F', sizeof(*ske));
+  silc_free(ske);
 }
 
 /* Return user context */
@@ -972,7 +980,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1)
   SilcSKEStatus status;
   SilcSKEStartPayload payload;
   SilcSKESecurityProperties prop;
-  SilcSKEDiffieHellmanGroup group;
+  SilcSKEDiffieHellmanGroup group = NULL;
   SilcBuffer packet_buf = &ske->packet->buffer;
   SilcUInt16 remote_port = 0;
   SilcID id;
@@ -1084,9 +1092,8 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1)
  err:
   if (payload)
     silc_ske_payload_start_free(payload);
-
-  silc_ske_group_free(group);
-
+  if (group)
+    silc_ske_group_free(group);
   if (prop->cipher)
     silc_cipher_free(prop->cipher);
   if (prop->hash)
@@ -1491,6 +1498,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_end)
                              ske->rekey, ske->callbacks->context);
 
   silc_packet_free(ske->packet);
+  silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
 
   return SILC_FSM_FINISH;
 }
@@ -1507,6 +1515,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_aborted)
   /* Send FAILURE packet */
   SILC_PUT32_MSB(SILC_SKE_STATUS_ERROR, data);
   silc_packet_send(ske->stream, SILC_PACKET_FAILURE, 0, data, 4);
+  silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
 
   return SILC_FSM_FINISH;
 }
@@ -1535,6 +1544,8 @@ SILC_FSM_STATE(silc_ske_st_initiator_error)
     ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL,
                              ske->callbacks->context);
 
+  silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
+
   return SILC_FSM_FINISH;
 }
 
@@ -1552,6 +1563,8 @@ SILC_FSM_STATE(silc_ske_st_initiator_failure)
     ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL,
                              ske->callbacks->context);
 
+  silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
+
   return SILC_FSM_FINISH;
 }
 
@@ -1561,7 +1574,10 @@ static void silc_ske_initiator_finished(SilcFSM fsm, void *fsm_context,
                                        void *destructor_context)
 {
   SilcSKE ske = fsm_context;
-  silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
+
+  ske->running = FALSE;
+  if (ske->freed)
+    silc_ske_free(ske);
 }
 
 /* Starts the protocol as initiator */
@@ -1598,6 +1614,7 @@ silc_ske_initiator(SilcSKE ske,
 
   ske->start_payload = start_payload;
   ske->version = params->version;
+  ske->running = TRUE;
 
   /* Link to packet stream to get key exchange packets */
   ske->stream = stream;
@@ -2158,7 +2175,6 @@ SILC_FSM_STATE(silc_ske_st_responder_error)
     ske->status = SILC_SKE_STATUS_BAD_PAYLOAD;
   SILC_PUT32_MSB(ske->status, tmp);
   silc_packet_send(ske->stream, SILC_PACKET_FAILURE, 0, tmp, 4);
-
   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
 
   return SILC_FSM_FINISH;
@@ -2168,7 +2184,11 @@ SILC_FSM_STATE(silc_ske_st_responder_error)
 static void silc_ske_responder_finished(SilcFSM fsm, void *fsm_context,
                                        void *destructor_context)
 {
+  SilcSKE ske = fsm_context;
 
+  ske->running = FALSE;
+  if (ske->freed)
+    silc_ske_free(ske);
 }
 
 /* Starts the protocol as responder. */
@@ -2198,6 +2218,7 @@ silc_ske_responder(SilcSKE ske,
   ske->version = strdup(params->version);
   if (!ske->version)
     return NULL;
+  ske->running = TRUE;
 
   /* Link to packet stream to get key exchange packets */
   ske->stream = stream;
@@ -2686,3 +2707,10 @@ SilcSKESecurityProperties silc_ske_get_security_properties(SilcSKE ske)
 {
   return ske->prop;
 }
+
+/* Get key material */
+
+SilcSKEKeyMaterial silc_ske_get_key_material(SilcSKE ske)
+{
+  return ske->keymat;
+}
index 98d3f63a5c983319a8dfe293fafd3d86720f808a..c0febeaf69f6ef5901824accf24b13a3c83e98dd 100644 (file)
@@ -74,6 +74,7 @@ typedef enum {
   SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH,         /* Payload includes garbage */
   SILC_SKE_STATUS_SIGNATURE_ERROR,            /* Error computing signature */
   SILC_SKE_STATUS_OUT_OF_MEMORY,              /* System out of memory */
+  SILC_SKE_STATUS_TIMEOUT,                    /* Timeout */
 } SilcSKEStatus;
 /***/
 
@@ -165,7 +166,7 @@ typedef struct {
  *    This context is returned after key exchange protocol to application
  *    in the completion callback.  Application may save it and use it later
  *    to perform the rekey with silc_ske_rekey_initiator_start and/or
- *    silc_ske_rekey_responder_start functions.  If application does not
+ *    silc_ske_rekey_responder functions.  If application does not
  *    need the context, it may free it with silc_free function.
  *
  *    Application may save application specific data to `user_context'.
@@ -455,7 +456,7 @@ silc_ske_initiator(SilcSKE ske,
                   SilcSKEParams params,
                   SilcSKEStartPayload start_payload);
 
-/****f* silcske/SilcSKEAPI/silc_ske_responder_start
+/****f* silcske/SilcSKEAPI/silc_ske_responder
  *
  * SYNOPSIS
  *
@@ -565,6 +566,21 @@ SilcBool silc_ske_parse_version(SilcSKE ske,
  ***/
 SilcSKESecurityProperties silc_ske_get_security_properties(SilcSKE ske);
 
+/****f* silcske/SilcSKEAPI/silc_ske_get_key_material
+ *
+ * SYNOPSIS
+ *
+ *    SilcSKEKeyMaterial silc_ske_get_key_material(SilcSKE ske);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the negotiated key material from the `ske' or NULL if the
+ *    key material does not exist.  The caller must not free the returned
+ *    pointer.
+ *
+ ***/
+SilcSKEKeyMaterial silc_ske_get_key_material(SilcSKE ske);
+
 /****f* silcske/SilcSKEAPI/silc_ske_process_key_material_data
  *
  * SYNOPSIS
index ae61adf75e30332679a9bad5015937ac76088b18..8904b05d93327b710cd05dff28af99bf6a409fb5 100644 (file)
@@ -72,7 +72,9 @@ struct SilcSKEStruct {
   SilcUInt16 session_port;
 
   unsigned int aborted    : 1;
+  unsigned int freed      : 1;
   unsigned int responder  : 1;
+  unsigned int running    : 1;
 };
 
 #endif /* SILCSKE_I_H */