updates.
authorPekka Riikonen <priikone@silcnet.org>
Thu, 5 Apr 2001 14:53:18 +0000 (14:53 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 5 Apr 2001 14:53:18 +0000 (14:53 +0000)
CHANGES
apps/silcd/protocol.h
apps/silcd/server.c
lib/silcclient/client.c
lib/silcclient/protocol.h

diff --git a/CHANGES b/CHANGES
index 6a860723407f325f30c9f6f2a4bc23fc396ad409..12b4ed672ee107f763d255c430a79fdab3db56d5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,26 @@
+Thu Apr  5 17:42:30 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Added the PFS support as defined in the specification to the
+         SKE protocol.  Affected files lib/silcske/*.c.
+
+       * Added `ske_group' field to the SilcServerRekey context to hold
+         the number of the SKE group that is used with PFS in re-key.
+         Affected file silcd/idlist.h.
+
+       * Added PFS re-key support to the server.  Affected file is
+         silcd/protocol.c.
+
+       * Added silc_protocol_cancel to cancel execution of the next
+         state of the protocol.  Affected file is
+         lib/silccore/silcprotocol.[ch].
+
+       * Added the re-key support with and without PFS to the client
+         library.  Re-key is performed once in an hour, by default.
+
+       * Removed the `hmac_key' and `hmac_key_len' fields from the
+         SilcClientConnection structure; not needed.  Affected file is
+         lib/silcclient/client.h.
+
 Wed Apr  4 16:32:31 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Do not ask whether user wants to use the negotiated private key
index 1977bf8aa05c5be282d61aed9e5b61c7b92c46c8..d0c2bba34398e33a9022cdeb4d519169103166bc 100644 (file)
@@ -103,8 +103,12 @@ int silc_server_protocol_ke_set_keys(SilcSKE ske,
                                     SilcPKCS pkcs,
                                     SilcHash hash,
                                     SilcHmac hmac,
+                                    SilcSKEDiffieHellmanGroup group,
                                     bool is_responder);
 void silc_server_protocol_rekey_generate(SilcServer server,
                                         SilcServerRekeyInternalContext *ctx);
+void 
+silc_server_protocol_rekey_generate_pfs(SilcServer server,
+                                       SilcServerRekeyInternalContext *ctx);
 
 #endif
index 786566f0301812b55a6422c1fd7cb0078f31c740..c2dd90f453139ed9dc1cac2b3ac3621441781b40 100644 (file)
@@ -744,6 +744,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
                                        ctx->ske->prop->pkcs,
                                        ctx->ske->prop->hash,
                                        ctx->ske->prop->hmac,
+                                       ctx->ske->prop->group,
                                        ctx->responder)) {
     silc_protocol_free(protocol);
     sock->protocol = NULL;
@@ -848,8 +849,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   SilcServerEntry id_entry;
   SilcBuffer packet;
   SilcServerHBContext hb_context;
-  SilcServerRekeyContext rekey;
   unsigned char *id_string;
+  SilcIDListData idata;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -914,7 +915,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   sock->type = SILC_SOCKET_TYPE_ROUTER;
   server->id_entry->router = id_entry;
   server->router = id_entry;
-  server->router->data.registered = TRUE;
+  idata = (SilcIDListData)sock->user_data;
+  idata->registered = TRUE;
 
   /* Perform keepalive. The `hb_context' will be freed automatically
      when finally calling the silc_socket_free function. XXX hardcoded 
@@ -926,14 +928,11 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
                            server->timeout_queue);
 
   /* Register re-key timeout */
-  /* XXX this leaks memory as this is not freed anywhere, currently */
-  rekey = silc_calloc(1, sizeof(*rekey));
-  rekey->server = server;
-  rekey->sock = sock;
-  rekey->timeout = 3600; /* XXX hardcoded */
+  idata->rekey->timeout = 3600; /* XXX hardcoded */
+  idata->rekey->context = (void *)server;
   silc_task_register(server->timeout_queue, sock->sock, 
                     silc_server_rekey_callback,
-                    (void *)rekey, rekey->timeout, 0,
+                    (void *)sock, idata->rekey->timeout, 0,
                     SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 
   /* If we are router then announce our possible servers. */
@@ -1099,6 +1098,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_second)
                                        ctx->ske->prop->pkcs,
                                        ctx->ske->prop->hash,
                                        ctx->ske->prop->hmac,
+                                       ctx->ske->prop->group,
                                        ctx->responder)) {
     silc_protocol_free(protocol);
     sock->protocol = NULL;
@@ -1756,25 +1756,40 @@ void silc_server_packet_parse_type(SilcServer server,
       break;
 
     if (sock->protocol && sock->protocol->protocol &&
-       sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE) {
-
-      SilcServerKEInternalContext *proto_ctx = 
-       (SilcServerKEInternalContext *)sock->protocol->context;
+       (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE ||
+        sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)) {
 
-      if (proto_ctx->packet)
-       silc_packet_context_free(proto_ctx->packet);
+      if (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY) {
+       SilcServerRekeyInternalContext *proto_ctx = 
+         (SilcServerRekeyInternalContext *)sock->protocol->context;
+       
+       if (proto_ctx->packet)
+         silc_packet_context_free(proto_ctx->packet);
+       
+       proto_ctx->packet = silc_packet_context_dup(packet);
 
-      proto_ctx->packet = silc_packet_context_dup(packet);
-      proto_ctx->dest_id_type = packet->src_id_type;
-      proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
-                                         packet->src_id_type);
-      if (!proto_ctx->dest_id)
-       break;
+       /* Let the protocol handle the packet */
+       sock->protocol->execute(server->timeout_queue, 0, 
+                               sock->protocol, sock->sock, 0, 0);
+      } else {
+       SilcServerKEInternalContext *proto_ctx = 
+         (SilcServerKEInternalContext *)sock->protocol->context;
+       
+       if (proto_ctx->packet)
+         silc_packet_context_free(proto_ctx->packet);
+       
+       proto_ctx->packet = silc_packet_context_dup(packet);
+       proto_ctx->dest_id_type = packet->src_id_type;
+       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
+                                           packet->src_id_type);
+       if (!proto_ctx->dest_id)
+         break;
 
-      /* Let the protocol handle the packet */
-      sock->protocol->execute(server->timeout_queue, 0, 
-                             sock->protocol, sock->sock,
-                             0, 100000);
+       /* Let the protocol handle the packet */
+       sock->protocol->execute(server->timeout_queue, 0, 
+                               sock->protocol, sock->sock,
+                               0, 100000);
+      }
     } else {
       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
                      "protocol active, packet dropped."));
@@ -1787,25 +1802,40 @@ void silc_server_packet_parse_type(SilcServer server,
       break;
 
     if (sock->protocol && sock->protocol->protocol &&
-       sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE) {
+       (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE ||
+        sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)) {
 
-      SilcServerKEInternalContext *proto_ctx = 
-       (SilcServerKEInternalContext *)sock->protocol->context;
-
-      if (proto_ctx->packet)
-       silc_packet_context_free(proto_ctx->packet);
+      if (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY) {
+       SilcServerRekeyInternalContext *proto_ctx = 
+         (SilcServerRekeyInternalContext *)sock->protocol->context;
+       
+       if (proto_ctx->packet)
+         silc_packet_context_free(proto_ctx->packet);
+       
+       proto_ctx->packet = silc_packet_context_dup(packet);
 
-      proto_ctx->packet = silc_packet_context_dup(packet);
-      proto_ctx->dest_id_type = packet->src_id_type;
-      proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
-                                         packet->src_id_type);
-      if (!proto_ctx->dest_id)
-       break;
+       /* Let the protocol handle the packet */
+       sock->protocol->execute(server->timeout_queue, 0, 
+                               sock->protocol, sock->sock, 0, 0);
+      } else {
+       SilcServerKEInternalContext *proto_ctx = 
+         (SilcServerKEInternalContext *)sock->protocol->context;
+       
+       if (proto_ctx->packet)
+         silc_packet_context_free(proto_ctx->packet);
+       
+       proto_ctx->packet = silc_packet_context_dup(packet);
+       proto_ctx->dest_id_type = packet->src_id_type;
+       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
+                                           packet->src_id_type);
+       if (!proto_ctx->dest_id)
+         break;
 
-      /* Let the protocol handle the packet */
-      sock->protocol->execute(server->timeout_queue, 0, 
-                             sock->protocol, sock->sock,
-                             0, 100000);
+       /* Let the protocol handle the packet */
+       sock->protocol->execute(server->timeout_queue, 0, 
+                               sock->protocol, sock->sock,
+                               0, 100000);
+      }
     } else {
       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
                      "protocol active, packet dropped."));
@@ -3606,8 +3636,9 @@ SilcClientEntry silc_server_get_client_resolve(SilcServer server,
 
 SILC_TASK_CALLBACK(silc_server_rekey_callback)
 {
-  SilcServerRekeyContext rekey = (SilcServerRekeyContext)context;
-  SilcServer server = rekey->server;
+  SilcSocketConnection sock = (SilcSocketConnection)context;
+  SilcIDListData idata = (SilcIDListData)sock->user_data;
+  SilcServer server = (SilcServer)idata->rekey->context;
   SilcProtocol protocol;
   SilcServerRekeyInternalContext *proto_ctx;
 
@@ -3617,24 +3648,24 @@ SILC_TASK_CALLBACK(silc_server_rekey_callback)
      to the protocol. */
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
   proto_ctx->server = (void *)server;
-  proto_ctx->context = context;
-  proto_ctx->sock = rekey->sock;
+  proto_ctx->sock = sock;
   proto_ctx->responder = FALSE;
+  proto_ctx->pfs = idata->rekey->pfs;
       
   /* Perform rekey protocol. Will call the final callback after the
      protocol is over. */
   silc_protocol_alloc(SILC_PROTOCOL_SERVER_REKEY, 
                      &protocol, proto_ctx, silc_server_rekey_final);
-  rekey->sock->protocol = protocol;
+  sock->protocol = protocol;
       
   /* Run the protocol */
   protocol->execute(server->timeout_queue, 0, protocol, 
-                   rekey->sock->sock, 0, 0);
+                   sock->sock, 0, 0);
 
   /* Re-register re-key timeout */
-  silc_task_register(server->timeout_queue, 0
+  silc_task_register(server->timeout_queue, sock->sock
                     silc_server_rekey_callback,
-                    context, rekey->timeout, 0,
+                    context, idata->rekey->timeout, 0,
                     SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 }
 
@@ -3654,6 +3685,7 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_final)
   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
     /* Error occured during protocol */
+    silc_protocol_cancel(server->timeout_queue, protocol);
     silc_protocol_free(protocol);
     sock->protocol = NULL;
     if (ctx->keymat)
@@ -3667,12 +3699,10 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_final)
   }
 
   /* Take the keys into use */
-  if (ctx->pfs == TRUE) {
-
-  } else {
-    /* Then just generate the new keys and take them into use */
+  if (ctx->pfs == TRUE)
+    silc_server_protocol_rekey_generate_pfs(server, ctx);
+  else
     silc_server_protocol_rekey_generate(server, ctx);
-  }
 
   /* Cleanup */
   silc_protocol_free(protocol);
index 8f40f8599085e273d2e021f2d2a9603e49cf06c8..58053e9d30b3e1769272b7dc6a983280c7d56800 100644 (file)
@@ -27,6 +27,8 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
+SILC_TASK_CALLBACK(silc_client_rekey_callback);
+SILC_TASK_CALLBACK(silc_client_rekey_final);
 
 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
 static void silc_client_packet_parse_type(SilcClient client, 
@@ -448,7 +450,8 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
                                   ctx->ske->prop->cipher,
                                   ctx->ske->prop->pkcs,
                                   ctx->ske->prop->hash,
-                                  ctx->ske->prop->hmac);
+                                  ctx->ske->prop->hmac,
+                                  ctx->ske->prop->group);
   silc_ske_free_key_material(ctx->keymat);
 
   /* Allocate internal context for the authentication protocol. This
@@ -553,6 +556,14 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
   conn->remote_id_data_len = SILC_ID_SERVER_LEN;
 
+  /* Register re-key timeout */
+  conn->rekey->timeout = 3600; /* XXX hardcoded */
+  conn->rekey->context = (void *)client;
+  silc_task_register(client->timeout_queue, conn->sock->sock, 
+                    silc_client_rekey_callback,
+                    (void *)conn->sock, conn->rekey->timeout, 0,
+                    SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+
   silc_task_unregister_by_callback(client->timeout_queue,
                                   silc_client_failure_callback);
   silc_protocol_free(protocol);
@@ -879,23 +890,39 @@ void silc_client_packet_parse_type(SilcClient client,
 
   case SILC_PACKET_KEY_EXCHANGE_1:
     if (sock->protocol && sock->protocol->protocol && 
-       sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
-      SilcClientKEInternalContext *proto_ctx = 
-       (SilcClientKEInternalContext *)sock->protocol->context;
-
-      if (proto_ctx->packet)
-       silc_packet_context_free(proto_ctx->packet);
-
-      proto_ctx->packet = silc_packet_context_dup(packet);
-      proto_ctx->dest_id_type = packet->src_id_type;
-      proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
-                                         packet->src_id_type);
-      if (!proto_ctx->dest_id)
-       break;
-
-      /* Let the protocol handle the packet */
-      sock->protocol->execute(client->timeout_queue, 0,
-                             sock->protocol, sock->sock, 0, 0);
+       (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
+        sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
+
+      if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
+       SilcClientRekeyInternalContext *proto_ctx = 
+         (SilcClientRekeyInternalContext *)sock->protocol->context;
+       
+       if (proto_ctx->packet)
+         silc_packet_context_free(proto_ctx->packet);
+       
+       proto_ctx->packet = silc_packet_context_dup(packet);
+
+       /* Let the protocol handle the packet */
+       sock->protocol->execute(client->timeout_queue, 0, 
+                               sock->protocol, sock->sock, 0, 0);
+      } else {
+       SilcClientKEInternalContext *proto_ctx = 
+         (SilcClientKEInternalContext *)sock->protocol->context;
+       
+       if (proto_ctx->packet)
+         silc_packet_context_free(proto_ctx->packet);
+       
+       proto_ctx->packet = silc_packet_context_dup(packet);
+       proto_ctx->dest_id_type = packet->src_id_type;
+       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
+                                           packet->src_id_type);
+       if (!proto_ctx->dest_id)
+         break;
+       
+       /* Let the protocol handle the packet */
+       sock->protocol->execute(client->timeout_queue, 0,
+                               sock->protocol, sock->sock, 0, 0);
+      }
     } else {
       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
                      "protocol active, packet dropped."));
@@ -903,23 +930,39 @@ void silc_client_packet_parse_type(SilcClient client,
     break;
   case SILC_PACKET_KEY_EXCHANGE_2:
     if (sock->protocol && sock->protocol->protocol && 
-       sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
-      SilcClientKEInternalContext *proto_ctx = 
-       (SilcClientKEInternalContext *)sock->protocol->context;
-
-      if (proto_ctx->packet)
-       silc_packet_context_free(proto_ctx->packet);
-
-      proto_ctx->packet = silc_packet_context_dup(packet);
-      proto_ctx->dest_id_type = packet->src_id_type;
-      proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
-                                         packet->src_id_type);
-      if (!proto_ctx->dest_id)
-       break;
-
-      /* Let the protocol handle the packet */
-      sock->protocol->execute(client->timeout_queue, 0,
-                             sock->protocol, sock->sock, 0, 0);
+       (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
+        sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
+
+      if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
+       SilcClientRekeyInternalContext *proto_ctx = 
+         (SilcClientRekeyInternalContext *)sock->protocol->context;
+       
+       if (proto_ctx->packet)
+         silc_packet_context_free(proto_ctx->packet);
+       
+       proto_ctx->packet = silc_packet_context_dup(packet);
+
+       /* Let the protocol handle the packet */
+       sock->protocol->execute(client->timeout_queue, 0, 
+                               sock->protocol, sock->sock, 0, 0);
+      } else {
+       SilcClientKEInternalContext *proto_ctx = 
+         (SilcClientKEInternalContext *)sock->protocol->context;
+       
+       if (proto_ctx->packet)
+         silc_packet_context_free(proto_ctx->packet);
+       
+       proto_ctx->packet = silc_packet_context_dup(packet);
+       proto_ctx->dest_id_type = packet->src_id_type;
+       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
+                                           packet->src_id_type);
+       if (!proto_ctx->dest_id)
+         break;
+       
+       /* Let the protocol handle the packet */
+       sock->protocol->execute(client->timeout_queue, 0,
+                               sock->protocol, sock->sock, 0, 0);
+      }
     } else {
       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
                      "protocol active, packet dropped."));
@@ -962,6 +1005,34 @@ void silc_client_packet_parse_type(SilcClient client,
     silc_client_key_agreement(client, sock, packet);
     break;
 
+  case SILC_PACKET_REKEY:
+    SILC_LOG_DEBUG(("Re-key packet"));
+    /* We ignore this for now */
+    break;
+
+  case SILC_PACKET_REKEY_DONE:
+    SILC_LOG_DEBUG(("Re-key done packet"));
+
+    if (sock->protocol && sock->protocol->protocol && 
+       sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
+
+      SilcClientRekeyInternalContext *proto_ctx = 
+       (SilcClientRekeyInternalContext *)sock->protocol->context;
+      
+      if (proto_ctx->packet)
+       silc_packet_context_free(proto_ctx->packet);
+      
+      proto_ctx->packet = silc_packet_context_dup(packet);
+      
+      /* Let the protocol handle the packet */
+      sock->protocol->execute(client->timeout_queue, 0, 
+                             sock->protocol, sock->sock, 0, 100000);
+    } else {
+      SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
+                     "protocol active, packet dropped."));
+    }
+    break;
+
   default:
     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
     break;
@@ -1109,12 +1180,10 @@ void silc_client_close_connection(SilcClient client,
       silc_cipher_free(conn->receive_key);
     if (conn->hmac)
       silc_hmac_free(conn->hmac);
-    if (conn->hmac_key) {
-      memset(conn->hmac_key, 0, conn->hmac_key_len);
-      silc_free(conn->hmac_key);
-    }
     if (conn->pending_commands)
       silc_dlist_uninit(conn->pending_commands);
+    if (conn->rekey)
+      silc_free(conn->rekey);
 
     conn->sock = NULL;
     conn->remote_port = 0;
@@ -1122,13 +1191,12 @@ void silc_client_close_connection(SilcClient client,
     conn->send_key = NULL;
     conn->receive_key = NULL;
     conn->hmac = NULL;
-    conn->hmac_key = NULL;
-    conn->hmac_key_len = 0;
     conn->local_id = NULL;
     conn->local_id_data = NULL;
     conn->remote_host = NULL;
     conn->current_channel = NULL;
     conn->pending_commands = NULL;
+    conn->rekey = NULL;
 
     silc_client_del_connection(client, conn);
   }
@@ -1486,3 +1554,88 @@ void silc_client_process_failure(SilcClient client,
                       SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
   }
 }
+
+/* A timeout callback for the re-key. We will be the initiator of the
+   re-key protocol. */
+
+SILC_TASK_CALLBACK(silc_client_rekey_callback)
+{
+  SilcSocketConnection sock = (SilcSocketConnection)context;
+  SilcClientConnection conn = (SilcClientConnection)sock->user_data;
+  SilcClient client = (SilcClient)conn->rekey->context;
+  SilcProtocol protocol;
+  SilcClientRekeyInternalContext *proto_ctx;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  /* Allocate internal protocol context. This is sent as context
+     to the protocol. */
+  proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
+  proto_ctx->client = (void *)client;
+  proto_ctx->sock = sock;
+  proto_ctx->responder = FALSE;
+  proto_ctx->pfs = conn->rekey->pfs;
+      
+  /* Perform rekey protocol. Will call the final callback after the
+     protocol is over. */
+  silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY, 
+                     &protocol, proto_ctx, silc_client_rekey_final);
+  sock->protocol = protocol;
+      
+  /* Run the protocol */
+  protocol->execute(client->timeout_queue, 0, protocol, 
+                   sock->sock, 0, 0);
+
+  /* Re-register re-key timeout */
+  silc_task_register(client->timeout_queue, sock->sock, 
+                    silc_client_rekey_callback,
+                    context, conn->rekey->timeout, 0,
+                    SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+}
+
+/* The final callback for the REKEY protocol. This will actually take the
+   new key material into use. */
+
+SILC_TASK_CALLBACK(silc_client_rekey_final)
+{
+  SilcProtocol protocol = (SilcProtocol)context;
+  SilcClientRekeyInternalContext *ctx =
+    (SilcClientRekeyInternalContext *)protocol->context;
+  SilcClient client = (SilcClient)ctx->client;
+  SilcSocketConnection sock = ctx->sock;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
+      protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
+    /* Error occured during protocol */
+    silc_protocol_cancel(client->timeout_queue, protocol);
+    silc_protocol_free(protocol);
+    sock->protocol = NULL;
+    if (ctx->keymat)
+      silc_ske_free_key_material(ctx->keymat);
+    if (ctx->packet)
+      silc_packet_context_free(ctx->packet);
+    if (ctx->ske)
+      silc_ske_free(ctx->ske);
+    silc_free(ctx);
+    return;
+  }
+
+  /* Take the keys into use */
+  if (ctx->pfs == TRUE)
+    silc_client_protocol_rekey_generate_pfs(client, ctx);
+  else
+    silc_client_protocol_rekey_generate(client, ctx);
+
+  /* Cleanup */
+  silc_protocol_free(protocol);
+  sock->protocol = NULL;
+  if (ctx->keymat)
+    silc_ske_free_key_material(ctx->keymat);
+  if (ctx->packet)
+    silc_packet_context_free(ctx->packet);
+  if (ctx->ske)
+    silc_ske_free(ctx->ske);
+  silc_free(ctx);
+}
index 54f617598e392172de2bd8dddaf492e74ca67a7a..fc73f6de37e018723cad55286fa19065f1d034fb 100644 (file)
@@ -25,6 +25,7 @@
 #define SILC_PROTOCOL_CLIENT_NONE               0
 #define SILC_PROTOCOL_CLIENT_CONNECTION_AUTH    1
 #define SILC_PROTOCOL_CLIENT_KEY_EXCHANGE       2
+#define SILC_PROTOCOL_CLIENT_REKEY              3
 /* #define SILC_PROTOCOL_CLIENT_MAX             255 */
 
 /* Internal context for key exchange protocol */
@@ -72,6 +73,18 @@ typedef struct {
   SilcTask timeout_task;
 } SilcClientConnAuthInternalContext;
 
+/* Internal context for the rekey protocol */
+typedef struct {
+  void *client;
+  void *context;
+  SilcSocketConnection sock;
+  bool responder;                  /* TRUE if we are receiving party */
+  bool pfs;                        /* TRUE if PFS is to be used */
+  SilcSKE ske;                     /* Defined if PFS is used */
+  SilcSKEKeyMaterial *keymat;      /* Defined if PFS is used */
+  SilcPacketContext *packet;
+} SilcClientRekeyInternalContext;
+
 /* Prototypes */
 void silc_client_protocols_register(void);
 void silc_client_protocols_unregister(void);
@@ -90,6 +103,12 @@ void silc_client_protocol_ke_set_keys(SilcSKE ske,
                                      SilcCipher cipher,
                                      SilcPKCS pkcs,
                                      SilcHash hash,
-                                     SilcHmac hmac);
+                                     SilcHmac hmac,
+                                     SilcSKEDiffieHellmanGroup group);
+void silc_client_protocol_rekey_generate(SilcClient client,
+                                        SilcClientRekeyInternalContext *ctx);
+void 
+silc_client_protocol_rekey_generate_pfs(SilcClient client,
+                                       SilcClientRekeyInternalContext *ctx);
 
 #endif