SKE: support for simplified key exchange
authorPekka Riikonen <priikone@silcnet.org>
Mon, 28 Apr 2014 19:39:06 +0000 (22:39 +0300)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 28 Apr 2014 19:39:06 +0000 (22:39 +0300)
This commit adds support for simplified SILC Key Exchange protocol by
allowing the caller to specify the security properties to be used in
the key exchange.  This will stop the library from exchanging the
SILC_PACKET_KEY_EXCHANGE packet containing the properties.

Support for not sending the SILC_PACKET_SUCCESS acks after a successful
key exchange.

These two changes allow the SKE to be simplified to exchanging only
the SILC_PACKET_KEY_EXHANGE_1 and SILC_PACKET_KEY_EXCHANGE_2 packets
to produce the shared key and to do mutual authentication.

The commit also adds support for generating small proposals in
SILC_PACKET_KEY_EXCHANGE packet by including only one security property
per item instead of listing all of them in the proposal.

Additionally the commit adds support for probe timeout which affects
the first packet sent by initiator.  If responder does not respond to
the first packet in the specified timeframe the key exchange will
timeout.  If it replies the normal key exchange timeout has effect after
that.

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

index f6333e8f0c0bc8717d729d6aa53cd8311b90cc00..d5b3b128e1b2e7efeb51ff3bc9d3e315fdcc4f00 100644 (file)
@@ -153,13 +153,16 @@ void silc_ske_group_free(SilcSKEDiffieHellmanGroup group)
 
 /* Returns comma separated list of supported groups */
 
-char *silc_ske_get_supported_groups()
+char *silc_ske_get_supported_groups(SilcUInt32 limit)
 {
   char *list = NULL;
   int i, len;
 
+  if (!limit)
+    limit = ~0;
+
   len = 0;
-  for (i = 0; silc_ske_groups[i].name; i++) {
+  for (i = 0; silc_ske_groups[i].name && i < limit; i++) {
     len += strlen(silc_ske_groups[i].name);
     list = silc_realloc(list, len + 1);
 
index ad45ea8d74a1d14410310a722affb97e80a36506..9c5451be24b166cb87312be6790d1deddb3a0da4 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2005 Pekka Riikonen
+  Copyright (C) 2000 - 2014 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
@@ -156,6 +156,15 @@ silc_ske_payload_start_decode(SilcSKE ske,
     goto err;
   }
 
+  if (payload->len != 4 + payload->cookie_len + payload->version_len +
+      payload->ke_grp_len + payload->pkcs_alg_len + payload->enc_alg_len +
+      payload->hash_alg_len + payload->hmac_alg_len + payload->comp_alg_len +
+      (2 * 7)) {
+    SILC_LOG_ERROR(("Invalid fields in KE Start Payload"));
+    status = SILC_SKE_STATUS_BAD_PAYLOAD;
+    goto err;
+  }
+
   /* Return the payload */
   *return_payload = payload;
 
index 36d36ac8d5e395c80b3a2fa8b54b23793ba8063b..129c178e6896ec67261dca6984d5287e14567b79 100644 (file)
@@ -864,7 +864,8 @@ silc_ske_make_rekey_material(SilcSKE ske, SilcSKEKeyMaterial keymat)
 static SilcSKEStartPayload
 silc_ske_assemble_security_properties(SilcSKE ske,
                                      SilcSKESecurityPropertyFlag flags,
-                                     const char *version)
+                                     const char *version,
+                                     SilcBool small_proposal)
 {
   SilcSKEStartPayload rp;
   int i;
@@ -899,34 +900,48 @@ silc_ske_assemble_security_properties(SilcSKE ske,
     rp->version_len = strlen(version);
 
   /* Get supported Key Exhange groups */
-  rp->ke_grp_list = silc_ske_get_supported_groups();
+  rp->ke_grp_list = silc_ske_get_supported_groups(small_proposal);
   if (rp->ke_grp_list)
     rp->ke_grp_len = strlen(rp->ke_grp_list);
 
   /* Get supported PKCS algorithms */
-  rp->pkcs_alg_list = silc_pkcs_get_supported();
+  if (small_proposal)
+    rp->pkcs_alg_list = strdup(silc_default_pkcs_alg[0].name);
+  else
+    rp->pkcs_alg_list = silc_pkcs_get_supported();
   if (rp->pkcs_alg_list)
     rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
 
   /* Get supported encryption algorithms */
-  rp->enc_alg_list = silc_cipher_get_supported();
+  if (small_proposal)
+    rp->enc_alg_list = strdup(silc_default_ciphers[0].name);
+  else
+    rp->enc_alg_list = silc_cipher_get_supported();
   if (rp->enc_alg_list)
     rp->enc_alg_len = strlen(rp->enc_alg_list);
 
   /* Get supported hash algorithms */
-  rp->hash_alg_list = silc_hash_get_supported();
+  if (small_proposal)
+    rp->hash_alg_list = strdup(silc_default_hash[0].name);
+  else
+    rp->hash_alg_list = silc_hash_get_supported();
   if (rp->hash_alg_list)
     rp->hash_alg_len = strlen(rp->hash_alg_list);
 
   /* Get supported HMACs */
-  rp->hmac_alg_list = silc_hmac_get_supported();
+  if (small_proposal)
+    rp->hmac_alg_list = strdup(silc_default_hmacs[0].name);
+  else
+    rp->hmac_alg_list = silc_hmac_get_supported();
   if (rp->hmac_alg_list)
     rp->hmac_alg_len = strlen(rp->hmac_alg_list);
 
-  /* XXX */
-  /* Get supported compression algorithms */
-  rp->comp_alg_list = strdup("none");
-  rp->comp_alg_len = strlen("none");
+  if (!small_proposal) {
+    /* XXX */
+    /* Get supported compression algorithms */
+    rp->comp_alg_list = strdup("none");
+    rp->comp_alg_len = strlen("none");
+  }
 
   rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
     2 + rp->version_len +
@@ -951,7 +966,7 @@ SILC_TASK_CALLBACK(silc_ske_packet_send_retry)
     silc_free(ske->retrans.data);
     ske->retrans.data = NULL;
     ske->status = SILC_SKE_STATUS_TIMEOUT;
-        silc_ske_notify_failure(ske);
+    silc_ske_notify_failure(ske);
     silc_fsm_continue_sync(&ske->fsm);
     return;
   }
@@ -1046,6 +1061,21 @@ SILC_TASK_CALLBACK(silc_ske_timeout)
   silc_fsm_continue_sync(&ske->fsm);
 }
 
+/* Key exchange timeout task callback */
+
+SILC_TASK_CALLBACK(silc_ske_probe_timeout)
+{
+  SilcSKE ske = context;
+
+  SILC_LOG_DEBUG(("Probe timeout"));
+
+  ske->packet = NULL;
+  ske->status = SILC_SKE_STATUS_PROBE_TIMEOUT;
+  silc_ske_notify_failure(ske);
+
+  silc_fsm_continue_sync(&ske->fsm);
+}
+
 /******************************* Protocol API *******************************/
 
 /* Allocates new SKE object. */
@@ -1229,10 +1259,6 @@ SILC_FSM_STATE(silc_ske_st_initiator_start)
     return SILC_FSM_CONTINUE;
   }
 
-  /* Add key exchange timeout */
-  silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout,
-                                ske, ske->timeout, 0);
-
   /** Wait for responder proposal */
   SILC_LOG_DEBUG(("Waiting for responder proposal"));
   silc_fsm_next(fsm, silc_ske_st_initiator_phase1);
@@ -1263,6 +1289,8 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1)
     return SILC_FSM_WAIT;
   }
 
+  silc_schedule_task_del_by_all(ske->schedule, 0, silc_ske_probe_timeout, ske);
+
   /* Decode the payload */
   status = silc_ske_payload_start_decode(ske, packet_buf, &payload);
   if (status != SILC_SKE_STATUS_OK) {
@@ -1275,7 +1303,9 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1)
   }
 
   /* Get remote ID and set it to stream */
-  if (ske->packet->src_id_len) {
+  if (ske->packet->src_id_len &&
+      (ske->packet->src_id_type == SILC_ID_SERVER ||
+       ske->packet->src_id_type == SILC_ID_CLIENT)) {
     silc_id_str2id(ske->packet->src_id, ske->packet->src_id_len,
                   ske->packet->src_id_type,
                   (ske->packet->src_id_type == SILC_ID_SERVER ?
@@ -1732,20 +1762,26 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase4)
     goto err;
   }
 
-  /* Send SUCCESS packet */
-  SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, hash);
-  if (!silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, hash, 4)) {
-    /** Error sending packet */
-    SILC_LOG_DEBUG(("Error sending packet"));
-    ske->status = SILC_SKE_STATUS_ERROR;
-    silc_fsm_next(fsm, silc_ske_st_initiator_error);
+  if (!ske->no_acks) {
+    /* Send SUCCESS packet */
+    SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, hash);
+    if (!silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, hash, 4)) {
+      /** Error sending packet */
+      SILC_LOG_DEBUG(("Error sending packet"));
+      ske->status = SILC_SKE_STATUS_ERROR;
+      silc_fsm_next(fsm, silc_ske_st_initiator_error);
+      return SILC_FSM_CONTINUE;
+    }
+
+    /** Waiting completion */
+    silc_fsm_next(fsm, silc_ske_st_initiator_end);
+    return SILC_FSM_WAIT;
+  } else {
+    /** Complete protocol */
+    silc_fsm_next(fsm, silc_ske_st_initiator_end);
     return SILC_FSM_CONTINUE;
   }
 
-  /** Waiting completion */
-  silc_fsm_next(fsm, silc_ske_st_initiator_end);
-  return SILC_FSM_WAIT;
-
  err:
   memset(hash, 'F', sizeof(hash));
   silc_ske_payload_ke_free(payload);
@@ -1778,7 +1814,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_end)
 
   SILC_LOG_DEBUG(("Start"));
 
-  if (ske->packet->type != SILC_PACKET_SUCCESS) {
+  if (!ske->no_acks && ske->packet->type != SILC_PACKET_SUCCESS) {
     SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
     silc_ske_install_retransmission(ske);
     silc_packet_free(ske->packet);
@@ -1788,7 +1824,8 @@ SILC_FSM_STATE(silc_ske_st_initiator_end)
 
   SILC_LOG_DEBUG(("Key exchange completed successfully"));
 
-  silc_packet_free(ske->packet);
+  if (ske->packet)
+    silc_packet_free(ske->packet);
   ske->packet = NULL;
   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
   silc_schedule_task_del_by_context(ske->schedule, ske);
@@ -1826,7 +1863,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_aborted)
 SILC_FSM_STATE(silc_ske_st_initiator_error)
 {
   SilcSKE ske = fsm_context;
-  SilcSKEStatus status;
+  SilcUInt32 status;
   unsigned char data[4];
 
   SILC_LOG_DEBUG(("Error %s (%d) occurred during key exchange",
@@ -1837,7 +1874,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_error)
     status = SILC_SKE_STATUS_ERROR;
 
   /* Send FAILURE packet */
-  SILC_PUT32_MSB((SilcUInt32)status, data);
+  SILC_PUT32_MSB(status, data);
   silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, data, 4);
 
   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
@@ -1854,13 +1891,15 @@ SILC_FSM_STATE(silc_ske_st_initiator_error)
 SILC_FSM_STATE(silc_ske_st_initiator_failure)
 {
   SilcSKE ske = fsm_context;
-  SilcUInt32 error = SILC_SKE_STATUS_ERROR;
+  SilcUInt32 error = ske->status;
 
   if (ske->packet && silc_buffer_len(&ske->packet->buffer) == 4) {
     SILC_GET32_MSB(error, ske->packet->buffer.data);
     silc_packet_free(ske->packet);
     ske->packet = NULL;
   }
+  if (error == SILC_SKE_STATUS_OK)
+    error = SILC_SKE_STATUS_ERROR;
   ske->status = error;
 
   SILC_LOG_DEBUG(("Error %s (%d) received during key exchange",
@@ -1898,17 +1937,22 @@ SilcAsyncOperation silc_ske_initiator(SilcSKE ske,
     ske->session_port = params->session_port;
 
   /* Generate security properties if not provided */
-  if (!start_payload) {
-    start_payload = silc_ske_assemble_security_properties(ske,
-                                                         params->flags,
-                                                         params->version);
+  if (!start_payload && !params->prop) {
+    start_payload =
+      silc_ske_assemble_security_properties(ske, params->flags,
+                                           params->version,
+                                           params->small_proposal);
     if (!start_payload)
       return NULL;
   }
 
   ske->timeout = params->timeout_secs ? params->timeout_secs : 30;
+  ske->probe_timeout = (params->probe_timeout_secs ?
+                       params->probe_timeout_secs : 30);
   ske->start_payload = start_payload;
+  ske->prop = params->prop;
   ske->version = params->version;
+  ske->no_acks = params->no_acks;
   ++ske->refcnt;
 
   /* Link to packet stream to get key exchange packets */
@@ -1919,8 +1963,18 @@ SilcAsyncOperation silc_ske_initiator(SilcSKE ske,
                          SILC_PACKET_SUCCESS,
                          SILC_PACKET_FAILURE, -1);
 
+  /* Add key exchange timeout */
+  silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout,
+                                ske, ske->timeout, 0);
+  if (ske->timeout != ske->probe_timeout)
+    silc_schedule_task_add_timeout(ske->schedule, silc_ske_probe_timeout,
+                                  ske, ske->probe_timeout, 0);
+
   /* Start SKE as initiator */
-  silc_fsm_start(&ske->fsm, silc_ske_st_initiator_start);
+  if (!ske->prop)
+    silc_fsm_start(&ske->fsm, silc_ske_st_initiator_start);
+  else
+    silc_fsm_start(&ske->fsm, silc_ske_st_initiator_phase2);
 
   return &ske->op;
 }
@@ -1941,12 +1995,11 @@ SILC_FSM_STATE(silc_ske_st_responder_start)
     return SILC_FSM_CONTINUE;
   }
 
-  /* Add key exchange timeout */
-  silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout,
-                                ske, ske->timeout, 0);
-
   /** Wait for initiator */
-  silc_fsm_next(fsm, silc_ske_st_responder_phase1);
+  if (!ske->prop)
+    silc_fsm_next(fsm, silc_ske_st_responder_phase1);
+  else
+    silc_fsm_next(fsm, silc_ske_st_responder_phase2);
   return SILC_FSM_WAIT;
 }
 
@@ -1975,7 +2028,9 @@ SILC_FSM_STATE(silc_ske_st_responder_phase1)
   }
 
   /* Get remote ID and set it to stream */
-  if (ske->packet->src_id_len) {
+  if (ske->packet->src_id_len &&
+      (ske->packet->src_id_type == SILC_ID_SERVER ||
+       ske->packet->src_id_type == SILC_ID_CLIENT)) {
     silc_id_str2id(ske->packet->src_id, ske->packet->src_id_len,
                   ske->packet->src_id_type,
                   (ske->packet->src_id_type == SILC_ID_SERVER ?
@@ -2194,8 +2249,9 @@ SILC_FSM_STATE(silc_ske_st_responder_phase4)
 
   /* The public key verification was performed only if the Mutual
      Authentication flag is set. */
-  if (ske->start_payload &&
-      ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
+  if ((ske->start_payload &&
+       ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) ||
+      ske->prop->flags & SILC_SKE_SP_FLAG_MUTUAL) {
     unsigned char hash[SILC_HASH_MAXLEN];
     SilcUInt32 hash_len;
 
@@ -2385,9 +2441,15 @@ SILC_FSM_STATE(silc_ske_st_responder_phase5)
     return SILC_FSM_CONTINUE;
   }
 
-  /** Waiting completion */
-  silc_fsm_next(fsm, silc_ske_st_responder_end);
-  return SILC_FSM_WAIT;
+  if (!ske->no_acks) {
+    /** Waiting completion */
+    silc_fsm_next(fsm, silc_ske_st_responder_end);
+    return SILC_FSM_WAIT;
+  } else {
+    /** Complete protocol */
+    silc_fsm_next(fsm, silc_ske_st_responder_end);
+    return SILC_FSM_CONTINUE;
+  }
 }
 
 /* Protocol completed */
@@ -2398,14 +2460,15 @@ SILC_FSM_STATE(silc_ske_st_responder_end)
   unsigned char tmp[4];
   SilcUInt32 hash_len, key_len, block_len;
 
-  if (ske->packet->type != SILC_PACKET_SUCCESS) {
+  if (!ske->no_acks && ske->packet->type != SILC_PACKET_SUCCESS) {
     SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
     silc_ske_install_retransmission(ske);
     silc_packet_free(ske->packet);
     ske->packet = NULL;
     return SILC_FSM_WAIT;
   }
-  silc_packet_free(ske->packet);
+  if (ske->packet)
+    silc_packet_free(ske->packet);
   ske->packet = NULL;
 
   /* Process key material */
@@ -2422,9 +2485,11 @@ SILC_FSM_STATE(silc_ske_st_responder_end)
     return SILC_FSM_CONTINUE;
   }
 
-  /* Send SUCCESS packet */
-  SILC_PUT32_MSB(SILC_SKE_STATUS_OK, tmp);
-  silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, tmp, 4);
+  if (!ske->no_acks) {
+    /* Send SUCCESS packet */
+    SILC_PUT32_MSB(SILC_SKE_STATUS_OK, tmp);
+    silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, tmp, 4);
+  }
 
   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
   silc_schedule_task_del_by_context(ske->schedule, ske);
@@ -2462,7 +2527,7 @@ SILC_FSM_STATE(silc_ske_st_responder_aborted)
 SILC_FSM_STATE(silc_ske_st_responder_failure)
 {
   SilcSKE ske = fsm_context;
-  SilcUInt32 error = SILC_SKE_STATUS_ERROR;
+  SilcUInt32 error = ske->status;
 
   SILC_LOG_DEBUG(("Key exchange protocol failed"));
 
@@ -2471,9 +2536,9 @@ SILC_FSM_STATE(silc_ske_st_responder_failure)
     silc_packet_free(ske->packet);
     ske->packet = NULL;
   }
+  if (error == SILC_SKE_STATUS_OK)
+    error = SILC_SKE_STATUS_ERROR;
   ske->status = error;
-  if (ske->status == SILC_SKE_STATUS_OK)
-    ske->status = SILC_SKE_STATUS_ERROR;
 
   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
   silc_schedule_task_del_by_context(ske->schedule, ske);
@@ -2490,16 +2555,16 @@ SILC_FSM_STATE(silc_ske_st_responder_error)
 {
   SilcSKE ske = fsm_context;
   unsigned char tmp[4];
+  SilcUInt32 status;
 
   SILC_LOG_DEBUG(("Error %d (%s) during key exchange protocol",
                  ske->status, silc_ske_map_status(ske->status)));
 
   /* Send FAILURE packet */
-  if (ske->status == SILC_SKE_STATUS_OUT_OF_MEMORY)
-    ske->status = SILC_SKE_STATUS_ERROR;
-  else if (ske->status > SILC_SKE_STATUS_INVALID_COOKIE)
-    ske->status = SILC_SKE_STATUS_BAD_PAYLOAD;
-  SILC_PUT32_MSB(ske->status, tmp);
+  status = ske->status;
+  if (status > SILC_SKE_STATUS_INVALID_COOKIE)
+    status = SILC_SKE_STATUS_ERROR;
+  SILC_PUT32_MSB(status, tmp);
   silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, tmp, 4);
 
   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
@@ -2534,6 +2599,8 @@ SilcAsyncOperation silc_ske_responder(SilcSKE ske,
   if (ske->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)
     ske->session_port = params->session_port;
   ske->version = params->version;
+  ske->no_acks = params->no_acks;
+  ske->prop = params->prop;
   if (!ske->version)
     return NULL;
   ++ske->refcnt;
@@ -2546,6 +2613,10 @@ SilcAsyncOperation silc_ske_responder(SilcSKE ske,
                          SILC_PACKET_SUCCESS,
                          SILC_PACKET_FAILURE, -1);
 
+  /* Add key exchange timeout */
+  silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout,
+                                ske, ske->timeout, 0);
+
   /* Start SKE as responder */
   silc_fsm_start(&ske->fsm, silc_ske_st_responder_start);
 
@@ -3627,7 +3698,7 @@ const char *silc_ske_status_string[] =
   "Unsupported PKCS",
   "Unsupported hash function",
   "Unsupported HMAC",
-  "Unsupported public key (or certificate)",
+  "Public key not accepted",
   "Incorrect signature",
   "Bad or unsupported version",
   "Invalid cookie",
@@ -3639,6 +3710,7 @@ const char *silc_ske_status_string[] =
   "Error computing signature",
   "System out of memory",
   "Key exchange timeout",
+  "Key exchange timeout",
 
   NULL
 };
index 9c637de61942b32f1654f903312ed80bea8529c5..ecb529fb210a5bf2fa4983790b0d3f16e65f26da 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2007 Pekka Riikonen
+  Copyright (C) 2000 - 2014 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
@@ -75,6 +75,7 @@ typedef enum {
   SILC_SKE_STATUS_SIGNATURE_ERROR,            /* Error computing signature */
   SILC_SKE_STATUS_OUT_OF_MEMORY,              /* System out of memory */
   SILC_SKE_STATUS_TIMEOUT,                    /* Timeout */
+  SILC_SKE_STATUS_PROBE_TIMEOUT,              /* Probe timeout */
 } SilcSKEStatus;
 /***/
 
@@ -212,6 +213,24 @@ typedef struct SilcSKEParamsObject {
      this time it will timeout.  If not specified (zero), default value
      (30 seconds) will be used. */
   SilcUInt16 timeout_secs;
+
+  /* Same as timeout_secs but affects only the first packet sent as
+     initiator.  If the responder does not reply to the first packet in this
+     time frame the key exchange will timeout.  If not specified (zero),
+     default value (30 seconds) will be used. */
+  SilcUInt16 probe_timeout_secs;
+
+  /* If TRUE small proposal is sent with only one security property
+     proposed instead of list of all currently registered. */
+  SilcBool small_proposal;
+
+  /* If TRUE protocol does not end in SUCCESS acknowledgements. */
+  SilcBool no_acks;
+
+  /* Pre-allocated security properties to use in negotiation.  If provided
+     the library will perform only key exchange and proposals aren't
+     exchanged at all. */
+  SilcSKESecurityProperties prop;
 } *SilcSKEParams, SilcSKEParamsStruct;
 /***/
 
@@ -413,7 +432,7 @@ void *silc_ske_get_context(SilcSKE ske);
  *    or certificate.  The verification process is most likely asynchronous.
  *    That is why the application must call the completion callback when the
  *    verification process has been completed.  If this SKE session context
- *    is used to perform  rekey, this callback usually is not provided as
+ *    is used to perform rekey, this callback usually is not provided as
  *    argument since sending public key in rekey is not mandatory.  Setting
  *    this callback implies that remote end MUST send its public key.
  *
index 09c837c656fd03fb2d55cf6f9fecde703861060a..e492531230a45cf778d6a9f2b0ca7c2669f27c7b 100644 (file)
@@ -102,16 +102,17 @@ void silc_ske_group_free(SilcSKEDiffieHellmanGroup group);
  *
  * SYNOPSIS
  *
- *    char *silc_ske_get_supported_groups();
+ *    char *silc_ske_get_supported_groups(SilcUInt32 limit);
  *
  * DESCRIPTION
  *
  *    Returns a comma separated list of support Diffie Hellman groups.
  *    This can be used to get the list of supported groups for SKE
- *    packets.
+ *    packets.  The `limit' specifies the maximum number of groups
+ *    to return.
  *
  ***/
-char *silc_ske_get_supported_groups();
+char *silc_ske_get_supported_groups(SilcUInt32 limit);
 
 /****f* silcske/SilcSKEGroups/silc_ske_group_get_number
  *
index b7b6e2e76157315174ed1e609b838f1728efbd17..3467bc9392567e075595e9dacaab45b35342d291 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2005 - 2008 Pekka Riikonen
+  Copyright (C) 2005 - 2014 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
@@ -88,6 +88,7 @@ struct SilcSKEStruct {
   } retrans;
 
   SilcUInt16 timeout;                /* SKE timeout */
+  SilcUInt16 probe_timeout;          /* First packet timeout */
   SilcUInt16 refcnt;                 /* Reference counter */
 
   unsigned int aborted          : 1;  /* Set when SKE aborted */
@@ -95,6 +96,7 @@ struct SilcSKEStruct {
   unsigned int rekeying         : 1;  /* Set when rekeying */
   unsigned int failure_notified : 1;  /* Set to indicate that we already called
                                         the failure notify routine */
+  unsigned int no_acks          : 1;  /* No SUCCESS acks */
 };
 
 #endif /* SILCSKE_I_H */