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