updates.
[silc.git] / lib / silcclient / protocol.c
1 /*
2
3   protocol.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /*
21  * Client side of the protocols.
22  */
23 /* $Id$ */
24
25 #include "clientlibincludes.h"
26 #include "client_internal.h"
27
28 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth);
29 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange);
30 SILC_TASK_CALLBACK(silc_client_protocol_rekey);
31
32 extern char *silc_version_string;
33
34 /*
35  * Key Exhange protocol functions
36  */
37
38 /* Function that is called when SKE protocol sends packets to network. */
39
40 void silc_client_protocol_ke_send_packet(SilcSKE ske,
41                                          SilcBuffer packet,
42                                          SilcPacketType type,
43                                          void *context)
44 {
45   SilcProtocol protocol = (SilcProtocol)context;
46   SilcClientKEInternalContext *ctx = 
47     (SilcClientKEInternalContext *)protocol->context;
48   SilcClient client = (SilcClient)ctx->client;
49
50   /* Send the packet immediately */
51   silc_client_packet_send(client, ske->sock, type, NULL, 0, NULL, NULL,
52                           packet->data, packet->len, TRUE);
53 }
54
55 /* Callback that is called when we have received KE2 payload from
56    responder. We try to verify the public key now. */
57
58 SilcSKEStatus silc_client_protocol_ke_verify_key(SilcSKE ske,
59                                                  unsigned char *pk_data,
60                                                  uint32 pk_len,
61                                                  SilcSKEPKType pk_type,
62                                                  void *context)
63 {
64   SilcProtocol protocol = (SilcProtocol)context;
65   SilcClientKEInternalContext *ctx = 
66     (SilcClientKEInternalContext *)protocol->context;
67   SilcClient client = (SilcClient)ctx->client;
68
69   SILC_LOG_DEBUG(("Start"));
70
71   /* Verify public key from user. */
72   if (!client->ops->verify_public_key(client, ctx->sock->user_data, 
73                                       ctx->sock->type,
74                                       pk_data, pk_len, pk_type))
75     return SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
76
77   return SILC_SKE_STATUS_OK;
78 }
79
80 /* Sets the negotiated key material into use for particular connection. */
81
82 void silc_client_protocol_ke_set_keys(SilcSKE ske,
83                                       SilcSocketConnection sock,
84                                       SilcSKEKeyMaterial *keymat,
85                                       SilcCipher cipher,
86                                       SilcPKCS pkcs,
87                                       SilcHash hash,
88                                       SilcHmac hmac,
89                                       SilcSKEDiffieHellmanGroup group)
90 {
91   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
92
93   SILC_LOG_DEBUG(("Setting new keys into use"));
94
95   /* Allocate cipher to be used in the communication */
96   silc_cipher_alloc(cipher->cipher->name, &conn->send_key);
97   silc_cipher_alloc(cipher->cipher->name, &conn->receive_key);
98
99   conn->send_key->cipher->set_key(conn->send_key->context, 
100                                  keymat->send_enc_key, 
101                                  keymat->enc_key_len);
102   conn->send_key->set_iv(conn->send_key, keymat->send_iv);
103   conn->receive_key->cipher->set_key(conn->receive_key->context, 
104                                     keymat->receive_enc_key, 
105                                     keymat->enc_key_len);
106   conn->receive_key->set_iv(conn->receive_key, keymat->receive_iv);
107
108   /* Allocate PKCS to be used */
109 #if 0
110   /* XXX Do we ever need to allocate PKCS for the connection??
111      If yes, we need to change KE protocol to get the initiators
112      public key. */
113   silc_pkcs_alloc(pkcs->pkcs->name, &conn->public_Key);
114   silc_pkcs_set_public_key(conn->public_key, ske->ke2_payload->pk_data, 
115                            ske->ke2_payload->pk_len);
116 #endif
117
118   conn->rekey = silc_calloc(1, sizeof(*conn->rekey));
119   conn->rekey->send_enc_key = 
120     silc_calloc(keymat->enc_key_len / 8,
121                 sizeof(*conn->rekey->send_enc_key));
122   memcpy(conn->rekey->send_enc_key, 
123          keymat->send_enc_key, keymat->enc_key_len / 8);
124   conn->rekey->enc_key_len = keymat->enc_key_len / 8;
125
126   if (ske->start_payload->flags & SILC_SKE_SP_FLAG_PFS)
127     conn->rekey->pfs = TRUE;
128   conn->rekey->ske_group = silc_ske_group_get_number(group);
129
130   /* Save HMAC key to be used in the communication. */
131   silc_hmac_alloc(hmac->hmac->name, NULL, &conn->hmac_send);
132   silc_hmac_set_key(conn->hmac_send, keymat->hmac_key, keymat->hmac_key_len);
133   conn->hmac_receive = conn->hmac_send;
134
135   /* Save the HASH function */
136   silc_hash_alloc(hash->hash->name, &conn->hash);
137 }
138
139 /* Checks the version string of the server. */
140
141 SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
142                                      uint32 len)
143 {
144   SilcClientConnection conn = (SilcClientConnection)ske->sock->user_data;
145   SilcClient client = (SilcClient)ske->user_data;
146   SilcSKEStatus status = SILC_SKE_STATUS_OK;
147   char *cp;
148   int maj = 0, min = 0, build = 0, maj2, min2, build2;
149
150   /* Check for initial version string */
151   if (!strstr(version, "SILC-1.0-"))
152     status = SILC_SKE_STATUS_BAD_VERSION;
153
154   /* Check software version */
155
156   cp = version + 9;
157   maj = atoi(cp);
158   cp = strchr(cp, '.');
159   if (cp) {
160     min = atoi(cp + 1);
161     cp++;
162   }
163   cp = strchr(cp, '.');
164   if (cp)
165     build = atoi(cp + 1);
166
167   cp = silc_version_string + 9;
168   maj2 = atoi(cp);
169   cp = strchr(cp, '.');
170   if (cp) {
171     min2 = atoi(cp + 1);
172     cp++;
173   }
174   cp = strchr(cp, '.');
175   if (cp)
176     build2 = atoi(cp + 1);
177
178   if (maj != maj2)
179     status = SILC_SKE_STATUS_BAD_VERSION;
180 #if 0
181   if (min < min2)
182     status = SILC_SKE_STATUS_BAD_VERSION;
183 #endif
184
185   if (status != SILC_SKE_STATUS_OK)
186     client->ops->say(client, conn, 
187                      "We don't support server version `%s'", version);
188
189   return status;
190 }
191
192 /* Performs key exchange protocol. This is used for both initiator
193    and responder key exchange. This may be called recursively. */
194
195 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
196 {
197   SilcProtocol protocol = (SilcProtocol)context;
198   SilcClientKEInternalContext *ctx = 
199     (SilcClientKEInternalContext *)protocol->context;
200   SilcClient client = (SilcClient)ctx->client;
201   SilcClientConnection conn = ctx->sock->user_data;
202   SilcSKEStatus status = 0;
203
204   SILC_LOG_DEBUG(("Start"));
205
206   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
207     protocol->state = SILC_PROTOCOL_STATE_START;
208
209   switch(protocol->state) {
210   case SILC_PROTOCOL_STATE_START:
211     {
212       /*
213        * Start Protocol
214        */
215       SilcSKE ske;
216
217       /* Allocate Key Exchange object */
218       ske = silc_ske_alloc();
219       ctx->ske = ske;
220       ske->rng = client->rng;
221       ske->user_data = (void *)client;
222       
223       if (ctx->responder == TRUE) {
224         /* Start the key exchange by processing the received security
225            properties packet from initiator. */
226         status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
227                                           silc_version_string,
228                                           ctx->packet->buffer, TRUE,
229                                           NULL, NULL);
230       } else {
231         SilcSKEStartPayload *start_payload;
232
233         /* Assemble security properties. */
234         silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE, 
235                                               silc_version_string,
236                                               &start_payload);
237
238         /* Start the key exchange by sending our security properties
239            to the remote end. */
240         status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
241                                           start_payload,
242                                           ctx->send_packet,
243                                           context);
244       }
245
246       if (status != SILC_SKE_STATUS_OK) {
247         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
248                           status));
249         SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
250                         status));
251
252         protocol->state = SILC_PROTOCOL_STATE_ERROR;
253         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
254         return;
255       }
256
257       /* Advance protocol state and call the next state if we are responder */
258       protocol->state++;
259       if (ctx->responder == TRUE)
260         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
261     }
262     break;
263   case 2:
264     {
265       /* 
266        * Phase 1 
267        */
268       if (ctx->responder == TRUE) {
269         /* Sends the selected security properties to the initiator. */
270         status = 
271           silc_ske_responder_phase_1(ctx->ske, 
272                                      ctx->ske->start_payload,
273                                      ctx->send_packet,
274                                      context);
275       } else {
276         /* Call Phase-1 function. This processes the Key Exchange Start
277            paylaod reply we just got from the responder. The callback
278            function will receive the processed payload where we will
279            save it. */
280         status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer, 
281                                             NULL, NULL);
282       }
283
284       if (status != SILC_SKE_STATUS_OK) {
285         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
286                           status));
287         SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
288                         status));
289
290         protocol->state = SILC_PROTOCOL_STATE_ERROR;
291         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
292         return;
293       }
294
295       /* Advance protocol state and call next state if we are initiator */
296       protocol->state++;
297       if (ctx->responder == FALSE)
298         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
299     }
300     break;
301   case 3:
302     {
303       /* 
304        * Phase 2 
305        */
306       if (ctx->responder == TRUE) {
307         /* Process the received Key Exchange 1 Payload packet from
308            the initiator. This also creates our parts of the Diffie
309            Hellman algorithm. */
310         status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer, 
311                                             ctx->verify, context, NULL, NULL);
312       } else {
313         /* Call the Phase-2 function. This creates Diffie Hellman
314            key exchange parameters and sends our public part inside
315            Key Exhange 1 Payload to the responder. */
316         status = silc_ske_initiator_phase_2(ctx->ske,
317                                             client->public_key,
318                                             client->private_key,
319                                             ctx->send_packet,
320                                             context);
321       }
322
323       if (status != SILC_SKE_STATUS_OK) {
324         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
325                           status));
326         SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
327                         status));
328
329         protocol->state = SILC_PROTOCOL_STATE_ERROR;
330         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
331         return;
332       }
333
334       /* Advance protocol state and call the next state if we are responder */
335       protocol->state++;
336       if (ctx->responder == TRUE)
337         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
338     }
339     break;
340   case 4:
341     {
342       /* 
343        * Finish protocol
344        */
345       if (ctx->responder == TRUE) {
346         /* This creates the key exchange material and sends our
347            public parts to the initiator inside Key Exchange 2 Payload. */
348         status = 
349           silc_ske_responder_finish(ctx->ske, 
350                                     client->public_key, client->private_key,
351                                     SILC_SKE_PK_TYPE_SILC,
352                                     ctx->send_packet,
353                                     context);
354         status = 0;
355       } else {
356         /* Finish the protocol. This verifies the Key Exchange 2 payload
357            sent by responder. */
358         status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
359                                            ctx->verify, context, NULL, NULL);
360       }
361
362       if (status != SILC_SKE_STATUS_OK) {
363
364         if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
365           client->ops->say(client, conn, 
366                            "Received unsupported server %s public key",
367                            ctx->sock->hostname);
368         } else {
369           client->ops->say(client, conn,
370                            "Error during key exchange protocol with server %s",
371                            ctx->sock->hostname);
372         }
373         protocol->state = SILC_PROTOCOL_STATE_ERROR;
374         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
375         return;
376       }
377       
378       /* Send Ok to the other end. We will end the protocol as server
379          sends Ok to us when we will take the new keys into use. */
380       if (ctx->responder == FALSE)
381         silc_ske_end(ctx->ske, ctx->send_packet, context);
382       
383       /* End the protocol on the next round */
384       protocol->state = SILC_PROTOCOL_STATE_END;
385     }
386     break;
387
388   case SILC_PROTOCOL_STATE_END:
389     {
390       /* 
391        * End protocol
392        */
393       SilcSKEKeyMaterial *keymat;
394       int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher);
395       int hash_len = ctx->ske->prop->hash->hash->hash_len;
396
397       /* Process the key material */
398       keymat = silc_calloc(1, sizeof(*keymat));
399       status = silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
400                                              keymat);
401       if (status != SILC_SKE_STATUS_OK) {
402         protocol->state = SILC_PROTOCOL_STATE_ERROR;
403         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 300000);
404         silc_ske_free_key_material(keymat);
405         return;
406       }
407       ctx->keymat = keymat;
408
409       /* Send Ok to the other end if we are responder. If we are initiator
410          we have sent this already. */
411       if (ctx->responder == TRUE)
412         silc_ske_end(ctx->ske, ctx->send_packet, context);
413
414       /* Unregister the timeout task since the protocol has ended. 
415          This was the timeout task to be executed if the protocol is
416          not completed fast enough. */
417       if (ctx->timeout_task)
418         silc_task_unregister(client->timeout_queue, ctx->timeout_task);
419
420       /* Protocol has ended, call the final callback */
421       if (protocol->final_callback)
422         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
423       else
424         silc_protocol_free(protocol);
425     }
426     break;
427
428   case SILC_PROTOCOL_STATE_ERROR:
429     /*
430      * Error during protocol
431      */
432     
433     /* Send abort notification */
434     silc_ske_abort(ctx->ske, ctx->ske->status, 
435                    ctx->send_packet, context);
436
437     /* On error the final callback is always called. */
438     if (protocol->final_callback)
439       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
440     else
441       silc_protocol_free(protocol);
442     break;
443
444   case SILC_PROTOCOL_STATE_FAILURE:
445     /*
446      * Received failure from remote.
447      */
448
449     /* Unregister the timeout task since the protocol has ended. 
450        This was the timeout task to be executed if the protocol is
451        not completed fast enough. */
452     if (ctx->timeout_task)
453       silc_task_unregister(client->timeout_queue, ctx->timeout_task);
454
455     /* On error the final callback is always called. */
456     if (protocol->final_callback)
457       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
458     else
459       silc_protocol_free(protocol);
460     break;
461   case SILC_PROTOCOL_STATE_UNKNOWN:
462     break;
463   }
464 }
465
466 /*
467  * Connection Authentication protocol functions
468  */
469
470 static int
471 silc_client_get_public_key_auth(SilcClient client,
472                                 char *filepath,
473                                 unsigned char *auth_data,
474                                 uint32 *auth_data_len,
475                                 SilcSKE ske)
476 {
477   int len;
478   SilcPKCS pkcs;
479   SilcBuffer auth;
480   SilcPublicKey pub_key;
481
482   if (!silc_pkcs_load_public_key(filepath,&pub_key, SILC_PKCS_FILE_PEM))
483     if (!silc_pkcs_load_public_key(filepath, &pub_key, SILC_PKCS_FILE_BIN))
484       return FALSE;
485
486   silc_pkcs_alloc(pub_key->name, &pkcs);
487   if (!silc_pkcs_public_key_set(pkcs, pub_key)) {
488     silc_pkcs_free(pkcs);
489     silc_pkcs_public_key_free(pub_key);
490     return FALSE;
491   }
492
493   /* Make the authentication data. Protocol says it is HASH plus
494      KE Start Payload. */
495   len = ske->hash_len + ske->start_payload_copy->len;
496   auth = silc_buffer_alloc(len);
497   silc_buffer_pull_tail(auth, len);
498   silc_buffer_format(auth,
499                      SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
500                      SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
501                                           ske->start_payload_copy->len),
502                      SILC_STR_END);
503
504   if (silc_pkcs_sign(pkcs, auth->data, auth->len, auth_data, auth_data_len)) {
505     silc_pkcs_free(pkcs);
506     silc_buffer_free(auth);
507     silc_pkcs_public_key_free(pub_key);
508     return TRUE;
509   }
510
511   silc_pkcs_free(pkcs);
512   silc_buffer_free(auth);
513   silc_pkcs_public_key_free(pub_key);
514   return FALSE;
515 }
516
517 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
518 {
519   SilcProtocol protocol = (SilcProtocol)context;
520   SilcClientConnAuthInternalContext *ctx = 
521     (SilcClientConnAuthInternalContext *)protocol->context;
522   SilcClient client = (SilcClient)ctx->client;
523   SilcClientConnection conn = ctx->sock->user_data;
524
525   SILC_LOG_DEBUG(("Start"));
526
527   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
528     protocol->state = SILC_PROTOCOL_STATE_START;
529
530   switch(protocol->state) {
531   case SILC_PROTOCOL_STATE_START:
532     {
533       /* 
534        * Start protocol. We send authentication data to the server
535        * to be authenticated.
536        */
537       SilcBuffer packet;
538       int payload_len = 0;
539       unsigned char *auth_data = NULL;
540       uint32 auth_data_len = 0;
541
542       switch(ctx->auth_meth) {
543       case SILC_AUTH_NONE:
544         /* No authentication required */
545         break;
546
547       case SILC_AUTH_PASSWORD:
548         /* Password authentication */
549         if (ctx->auth_data && ctx->auth_data_len) {
550           auth_data = ctx->auth_data;
551           auth_data_len = ctx->auth_data_len;
552           break;
553         }
554
555         client->ops->say(client, conn, 
556                          "Password authentication required by server %s",
557                          ctx->sock->hostname);
558         auth_data = client->ops->ask_passphrase(client, conn);
559         auth_data_len = strlen(auth_data);
560         break;
561
562       case SILC_AUTH_PUBLIC_KEY:
563         {
564           unsigned char sign[1024];
565
566           /* Public key authentication */
567           silc_client_get_public_key_auth(client, ctx->auth_data,
568                                           sign, &auth_data_len, 
569                                           ctx->ske);
570           auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
571           memcpy(auth_data, sign, auth_data_len);
572           break;
573         }
574       }
575
576       payload_len = 4 + auth_data_len;
577       packet = silc_buffer_alloc(payload_len);
578       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
579       silc_buffer_format(packet,
580                          SILC_STR_UI_SHORT(payload_len),
581                          SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
582                          SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
583                          SILC_STR_END);
584
585       /* Send the packet to server */
586       silc_client_packet_send(client, ctx->sock,
587                               SILC_PACKET_CONNECTION_AUTH,
588                               NULL, 0, NULL, NULL,
589                               packet->data, packet->len, TRUE);
590
591       if (auth_data) {
592         memset(auth_data, 0, auth_data_len);
593         silc_free(auth_data);
594       }
595       silc_buffer_free(packet);
596       
597       /* Next state is end of protocol */
598       protocol->state = SILC_PROTOCOL_STATE_END;
599     }
600     break;
601
602   case SILC_PROTOCOL_STATE_END:
603     {
604       /* 
605        * End protocol. Nothing special to be done here.
606        */
607
608       /* Protocol has ended, call the final callback */
609       if (protocol->final_callback)
610         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
611       else
612         silc_protocol_free(protocol);
613     }
614     break;
615
616   case SILC_PROTOCOL_STATE_ERROR:
617     {
618       /* 
619        * Error. Send notify to remote.
620        */
621       unsigned char error[4];
622
623       SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
624
625       /* Error in protocol. Send FAILURE packet. Although I don't think
626          this could ever happen on client side. */
627       silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
628                               NULL, 0, NULL, NULL, error, 4, TRUE);
629
630       /* On error the final callback is always called. */
631       if (protocol->final_callback)
632         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
633       else
634         silc_protocol_free(protocol);
635     }
636
637   case SILC_PROTOCOL_STATE_FAILURE:
638     /*
639      * Received failure from remote.
640      */
641
642     /* On error the final callback is always called. */
643     if (protocol->final_callback)
644       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
645     else
646       silc_protocol_free(protocol);
647     break;
648
649   case SILC_PROTOCOL_STATE_UNKNOWN:
650     break;
651   }
652 }
653
654 /*
655  * Re-key protocol routines
656  */
657
658 /* Actually takes the new keys into use. */
659
660 static void 
661 silc_client_protocol_rekey_validate(SilcClient client,
662                                     SilcClientRekeyInternalContext *ctx,
663                                     SilcSocketConnection sock,
664                                     SilcSKEKeyMaterial *keymat,
665                                     bool send)
666 {
667   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
668
669   if (ctx->responder == TRUE) {
670     if (send) {
671       silc_cipher_set_key(conn->send_key, keymat->receive_enc_key, 
672                           keymat->enc_key_len);
673       silc_cipher_set_iv(conn->send_key, keymat->receive_iv);
674     } else {
675       silc_cipher_set_key(conn->receive_key, keymat->send_enc_key, 
676                           keymat->enc_key_len);
677       silc_cipher_set_iv(conn->receive_key, keymat->send_iv);
678     }
679   } else {
680     if (send) {
681       silc_cipher_set_key(conn->send_key, keymat->send_enc_key, 
682                           keymat->enc_key_len);
683       silc_cipher_set_iv(conn->send_key, keymat->send_iv);
684     } else {
685       silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key, 
686                           keymat->enc_key_len);
687       silc_cipher_set_iv(conn->receive_key, keymat->receive_iv);
688     }
689   }
690
691   if (send) {
692     silc_hmac_alloc(conn->hmac_receive->hmac->name, NULL, &conn->hmac_send);
693     silc_hmac_set_key(conn->hmac_send, keymat->hmac_key, 
694                       keymat->hmac_key_len);
695   } else {
696     silc_hmac_free(conn->hmac_receive);
697     conn->hmac_receive = conn->hmac_send;
698   }
699
700   /* Save the current sending encryption key */
701   if (!send) {
702     memset(conn->rekey->send_enc_key, 0, conn->rekey->enc_key_len);
703     silc_free(conn->rekey->send_enc_key);
704     conn->rekey->send_enc_key = 
705       silc_calloc(keymat->enc_key_len / 8,
706                   sizeof(*conn->rekey->send_enc_key));
707     memcpy(conn->rekey->send_enc_key, keymat->send_enc_key, 
708            keymat->enc_key_len / 8);
709     conn->rekey->enc_key_len = keymat->enc_key_len / 8;
710   }
711 }
712
713 /* This function actually re-generates (when not using PFS) the keys and
714    takes them into use. */
715
716 static void 
717 silc_client_protocol_rekey_generate(SilcClient client,
718                                     SilcClientRekeyInternalContext *ctx,
719                                     bool send)
720 {
721   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
722   SilcSKEKeyMaterial *keymat;
723   uint32 key_len = silc_cipher_get_key_len(conn->send_key);
724   uint32 hash_len = conn->hash->hash->hash_len;
725
726   SILC_LOG_DEBUG(("Generating new %s session keys (no PFS)",
727                   send ? "sending" : "receiving"));
728
729   /* Generate the new key */
730   keymat = silc_calloc(1, sizeof(*keymat));
731   silc_ske_process_key_material_data(conn->rekey->send_enc_key,
732                                      conn->rekey->enc_key_len,
733                                      16, key_len, hash_len, 
734                                      conn->hash, keymat);
735
736   /* Set the keys into use */
737   silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
738
739   silc_ske_free_key_material(keymat);
740 }
741
742 /* This function actually re-generates (with PFS) the keys and
743    takes them into use. */
744
745 static void 
746 silc_client_protocol_rekey_generate_pfs(SilcClient client,
747                                         SilcClientRekeyInternalContext *ctx,
748                                         bool send)
749 {
750   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
751   SilcSKEKeyMaterial *keymat;
752   uint32 key_len = silc_cipher_get_key_len(conn->send_key);
753   uint32 hash_len = conn->hash->hash->hash_len;
754   unsigned char *tmpbuf;
755   uint32 klen;
756
757   SILC_LOG_DEBUG(("Generating new %s session keys (with PFS)",
758                   send ? "sending" : "receiving"));
759
760   /* Encode KEY to binary data */
761   tmpbuf = silc_mp_mp2bin(ctx->ske->KEY, 0, &klen);
762
763   /* Generate the new key */
764   keymat = silc_calloc(1, sizeof(*keymat));
765   silc_ske_process_key_material_data(tmpbuf, klen, 16, key_len, hash_len, 
766                                      conn->hash, keymat);
767
768   /* Set the keys into use */
769   silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
770
771   memset(tmpbuf, 0, klen);
772   silc_free(tmpbuf);
773   silc_ske_free_key_material(keymat);
774 }
775
776 /* Packet sending callback. This function is provided as packet sending
777    routine to the Key Exchange functions. */
778
779 static void 
780 silc_client_protocol_rekey_send_packet(SilcSKE ske,
781                                        SilcBuffer packet,
782                                        SilcPacketType type,
783                                        void *context)
784 {
785   SilcProtocol protocol = (SilcProtocol)context;
786   SilcClientRekeyInternalContext *ctx = 
787     (SilcClientRekeyInternalContext *)protocol->context;
788   SilcClient client = (SilcClient)ctx->client;
789
790   /* Send the packet immediately */
791   silc_client_packet_send(client, ctx->sock, type, NULL, 0, NULL, NULL,
792                           packet->data, packet->len, FALSE);
793 }
794
795 /* Performs re-key as defined in the SILC protocol specification. */
796
797 SILC_TASK_CALLBACK(silc_client_protocol_rekey)
798 {
799   SilcProtocol protocol = (SilcProtocol)context;
800   SilcClientRekeyInternalContext *ctx = 
801     (SilcClientRekeyInternalContext *)protocol->context;
802   SilcClient client = (SilcClient)ctx->client;
803   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
804   SilcSKEStatus status;
805
806   SILC_LOG_DEBUG(("Start"));
807
808   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
809     protocol->state = SILC_PROTOCOL_STATE_START;
810
811   SILC_LOG_DEBUG(("State=%d", protocol->state));
812
813   switch(protocol->state) {
814   case SILC_PROTOCOL_STATE_START:
815     {
816       /* 
817        * Start protocol.
818        */
819
820       if (ctx->responder == TRUE) {
821         /*
822          * We are receiving party
823          */
824
825         if (ctx->pfs == TRUE) {
826           /* 
827            * Use Perfect Forward Secrecy, ie. negotiate the key material
828            * using the SKE protocol.
829            */
830
831           if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
832             /* Error in protocol */
833             protocol->state = SILC_PROTOCOL_STATE_ERROR;
834             protocol->execute(client->timeout_queue, 0, protocol, fd, 
835                               0, 300000);
836           }
837
838           ctx->ske = silc_ske_alloc();
839           ctx->ske->rng = client->rng;
840           ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
841           silc_ske_get_group_by_number(conn->rekey->ske_group,
842                                        &ctx->ske->prop->group);
843
844           status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer,
845                                               NULL, NULL, NULL, NULL);
846           if (status != SILC_SKE_STATUS_OK) {
847             SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
848                               status));
849             
850             protocol->state = SILC_PROTOCOL_STATE_ERROR;
851             protocol->execute(client->timeout_queue, 0, 
852                               protocol, fd, 0, 300000);
853             return;
854           }
855
856           /* Advance the protocol state */
857           protocol->state++;
858           protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
859         } else {
860           /*
861            * Do normal and simple re-key.
862            */
863
864           /* Send the REKEY_DONE to indicate we will take new keys into use */
865           silc_client_packet_send(client, ctx->sock, 
866                                   SILC_PACKET_REKEY_DONE, 
867                                   NULL, 0, NULL, NULL, NULL, 0, FALSE);
868
869           /* After we send REKEY_DONE we must set the sending encryption
870              key to the new key since all packets after this packet must
871              encrypted with the new key. */
872           silc_client_protocol_rekey_generate(client, ctx, TRUE);
873
874           /* The protocol ends in next stage. */
875           protocol->state = SILC_PROTOCOL_STATE_END;
876         }
877       
878       } else {
879         /*
880          * We are the initiator of this protocol
881          */
882
883         /* Start the re-key by sending the REKEY packet */
884         silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY, 
885                                 NULL, 0, NULL, NULL, NULL, 0, FALSE);
886
887         if (ctx->pfs == TRUE) {
888           /* 
889            * Use Perfect Forward Secrecy, ie. negotiate the key material
890            * using the SKE protocol.
891            */
892           ctx->ske = silc_ske_alloc();
893           ctx->ske->rng = client->rng;
894           ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
895           silc_ske_get_group_by_number(conn->rekey->ske_group,
896                                        &ctx->ske->prop->group);
897
898           status = 
899             silc_ske_initiator_phase_2(ctx->ske, NULL, NULL,
900                                        silc_client_protocol_rekey_send_packet,
901                                        context);
902
903           if (status != SILC_SKE_STATUS_OK) {
904             SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
905                               status));
906             
907             protocol->state = SILC_PROTOCOL_STATE_ERROR;
908             protocol->execute(client->timeout_queue, 0, 
909                               protocol, fd, 0, 300000);
910             return;
911           }
912
913           /* Advance the protocol state */
914           protocol->state++;
915         } else {
916           /*
917            * Do normal and simple re-key.
918            */
919
920           /* Send the REKEY_DONE to indicate we will take new keys into use 
921              now. */ 
922           silc_client_packet_send(client, ctx->sock, 
923                                   SILC_PACKET_REKEY_DONE, 
924                                   NULL, 0, NULL, NULL, NULL, 0, FALSE);
925
926           /* After we send REKEY_DONE we must set the sending encryption
927              key to the new key since all packets after this packet must
928              encrypted with the new key. */
929           silc_client_protocol_rekey_generate(client, ctx, TRUE);
930
931           /* The protocol ends in next stage. */
932           protocol->state = SILC_PROTOCOL_STATE_END;
933         }
934       }
935     }
936     break;
937
938   case 2:
939     /*
940      * Second state, used only when oding re-key with PFS.
941      */
942     if (ctx->responder == TRUE) {
943       if (ctx->pfs == TRUE) {
944         /*
945          * Send our KE packe to the initiator now that we've processed
946          * the initiator's KE packet.
947          */
948         status = 
949           silc_ske_responder_finish(ctx->ske, NULL, NULL, 
950                                     SILC_SKE_PK_TYPE_SILC,
951                                     silc_client_protocol_rekey_send_packet,
952                                     context);
953
954           if (status != SILC_SKE_STATUS_OK) {
955             SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
956                               status));
957             
958             protocol->state = SILC_PROTOCOL_STATE_ERROR;
959             protocol->execute(client->timeout_queue, 0, 
960                               protocol, fd, 0, 300000);
961             return;
962           }
963       }
964
965     } else {
966       if (ctx->pfs == TRUE) {
967         /*
968          * The packet type must be KE packet
969          */
970         if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
971           /* Error in protocol */
972           protocol->state = SILC_PROTOCOL_STATE_ERROR;
973           protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 300000);
974         }
975         
976         status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
977                                            NULL, NULL, NULL, NULL);
978         if (status != SILC_SKE_STATUS_OK) {
979           SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
980                             status));
981           
982           protocol->state = SILC_PROTOCOL_STATE_ERROR;
983           protocol->execute(client->timeout_queue, 0, 
984                             protocol, fd, 0, 300000);
985           return;
986         }
987       }
988     }
989
990     /* Send the REKEY_DONE to indicate we will take new keys into use 
991        now. */ 
992     silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE, 
993                             NULL, 0, NULL, NULL, NULL, 0, FALSE);
994     
995     /* After we send REKEY_DONE we must set the sending encryption
996        key to the new key since all packets after this packet must
997        encrypted with the new key. */
998     silc_client_protocol_rekey_generate_pfs(client, ctx, TRUE);
999
1000     /* The protocol ends in next stage. */
1001     protocol->state = SILC_PROTOCOL_STATE_END;
1002     break;
1003
1004   case SILC_PROTOCOL_STATE_END:
1005     /* 
1006      * End protocol
1007      */
1008
1009     if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
1010       /* Error in protocol */
1011       protocol->state = SILC_PROTOCOL_STATE_ERROR;
1012       protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
1013     }
1014
1015     /* We received the REKEY_DONE packet and all packets after this is
1016        encrypted with the new key so set the decryption key to the new key */
1017     silc_client_protocol_rekey_generate(client, ctx, FALSE);
1018
1019     /* Protocol has ended, call the final callback */
1020     if (protocol->final_callback)
1021       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
1022     else
1023       silc_protocol_free(protocol);
1024     break;
1025
1026   case SILC_PROTOCOL_STATE_ERROR:
1027     /*
1028      * Error occured
1029      */
1030
1031     if (ctx->pfs == TRUE) {
1032       /* Send abort notification */
1033       silc_ske_abort(ctx->ske, ctx->ske->status, 
1034                      silc_client_protocol_ke_send_packet,
1035                      context);
1036     }
1037
1038     /* On error the final callback is always called. */
1039     if (protocol->final_callback)
1040       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
1041     else
1042       silc_protocol_free(protocol);
1043     break;
1044
1045   case SILC_PROTOCOL_STATE_FAILURE:
1046     /*
1047      * We have received failure from remote
1048      */
1049
1050     /* On error the final callback is always called. */
1051     if (protocol->final_callback)
1052       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
1053     else
1054       silc_protocol_free(protocol);
1055     break;
1056
1057   case SILC_PROTOCOL_STATE_UNKNOWN:
1058     break;
1059   }
1060
1061 }
1062
1063 /* Registers protocols used in client */
1064
1065 void silc_client_protocols_register(void)
1066 {
1067   silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1068                          silc_client_protocol_connection_auth);
1069   silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1070                          silc_client_protocol_key_exchange);
1071   silc_protocol_register(SILC_PROTOCOL_CLIENT_REKEY,
1072                          silc_client_protocol_rekey);
1073 }
1074
1075 /* Unregisters protocols */
1076
1077 void silc_client_protocols_unregister(void)
1078 {
1079   silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1080                            silc_client_protocol_connection_auth);
1081   silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1082                            silc_client_protocol_key_exchange);
1083   silc_protocol_unregister(SILC_PROTOCOL_CLIENT_REKEY,
1084                            silc_client_protocol_rekey);
1085 }