SKE: support for simplified key exchange
[silc.git] / lib / silcske / silcske.c
1 /*
2
3   silcske.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2000 - 2014 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; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "silc.h"
22 #include "silcske.h"
23 #include "groups_internal.h"
24
25 /************************** Types and definitions ***************************/
26
27 /* Structure to hold all SKE callbacks. */
28 struct SilcSKECallbacksStruct {
29   SilcSKEVerifyCb verify_key;
30   SilcSKECompletionCb completed;
31   void *context;
32 };
33
34 /************************ Static utility functions **************************/
35
36 /* States */
37 SILC_FSM_STATE(silc_ske_st_initiator_start);
38 SILC_FSM_STATE(silc_ske_st_initiator_phase1);
39 SILC_FSM_STATE(silc_ske_st_initiator_phase2);
40 SILC_FSM_STATE(silc_ske_st_initiator_phase3);
41 SILC_FSM_STATE(silc_ske_st_initiator_phase4);
42 SILC_FSM_STATE(silc_ske_st_initiator_end);
43 SILC_FSM_STATE(silc_ske_st_initiator_aborted);
44 SILC_FSM_STATE(silc_ske_st_initiator_error);
45 SILC_FSM_STATE(silc_ske_st_initiator_failure);
46 SILC_FSM_STATE(silc_ske_st_responder_start);
47 SILC_FSM_STATE(silc_ske_st_responder_phase1);
48 SILC_FSM_STATE(silc_ske_st_responder_phase2);
49 SILC_FSM_STATE(silc_ske_st_responder_phase4);
50 SILC_FSM_STATE(silc_ske_st_responder_phase5);
51 SILC_FSM_STATE(silc_ske_st_responder_end);
52 SILC_FSM_STATE(silc_ske_st_responder_aborted);
53 SILC_FSM_STATE(silc_ske_st_responder_failure);
54 SILC_FSM_STATE(silc_ske_st_responder_error);
55 SILC_FSM_STATE(silc_ske_st_rekey_initiator_start);
56 SILC_FSM_STATE(silc_ske_st_rekey_initiator_done);
57 SILC_FSM_STATE(silc_ske_st_rekey_initiator_end);
58 SILC_FSM_STATE(silc_ske_st_rekey_responder_wait);
59 SILC_FSM_STATE(silc_ske_st_rekey_responder_start);
60 SILC_FSM_STATE(silc_ske_st_rekey_responder_done);
61 SILC_FSM_STATE(silc_ske_st_rekey_responder_end);
62 SILC_TASK_CALLBACK(silc_ske_packet_send_retry);
63
64 SilcSKEKeyMaterial
65 silc_ske_process_key_material(SilcSKE ske,
66                               SilcUInt32 req_iv_len,
67                               SilcUInt32 req_enc_key_len,
68                               SilcUInt32 req_hmac_key_len,
69                               SilcSKERekeyMaterial *rekey);
70 static SilcBool silc_ske_packet_send(SilcSKE ske,
71                                      SilcPacketType type,
72                                      SilcPacketFlags flags,
73                                      const unsigned char *data,
74                                      SilcUInt32 data_len);
75
76 /*
77  * Notify the owner of the ske that we failed.  Ensures that we don't make the
78  * same callout twice, as the notification callback routines are not designed
79  * to handle that case.
80  */
81 static void silc_ske_notify_failure(SilcSKE ske)
82 {
83   SILC_LOG_DEBUG(("Notifying SKE %p owner of failure (failure_notified = %d)",
84                   ske, ske->failure_notified));
85
86   /*
87    * First, check if we have already made a failure callout.  If so, then we
88    * will stop here.
89    */
90   if (ske->failure_notified)
91     return;
92
93   /*
94    * Mark ourselves as having already sent the failure notification here and
95    * now.
96    */
97   ske->failure_notified = TRUE;
98
99   SILC_LOG_DEBUG(("Deliver failure notification for SKE %p (%s)",
100                   ske, ske->responder ? "responder" : "initiator"));
101
102   /*
103    * Finally, make the call to the owner's registered failure callback.
104    */
105   if (ske->responder)
106     silc_fsm_next(&ske->fsm, silc_ske_st_responder_failure);
107   else
108     silc_fsm_next(&ske->fsm, silc_ske_st_initiator_failure);
109 }
110
111 /* Packet callback */
112
113 static SilcBool silc_ske_packet_receive(SilcPacketEngine engine,
114                                         SilcPacketStream stream,
115                                         SilcPacket packet,
116                                         void *callback_context,
117                                         void *app_context)
118 {
119   SilcSKE ske = callback_context;
120
121   /* Clear retransmission */
122   ske->retry_timer = SILC_SKE_RETRY_MIN;
123   ske->retry_count = 0;
124   silc_schedule_task_del_by_callback(ske->schedule,
125                                      silc_ske_packet_send_retry);
126
127   /* Signal for new packet */
128   ske->packet = packet;
129
130   /* Check if we were aborted */
131   if (ske->aborted) {
132     silc_packet_free(packet);
133     ske->packet = NULL;
134
135     if (ske->responder)
136       silc_fsm_next(&ske->fsm, silc_ske_st_responder_aborted);
137     else
138       silc_fsm_next(&ske->fsm, silc_ske_st_initiator_aborted);
139
140     silc_fsm_continue_sync(&ske->fsm);
141     return TRUE;
142   }
143
144   /* See if received failure from remote */
145   if (packet->type == SILC_PACKET_FAILURE)
146     silc_ske_notify_failure(ske);
147
148   /* Handle rekey and SUCCESS packets synchronously.  After SUCCESS packets
149      they keys are taken into use immediately, hence the synchronous
150      processing to get the keys in use as soon as possible. */
151   if (ske->rekeying || packet->type == SILC_PACKET_SUCCESS)
152     silc_fsm_continue_sync(&ske->fsm);
153   else
154     silc_fsm_continue(&ske->fsm);
155
156   return TRUE;
157 }
158
159 /* Packet stream callbacks */
160 static SilcPacketCallbacks silc_ske_stream_cbs =
161 {
162   silc_ske_packet_receive, NULL, NULL
163 };
164
165 /* Aborts SKE protocol */
166
167 static void silc_ske_abort(SilcAsyncOperation op, void *context)
168 {
169   SilcSKE ske = context;
170   ske->aborted = TRUE;
171 }
172
173 /* Public key verification completion callback */
174
175 static void silc_ske_pk_verified(SilcSKE ske, SilcSKEStatus status,
176                                  void *completion_context)
177 {
178   ske->status = status;
179   SILC_FSM_CALL_CONTINUE(&ske->fsm);
180 }
181
182 /* SKR find callback */
183
184 static void silc_ske_skr_callback(SilcSKR repository,
185                                   SilcSKRFind find,
186                                   SilcSKRStatus status,
187                                   SilcDList keys, void *context)
188 {
189   SilcSKE ske = context;
190
191   silc_skr_find_free(find);
192
193   if (status != SILC_SKR_OK) {
194     if (ske->callbacks->verify_key) {
195       /* Verify from application */
196       ske->callbacks->verify_key(ske, ske->prop->public_key,
197                                  ske->callbacks->context,
198                                  silc_ske_pk_verified, NULL);
199       return;
200     }
201   }
202
203   if (keys)
204     silc_dlist_uninit(keys);
205
206   /* Continue */
207   ske->status = (status == SILC_SKR_OK ? SILC_SKE_STATUS_OK :
208                  SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY);
209   SILC_FSM_CALL_CONTINUE(&ske->fsm);
210 }
211
212 /* Checks remote and local versions */
213
214 static SilcSKEStatus silc_ske_check_version(SilcSKE ske)
215 {
216   if (!ske->remote_version || !ske->version)
217     return SILC_SKE_STATUS_BAD_VERSION;
218
219   if (!silc_parse_version_string(ske->remote_version, NULL, NULL,
220                                  NULL, NULL, NULL))
221     return SILC_SKE_STATUS_BAD_VERSION;
222
223   return SILC_SKE_STATUS_OK;
224 }
225
226 /* Selects the supported security properties from the initiator's Key
227    Exchange Start Payload.  A responder function.  Saves our reply
228    start payload to ske->start_payload. */
229
230 static SilcSKEStatus
231 silc_ske_select_security_properties(SilcSKE ske,
232                                     SilcSKEStartPayload remote_payload,
233                                     SilcSKESecurityProperties *prop)
234 {
235   SilcSKEStatus status;
236   SilcSKEStartPayload rp, payload;
237   char *cp;
238   int len;
239
240   SILC_LOG_DEBUG(("Parsing KE Start Payload"));
241
242   rp = remote_payload;
243   if (!rp)
244     return SILC_SKE_STATUS_BAD_VERSION;
245
246   /* Check for mandatory fields */
247   if (!rp->ke_grp_len) {
248     SILC_LOG_DEBUG(("KE group not defined in payload"));
249     return SILC_SKE_STATUS_BAD_PAYLOAD;
250   }
251   if (!rp->pkcs_alg_len) {
252     SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
253     return SILC_SKE_STATUS_BAD_PAYLOAD;
254   }
255   if (!rp->enc_alg_len) {
256     SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
257     return SILC_SKE_STATUS_BAD_PAYLOAD;
258   }
259   if (!rp->hash_alg_len) {
260     SILC_LOG_DEBUG(("Hash alg not defined in payload"));
261     return SILC_SKE_STATUS_BAD_PAYLOAD;
262   }
263   if (!rp->hmac_alg_len) {
264     SILC_LOG_DEBUG(("HMAC not defined in payload"));
265     return SILC_SKE_STATUS_BAD_PAYLOAD;
266   }
267
268   /* Allocate security properties */
269   *prop = silc_calloc(1, sizeof(**prop));
270   if (!(*prop))
271     return SILC_SKE_STATUS_OUT_OF_MEMORY;
272
273   /* Allocate our reply start payload */
274   payload = silc_calloc(1, sizeof(*payload));
275   if (!payload) {
276     silc_free(*prop);
277     return SILC_SKE_STATUS_OUT_OF_MEMORY;
278   }
279
280   /* Check version string */
281   ske->remote_version = silc_memdup(rp->version, rp->version_len);
282   status = silc_ske_check_version(ske);
283   if (status != SILC_SKE_STATUS_OK) {
284     ske->status = status;
285     return status;
286   }
287
288   /* Flags are returned unchanged. */
289   (*prop)->flags = payload->flags = rp->flags;
290
291   /* Take cookie, we must return it to sender unmodified. */
292   payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
293   if (!payload->cookie) {
294     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
295     return status;
296   }
297   payload->cookie_len = SILC_SKE_COOKIE_LEN;
298   memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
299
300   /* In case IV included flag and session port is set the first 16-bits of
301      cookie will include our session port. */
302   if (rp->flags & SILC_SKE_SP_FLAG_IV_INCLUDED && ske->session_port) {
303     /* Take remote port */
304     SILC_GET16_MSB((*prop)->remote_port, payload->cookie);
305
306     /* Put out port */
307     SILC_PUT16_MSB(ske->session_port, payload->cookie);
308   }
309
310   /* Put our version to our reply */
311   payload->version = strdup(ske->version);
312   if (!payload->version) {
313     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
314     return status;
315   }
316   payload->version_len = strlen(ske->version);
317
318   /* Get supported Key Exchange groups */
319   cp = rp->ke_grp_list;
320   if (cp && strchr(cp, ',')) {
321     while(cp) {
322       char *item;
323
324       len = strcspn(cp, ",");
325       item = silc_calloc(len + 1, sizeof(char));
326       if (!item) {
327         ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
328         return status;
329       }
330       memcpy(item, cp, len);
331
332       SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
333
334       if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
335         SILC_LOG_DEBUG(("Found KE group `%s'", item));
336
337         payload->ke_grp_len = len;
338         payload->ke_grp_list = item;
339         break;
340       }
341
342       cp += len;
343       if (strlen(cp) == 0)
344         cp = NULL;
345       else
346         cp++;
347
348       if (item)
349         silc_free(item);
350     }
351
352     if (!payload->ke_grp_len && !payload->ke_grp_list) {
353       SILC_LOG_DEBUG(("Could not find supported KE group"));
354       silc_free(payload);
355       return SILC_SKE_STATUS_UNKNOWN_GROUP;
356     }
357   } else {
358     SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
359     SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
360
361     payload->ke_grp_len = rp->ke_grp_len;
362     payload->ke_grp_list = strdup(rp->ke_grp_list);
363   }
364
365   /* Save group to security properties */
366   status = silc_ske_group_get_by_name(payload->ke_grp_list, &(*prop)->group);
367   if (status != SILC_SKE_STATUS_OK) {
368     silc_free(payload);
369     return SILC_SKE_STATUS_UNKNOWN_GROUP;
370   }
371
372   /* Get supported PKCS algorithms */
373   cp = rp->pkcs_alg_list;
374   if (cp && strchr(cp, ',')) {
375     while(cp) {
376       char *item;
377
378       len = strcspn(cp, ",");
379       item = silc_calloc(len + 1, sizeof(char));
380       if (!item) {
381         ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
382         return status;
383       }
384       memcpy(item, cp, len);
385
386       SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
387
388       if (silc_pkcs_find_algorithm(item, NULL)) {
389         SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
390
391         payload->pkcs_alg_len = len;
392         payload->pkcs_alg_list = item;
393         break;
394       }
395
396       cp += len;
397       if (strlen(cp) == 0)
398         cp = NULL;
399       else
400         cp++;
401
402       if (item)
403         silc_free(item);
404     }
405
406     if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
407       SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
408       silc_free(payload->ke_grp_list);
409       silc_free(payload);
410       return SILC_SKE_STATUS_UNKNOWN_PKCS;
411     }
412   } else {
413     SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
414     SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
415
416     payload->pkcs_alg_len = rp->pkcs_alg_len;
417     payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
418   }
419
420   /* Get supported encryption algorithms */
421   cp = rp->enc_alg_list;
422   if (cp && strchr(cp, ',')) {
423     while(cp) {
424       char *item;
425
426       len = strcspn(cp, ",");
427       item = silc_calloc(len + 1, sizeof(char));
428       if (!item) {
429         ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
430         return status;
431       }
432       memcpy(item, cp, len);
433
434       SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
435
436       if (silc_cipher_is_supported(item) == TRUE) {
437         SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
438
439         payload->enc_alg_len = len;
440         payload->enc_alg_list = item;
441         break;
442       }
443
444       cp += len;
445       if (strlen(cp) == 0)
446         cp = NULL;
447       else
448         cp++;
449
450       if (item)
451         silc_free(item);
452     }
453
454     if (!payload->enc_alg_len && !payload->enc_alg_list) {
455       SILC_LOG_DEBUG(("Could not find supported encryption alg"));
456       silc_free(payload->ke_grp_list);
457       silc_free(payload->pkcs_alg_list);
458       silc_free(payload);
459       return SILC_SKE_STATUS_UNKNOWN_CIPHER;
460     }
461   } else {
462     SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
463                     rp->enc_alg_list));
464
465     payload->enc_alg_len = rp->enc_alg_len;
466     payload->enc_alg_list = strdup(rp->enc_alg_list);
467   }
468
469   /* Save selected cipher to security properties */
470   if (silc_cipher_alloc(payload->enc_alg_list, &(*prop)->cipher) == FALSE) {
471     silc_free(payload->ke_grp_list);
472     silc_free(payload->pkcs_alg_list);
473     silc_free(payload);
474     return SILC_SKE_STATUS_UNKNOWN_CIPHER;
475   }
476
477   /* Get supported hash algorithms */
478   cp = rp->hash_alg_list;
479   if (cp && strchr(cp, ',')) {
480     while(cp) {
481       char *item;
482
483       len = strcspn(cp, ",");
484       item = silc_calloc(len + 1, sizeof(char));
485       if (!item) {
486         ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
487         return status;
488       }
489       memcpy(item, cp, len);
490
491       SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
492
493       if (silc_hash_is_supported(item) == TRUE) {
494         SILC_LOG_DEBUG(("Found hash alg `%s'", item));
495
496         payload->hash_alg_len = len;
497         payload->hash_alg_list = item;
498         break;
499       }
500
501       cp += len;
502       if (strlen(cp) == 0)
503         cp = NULL;
504       else
505         cp++;
506
507       if (item)
508         silc_free(item);
509     }
510
511     if (!payload->hash_alg_len && !payload->hash_alg_list) {
512       SILC_LOG_DEBUG(("Could not find supported hash alg"));
513       silc_free(payload->ke_grp_list);
514       silc_free(payload->pkcs_alg_list);
515       silc_free(payload->enc_alg_list);
516       silc_free(payload);
517       return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
518     }
519   } else {
520     SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
521                     rp->hash_alg_list));
522
523     payload->hash_alg_len = rp->hash_alg_len;
524     payload->hash_alg_list = strdup(rp->hash_alg_list);
525   }
526
527   /* Save selected hash algorithm to security properties */
528   if (silc_hash_alloc(payload->hash_alg_list, &(*prop)->hash) == FALSE) {
529     silc_free(payload->ke_grp_list);
530     silc_free(payload->pkcs_alg_list);
531     silc_free(payload->enc_alg_list);
532     silc_free(payload);
533     return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
534   }
535
536   /* Get supported HMACs */
537   cp = rp->hmac_alg_list;
538   if (cp && strchr(cp, ',')) {
539     while(cp) {
540       char *item;
541
542       len = strcspn(cp, ",");
543       item = silc_calloc(len + 1, sizeof(char));
544       if (!item) {
545         ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
546         return status;
547       }
548       memcpy(item, cp, len);
549
550       SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
551
552       if (silc_hmac_is_supported(item) == TRUE) {
553         SILC_LOG_DEBUG(("Found HMAC `%s'", item));
554
555         payload->hmac_alg_len = len;
556         payload->hmac_alg_list = item;
557         break;
558       }
559
560       cp += len;
561       if (strlen(cp) == 0)
562         cp = NULL;
563       else
564         cp++;
565
566       if (item)
567         silc_free(item);
568     }
569
570     if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
571       SILC_LOG_DEBUG(("Could not find supported HMAC"));
572       silc_free(payload->ke_grp_list);
573       silc_free(payload->pkcs_alg_list);
574       silc_free(payload->enc_alg_list);
575       silc_free(payload->hash_alg_list);
576       silc_free(payload);
577       return SILC_SKE_STATUS_UNKNOWN_HMAC;
578     }
579   } else {
580     SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
581                     rp->hmac_alg_list));
582
583     payload->hmac_alg_len = rp->hmac_alg_len;
584     payload->hmac_alg_list = strdup(rp->hmac_alg_list);
585   }
586
587   /* Save selected HMACc to security properties */
588   if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &(*prop)->hmac) == FALSE) {
589     silc_free(payload->ke_grp_list);
590     silc_free(payload->pkcs_alg_list);
591     silc_free(payload->enc_alg_list);
592     silc_free(payload->hash_alg_list);
593     silc_free(payload);
594     return SILC_SKE_STATUS_UNKNOWN_HMAC;
595   }
596
597   /* Get supported compression algorithms */
598   cp = rp->comp_alg_list;
599   if (cp && strchr(cp, ',')) {
600     while(cp) {
601       char *item;
602
603       len = strcspn(cp, ",");
604       item = silc_calloc(len + 1, sizeof(char));
605       if (!item) {
606         ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
607         return status;
608       }
609       memcpy(item, cp, len);
610
611       SILC_LOG_DEBUG(("Proposed Compression `%s'", item));
612
613 #if 1
614       if (!strcmp(item, "none")) {
615         SILC_LOG_DEBUG(("Found Compression `%s'", item));
616         payload->comp_alg_len = len;
617         payload->comp_alg_list = item;
618         break;
619       }
620 #else
621       if (silc_hmac_is_supported(item) == TRUE) {
622         SILC_LOG_DEBUG(("Found Compression `%s'", item));
623         payload->comp_alg_len = len;
624         payload->comp_alg_list = item;
625         break;
626       }
627 #endif
628
629       cp += len;
630       if (strlen(cp) == 0)
631         cp = NULL;
632       else
633         cp++;
634
635       if (item)
636         silc_free(item);
637     }
638   }
639
640   payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
641     2 + payload->version_len +
642     2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
643     2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
644     2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
645
646   /* Save our reply payload */
647   ske->start_payload = payload;
648
649   return SILC_SKE_STATUS_OK;
650 }
651
652 /* Creates random number such that 1 < rnd < n and at most length
653    of len bits. The rnd sent as argument must be initialized. */
654
655 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
656                                          SilcUInt32 len,
657                                          SilcMPInt *rnd)
658 {
659   SilcSKEStatus status = SILC_SKE_STATUS_OK;
660   unsigned char *string;
661   SilcUInt32 l;
662
663   if (!len)
664     return SILC_SKE_STATUS_ERROR;
665
666   SILC_LOG_DEBUG(("Creating random number"));
667
668   l = ((len - 1) / 8);
669
670   /* Get the random number as string */
671   string = silc_rng_get_rn_data(ske->rng, l);
672   if (!string)
673     return SILC_SKE_STATUS_OUT_OF_MEMORY;
674
675   /* Decode the string into a MP integer */
676   silc_mp_bin2mp(string, l, rnd);
677   silc_mp_mod_2exp(rnd, rnd, len);
678
679   /* Checks */
680   if (silc_mp_cmp_ui(rnd, 1) < 0)
681     status = SILC_SKE_STATUS_ERROR;
682   if (silc_mp_cmp(rnd, n) >= 0)
683     status = SILC_SKE_STATUS_ERROR;
684
685   memset(string, 'F', l);
686   silc_free(string);
687
688   return status;
689 }
690
691 /* Creates a hash value HASH as defined in the SKE protocol. If the
692    `initiator' is TRUE then this function is used to create the HASH_i
693    hash value defined in the protocol. If it is FALSE then this is used
694    to create the HASH value defined by the protocol. */
695
696 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
697                                         unsigned char *return_hash,
698                                         SilcUInt32 *return_hash_len,
699                                         int initiator)
700 {
701   SilcSKEStatus status = SILC_SKE_STATUS_OK;
702   SilcBuffer buf;
703   unsigned char *e, *f, *KEY, *s_data;
704   SilcUInt32 e_len, f_len, KEY_len, s_len;
705   int ret;
706
707   SILC_LOG_DEBUG(("Start"));
708
709   if (initiator == FALSE) {
710     s_data = (ske->start_payload_copy ?
711              silc_buffer_data(ske->start_payload_copy) : NULL);
712     s_len = (ske->start_payload_copy ?
713              silc_buffer_len(ske->start_payload_copy) : 0);
714     e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
715     if (!e)
716       return SILC_SKE_STATUS_OUT_OF_MEMORY;
717     f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
718     if (!f)
719       return SILC_SKE_STATUS_OUT_OF_MEMORY;
720     KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
721     if (!KEY)
722       return SILC_SKE_STATUS_OUT_OF_MEMORY;
723
724     /* Format the buffer used to compute the hash value */
725     buf = silc_buffer_alloc_size(s_len +
726                                  ske->ke2_payload->pk_len +
727                                  ske->ke1_payload->pk_len +
728                                  e_len + f_len + KEY_len);
729     if (!buf)
730       return SILC_SKE_STATUS_OUT_OF_MEMORY;
731
732     /* Initiator is not required to send its public key */
733     if (!ske->ke1_payload->pk_data) {
734       ret =
735         silc_buffer_format(buf,
736                            SILC_STR_DATA(s_data, s_len),
737                            SILC_STR_DATA(ske->ke2_payload->pk_data,
738                                          ske->ke2_payload->pk_len),
739                            SILC_STR_DATA(e, e_len),
740                            SILC_STR_DATA(f, f_len),
741                            SILC_STR_DATA(KEY, KEY_len),
742                            SILC_STR_END);
743     } else {
744       ret =
745         silc_buffer_format(buf,
746                            SILC_STR_DATA(s_data, s_len),
747                            SILC_STR_DATA(ske->ke2_payload->pk_data,
748                                          ske->ke2_payload->pk_len),
749                            SILC_STR_DATA(ske->ke1_payload->pk_data,
750                                          ske->ke1_payload->pk_len),
751                            SILC_STR_DATA(e, e_len),
752                            SILC_STR_DATA(f, f_len),
753                            SILC_STR_DATA(KEY, KEY_len),
754                            SILC_STR_END);
755     }
756     if (ret == -1) {
757       silc_buffer_free(buf);
758       memset(e, 0, e_len);
759       memset(f, 0, f_len);
760       memset(KEY, 0, KEY_len);
761       silc_free(e);
762       silc_free(f);
763       silc_free(KEY);
764       return SILC_SKE_STATUS_ERROR;
765     }
766
767     memset(e, 0, e_len);
768     memset(f, 0, f_len);
769     memset(KEY, 0, KEY_len);
770     silc_free(e);
771     silc_free(f);
772     silc_free(KEY);
773   } else {
774     s_data = (ske->start_payload_copy ?
775              silc_buffer_data(ske->start_payload_copy) : NULL);
776     s_len = (ske->start_payload_copy ?
777              silc_buffer_len(ske->start_payload_copy) : 0);
778     e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
779     if (!e)
780       return SILC_SKE_STATUS_OUT_OF_MEMORY;
781
782     buf = silc_buffer_alloc_size(s_len + ske->ke1_payload->pk_len + e_len);
783     if (!buf)
784       return SILC_SKE_STATUS_OUT_OF_MEMORY;
785
786     /* Format the buffer used to compute the hash value */
787     ret =
788       silc_buffer_format(buf,
789                          SILC_STR_DATA(s_data, s_len),
790                          SILC_STR_DATA(ske->ke1_payload->pk_data,
791                                        ske->ke1_payload->pk_len),
792                          SILC_STR_DATA(e, e_len),
793                          SILC_STR_END);
794     if (ret == -1) {
795       silc_buffer_free(buf);
796       memset(e, 0, e_len);
797       silc_free(e);
798       return SILC_SKE_STATUS_ERROR;
799     }
800
801     SILC_LOG_HEXDUMP(("hash buf"), buf->data, silc_buffer_len(buf));
802
803     memset(e, 0, e_len);
804     silc_free(e);
805   }
806
807   /* Make the hash */
808   silc_hash_make(ske->prop->hash, buf->data, silc_buffer_len(buf),
809                  return_hash);
810   *return_hash_len = silc_hash_len(ske->prop->hash);
811
812   if (initiator == FALSE) {
813     SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
814   } else {
815     SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
816   }
817
818   silc_buffer_free(buf);
819
820   return status;
821 }
822
823 /* Generate rekey material */
824
825 static SilcSKERekeyMaterial
826 silc_ske_make_rekey_material(SilcSKE ske, SilcSKEKeyMaterial keymat)
827 {
828   SilcSKERekeyMaterial rekey;
829   const char *hash;
830
831   if (!keymat)
832     return NULL;
833
834   /* Create rekey material */
835   rekey = silc_calloc(1, sizeof(*rekey));
836   if (!rekey)
837     return NULL;
838
839   if (ske->prop) {
840     if (ske->prop->group)
841       rekey->ske_group = silc_ske_group_get_number(ske->prop->group);
842     rekey->pfs = (ske->prop->flags & SILC_SKE_SP_FLAG_PFS ? TRUE : FALSE);
843     hash = silc_hash_get_name(ske->prop->hash);
844     rekey->hash = silc_memdup(hash, strlen(hash));
845     if (!rekey->hash)
846       return NULL;
847   }
848
849   if (rekey->pfs == FALSE) {
850     rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
851                                       keymat->enc_key_len / 8);
852     if (!rekey->send_enc_key) {
853       silc_free(rekey);
854       return NULL;
855     }
856     rekey->enc_key_len = keymat->enc_key_len;
857   }
858
859   return rekey;
860 }
861
862 /* Assembles security properties */
863
864 static SilcSKEStartPayload
865 silc_ske_assemble_security_properties(SilcSKE ske,
866                                       SilcSKESecurityPropertyFlag flags,
867                                       const char *version,
868                                       SilcBool small_proposal)
869 {
870   SilcSKEStartPayload rp;
871   int i;
872
873   SILC_LOG_DEBUG(("Assembling KE Start Payload"));
874
875   rp = silc_calloc(1, sizeof(*rp));
876   if (!rp)
877     return NULL;
878
879   /* Set flags */
880   rp->flags = (unsigned char)flags;
881
882   /* Set random cookie */
883   rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
884   if (!rp->cookie) {
885     silc_free(rp);
886     return NULL;
887   }
888   for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
889     rp->cookie[i] = silc_rng_get_byte_fast(ske->rng);
890   rp->cookie_len = SILC_SKE_COOKIE_LEN;
891
892   /* In case IV included flag and session port is set the first 16-bits of
893      cookie will include our session port. */
894   if (flags & SILC_SKE_SP_FLAG_IV_INCLUDED && ske->session_port)
895     SILC_PUT16_MSB(ske->session_port, rp->cookie);
896
897   /* Put version */
898   rp->version = strdup(version);
899   if (rp->version)
900     rp->version_len = strlen(version);
901
902   /* Get supported Key Exhange groups */
903   rp->ke_grp_list = silc_ske_get_supported_groups(small_proposal);
904   if (rp->ke_grp_list)
905     rp->ke_grp_len = strlen(rp->ke_grp_list);
906
907   /* Get supported PKCS algorithms */
908   if (small_proposal)
909     rp->pkcs_alg_list = strdup(silc_default_pkcs_alg[0].name);
910   else
911     rp->pkcs_alg_list = silc_pkcs_get_supported();
912   if (rp->pkcs_alg_list)
913     rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
914
915   /* Get supported encryption algorithms */
916   if (small_proposal)
917     rp->enc_alg_list = strdup(silc_default_ciphers[0].name);
918   else
919     rp->enc_alg_list = silc_cipher_get_supported();
920   if (rp->enc_alg_list)
921     rp->enc_alg_len = strlen(rp->enc_alg_list);
922
923   /* Get supported hash algorithms */
924   if (small_proposal)
925     rp->hash_alg_list = strdup(silc_default_hash[0].name);
926   else
927     rp->hash_alg_list = silc_hash_get_supported();
928   if (rp->hash_alg_list)
929     rp->hash_alg_len = strlen(rp->hash_alg_list);
930
931   /* Get supported HMACs */
932   if (small_proposal)
933     rp->hmac_alg_list = strdup(silc_default_hmacs[0].name);
934   else
935     rp->hmac_alg_list = silc_hmac_get_supported();
936   if (rp->hmac_alg_list)
937     rp->hmac_alg_len = strlen(rp->hmac_alg_list);
938
939   if (!small_proposal) {
940     /* XXX */
941     /* Get supported compression algorithms */
942     rp->comp_alg_list = strdup("none");
943     rp->comp_alg_len = strlen("none");
944   }
945
946   rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
947     2 + rp->version_len +
948     2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
949     2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
950     2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
951
952   return rp;
953 }
954
955 /* Packet retransmission callback. */
956
957 SILC_TASK_CALLBACK(silc_ske_packet_send_retry)
958 {
959   SilcSKE ske = context;
960
961   if (ske->retry_count++ >= SILC_SKE_RETRY_COUNT ||
962       ske->aborted) {
963     SILC_LOG_DEBUG(("Retransmission limit reached, packet was lost"));
964     ske->retry_count = 0;
965     ske->retry_timer = SILC_SKE_RETRY_MIN;
966     silc_free(ske->retrans.data);
967     ske->retrans.data = NULL;
968     ske->status = SILC_SKE_STATUS_TIMEOUT;
969     silc_ske_notify_failure(ske);
970     silc_fsm_continue_sync(&ske->fsm);
971     return;
972   }
973
974   SILC_LOG_DEBUG(("Retransmitting packet"));
975   silc_ske_packet_send(ske, ske->retrans.type, ske->retrans.flags,
976                        ske->retrans.data, ske->retrans.data_len);
977 }
978
979 /* Install retransmission timer */
980
981 static void silc_ske_install_retransmission(SilcSKE ske)
982 {
983   if (!silc_packet_stream_is_udp(ske->stream))
984     return;
985
986   if (ske->retrans.data) {
987     SILC_LOG_DEBUG(("Installing retransmission timer %d secs",
988                     ske->retry_timer));
989     silc_schedule_task_add_timeout(ske->schedule, silc_ske_packet_send_retry,
990                                    ske, ske->retry_timer, 0);
991   }
992   ske->retry_timer = ((ske->retry_timer * SILC_SKE_RETRY_MUL) +
993                       (silc_rng_get_rn16(ske->rng) % SILC_SKE_RETRY_RAND));
994 }
995
996 /* Sends SILC packet.  Handles retransmissions with UDP streams. */
997
998 static SilcBool silc_ske_packet_send(SilcSKE ske,
999                                      SilcPacketType type,
1000                                      SilcPacketFlags flags,
1001                                      const unsigned char *data,
1002                                      SilcUInt32 data_len)
1003 {
1004   SilcBool ret;
1005
1006   /* Send the packet */
1007   ret = silc_packet_send(ske->stream, type, flags, data, data_len);
1008
1009   if (silc_packet_stream_is_udp(ske->stream) &&
1010       type != SILC_PACKET_FAILURE && type != SILC_PACKET_REKEY) {
1011     silc_free(ske->retrans.data);
1012     ske->retrans.type = type;
1013     ske->retrans.flags = flags;
1014     ske->retrans.data = silc_memdup(data, data_len);
1015     if (ske->retrans.data) {
1016       ske->retrans.data_len = data_len;
1017       silc_ske_install_retransmission(ske);
1018     }
1019   }
1020
1021   return ret;
1022 }
1023
1024 /* Calls completion callback.  Completion is called always in this function
1025    and must not be called anywhere else. */
1026
1027 static void silc_ske_completion(SilcSKE ske)
1028 {
1029   /* Call the completion callback */
1030   if (!ske->aborted && ske->callbacks->completed) {
1031     if (ske->status != SILC_SKE_STATUS_OK)
1032       ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL,
1033                                 ske->callbacks->context);
1034     else
1035       ske->callbacks->completed(ske, ske->status, ske->prop, ske->keymat,
1036                                 ske->rekey, ske->callbacks->context);
1037   }
1038 }
1039
1040 /* SKE FSM destructor. */
1041
1042 static void silc_ske_finished(SilcFSM fsm, void *fsm_context,
1043                               void *destructor_context)
1044 {
1045   SilcSKE ske = fsm_context;
1046   silc_ske_free(ske);
1047 }
1048
1049 /* Key exchange timeout task callback */
1050
1051 SILC_TASK_CALLBACK(silc_ske_timeout)
1052 {
1053   SilcSKE ske = context;
1054
1055   SILC_LOG_DEBUG(("Timeout"));
1056
1057   ske->packet = NULL;
1058   ske->status = SILC_SKE_STATUS_TIMEOUT;
1059   silc_ske_notify_failure(ske);
1060
1061   silc_fsm_continue_sync(&ske->fsm);
1062 }
1063
1064 /* Key exchange timeout task callback */
1065
1066 SILC_TASK_CALLBACK(silc_ske_probe_timeout)
1067 {
1068   SilcSKE ske = context;
1069
1070   SILC_LOG_DEBUG(("Probe timeout"));
1071
1072   ske->packet = NULL;
1073   ske->status = SILC_SKE_STATUS_PROBE_TIMEOUT;
1074   silc_ske_notify_failure(ske);
1075
1076   silc_fsm_continue_sync(&ske->fsm);
1077 }
1078
1079 /******************************* Protocol API *******************************/
1080
1081 /* Allocates new SKE object. */
1082
1083 SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule,
1084                        SilcSKR repository, SilcPublicKey public_key,
1085                        SilcPrivateKey private_key, void *context)
1086 {
1087   SilcSKE ske;
1088
1089   SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
1090
1091   if (!rng || !schedule)
1092     return NULL;
1093
1094   if (!public_key) {
1095     SILC_LOG_ERROR(("Public key must be given to silc_ske_alloc"));
1096     return NULL;
1097   }
1098
1099   ske = silc_calloc(1, sizeof(*ske));
1100   if (!ske)
1101     return NULL;
1102   ske->status = SILC_SKE_STATUS_OK;
1103   ske->rng = rng;
1104   ske->repository = repository;
1105   ske->user_data = context;
1106   ske->schedule = schedule;
1107   ske->public_key = public_key;
1108   ske->private_key = private_key;
1109   ske->retry_timer = SILC_SKE_RETRY_MIN;
1110   ske->refcnt = 1;
1111
1112   return ske;
1113 }
1114
1115 /* Free's SKE object. */
1116
1117 void silc_ske_free(SilcSKE ske)
1118 {
1119   if (!ske)
1120     return;
1121
1122   SILC_LOG_DEBUG(("Freeing Key Exchange object %p: aborted=%u refcount=%hu",
1123                   ske, ske->aborted, ske->refcnt));
1124
1125   if (ske->aborted) {
1126     /*
1127      * If already aborted, destroy the session immediately.  Only do the
1128      * notification work if we have not already though, as doing so twice
1129      * results in memory corruption.  We may have silc_ske_free called
1130      * twice, once when the abort is requested, and then again when the
1131      * FSM finish routine is called.  We have to be prepared to handle
1132      * that case.
1133      */
1134     ske->packet = NULL;
1135     ske->status = SILC_SKE_STATUS_ERROR;
1136
1137     silc_ske_notify_failure(ske);
1138
1139     if (silc_fsm_is_started(&ske->fsm))
1140       silc_fsm_continue_sync(&ske->fsm);
1141     else
1142       SILC_LOG_DEBUG(("Not continuing FSM as it's finished for SKE %p", ske));
1143   }
1144
1145   ske->refcnt--;
1146   if (ske->refcnt > 0)
1147     return;
1148
1149   /* Free start payload */
1150   if (ske->start_payload)
1151     silc_ske_payload_start_free(ske->start_payload);
1152
1153   /* Free KE payload */
1154   if (ske->ke1_payload)
1155     silc_ske_payload_ke_free(ske->ke1_payload);
1156   if (ske->ke2_payload)
1157     silc_ske_payload_ke_free(ske->ke2_payload);
1158   silc_free(ske->remote_version);
1159
1160   /* Free rest */
1161   if (ske->prop) {
1162     if (ske->prop->group)
1163       silc_ske_group_free(ske->prop->group);
1164     if (ske->prop->cipher)
1165       silc_cipher_free(ske->prop->cipher);
1166     if (ske->prop->hash)
1167       silc_hash_free(ske->prop->hash);
1168     if (ske->prop->hmac)
1169       silc_hmac_free(ske->prop->hmac);
1170     if (ske->prop->public_key)
1171       silc_pkcs_public_key_free(ske->prop->public_key);
1172     silc_free(ske->prop);
1173   }
1174   if (ske->keymat)
1175     silc_ske_free_key_material(ske->keymat);
1176   if (ske->start_payload_copy)
1177     silc_buffer_free(ske->start_payload_copy);
1178   if (ske->x) {
1179     silc_mp_uninit(ske->x);
1180     silc_free(ske->x);
1181   }
1182   if (ske->KEY) {
1183     silc_mp_uninit(ske->KEY);
1184     silc_free(ske->KEY);
1185   }
1186   silc_free(ske->retrans.data);
1187   silc_free(ske->hash);
1188   silc_free(ske->callbacks);
1189
1190   memset(ske, 0xdd, sizeof(*ske));
1191   silc_free(ske);
1192 }
1193
1194 /* Return user context */
1195
1196 void *silc_ske_get_context(SilcSKE ske)
1197 {
1198   return ske->user_data;
1199 }
1200
1201 /* Sets protocol callbacks */
1202
1203 void silc_ske_set_callbacks(SilcSKE ske,
1204                             SilcSKEVerifyCb verify_key,
1205                             SilcSKECompletionCb completed,
1206                             void *context)
1207 {
1208   if (ske->callbacks)
1209     silc_free(ske->callbacks);
1210   ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
1211   if (!ske->callbacks)
1212     return;
1213   ske->callbacks->verify_key = verify_key;
1214   ske->callbacks->completed = completed;
1215   ske->callbacks->context = context;
1216 }
1217
1218
1219 /******************************** Initiator *********************************/
1220
1221 /* Start protocol.  Send our proposal */
1222
1223 SILC_FSM_STATE(silc_ske_st_initiator_start)
1224 {
1225   SilcSKE ske = fsm_context;
1226   SilcBuffer payload_buf;
1227   SilcStatus status;
1228
1229   SILC_LOG_DEBUG(("Start"));
1230
1231   if (ske->aborted) {
1232     /** Aborted */
1233     silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
1234     return SILC_FSM_CONTINUE;
1235   }
1236
1237   /* Encode the payload */
1238   status = silc_ske_payload_start_encode(ske, ske->start_payload,
1239                                          &payload_buf);
1240   if (status != SILC_SKE_STATUS_OK) {
1241     /** Error encoding Start Payload */
1242     ske->status = status;
1243     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1244     return SILC_FSM_CONTINUE;
1245   }
1246
1247   /* Save the the payload buffer for future use. It is later used to
1248      compute the HASH value. */
1249   ske->start_payload_copy = payload_buf;
1250
1251   /* Send the packet. */
1252   if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE, 0,
1253                             silc_buffer_data(payload_buf),
1254                             silc_buffer_len(payload_buf))) {
1255     /** Error sending packet */
1256     SILC_LOG_DEBUG(("Error sending packet"));
1257     ske->status = SILC_SKE_STATUS_ERROR;
1258     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1259     return SILC_FSM_CONTINUE;
1260   }
1261
1262   /** Wait for responder proposal */
1263   SILC_LOG_DEBUG(("Waiting for responder proposal"));
1264   silc_fsm_next(fsm, silc_ske_st_initiator_phase1);
1265   return SILC_FSM_WAIT;
1266 }
1267
1268 /* Phase-1.  Receives responder's proposal */
1269
1270 SILC_FSM_STATE(silc_ske_st_initiator_phase1)
1271 {
1272   SilcSKE ske = fsm_context;
1273   SilcSKEStatus status;
1274   SilcSKEStartPayload payload;
1275   SilcSKESecurityProperties prop;
1276   SilcSKEDiffieHellmanGroup group = NULL;
1277   SilcBuffer packet_buf = &ske->packet->buffer;
1278   SilcUInt16 remote_port = 0;
1279   SilcID id;
1280   int coff = 0;
1281
1282   SILC_LOG_DEBUG(("Start"));
1283
1284   if (ske->packet->type != SILC_PACKET_KEY_EXCHANGE) {
1285     SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
1286     silc_ske_install_retransmission(ske);
1287     silc_packet_free(ske->packet);
1288     ske->packet = NULL;
1289     return SILC_FSM_WAIT;
1290   }
1291
1292   silc_schedule_task_del_by_all(ske->schedule, 0, silc_ske_probe_timeout, ske);
1293
1294   /* Decode the payload */
1295   status = silc_ske_payload_start_decode(ske, packet_buf, &payload);
1296   if (status != SILC_SKE_STATUS_OK) {
1297     /** Error decoding Start Payload */
1298     silc_packet_free(ske->packet);
1299     ske->packet = NULL;
1300     ske->status = status;
1301     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1302     return SILC_FSM_CONTINUE;
1303   }
1304
1305   /* Get remote ID and set it to stream */
1306   if (ske->packet->src_id_len &&
1307       (ske->packet->src_id_type == SILC_ID_SERVER ||
1308        ske->packet->src_id_type == SILC_ID_CLIENT)) {
1309     silc_id_str2id(ske->packet->src_id, ske->packet->src_id_len,
1310                    ske->packet->src_id_type,
1311                    (ske->packet->src_id_type == SILC_ID_SERVER ?
1312                     (void *)&id.u.server_id : (void *)&id.u.client_id),
1313                    (ske->packet->src_id_type == SILC_ID_SERVER ?
1314                     sizeof(id.u.server_id) : sizeof(id.u.client_id)));
1315     silc_packet_set_ids(ske->stream, 0, NULL, ske->packet->src_id_type,
1316                         (ske->packet->src_id_type == SILC_ID_SERVER ?
1317                          (void *)&id.u.server_id : (void *)&id.u.client_id));
1318   }
1319
1320   silc_packet_free(ske->packet);
1321   ske->packet = NULL;
1322
1323   /* Check that the cookie is returned unmodified.  In case IV included
1324      flag and session port has been set, the first two bytes of cookie
1325      are the session port and we ignore them in this check. */
1326   if (payload->flags & SILC_SKE_SP_FLAG_IV_INCLUDED && ske->session_port) {
1327     /* Take remote port */
1328     SILC_GET16_MSB(remote_port, ske->start_payload->cookie);
1329     coff = 2;
1330   }
1331   if (memcmp(ske->start_payload->cookie + coff, payload->cookie + coff,
1332              SILC_SKE_COOKIE_LEN - coff)) {
1333     /** Invalid cookie */
1334     SILC_LOG_ERROR(("Invalid cookie, modified or unsupported feature"));
1335     ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
1336     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1337     return SILC_FSM_CONTINUE;
1338   }
1339
1340   /* Check version string */
1341   ske->remote_version = silc_memdup(payload->version, payload->version_len);
1342   status = silc_ske_check_version(ske);
1343   if (status != SILC_SKE_STATUS_OK) {
1344     /** Version mismatch */
1345     ske->status = status;
1346     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1347     return SILC_FSM_CONTINUE;
1348   }
1349
1350   /* Free our KE Start Payload context, we don't need it anymore. */
1351   silc_ske_payload_start_free(ske->start_payload);
1352   ske->start_payload = NULL;
1353
1354   /* Take the selected security properties into use while doing
1355      the key exchange.  This is used only while doing the key
1356      exchange. */
1357   ske->prop = prop = silc_calloc(1, sizeof(*prop));
1358   if (!ske->prop)
1359     goto err;
1360   prop->flags = payload->flags;
1361   status = silc_ske_group_get_by_name(payload->ke_grp_list, &group);
1362   if (status != SILC_SKE_STATUS_OK)
1363     goto err;
1364
1365   prop->group = group;
1366   prop->remote_port = remote_port;
1367
1368   if (silc_pkcs_find_algorithm(payload->pkcs_alg_list, NULL) == NULL) {
1369     status = SILC_SKE_STATUS_UNKNOWN_PKCS;
1370     goto err;
1371   }
1372   if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
1373     status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
1374     goto err;
1375   }
1376   if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
1377     status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1378     goto err;
1379   }
1380   if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
1381     status = SILC_SKE_STATUS_UNKNOWN_HMAC;
1382     goto err;
1383   }
1384
1385   /* Save remote's KE Start Payload */
1386   ske->start_payload = payload;
1387
1388   /** Send KE Payload */
1389   silc_fsm_next(fsm, silc_ske_st_initiator_phase2);
1390   return SILC_FSM_CONTINUE;
1391
1392  err:
1393   if (payload)
1394     silc_ske_payload_start_free(payload);
1395   if (group)
1396     silc_ske_group_free(group);
1397   if (prop) {
1398     if (prop->cipher)
1399       silc_cipher_free(prop->cipher);
1400     if (prop->hash)
1401       silc_hash_free(prop->hash);
1402     if (prop->hmac)
1403       silc_hmac_free(prop->hmac);
1404     silc_free(prop);
1405   }
1406   ske->prop = NULL;
1407
1408   if (status == SILC_SKE_STATUS_OK)
1409     status = SILC_SKE_STATUS_ERROR;
1410
1411   /** Error */
1412   ske->status = status;
1413   silc_fsm_next(fsm, silc_ske_st_initiator_error);
1414   return SILC_FSM_CONTINUE;
1415 }
1416
1417 /* Phase-2.  Send KE payload */
1418
1419 SILC_FSM_STATE(silc_ske_st_initiator_phase2)
1420 {
1421   SilcSKE ske = fsm_context;
1422   SilcSKEStatus status;
1423   SilcBuffer payload_buf;
1424   SilcMPInt *x;
1425   SilcSKEKEPayload payload;
1426   SilcUInt32 pk_len;
1427
1428   SILC_LOG_DEBUG(("Start"));
1429
1430   /* Create the random number x, 1 < x < q. */
1431   x = silc_calloc(1, sizeof(*x));
1432   if (!x) {
1433     /** Out of memory */
1434     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1435     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1436     return SILC_FSM_CONTINUE;
1437   }
1438   silc_mp_init(x);
1439   status =
1440     silc_ske_create_rnd(ske, &ske->prop->group->group_order,
1441                         silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
1442                         x);
1443   if (status != SILC_SKE_STATUS_OK) {
1444     /** Error generating random number */
1445     silc_mp_uninit(x);
1446     silc_free(x);
1447     ske->status = status;
1448     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1449     return SILC_FSM_CONTINUE;
1450   }
1451
1452   /* Encode the result to Key Exchange Payload. */
1453
1454   payload = silc_calloc(1, sizeof(*payload));
1455   if (!payload) {
1456     /** Out of memory */
1457     silc_mp_uninit(x);
1458     silc_free(x);
1459     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1460     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1461     return SILC_FSM_CONTINUE;
1462   }
1463   ske->ke1_payload = payload;
1464
1465   SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
1466
1467   /* Do the Diffie Hellman computation, e = g ^ x mod p */
1468   silc_mp_init(&payload->x);
1469   silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
1470                   &ske->prop->group->group);
1471
1472   /* Get public key */
1473   payload->pk_data = silc_pkcs_public_key_encode(ske->public_key, &pk_len);
1474   if (!payload->pk_data) {
1475     /** Error encoding public key */
1476     silc_mp_uninit(x);
1477     silc_free(x);
1478     silc_mp_uninit(&payload->x);
1479     silc_free(payload);
1480     ske->ke1_payload = NULL;
1481     ske->status = SILC_SKE_STATUS_ERROR;
1482     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1483     return SILC_FSM_CONTINUE;
1484   }
1485   payload->pk_len = pk_len;
1486   payload->pk_type = silc_pkcs_get_type(ske->public_key);
1487
1488   /* Compute signature data if we are doing mutual authentication */
1489   if (ske->private_key && ske->prop->flags & SILC_SKE_SP_FLAG_MUTUAL) {
1490     unsigned char hash[SILC_HASH_MAXLEN], sign[65536 + 1];
1491     SilcUInt32 hash_len, sign_len;
1492
1493     SILC_LOG_DEBUG(("We are doing mutual authentication"));
1494     SILC_LOG_DEBUG(("Computing HASH_i value"));
1495
1496     /* Compute the hash value */
1497     memset(hash, 0, sizeof(hash));
1498     if (silc_ske_make_hash(ske, hash, &hash_len, TRUE) != SILC_SKE_STATUS_OK)
1499       {
1500         /** Error computing hash */
1501         silc_mp_uninit(x);
1502         silc_free(x);
1503         silc_mp_uninit(&payload->x);
1504         silc_free(payload->pk_data);
1505         silc_free(payload);
1506         ske->ke1_payload = NULL;
1507         ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
1508         silc_fsm_next(fsm, silc_ske_st_initiator_error);
1509         return SILC_FSM_CONTINUE;
1510       }
1511
1512     SILC_LOG_DEBUG(("Signing HASH_i value"));
1513
1514     /* Sign the hash value */
1515     if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
1516                         sizeof(sign) - 1, &sign_len, FALSE, ske->prop->hash)) {
1517       /** Error computing signature */
1518       silc_mp_uninit(x);
1519       silc_free(x);
1520       silc_mp_uninit(&payload->x);
1521       silc_free(payload->pk_data);
1522       silc_free(payload);
1523       ske->ke1_payload = NULL;
1524       ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
1525       silc_fsm_next(fsm, silc_ske_st_initiator_error);
1526       return SILC_FSM_CONTINUE;
1527     }
1528     payload->sign_data = silc_memdup(sign, sign_len);
1529     if (payload->sign_data)
1530       payload->sign_len = sign_len;
1531     memset(sign, 0, sizeof(sign));
1532   }
1533
1534   status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
1535   if (status != SILC_SKE_STATUS_OK) {
1536     /** Error encoding KE payload */
1537     silc_mp_uninit(x);
1538     silc_free(x);
1539     silc_mp_uninit(&payload->x);
1540     silc_free(payload->pk_data);
1541     silc_free(payload->sign_data);
1542     silc_free(payload);
1543     ske->ke1_payload = NULL;
1544     ske->status = status;
1545     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1546     return SILC_FSM_CONTINUE;
1547   }
1548
1549   ske->x = x;
1550
1551   /* Check for backwards compatibility */
1552
1553   /* Send the packet. */
1554   if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE_1, 0,
1555                             silc_buffer_data(payload_buf),
1556                             silc_buffer_len(payload_buf))) {
1557     /** Error sending packet */
1558     SILC_LOG_DEBUG(("Error sending packet"));
1559     ske->status = SILC_SKE_STATUS_ERROR;
1560     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1561     return SILC_FSM_CONTINUE;
1562   }
1563
1564   silc_buffer_free(payload_buf);
1565
1566   /** Waiting responder's KE payload */
1567   silc_fsm_next(fsm, silc_ske_st_initiator_phase3);
1568   return SILC_FSM_WAIT;
1569 }
1570
1571 /* Phase-3.  Process responder's KE payload */
1572
1573 SILC_FSM_STATE(silc_ske_st_initiator_phase3)
1574 {
1575   SilcSKE ske = fsm_context;
1576   SilcSKEStatus status;
1577   SilcSKEKEPayload payload;
1578   SilcMPInt *KEY;
1579   SilcBuffer packet_buf = &ske->packet->buffer;
1580
1581   SILC_LOG_DEBUG(("Start"));
1582
1583   if (ske->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
1584     SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
1585     silc_ske_install_retransmission(ske);
1586     silc_packet_free(ske->packet);
1587     ske->packet = NULL;
1588     return SILC_FSM_WAIT;
1589   }
1590
1591   /* Decode the payload */
1592   status = silc_ske_payload_ke_decode(ske, packet_buf, &payload);
1593   if (status != SILC_SKE_STATUS_OK) {
1594     /** Error decoding KE payload */
1595     silc_packet_free(ske->packet);
1596     ske->packet = NULL;
1597     ske->status = status;
1598     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1599     return SILC_FSM_CONTINUE;
1600   }
1601   silc_packet_free(ske->packet);
1602   ske->packet = NULL;
1603   ske->ke2_payload = payload;
1604
1605   if (!payload->pk_data && (ske->callbacks->verify_key || ske->repository)) {
1606     SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
1607                     "even though we require it"));
1608     ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
1609     goto err;
1610   }
1611
1612   SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
1613
1614   /* Compute the shared secret key */
1615   KEY = silc_calloc(1, sizeof(*KEY));
1616   if (!KEY) {
1617     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1618     goto err;
1619   }
1620   silc_mp_init(KEY);
1621   silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
1622   ske->KEY = KEY;
1623
1624   /* Decode the remote's public key */
1625   if (payload->pk_data &&
1626       !silc_pkcs_public_key_alloc(payload->pk_type,
1627                                   payload->pk_data, payload->pk_len,
1628                                   &ske->prop->public_key)) {
1629     SILC_LOG_ERROR(("Unsupported/malformed public key received"));
1630     status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
1631     goto err;
1632   }
1633
1634   if (ske->prop->public_key && (ske->callbacks->verify_key ||
1635                                 ske->repository)) {
1636     SILC_LOG_DEBUG(("Verifying public key"));
1637
1638     /** Waiting public key verification */
1639     silc_fsm_next(fsm, silc_ske_st_initiator_phase4);
1640
1641     /* If repository is provided, verify the key from there. */
1642     if (ske->repository) {
1643       SilcSKRFind find;
1644
1645       find = silc_skr_find_alloc();
1646       if (!find) {
1647         status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1648         goto err;
1649       }
1650       silc_skr_find_set_pkcs_type(find,
1651                                   silc_pkcs_get_type(ske->prop->public_key));
1652       silc_skr_find_set_public_key(find, ske->prop->public_key);
1653       silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT);
1654
1655       /* Find key from repository */
1656       SILC_FSM_CALL(silc_skr_find(ske->repository, silc_fsm_get_schedule(fsm),
1657                                   find, silc_ske_skr_callback, ske));
1658     } else {
1659       /* Verify from application */
1660       SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key,
1661                                                ske->callbacks->context,
1662                                                silc_ske_pk_verified, NULL));
1663     }
1664     /* NOT REACHED */
1665   }
1666
1667   /** Process key material */
1668   silc_fsm_next(fsm, silc_ske_st_initiator_phase4);
1669   return SILC_FSM_CONTINUE;
1670
1671  err:
1672   silc_ske_payload_ke_free(payload);
1673   ske->ke2_payload = NULL;
1674
1675   silc_mp_uninit(ske->KEY);
1676   silc_free(ske->KEY);
1677   ske->KEY = NULL;
1678
1679   if (status == SILC_SKE_STATUS_OK)
1680     return SILC_SKE_STATUS_ERROR;
1681
1682   /** Error */
1683   ske->status = status;
1684   silc_fsm_next(fsm, silc_ske_st_initiator_error);
1685   return SILC_FSM_CONTINUE;
1686 }
1687
1688 /* Process key material */
1689
1690 SILC_FSM_STATE(silc_ske_st_initiator_phase4)
1691 {
1692   SilcSKE ske = fsm_context;
1693   SilcSKEStatus status;
1694   SilcSKEKEPayload payload;
1695   unsigned char hash[SILC_HASH_MAXLEN];
1696   SilcUInt32 hash_len;
1697   int key_len, block_len;
1698
1699   if (ske->aborted) {
1700     /** Aborted */
1701     silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
1702     return SILC_FSM_CONTINUE;
1703   }
1704
1705   /* Check result of public key verification */
1706   if (ske->status != SILC_SKE_STATUS_OK) {
1707     /** Public key not verified */
1708     SILC_LOG_DEBUG(("Public key verification failed"));
1709     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1710     return SILC_FSM_CONTINUE;
1711   }
1712
1713   payload = ske->ke2_payload;
1714
1715   /* Compute the HASH value */
1716   SILC_LOG_DEBUG(("Computing HASH value"));
1717   status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1718   if (status != SILC_SKE_STATUS_OK)
1719     goto err;
1720   ske->hash = silc_memdup(hash, hash_len);
1721   if (!ske->hash) {
1722     status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1723     goto err;
1724   }
1725   ske->hash_len = hash_len;
1726
1727   if (ske->prop->public_key) {
1728     SILC_LOG_DEBUG(("Public key is authentic"));
1729     SILC_LOG_DEBUG(("Verifying signature (HASH)"));
1730
1731     /* Verify signature */
1732     if (!silc_pkcs_verify(ske->prop->public_key, payload->sign_data,
1733                           payload->sign_len, hash, hash_len, NULL)) {
1734       SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
1735       status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
1736       goto err;
1737     }
1738
1739     SILC_LOG_DEBUG(("Signature is Ok"));
1740     memset(hash, 'F', hash_len);
1741   }
1742
1743   ske->status = SILC_SKE_STATUS_OK;
1744
1745   /* In case we are doing rekey move to finish it.  */
1746   if (ske->rekey) {
1747     /** Finish rekey */
1748     silc_fsm_next(fsm, silc_ske_st_rekey_initiator_done);
1749     return SILC_FSM_CONTINUE;
1750   }
1751
1752   /* Process key material */
1753   key_len = silc_cipher_get_key_len(ske->prop->cipher);
1754   block_len = silc_cipher_get_block_len(ske->prop->cipher);
1755   hash_len = silc_hash_len(ske->prop->hash);
1756   ske->keymat = silc_ske_process_key_material(ske, block_len,
1757                                               key_len, hash_len,
1758                                               &ske->rekey);
1759   if (!ske->keymat) {
1760     SILC_LOG_ERROR(("Error processing key material"));
1761     status = SILC_SKE_STATUS_ERROR;
1762     goto err;
1763   }
1764
1765   if (!ske->no_acks) {
1766     /* Send SUCCESS packet */
1767     SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, hash);
1768     if (!silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, hash, 4)) {
1769       /** Error sending packet */
1770       SILC_LOG_DEBUG(("Error sending packet"));
1771       ske->status = SILC_SKE_STATUS_ERROR;
1772       silc_fsm_next(fsm, silc_ske_st_initiator_error);
1773       return SILC_FSM_CONTINUE;
1774     }
1775
1776     /** Waiting completion */
1777     silc_fsm_next(fsm, silc_ske_st_initiator_end);
1778     return SILC_FSM_WAIT;
1779   } else {
1780     /** Complete protocol */
1781     silc_fsm_next(fsm, silc_ske_st_initiator_end);
1782     return SILC_FSM_CONTINUE;
1783   }
1784
1785  err:
1786   memset(hash, 'F', sizeof(hash));
1787   silc_ske_payload_ke_free(payload);
1788   ske->ke2_payload = NULL;
1789
1790   silc_mp_uninit(ske->KEY);
1791   silc_free(ske->KEY);
1792   ske->KEY = NULL;
1793
1794   if (ske->hash) {
1795     memset(ske->hash, 'F', hash_len);
1796     silc_free(ske->hash);
1797     ske->hash = NULL;
1798   }
1799
1800   if (status == SILC_SKE_STATUS_OK)
1801     status = SILC_SKE_STATUS_ERROR;
1802
1803   /** Error */
1804   ske->status = status;
1805   silc_fsm_next(fsm, silc_ske_st_initiator_error);
1806   return SILC_FSM_CONTINUE;
1807 }
1808
1809 /* Protocol completed */
1810
1811 SILC_FSM_STATE(silc_ske_st_initiator_end)
1812 {
1813   SilcSKE ske = fsm_context;
1814
1815   SILC_LOG_DEBUG(("Start"));
1816
1817   if (!ske->no_acks && ske->packet->type != SILC_PACKET_SUCCESS) {
1818     SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
1819     silc_ske_install_retransmission(ske);
1820     silc_packet_free(ske->packet);
1821     ske->packet = NULL;
1822     return SILC_FSM_WAIT;
1823   }
1824
1825   SILC_LOG_DEBUG(("Key exchange completed successfully"));
1826
1827   if (ske->packet)
1828     silc_packet_free(ske->packet);
1829   ske->packet = NULL;
1830   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1831   silc_schedule_task_del_by_context(ske->schedule, ske);
1832
1833   /* Call completion */
1834   silc_ske_completion(ske);
1835
1836   return SILC_FSM_FINISH;
1837 }
1838
1839 /* Aborted by application */
1840
1841 SILC_FSM_STATE(silc_ske_st_initiator_aborted)
1842 {
1843   SilcSKE ske = fsm_context;
1844   unsigned char data[4];
1845
1846   SILC_LOG_DEBUG(("Aborted by caller"));
1847
1848   /* Send FAILURE packet */
1849   SILC_PUT32_MSB(SILC_SKE_STATUS_ERROR, data);
1850   silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, data, 4);
1851
1852   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1853   silc_schedule_task_del_by_context(ske->schedule, ske);
1854
1855   /* Call completion */
1856   silc_ske_completion(ske);
1857
1858   return SILC_FSM_FINISH;
1859 }
1860
1861 /* Error occurred.  Send error to remote host */
1862
1863 SILC_FSM_STATE(silc_ske_st_initiator_error)
1864 {
1865   SilcSKE ske = fsm_context;
1866   SilcUInt32 status;
1867   unsigned char data[4];
1868
1869   SILC_LOG_DEBUG(("Error %s (%d) occurred during key exchange",
1870                   silc_ske_map_status(ske->status), ske->status));
1871
1872   status = ske->status;
1873   if (status > SILC_SKE_STATUS_INVALID_COOKIE)
1874     status = SILC_SKE_STATUS_ERROR;
1875
1876   /* Send FAILURE packet */
1877   SILC_PUT32_MSB(status, data);
1878   silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, data, 4);
1879
1880   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1881   silc_schedule_task_del_by_context(ske->schedule, ske);
1882
1883   /* Call completion */
1884   silc_ske_completion(ske);
1885
1886   return SILC_FSM_FINISH;
1887 }
1888
1889 /* Failure received from remote */
1890
1891 SILC_FSM_STATE(silc_ske_st_initiator_failure)
1892 {
1893   SilcSKE ske = fsm_context;
1894   SilcUInt32 error = ske->status;
1895
1896   if (ske->packet && silc_buffer_len(&ske->packet->buffer) == 4) {
1897     SILC_GET32_MSB(error, ske->packet->buffer.data);
1898     silc_packet_free(ske->packet);
1899     ske->packet = NULL;
1900   }
1901   if (error == SILC_SKE_STATUS_OK)
1902     error = SILC_SKE_STATUS_ERROR;
1903   ske->status = error;
1904
1905   SILC_LOG_DEBUG(("Error %s (%d) received during key exchange",
1906                   silc_ske_map_status(ske->status), ske->status));
1907
1908   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1909   silc_schedule_task_del_by_context(ske->schedule, ske);
1910
1911   /* Call completion */
1912   silc_ske_completion(ske);
1913
1914   return SILC_FSM_FINISH;
1915 }
1916
1917 /* Starts the protocol as initiator */
1918
1919 SilcAsyncOperation silc_ske_initiator(SilcSKE ske,
1920                                       SilcPacketStream stream,
1921                                       SilcSKEParams params,
1922                                       SilcSKEStartPayload start_payload)
1923 {
1924   SILC_LOG_DEBUG(("Start SKE %p as initiator; stream=%p; params=%p; "
1925                   "start_payload=%p", ske, stream, params, start_payload));
1926
1927   if (!ske || !stream || !params || !params->version)
1928     return NULL;
1929
1930   if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
1931     return NULL;
1932
1933   if (!silc_fsm_init(&ske->fsm, ske, silc_ske_finished, ske, ske->schedule))
1934     return NULL;
1935
1936   if (params->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)
1937     ske->session_port = params->session_port;
1938
1939   /* Generate security properties if not provided */
1940   if (!start_payload && !params->prop) {
1941     start_payload =
1942       silc_ske_assemble_security_properties(ske, params->flags,
1943                                             params->version,
1944                                             params->small_proposal);
1945     if (!start_payload)
1946       return NULL;
1947   }
1948
1949   ske->timeout = params->timeout_secs ? params->timeout_secs : 30;
1950   ske->probe_timeout = (params->probe_timeout_secs ?
1951                         params->probe_timeout_secs : 30);
1952   ske->start_payload = start_payload;
1953   ske->prop = params->prop;
1954   ske->version = params->version;
1955   ske->no_acks = params->no_acks;
1956   ++ske->refcnt;
1957
1958   /* Link to packet stream to get key exchange packets */
1959   ske->stream = stream;
1960   silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
1961                           SILC_PACKET_KEY_EXCHANGE,
1962                           SILC_PACKET_KEY_EXCHANGE_2,
1963                           SILC_PACKET_SUCCESS,
1964                           SILC_PACKET_FAILURE, -1);
1965
1966   /* Add key exchange timeout */
1967   silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout,
1968                                  ske, ske->timeout, 0);
1969   if (ske->timeout != ske->probe_timeout)
1970     silc_schedule_task_add_timeout(ske->schedule, silc_ske_probe_timeout,
1971                                    ske, ske->probe_timeout, 0);
1972
1973   /* Start SKE as initiator */
1974   if (!ske->prop)
1975     silc_fsm_start(&ske->fsm, silc_ske_st_initiator_start);
1976   else
1977     silc_fsm_start(&ske->fsm, silc_ske_st_initiator_phase2);
1978
1979   return &ske->op;
1980 }
1981
1982 /******************************** Responder *********************************/
1983
1984 /* Start protocol as responder.  Wait initiator's start payload */
1985
1986 SILC_FSM_STATE(silc_ske_st_responder_start)
1987 {
1988   SilcSKE ske = fsm_context;
1989
1990   SILC_LOG_DEBUG(("Start"));
1991
1992   if (ske->aborted) {
1993     /** Aborted */
1994     silc_fsm_next(fsm, silc_ske_st_responder_aborted);
1995     return SILC_FSM_CONTINUE;
1996   }
1997
1998   /** Wait for initiator */
1999   if (!ske->prop)
2000     silc_fsm_next(fsm, silc_ske_st_responder_phase1);
2001   else
2002     silc_fsm_next(fsm, silc_ske_st_responder_phase2);
2003   return SILC_FSM_WAIT;
2004 }
2005
2006 /* Decode initiator's start payload.  Select the security properties from
2007    the initiator's start payload and send our reply start payload back. */
2008
2009 SILC_FSM_STATE(silc_ske_st_responder_phase1)
2010 {
2011   SilcSKE ske = fsm_context;
2012   SilcSKEStatus status;
2013   SilcSKEStartPayload remote_payload = NULL;
2014   SilcBuffer packet_buf = &ske->packet->buffer;
2015   SilcID id;
2016
2017   SILC_LOG_DEBUG(("Start"));
2018
2019   /* Decode the payload */
2020   status = silc_ske_payload_start_decode(ske, packet_buf, &remote_payload);
2021   if (status != SILC_SKE_STATUS_OK) {
2022     /** Error decoding Start Payload */
2023     silc_packet_free(ske->packet);
2024     ske->packet = NULL;
2025     ske->status = status;
2026     silc_fsm_next(fsm, silc_ske_st_responder_error);
2027     return SILC_FSM_CONTINUE;
2028   }
2029
2030   /* Get remote ID and set it to stream */
2031   if (ske->packet->src_id_len &&
2032       (ske->packet->src_id_type == SILC_ID_SERVER ||
2033        ske->packet->src_id_type == SILC_ID_CLIENT)) {
2034     silc_id_str2id(ske->packet->src_id, ske->packet->src_id_len,
2035                    ske->packet->src_id_type,
2036                    (ske->packet->src_id_type == SILC_ID_SERVER ?
2037                     (void *)&id.u.server_id : (void *)&id.u.client_id),
2038                    (ske->packet->src_id_type == SILC_ID_SERVER ?
2039                     sizeof(id.u.server_id) : sizeof(id.u.client_id)));
2040     silc_packet_set_ids(ske->stream, 0, NULL, ske->packet->src_id_type,
2041                         (ske->packet->src_id_type == SILC_ID_SERVER ?
2042                          (void *)&id.u.server_id : (void *)&id.u.client_id));
2043   }
2044
2045   /* Take a copy of the payload buffer for future use. It is used to
2046      compute the HASH value. */
2047   ske->start_payload_copy = silc_buffer_copy(packet_buf);
2048   if (!ske->start_payload_copy) {
2049     silc_packet_free(ske->packet);
2050     ske->packet = NULL;
2051     ske->status = status;
2052     silc_fsm_next(fsm, silc_ske_st_responder_error);
2053     return SILC_FSM_CONTINUE;
2054   }
2055
2056   silc_packet_free(ske->packet);
2057   ske->packet = NULL;
2058
2059   /* Force the mutual authentication flag if we want to do it. */
2060   if (ske->flags & SILC_SKE_SP_FLAG_MUTUAL) {
2061     SILC_LOG_DEBUG(("Force mutual authentication"));
2062     remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
2063   }
2064
2065   /* Force PFS flag if we require it */
2066   if (ske->flags & SILC_SKE_SP_FLAG_PFS) {
2067     SILC_LOG_DEBUG(("Force PFS"));
2068     remote_payload->flags |= SILC_SKE_SP_FLAG_PFS;
2069   }
2070
2071   /* Disable IV Included flag if requested */
2072   if (remote_payload->flags & SILC_SKE_SP_FLAG_IV_INCLUDED &&
2073       !(ske->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)) {
2074     SILC_LOG_DEBUG(("We do not support IV Included flag"));
2075     remote_payload->flags &= ~SILC_SKE_SP_FLAG_IV_INCLUDED;
2076   }
2077
2078   /* Check and select security properties */
2079   status = silc_ske_select_security_properties(ske, remote_payload,
2080                                                &ske->prop);
2081   if (status != SILC_SKE_STATUS_OK) {
2082     /** Error selecting proposal */
2083     silc_ske_payload_start_free(remote_payload);
2084     ske->status = status;
2085     silc_fsm_next(fsm, silc_ske_st_responder_error);
2086     return SILC_FSM_CONTINUE;
2087   }
2088
2089   silc_ske_payload_start_free(remote_payload);
2090
2091   /* Encode our reply payload to send the selected security properties */
2092   status = silc_ske_payload_start_encode(ske, ske->start_payload,
2093                                          &packet_buf);
2094   if (status != SILC_SKE_STATUS_OK)
2095     goto err;
2096
2097   /* Send the packet. */
2098   if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE, 0,
2099                             silc_buffer_data(packet_buf),
2100                             silc_buffer_len(packet_buf)))
2101     goto err;
2102
2103   silc_buffer_free(packet_buf);
2104
2105   /** Waiting initiator's KE payload */
2106   silc_fsm_next(fsm, silc_ske_st_responder_phase2);
2107   return SILC_FSM_WAIT;
2108
2109  err:
2110   if (ske->prop->group)
2111     silc_ske_group_free(ske->prop->group);
2112   if (ske->prop->cipher)
2113     silc_cipher_free(ske->prop->cipher);
2114   if (ske->prop->hash)
2115     silc_hash_free(ske->prop->hash);
2116   if (ske->prop->hmac)
2117     silc_hmac_free(ske->prop->hmac);
2118   silc_free(ske->prop);
2119   ske->prop = NULL;
2120
2121   if (status == SILC_SKE_STATUS_OK)
2122     status = SILC_SKE_STATUS_ERROR;
2123
2124   /** Error */
2125   ske->status = status;
2126   silc_fsm_next(fsm, silc_ske_st_responder_error);
2127   return SILC_FSM_CONTINUE;
2128 }
2129
2130 /* Phase-2.  Decode initiator's KE payload */
2131
2132 SILC_FSM_STATE(silc_ske_st_responder_phase2)
2133 {
2134   SilcSKE ske = fsm_context;
2135   SilcSKEStatus status;
2136   SilcSKEKEPayload recv_payload;
2137   SilcBuffer packet_buf = &ske->packet->buffer;
2138
2139   SILC_LOG_DEBUG(("Start"));
2140
2141   if (ske->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
2142     SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
2143     silc_ske_install_retransmission(ske);
2144     silc_packet_free(ske->packet);
2145     ske->packet = NULL;
2146     return SILC_FSM_WAIT;
2147   }
2148
2149   /* Decode Key Exchange Payload */
2150   status = silc_ske_payload_ke_decode(ske, packet_buf, &recv_payload);
2151   if (status != SILC_SKE_STATUS_OK) {
2152     /** Error decoding KE payload */
2153     silc_packet_free(ske->packet);
2154     ske->packet = NULL;
2155     ske->status = status;
2156     silc_fsm_next(fsm, silc_ske_st_responder_error);
2157     return SILC_FSM_CONTINUE;
2158   }
2159
2160   ske->ke1_payload = recv_payload;
2161
2162   silc_packet_free(ske->packet);
2163   ske->packet = NULL;
2164
2165   /* Verify public key, except in rekey, when it is not sent */
2166   if (!ske->rekey) {
2167     if (!recv_payload->pk_data) {
2168       /** Public key not provided */
2169       SILC_LOG_ERROR(("Remote end did not send its public key (or "
2170                       "certificate), even though we require it"));
2171       ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
2172       silc_fsm_next(fsm, silc_ske_st_responder_error);
2173       return SILC_FSM_CONTINUE;
2174     }
2175
2176     /* Decode the remote's public key */
2177     if (!silc_pkcs_public_key_alloc(recv_payload->pk_type,
2178                                     recv_payload->pk_data,
2179                                     recv_payload->pk_len,
2180                                     &ske->prop->public_key)) {
2181       /** Error decoding public key */
2182       SILC_LOG_ERROR(("Unsupported/malformed public key received"));
2183       ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
2184       silc_fsm_next(fsm, silc_ske_st_responder_error);
2185       return SILC_FSM_CONTINUE;
2186     }
2187
2188     SILC_LOG_DEBUG(("Verifying public key"));
2189
2190     /** Waiting public key verification */
2191     silc_fsm_next(fsm, silc_ske_st_responder_phase4);
2192
2193     /* If repository is provided, verify the key from there. */
2194     if (ske->repository) {
2195       SilcSKRFind find;
2196
2197       find = silc_skr_find_alloc();
2198       if (!find) {
2199         ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2200         silc_fsm_next(fsm, silc_ske_st_responder_error);
2201         return SILC_FSM_CONTINUE;
2202       }
2203       silc_skr_find_set_pkcs_type(find,
2204                                   silc_pkcs_get_type(ske->prop->public_key));
2205       silc_skr_find_set_public_key(find, ske->prop->public_key);
2206       silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT);
2207
2208       /* Find key from repository */
2209       SILC_FSM_CALL(silc_skr_find(ske->repository,
2210                                   silc_fsm_get_schedule(fsm), find,
2211                                   silc_ske_skr_callback, ske));
2212     } else {
2213       /* Verify from application */
2214       if (ske->callbacks->verify_key)
2215         SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key,
2216                                                  ske->callbacks->context,
2217                                                  silc_ske_pk_verified, NULL));
2218     }
2219   }
2220
2221   /** Generate KE2 payload */
2222   silc_fsm_next(fsm, silc_ske_st_responder_phase4);
2223   return SILC_FSM_CONTINUE;
2224 }
2225
2226 /* Phase-4. Generate KE2 payload */
2227
2228 SILC_FSM_STATE(silc_ske_st_responder_phase4)
2229 {
2230   SilcSKE ske = fsm_context;
2231   SilcSKEStatus status;
2232   SilcSKEKEPayload recv_payload, send_payload = NULL;
2233   SilcMPInt *x = NULL, *KEY;
2234
2235   if (ske->aborted) {
2236     /** Aborted */
2237     silc_fsm_next(fsm, silc_ske_st_responder_aborted);
2238     return SILC_FSM_CONTINUE;
2239   }
2240
2241   /* Check result of public key verification */
2242   if (ske->status != SILC_SKE_STATUS_OK) {
2243     /** Public key not verified */
2244     SILC_LOG_DEBUG(("Public key verification failed"));
2245     goto err;
2246   }
2247
2248   recv_payload = ske->ke1_payload;
2249
2250   /* The public key verification was performed only if the Mutual
2251      Authentication flag is set. */
2252   if ((ske->start_payload &&
2253        ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) ||
2254       ske->prop->flags & SILC_SKE_SP_FLAG_MUTUAL) {
2255     unsigned char hash[SILC_HASH_MAXLEN];
2256     SilcUInt32 hash_len;
2257
2258     SILC_LOG_DEBUG(("We are doing mutual authentication"));
2259
2260     /* Compute the hash value */
2261     status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
2262     if (status != SILC_SKE_STATUS_OK) {
2263       /** Error computing hash */
2264       SILC_LOG_DEBUG(("Error computing hash"));
2265       ske->status = status;
2266       goto err;
2267     }
2268
2269     SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
2270
2271     /* Verify signature */
2272     if (!silc_pkcs_verify(ske->prop->public_key, recv_payload->sign_data,
2273                           recv_payload->sign_len, hash, hash_len, NULL)) {
2274       /** Incorrect signature */
2275       SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
2276       ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
2277       goto err;
2278     }
2279
2280     SILC_LOG_DEBUG(("Signature is Ok"));
2281
2282     memset(hash, 'F', hash_len);
2283   }
2284
2285   /* Create the random number x, 1 < x < q. */
2286   x = silc_calloc(1, sizeof(*x));
2287   if (!x) {
2288     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2289     goto err;
2290   }
2291   silc_mp_init(x);
2292   status =
2293     silc_ske_create_rnd(ske, &ske->prop->group->group_order,
2294                         silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
2295                         x);
2296   if (status != SILC_SKE_STATUS_OK) {
2297     /** Error generating random number */
2298     ske->status = status;
2299     goto err;
2300   }
2301
2302   /* Save the results for later processing */
2303   send_payload = silc_calloc(1, sizeof(*send_payload));
2304   if (!send_payload) {
2305     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2306     goto err;
2307   }
2308   ske->x = x;
2309   ske->ke2_payload = send_payload;
2310
2311   SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
2312
2313   /* Do the Diffie Hellman computation, f = g ^ x mod p */
2314   silc_mp_init(&send_payload->x);
2315   silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
2316                   &ske->prop->group->group);
2317
2318   SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
2319
2320   /* Compute the shared secret key */
2321   KEY = silc_calloc(1, sizeof(*KEY));
2322   if (!KEY) {
2323     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2324     goto err;
2325   }
2326   silc_mp_init(KEY);
2327   silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
2328                   &ske->prop->group->group);
2329   ske->KEY = KEY;
2330
2331   /** Send KE2 payload */
2332   silc_fsm_next(fsm, silc_ske_st_responder_phase5);
2333   return SILC_FSM_CONTINUE;
2334
2335  err:
2336   silc_mp_uninit(x);
2337   silc_free(x);
2338   ske->x = NULL;
2339   silc_free(send_payload);
2340   ske->ke2_payload = NULL;
2341
2342   silc_fsm_next(fsm, silc_ske_st_responder_error);
2343   return SILC_FSM_CONTINUE;
2344 }
2345
2346 /* Phase-5.  Send KE2 payload */
2347
2348 SILC_FSM_STATE(silc_ske_st_responder_phase5)
2349 {
2350   SilcSKE ske = fsm_context;
2351   SilcSKEStatus status;
2352   SilcBuffer payload_buf;
2353   unsigned char hash[SILC_HASH_MAXLEN], sign[65536 + 1], *pk;
2354   SilcUInt32 hash_len, sign_len, pk_len;
2355
2356   SILC_LOG_DEBUG(("Start"));
2357
2358   if (ske->public_key && ske->private_key) {
2359     SILC_LOG_DEBUG(("Getting public key"));
2360
2361     /* Get the public key */
2362     pk = silc_pkcs_public_key_encode(ske->public_key, &pk_len);
2363     if (!pk) {
2364       /** Error encoding public key */
2365       ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2366       silc_fsm_next(fsm, silc_ske_st_responder_error);
2367       return SILC_FSM_CONTINUE;
2368     }
2369     ske->ke2_payload->pk_data = pk;
2370     ske->ke2_payload->pk_len = pk_len;
2371   }
2372
2373   SILC_LOG_DEBUG(("Computing HASH value"));
2374
2375   /* Compute the hash value */
2376   memset(hash, 0, sizeof(hash));
2377   status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
2378   if (status != SILC_SKE_STATUS_OK) {
2379     /** Error computing hash */
2380     ske->status = status;
2381     silc_fsm_next(fsm, silc_ske_st_responder_error);
2382     return SILC_FSM_CONTINUE;
2383   }
2384   ske->hash = silc_memdup(hash, hash_len);
2385   if (!ske->hash) {
2386     /** Error computing hash */
2387     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2388     silc_fsm_next(fsm, silc_ske_st_responder_error);
2389     return SILC_FSM_CONTINUE;
2390   }
2391   ske->hash_len = hash_len;
2392
2393   if (ske->public_key && ske->private_key) {
2394     SILC_LOG_DEBUG(("Signing HASH value"));
2395
2396     /* Sign the hash value */
2397     if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
2398                         sizeof(sign) - 1, &sign_len, FALSE, ske->prop->hash)) {
2399       /** Error computing signature */
2400       ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
2401       silc_fsm_next(fsm, silc_ske_st_responder_error);
2402       return SILC_FSM_CONTINUE;
2403     }
2404     ske->ke2_payload->sign_data = silc_memdup(sign, sign_len);
2405     if (!ske->ke2_payload->sign_data) {
2406       /** Error computing hash */
2407       ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2408       silc_fsm_next(fsm, silc_ske_st_responder_error);
2409       return SILC_FSM_CONTINUE;
2410     }
2411     ske->ke2_payload->sign_len = sign_len;
2412     memset(sign, 0, sizeof(sign));
2413   }
2414   ske->ke2_payload->pk_type = silc_pkcs_get_type(ske->public_key);
2415
2416   /* Encode the Key Exchange Payload */
2417   status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
2418                                       &payload_buf);
2419   if (status != SILC_SKE_STATUS_OK) {
2420     /** Error encoding KE payload */
2421     ske->status = status;
2422     silc_fsm_next(fsm, silc_ske_st_responder_error);
2423     return SILC_FSM_CONTINUE;
2424   }
2425
2426   /* Send the packet. */
2427   if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE_2, 0,
2428                             payload_buf->data, silc_buffer_len(payload_buf))) {
2429     SILC_LOG_DEBUG(("Error sending packet"));
2430     ske->status = SILC_SKE_STATUS_ERROR;
2431     silc_fsm_next(fsm, silc_ske_st_responder_error);
2432     return SILC_FSM_CONTINUE;
2433   }
2434
2435   silc_buffer_free(payload_buf);
2436
2437   /* In case we are doing rekey move to finish it. */
2438   if (ske->rekey) {
2439     /** Finish rekey */
2440     silc_fsm_next(fsm, silc_ske_st_rekey_responder_done);
2441     return SILC_FSM_CONTINUE;
2442   }
2443
2444   if (!ske->no_acks) {
2445     /** Waiting completion */
2446     silc_fsm_next(fsm, silc_ske_st_responder_end);
2447     return SILC_FSM_WAIT;
2448   } else {
2449     /** Complete protocol */
2450     silc_fsm_next(fsm, silc_ske_st_responder_end);
2451     return SILC_FSM_CONTINUE;
2452   }
2453 }
2454
2455 /* Protocol completed */
2456
2457 SILC_FSM_STATE(silc_ske_st_responder_end)
2458 {
2459   SilcSKE ske = fsm_context;
2460   unsigned char tmp[4];
2461   SilcUInt32 hash_len, key_len, block_len;
2462
2463   if (!ske->no_acks && ske->packet->type != SILC_PACKET_SUCCESS) {
2464     SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
2465     silc_ske_install_retransmission(ske);
2466     silc_packet_free(ske->packet);
2467     ske->packet = NULL;
2468     return SILC_FSM_WAIT;
2469   }
2470   if (ske->packet)
2471     silc_packet_free(ske->packet);
2472   ske->packet = NULL;
2473
2474   /* Process key material */
2475   key_len = silc_cipher_get_key_len(ske->prop->cipher);
2476   block_len = silc_cipher_get_block_len(ske->prop->cipher);
2477   hash_len = silc_hash_len(ske->prop->hash);
2478   ske->keymat = silc_ske_process_key_material(ske, block_len,
2479                                               key_len, hash_len,
2480                                               &ske->rekey);
2481   if (!ske->keymat) {
2482     /** Error processing key material */
2483     ske->status = SILC_SKE_STATUS_ERROR;
2484     silc_fsm_next(fsm, silc_ske_st_responder_error);
2485     return SILC_FSM_CONTINUE;
2486   }
2487
2488   if (!ske->no_acks) {
2489     /* Send SUCCESS packet */
2490     SILC_PUT32_MSB(SILC_SKE_STATUS_OK, tmp);
2491     silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, tmp, 4);
2492   }
2493
2494   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2495   silc_schedule_task_del_by_context(ske->schedule, ske);
2496
2497   /* Call completion */
2498   silc_ske_completion(ske);
2499
2500   return SILC_FSM_FINISH;
2501 }
2502
2503 /* Aborted by application */
2504
2505 SILC_FSM_STATE(silc_ske_st_responder_aborted)
2506 {
2507   SilcSKE ske = fsm_context;
2508   unsigned char tmp[4];
2509
2510   SILC_LOG_DEBUG(("Key exchange protocol aborted"));
2511
2512   /* Send FAILURE packet */
2513   SILC_PUT32_MSB(SILC_SKE_STATUS_ERROR, tmp);
2514   silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, tmp, 4);
2515
2516   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2517   silc_schedule_task_del_by_context(ske->schedule, ske);
2518
2519   /* Call completion */
2520   silc_ske_completion(ske);
2521
2522   return SILC_FSM_FINISH;
2523 }
2524
2525 /* Failure received from remote */
2526
2527 SILC_FSM_STATE(silc_ske_st_responder_failure)
2528 {
2529   SilcSKE ske = fsm_context;
2530   SilcUInt32 error = ske->status;
2531
2532   SILC_LOG_DEBUG(("Key exchange protocol failed"));
2533
2534   if (ske->packet && silc_buffer_len(&ske->packet->buffer) == 4) {
2535     SILC_GET32_MSB(error, ske->packet->buffer.data);
2536     silc_packet_free(ske->packet);
2537     ske->packet = NULL;
2538   }
2539   if (error == SILC_SKE_STATUS_OK)
2540     error = SILC_SKE_STATUS_ERROR;
2541   ske->status = error;
2542
2543   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2544   silc_schedule_task_del_by_context(ske->schedule, ske);
2545
2546   /* Call completion */
2547   silc_ske_completion(ske);
2548
2549   return SILC_FSM_FINISH;
2550 }
2551
2552 /* Error occurred */
2553
2554 SILC_FSM_STATE(silc_ske_st_responder_error)
2555 {
2556   SilcSKE ske = fsm_context;
2557   unsigned char tmp[4];
2558   SilcUInt32 status;
2559
2560   SILC_LOG_DEBUG(("Error %d (%s) during key exchange protocol",
2561                   ske->status, silc_ske_map_status(ske->status)));
2562
2563   /* Send FAILURE packet */
2564   status = ske->status;
2565   if (status > SILC_SKE_STATUS_INVALID_COOKIE)
2566     status = SILC_SKE_STATUS_ERROR;
2567   SILC_PUT32_MSB(status, tmp);
2568   silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, tmp, 4);
2569
2570   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2571   silc_schedule_task_del_by_context(ske->schedule, ske);
2572
2573   /* Call completion */
2574   silc_ske_completion(ske);
2575
2576   return SILC_FSM_FINISH;
2577 }
2578
2579 /* Starts the protocol as responder. */
2580
2581 SilcAsyncOperation silc_ske_responder(SilcSKE ske,
2582                                       SilcPacketStream stream,
2583                                       SilcSKEParams params)
2584 {
2585   SILC_LOG_DEBUG(("Start SKE as responder"));
2586
2587   if (!ske || !stream || !params || !params->version)
2588     return NULL;
2589
2590   if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
2591     return NULL;
2592
2593   if (!silc_fsm_init(&ske->fsm, ske, silc_ske_finished, ske, ske->schedule))
2594     return NULL;
2595
2596   ske->responder = TRUE;
2597   ske->flags = params->flags;
2598   ske->timeout = params->timeout_secs ? params->timeout_secs : 30;
2599   if (ske->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)
2600     ske->session_port = params->session_port;
2601   ske->version = params->version;
2602   ske->no_acks = params->no_acks;
2603   ske->prop = params->prop;
2604   if (!ske->version)
2605     return NULL;
2606   ++ske->refcnt;
2607
2608   /* Link to packet stream to get key exchange packets */
2609   ske->stream = stream;
2610   silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
2611                           SILC_PACKET_KEY_EXCHANGE,
2612                           SILC_PACKET_KEY_EXCHANGE_1,
2613                           SILC_PACKET_SUCCESS,
2614                           SILC_PACKET_FAILURE, -1);
2615
2616   /* Add key exchange timeout */
2617   silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout,
2618                                  ske, ske->timeout, 0);
2619
2620   /* Start SKE as responder */
2621   silc_fsm_start(&ske->fsm, silc_ske_st_responder_start);
2622
2623   return &ske->op;
2624 }
2625
2626 /***************************** Initiator Rekey ******************************/
2627
2628 /* Start rekey */
2629
2630 SILC_FSM_STATE(silc_ske_st_rekey_initiator_start)
2631 {
2632   SilcSKE ske = fsm_context;
2633   SilcStatus status;
2634
2635   SILC_LOG_DEBUG(("Start rekey (%s)", ske->rekey->pfs ? "PFS" : "No PFS"));
2636
2637   if (ske->aborted) {
2638     /** Aborted */
2639     silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
2640     return SILC_FSM_CONTINUE;
2641   }
2642
2643   /* Add rekey exchange timeout */
2644   silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout,
2645                                  ske, 30, 0);
2646
2647   ske->prop = silc_calloc(1, sizeof(*ske->prop));
2648   if (!ske->prop) {
2649     /** No memory */
2650     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2651     silc_fsm_next(fsm, silc_ske_st_initiator_error);
2652     return SILC_FSM_CONTINUE;
2653   }
2654
2655   if (!silc_hash_alloc(ske->rekey->hash, &ske->prop->hash)) {
2656     /** Cannot allocate hash */
2657     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2658     silc_fsm_next(fsm, silc_ske_st_initiator_error);
2659     return SILC_FSM_CONTINUE;
2660   }
2661
2662   /* Send REKEY packet to start rekey protocol */
2663   if (!silc_ske_packet_send(ske, SILC_PACKET_REKEY, 0, NULL, 0)) {
2664     /** Error sending packet */
2665     SILC_LOG_DEBUG(("Error sending packet"));
2666     ske->status = SILC_SKE_STATUS_ERROR;
2667     silc_fsm_next(fsm, silc_ske_st_initiator_error);
2668     return SILC_FSM_CONTINUE;
2669   }
2670
2671   /* If doing rekey without PFS, move directly to the end of the protocol. */
2672   if (!ske->rekey->pfs) {
2673     /** Rekey without PFS */
2674     silc_fsm_next(fsm, silc_ske_st_rekey_initiator_done);
2675     return SILC_FSM_CONTINUE;
2676   }
2677
2678   status = silc_ske_group_get_by_number(ske->rekey->ske_group,
2679                                         &ske->prop->group);
2680   if (status != SILC_SKE_STATUS_OK) {
2681     /** Unknown group */
2682     silc_fsm_next(fsm, silc_ske_st_initiator_error);
2683     return SILC_FSM_CONTINUE;
2684   }
2685
2686   /** Rekey with PFS */
2687   silc_fsm_next(fsm, silc_ske_st_initiator_phase2);
2688   return SILC_FSM_CONTINUE;
2689 }
2690
2691 /* Sends REKEY_DONE packet to finish the protocol. */
2692
2693 SILC_FSM_STATE(silc_ske_st_rekey_initiator_done)
2694 {
2695   SilcSKE ske = fsm_context;
2696   SilcCipher send_key;
2697   SilcHmac hmac_send;
2698   SilcHash hash;
2699   SilcUInt32 key_len, block_len, hash_len, x_len;
2700   unsigned char *pfsbuf;
2701
2702   SILC_LOG_DEBUG(("Start"));
2703
2704   silc_packet_get_keys(ske->stream, &send_key, NULL, &hmac_send, NULL);
2705   key_len = silc_cipher_get_key_len(send_key);
2706   block_len = silc_cipher_get_block_len(send_key);
2707   hash = ske->prop->hash;
2708   hash_len = silc_hash_len(hash);
2709
2710   /* Process key material */
2711   if (ske->rekey->pfs) {
2712     /* PFS */
2713     pfsbuf = silc_mp_mp2bin(ske->KEY, 0, &x_len);
2714     if (!pfsbuf) {
2715       SILC_LOG_ERROR(("Error processing key material"));
2716       silc_fsm_next(fsm, silc_ske_st_initiator_error);
2717       return SILC_FSM_CONTINUE;
2718     }
2719     ske->keymat = silc_ske_process_key_material_data(pfsbuf, x_len,
2720                                                      block_len, key_len,
2721                                                      hash_len, hash);
2722     memset(pfsbuf, 0, x_len);
2723     silc_free(pfsbuf);
2724   } else {
2725     /* No PFS */
2726     ske->keymat =
2727       silc_ske_process_key_material_data(ske->rekey->send_enc_key,
2728                                          ske->rekey->enc_key_len / 8,
2729                                          block_len, key_len,
2730                                          hash_len, hash);
2731   }
2732
2733   if (!ske->keymat) {
2734     SILC_LOG_ERROR(("Error processing key material"));
2735     silc_fsm_next(fsm, silc_ske_st_initiator_error);
2736     return SILC_FSM_CONTINUE;
2737   }
2738
2739   ske->prop->cipher = send_key;
2740   ske->prop->hmac = hmac_send;
2741
2742   /* Get sending keys */
2743   if (!silc_ske_set_keys(ske, ske->keymat, ske->prop, &send_key, NULL,
2744                          &hmac_send, NULL, NULL)) {
2745     /** Cannot get keys */
2746     ske->status = SILC_SKE_STATUS_ERROR;
2747     ske->prop->cipher = NULL;
2748     ske->prop->hmac = NULL;
2749     silc_fsm_next(fsm, silc_ske_st_initiator_error);
2750     return SILC_FSM_CONTINUE;
2751   }
2752
2753   ske->prop->cipher = NULL;
2754   ske->prop->hmac = NULL;
2755
2756   /* Set the new keys into use.  This will also send REKEY_DONE packet.  Any
2757      packet sent after this call will be protected with the new keys. */
2758   if (!silc_packet_set_keys(ske->stream, send_key, NULL, hmac_send, NULL,
2759                             TRUE)) {
2760     /** Cannot set keys */
2761     SILC_LOG_DEBUG(("Cannot set new keys, error sending REKEY_DONE"));
2762     ske->status = SILC_SKE_STATUS_ERROR;
2763     silc_cipher_free(send_key);
2764     silc_hmac_free(hmac_send);
2765     silc_fsm_next(fsm, silc_ske_st_initiator_error);
2766     return SILC_FSM_CONTINUE;
2767   }
2768
2769   /** Wait for REKEY_DONE */
2770   silc_fsm_next(fsm, silc_ske_st_rekey_initiator_end);
2771   return SILC_FSM_WAIT;
2772 }
2773
2774 /* Rekey protocol end */
2775
2776 SILC_FSM_STATE(silc_ske_st_rekey_initiator_end)
2777 {
2778   SilcSKE ske = fsm_context;
2779   SilcCipher receive_key;
2780   SilcHmac hmac_receive;
2781   SilcSKERekeyMaterial rekey;
2782
2783   SILC_LOG_DEBUG(("Start"));
2784
2785   if (ske->packet->type != SILC_PACKET_REKEY_DONE) {
2786     SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
2787     silc_packet_free(ske->packet);
2788     ske->packet = NULL;
2789     return SILC_FSM_WAIT;
2790   }
2791
2792   silc_packet_get_keys(ske->stream, NULL, &receive_key, NULL, &hmac_receive);
2793   ske->prop->cipher = receive_key;
2794   ske->prop->hmac = hmac_receive;
2795
2796   /* Get receiving keys */
2797   if (!silc_ske_set_keys(ske, ske->keymat, ske->prop, NULL, &receive_key,
2798                          NULL, &hmac_receive, NULL)) {
2799     /** Cannot get keys */
2800     ske->status = SILC_SKE_STATUS_ERROR;
2801     ske->prop->cipher = NULL;
2802     ske->prop->hmac = NULL;
2803     silc_fsm_next(fsm, silc_ske_st_initiator_error);
2804     return SILC_FSM_CONTINUE;
2805   }
2806
2807   /* Set new receiving keys into use.  All packets received after this will
2808      be decrypted with the new keys. */
2809   if (!silc_packet_set_keys(ske->stream, NULL, receive_key, NULL,
2810                             hmac_receive, FALSE)) {
2811     /** Cannot set keys */
2812     SILC_LOG_DEBUG(("Cannot set new keys"));
2813     ske->status = SILC_SKE_STATUS_ERROR;
2814     silc_cipher_free(receive_key);
2815     silc_hmac_free(hmac_receive);
2816     silc_fsm_next(fsm, silc_ske_st_initiator_error);
2817     return SILC_FSM_CONTINUE;
2818   }
2819
2820   SILC_LOG_DEBUG(("Rekey completed successfully"));
2821
2822   /* Generate new rekey material */
2823   rekey = silc_ske_make_rekey_material(ske, ske->keymat);
2824   if (!rekey) {
2825     /** No memory */
2826     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2827     ske->prop->cipher = NULL;
2828     ske->prop->hmac = NULL;
2829     silc_fsm_next(fsm, silc_ske_st_initiator_error);
2830     return SILC_FSM_CONTINUE;
2831   }
2832   rekey->pfs = ske->rekey->pfs;
2833   ske->rekey = rekey;
2834
2835   ske->prop->cipher = NULL;
2836   ske->prop->hmac = NULL;
2837   silc_packet_free(ske->packet);
2838   ske->packet = NULL;
2839   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2840   silc_schedule_task_del_by_context(ske->schedule, ske);
2841
2842   /* Call completion */
2843   silc_ske_completion(ske);
2844
2845   return SILC_FSM_FINISH;
2846 }
2847
2848 /* Starts rekey protocol as initiator */
2849
2850 SilcAsyncOperation
2851 silc_ske_rekey_initiator(SilcSKE ske,
2852                          SilcPacketStream stream,
2853                          SilcSKERekeyMaterial rekey)
2854 {
2855   SILC_LOG_DEBUG(("Start SKE rekey as initator"));
2856
2857   if (!ske || !stream || !rekey) {
2858     SILC_LOG_ERROR(("Missing arguments to silc_ske_rekey_initiator"));
2859     SILC_ASSERT(rekey);
2860     return NULL;
2861   }
2862
2863   if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
2864     return NULL;
2865
2866   if (!silc_fsm_init(&ske->fsm, ske, silc_ske_finished, ske, ske->schedule))
2867     return NULL;
2868
2869   ske->rekey = rekey;
2870   ske->responder = FALSE;
2871   ske->rekeying = TRUE;
2872   ++ske->refcnt;
2873
2874   /* Link to packet stream to get key exchange packets */
2875   ske->stream = stream;
2876   silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
2877                           SILC_PACKET_REKEY,
2878                           SILC_PACKET_REKEY_DONE,
2879                           SILC_PACKET_KEY_EXCHANGE_2,
2880                           SILC_PACKET_SUCCESS,
2881                           SILC_PACKET_FAILURE, -1);
2882
2883   /* Start SKE rekey as initiator */
2884   silc_fsm_start(&ske->fsm, silc_ske_st_rekey_initiator_start);
2885
2886   return &ske->op;
2887 }
2888
2889 /***************************** Responder Rekey ******************************/
2890
2891 /* Wait for initiator's packet */
2892
2893 SILC_FSM_STATE(silc_ske_st_rekey_responder_wait)
2894 {
2895   SilcSKE ske = fsm_context;
2896
2897   SILC_LOG_DEBUG(("Start rekey (%s)", ske->rekey->pfs ? "PFS" : "No PFS"));
2898
2899   if (ske->aborted) {
2900     /** Aborted */
2901     silc_fsm_next(fsm, silc_ske_st_responder_aborted);
2902     return SILC_FSM_CONTINUE;
2903   }
2904
2905   /* Add rekey exchange timeout */
2906   silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout,
2907                                  ske, 30, 0);
2908
2909   silc_fsm_next(fsm, silc_ske_st_rekey_responder_start);
2910
2911   /* If REKEY packet already received process it directly */
2912   if (ske->packet && ske->packet->type == SILC_PACKET_REKEY)
2913     return SILC_FSM_CONTINUE;
2914
2915   /* Wait for REKEY */
2916   return SILC_FSM_WAIT;
2917 }
2918
2919 /* Process initiator's REKEY packet */
2920
2921 SILC_FSM_STATE(silc_ske_st_rekey_responder_start)
2922 {
2923   SilcSKE ske = fsm_context;
2924   SilcSKEStatus status;
2925
2926   SILC_LOG_DEBUG(("Start"));
2927
2928   if (ske->packet->type != SILC_PACKET_REKEY) {
2929     ske->status = SILC_SKE_STATUS_ERROR;
2930     silc_packet_free(ske->packet);
2931     ske->packet = NULL;
2932     silc_fsm_next(fsm, silc_ske_st_responder_error);
2933     return SILC_FSM_CONTINUE;
2934   }
2935
2936   ske->prop = silc_calloc(1, sizeof(*ske->prop));
2937   if (!ske->prop) {
2938     /** No memory */
2939     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2940     silc_fsm_next(fsm, silc_ske_st_responder_error);
2941     return SILC_FSM_CONTINUE;
2942   }
2943
2944   if (!silc_hash_alloc(ske->rekey->hash, &ske->prop->hash)) {
2945     /** Cannot allocate hash */
2946     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2947     silc_fsm_next(fsm, silc_ske_st_responder_error);
2948     return SILC_FSM_CONTINUE;
2949   }
2950
2951   /* If doing rekey without PFS, move directly to the end of the protocol. */
2952   if (!ske->rekey->pfs) {
2953     /** Rekey without PFS */
2954     silc_fsm_next(fsm, silc_ske_st_rekey_responder_done);
2955     return SILC_FSM_CONTINUE;
2956   }
2957
2958   status = silc_ske_group_get_by_number(ske->rekey->ske_group,
2959                                         &ske->prop->group);
2960   if (status != SILC_SKE_STATUS_OK) {
2961     /** Unknown group */
2962     silc_fsm_next(fsm, silc_ske_st_responder_error);
2963     return SILC_FSM_CONTINUE;
2964   }
2965
2966   /** Rekey with PFS */
2967   silc_fsm_next(fsm, silc_ske_st_responder_phase2);
2968   return SILC_FSM_WAIT;
2969 }
2970
2971 /* Sends REKEY_DONE packet to finish the protocol. */
2972
2973 SILC_FSM_STATE(silc_ske_st_rekey_responder_done)
2974 {
2975   SilcSKE ske = fsm_context;
2976   SilcCipher send_key;
2977   SilcHmac hmac_send;
2978   SilcHash hash;
2979   SilcUInt32 key_len, block_len, hash_len, x_len;
2980   unsigned char *pfsbuf;
2981
2982   SILC_LOG_DEBUG(("Start"));
2983
2984   silc_packet_get_keys(ske->stream, &send_key, NULL, &hmac_send, NULL);
2985   key_len = silc_cipher_get_key_len(send_key);
2986   block_len = silc_cipher_get_block_len(send_key);
2987   hash = ske->prop->hash;
2988   hash_len = silc_hash_len(hash);
2989
2990   /* Process key material */
2991   if (ske->rekey->pfs) {
2992     /* PFS */
2993     pfsbuf = silc_mp_mp2bin(ske->KEY, 0, &x_len);
2994     if (!pfsbuf) {
2995       SILC_LOG_ERROR(("Error processing key material"));
2996       silc_fsm_next(fsm, silc_ske_st_responder_error);
2997       return SILC_FSM_CONTINUE;
2998     }
2999     ske->keymat = silc_ske_process_key_material_data(pfsbuf, x_len,
3000                                                      block_len, key_len,
3001                                                      hash_len, hash);
3002     memset(pfsbuf, 0, x_len);
3003     silc_free(pfsbuf);
3004   } else {
3005     /* No PFS */
3006     ske->keymat =
3007       silc_ske_process_key_material_data(ske->rekey->send_enc_key,
3008                                          ske->rekey->enc_key_len / 8,
3009                                          block_len, key_len,
3010                                          hash_len, hash);
3011   }
3012
3013   if (!ske->keymat) {
3014     SILC_LOG_ERROR(("Error processing key material"));
3015     silc_fsm_next(fsm, silc_ske_st_responder_error);
3016     return SILC_FSM_CONTINUE;
3017   }
3018
3019   ske->prop->cipher = send_key;
3020   ske->prop->hmac = hmac_send;
3021
3022   /* Get sending keys */
3023   if (!silc_ske_set_keys(ske, ske->keymat, ske->prop, &send_key, NULL,
3024                          &hmac_send, NULL, NULL)) {
3025     /** Cannot get keys */
3026     ske->status = SILC_SKE_STATUS_ERROR;
3027     ske->prop->cipher = NULL;
3028     ske->prop->hmac = NULL;
3029     silc_fsm_next(fsm, silc_ske_st_responder_error);
3030     return SILC_FSM_CONTINUE;
3031   }
3032
3033   ske->prop->cipher = NULL;
3034   ske->prop->hmac = NULL;
3035
3036   /* Set the new keys into use.  This will also send REKEY_DONE packet.  Any
3037      packet sent after this call will be protected with the new keys. */
3038   if (!silc_packet_set_keys(ske->stream, send_key, NULL, hmac_send, NULL,
3039                             TRUE)) {
3040     /** Cannot set keys */
3041     SILC_LOG_DEBUG(("Cannot set new keys, error sending REKEY_DONE"));
3042     ske->status = SILC_SKE_STATUS_ERROR;
3043     silc_cipher_free(send_key);
3044     silc_hmac_free(hmac_send);
3045     silc_fsm_next(fsm, silc_ske_st_responder_error);
3046     return SILC_FSM_CONTINUE;
3047   }
3048
3049   /** Wait for REKEY_DONE */
3050   silc_fsm_next(fsm, silc_ske_st_rekey_responder_end);
3051   return SILC_FSM_WAIT;
3052 }
3053
3054 /* Rekey protocol end */
3055
3056 SILC_FSM_STATE(silc_ske_st_rekey_responder_end)
3057 {
3058   SilcSKE ske = fsm_context;
3059   SilcCipher receive_key;
3060   SilcHmac hmac_receive;
3061   SilcSKERekeyMaterial rekey;
3062
3063   SILC_LOG_DEBUG(("Start"));
3064
3065   if (ske->packet->type != SILC_PACKET_REKEY_DONE) {
3066     SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
3067     silc_packet_free(ske->packet);
3068     ske->packet = NULL;
3069     return SILC_FSM_WAIT;
3070   }
3071
3072   silc_packet_get_keys(ske->stream, NULL, &receive_key, NULL, &hmac_receive);
3073   ske->prop->cipher = receive_key;
3074   ske->prop->hmac = hmac_receive;
3075
3076   /* Get receiving keys */
3077   if (!silc_ske_set_keys(ske, ske->keymat, ske->prop, NULL, &receive_key,
3078                          NULL, &hmac_receive, NULL)) {
3079     /** Cannot get keys */
3080     ske->status = SILC_SKE_STATUS_ERROR;
3081     ske->prop->cipher = NULL;
3082     ske->prop->hmac = NULL;
3083     silc_fsm_next(fsm, silc_ske_st_responder_error);
3084     return SILC_FSM_CONTINUE;
3085   }
3086
3087   /* Set new receiving keys into use.  All packets received after this will
3088      be decrypted with the new keys. */
3089   if (!silc_packet_set_keys(ske->stream, NULL, receive_key, NULL,
3090                             hmac_receive, FALSE)) {
3091     /** Cannot set keys */
3092     SILC_LOG_DEBUG(("Cannot set new keys"));
3093     ske->status = SILC_SKE_STATUS_ERROR;
3094     ske->prop->cipher = NULL;
3095     ske->prop->hmac = NULL;
3096     silc_cipher_free(receive_key);
3097     silc_hmac_free(hmac_receive);
3098     silc_fsm_next(fsm, silc_ske_st_responder_error);
3099     return SILC_FSM_CONTINUE;
3100   }
3101
3102   SILC_LOG_DEBUG(("Rekey completed successfully"));
3103
3104   /* Generate new rekey material */
3105   rekey = silc_ske_make_rekey_material(ske, ske->keymat);
3106   if (!rekey) {
3107     /** No memory */
3108     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
3109     ske->prop->cipher = NULL;
3110     ske->prop->hmac = NULL;
3111     silc_fsm_next(fsm, silc_ske_st_responder_error);
3112     return SILC_FSM_CONTINUE;
3113   }
3114   rekey->pfs = ske->rekey->pfs;
3115   ske->rekey = rekey;
3116
3117   ske->prop->cipher = NULL;
3118   ske->prop->hmac = NULL;
3119   silc_packet_free(ske->packet);
3120   ske->packet = NULL;
3121   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
3122   silc_schedule_task_del_by_context(ske->schedule, ske);
3123
3124   /* Call completion */
3125   silc_ske_completion(ske);
3126
3127   return SILC_FSM_FINISH;
3128 }
3129
3130 /* Starts rekey protocol as responder */
3131
3132 SilcAsyncOperation
3133 silc_ske_rekey_responder(SilcSKE ske,
3134                          SilcPacketStream stream,
3135                          SilcSKERekeyMaterial rekey,
3136                          SilcPacket packet)
3137 {
3138   SILC_LOG_DEBUG(("Start SKE rekey as responder"));
3139
3140   if (!ske || !stream || !rekey)
3141     return NULL;
3142
3143   if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
3144     return NULL;
3145
3146   if (!silc_fsm_init(&ske->fsm, ske, silc_ske_finished, ske, ske->schedule))
3147     return NULL;
3148
3149   ske->rekey = rekey;
3150   ske->responder = TRUE;
3151   ske->rekeying = TRUE;
3152   ske->packet = packet;
3153   ++ske->refcnt;
3154
3155   /* Link to packet stream to get key exchange packets */
3156   ske->stream = stream;
3157   silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
3158                           SILC_PACKET_REKEY,
3159                           SILC_PACKET_REKEY_DONE,
3160                           SILC_PACKET_KEY_EXCHANGE_1,
3161                           SILC_PACKET_SUCCESS,
3162                           SILC_PACKET_FAILURE, -1);
3163
3164   /* Start SKE rekey as responder */
3165   silc_fsm_start_sync(&ske->fsm, silc_ske_st_rekey_responder_wait);
3166
3167   return &ske->op;
3168 }
3169
3170 /* Processes the provided key material `data' as the SILC protocol
3171    specification defines. */
3172
3173 SilcSKEKeyMaterial
3174 silc_ske_process_key_material_data(unsigned char *data,
3175                                    SilcUInt32 data_len,
3176                                    SilcUInt32 req_iv_len,
3177                                    SilcUInt32 req_enc_key_len,
3178                                    SilcUInt32 req_hmac_key_len,
3179                                    SilcHash hash)
3180 {
3181   SilcBuffer buf;
3182   unsigned char hashd[SILC_HASH_MAXLEN];
3183   SilcUInt32 hash_len = req_hmac_key_len;
3184   SilcUInt32 enc_key_len = req_enc_key_len / 8;
3185   SilcSKEKeyMaterial key;
3186
3187   SILC_LOG_DEBUG(("Start"));
3188
3189   if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
3190     return NULL;
3191
3192   key = silc_calloc(1, sizeof(*key));
3193   if (!key)
3194     return NULL;
3195
3196   buf = silc_buffer_alloc_size(1 + data_len);
3197   if (!buf)
3198     return NULL;
3199   silc_buffer_format(buf,
3200                      SILC_STR_UI_CHAR(0),
3201                      SILC_STR_DATA(data, data_len),
3202                      SILC_STR_END);
3203
3204   /* Take IVs */
3205   memset(hashd, 0, sizeof(hashd));
3206   buf->data[0] = 0;
3207   silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
3208   key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
3209   if (!key->send_iv) {
3210     silc_buffer_clear(buf);
3211     silc_buffer_free(buf);
3212     silc_free(key);
3213     return NULL;
3214   }
3215   memcpy(key->send_iv, hashd, req_iv_len);
3216   memset(hashd, 0, sizeof(hashd));
3217   buf->data[0] = 1;
3218   silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
3219   key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
3220   if (!key->receive_iv) {
3221     silc_buffer_clear(buf);
3222     silc_buffer_free(buf);
3223     silc_free(key);
3224     return NULL;
3225   }
3226   memcpy(key->receive_iv, hashd, req_iv_len);
3227   key->iv_len = req_iv_len;
3228
3229   /* Take the encryption keys. If requested key size is more than
3230      the size of hash length we will distribute more key material
3231      as protocol defines. */
3232   buf->data[0] = 2;
3233   if (enc_key_len > hash_len) {
3234     SilcBuffer dist;
3235     unsigned char k1[SILC_HASH_MAXLEN], k2[SILC_HASH_MAXLEN],
3236         k3[SILC_HASH_MAXLEN];
3237     unsigned char *dtmp;
3238
3239     /* XXX */
3240     if (enc_key_len > (3 * hash_len))
3241       return NULL;
3242
3243     /* Take first round */
3244     memset(k1, 0, sizeof(k1));
3245     silc_hash_make(hash, buf->data, silc_buffer_len(buf), k1);
3246
3247     /* Take second round */
3248     dist = silc_buffer_alloc_size(data_len + hash_len);
3249     if (!dist)
3250       return NULL;
3251     silc_buffer_format(dist,
3252                        SILC_STR_DATA(data, data_len),
3253                        SILC_STR_DATA(k1, hash_len),
3254                        SILC_STR_END);
3255     memset(k2, 0, sizeof(k2));
3256     silc_hash_make(hash, dist->data, silc_buffer_len(dist), k2);
3257
3258     /* Take third round */
3259     dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
3260     silc_buffer_pull_tail(dist, hash_len);
3261     silc_buffer_pull(dist, data_len + hash_len);
3262     silc_buffer_format(dist,
3263                        SILC_STR_DATA(k2, hash_len),
3264                        SILC_STR_END);
3265     silc_buffer_push(dist, data_len + hash_len);
3266     memset(k3, 0, sizeof(k3));
3267     silc_hash_make(hash, dist->data, silc_buffer_len(dist), k3);
3268
3269     /* Then, save the keys */
3270     dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
3271     if (!dtmp) {
3272       silc_buffer_clear(buf);
3273       silc_buffer_free(buf);
3274       silc_free(key);
3275       return NULL;
3276     }
3277     memcpy(dtmp, k1, hash_len);
3278     memcpy(dtmp + hash_len, k2, hash_len);
3279     memcpy(dtmp + hash_len + hash_len, k3, hash_len);
3280
3281     key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
3282     if (!key->send_enc_key) {
3283       silc_buffer_clear(buf);
3284       silc_buffer_free(buf);
3285       silc_free(key);
3286       silc_free(dtmp);
3287       return NULL;
3288     }
3289     memcpy(key->send_enc_key, dtmp, enc_key_len);
3290     key->enc_key_len = req_enc_key_len;
3291
3292     memset(dtmp, 0, (3 * hash_len));
3293     memset(k1, 0, sizeof(k1));
3294     memset(k2, 0, sizeof(k2));
3295     memset(k3, 0, sizeof(k3));
3296     silc_free(dtmp);
3297     silc_buffer_clear(dist);
3298     silc_buffer_free(dist);
3299   } else {
3300     /* Take normal hash as key */
3301     memset(hashd, 0, sizeof(hashd));
3302     silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
3303     key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
3304     if (!key->send_enc_key) {
3305       silc_buffer_clear(buf);
3306       silc_buffer_free(buf);
3307       silc_free(key);
3308       return NULL;
3309     }
3310     memcpy(key->send_enc_key, hashd, enc_key_len);
3311     key->enc_key_len = req_enc_key_len;
3312   }
3313
3314   buf->data[0] = 3;
3315   if (enc_key_len > hash_len) {
3316     SilcBuffer dist;
3317     unsigned char k1[SILC_HASH_MAXLEN], k2[SILC_HASH_MAXLEN],
3318         k3[SILC_HASH_MAXLEN];
3319     unsigned char *dtmp;
3320
3321     /* XXX */
3322     if (enc_key_len > (3 * hash_len))
3323       return NULL;
3324
3325     /* Take first round */
3326     memset(k1, 0, sizeof(k1));
3327     silc_hash_make(hash, buf->data, silc_buffer_len(buf), k1);
3328
3329     /* Take second round */
3330     dist = silc_buffer_alloc_size(data_len + hash_len);
3331     if (!dist)
3332       return NULL;
3333     silc_buffer_format(dist,
3334                        SILC_STR_DATA(data, data_len),
3335                        SILC_STR_DATA(k1, hash_len),
3336                        SILC_STR_END);
3337     memset(k2, 0, sizeof(k2));
3338     silc_hash_make(hash, dist->data, silc_buffer_len(dist), k2);
3339
3340     /* Take third round */
3341     dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
3342     silc_buffer_pull_tail(dist, hash_len);
3343     silc_buffer_pull(dist, data_len + hash_len);
3344     silc_buffer_format(dist,
3345                        SILC_STR_DATA(k2, hash_len),
3346                        SILC_STR_END);
3347     silc_buffer_push(dist, data_len + hash_len);
3348     memset(k3, 0, sizeof(k3));
3349     silc_hash_make(hash, dist->data, silc_buffer_len(dist), k3);
3350
3351     /* Then, save the keys */
3352     dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
3353     if (!dtmp) {
3354       silc_buffer_clear(buf);
3355       silc_buffer_free(buf);
3356       silc_free(key);
3357       return NULL;
3358     }
3359     memcpy(dtmp, k1, hash_len);
3360     memcpy(dtmp + hash_len, k2, hash_len);
3361     memcpy(dtmp + hash_len + hash_len, k3, hash_len);
3362
3363     key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
3364     if (!key->receive_enc_key) {
3365       silc_buffer_clear(buf);
3366       silc_buffer_free(buf);
3367       silc_free(key);
3368       silc_free(dtmp);
3369       return NULL;
3370     }
3371     memcpy(key->receive_enc_key, dtmp, enc_key_len);
3372     key->enc_key_len = req_enc_key_len;
3373
3374     memset(dtmp, 0, (3 * hash_len));
3375     memset(k1, 0, sizeof(k1));
3376     memset(k2, 0, sizeof(k2));
3377     memset(k3, 0, sizeof(k3));
3378     silc_free(dtmp);
3379     silc_buffer_clear(dist);
3380     silc_buffer_free(dist);
3381   } else {
3382     /* Take normal hash as key */
3383     memset(hashd, 0, sizeof(hashd));
3384     silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
3385     key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
3386     if (!key->receive_enc_key) {
3387       silc_buffer_clear(buf);
3388       silc_buffer_free(buf);
3389       silc_free(key);
3390       return NULL;
3391     }
3392     memcpy(key->receive_enc_key, hashd, enc_key_len);
3393     key->enc_key_len = req_enc_key_len;
3394   }
3395
3396   /* Take HMAC keys */
3397   memset(hashd, 0, sizeof(hashd));
3398   buf->data[0] = 4;
3399   silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
3400   key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
3401   if (!key->send_hmac_key) {
3402     silc_buffer_clear(buf);
3403     silc_buffer_free(buf);
3404     silc_free(key);
3405     return NULL;
3406   }
3407   memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
3408   memset(hashd, 0, sizeof(hashd));
3409   buf->data[0] = 5;
3410   silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
3411   key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
3412   if (!key->receive_hmac_key) {
3413     silc_buffer_clear(buf);
3414     silc_buffer_free(buf);
3415     silc_free(key);
3416     return NULL;
3417   }
3418   memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
3419   key->hmac_key_len = req_hmac_key_len;
3420   memset(hashd, 0, sizeof(hashd));
3421
3422   silc_buffer_clear(buf);
3423   silc_buffer_free(buf);
3424
3425   SILC_LOG_HEXDUMP(("enc"), key->send_enc_key, key->enc_key_len / 8);
3426
3427   return key;
3428 }
3429
3430 /* Processes negotiated key material as protocol specifies. This returns
3431    the actual keys to be used in the SILC. */
3432
3433 SilcSKEKeyMaterial
3434 silc_ske_process_key_material(SilcSKE ske,
3435                               SilcUInt32 req_iv_len,
3436                               SilcUInt32 req_enc_key_len,
3437                               SilcUInt32 req_hmac_key_len,
3438                               SilcSKERekeyMaterial *rekey)
3439 {
3440   SilcBuffer buf;
3441   unsigned char *tmpbuf;
3442   SilcUInt32 klen;
3443   SilcSKEKeyMaterial key;
3444
3445   /* Encode KEY to binary data */
3446   tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
3447
3448   buf = silc_buffer_alloc_size(klen + ske->hash_len);
3449   if (!buf)
3450     return NULL;
3451   silc_buffer_format(buf,
3452                      SILC_STR_DATA(tmpbuf, klen),
3453                      SILC_STR_DATA(ske->hash, ske->hash_len),
3454                      SILC_STR_END);
3455
3456   /* Process the key material */
3457   key = silc_ske_process_key_material_data(buf->data, silc_buffer_len(buf),
3458                                            req_iv_len, req_enc_key_len,
3459                                            req_hmac_key_len,
3460                                            ske->prop->hash);
3461
3462   memset(tmpbuf, 0, klen);
3463   silc_free(tmpbuf);
3464   silc_buffer_clear(buf);
3465   silc_buffer_free(buf);
3466
3467   if (rekey) {
3468     *rekey = silc_ske_make_rekey_material(ske, key);
3469     if (!(*rekey))
3470       return NULL;
3471   }
3472
3473   return key;
3474 }
3475
3476 /* Free key material structure */
3477
3478 void silc_ske_free_key_material(SilcSKEKeyMaterial key)
3479 {
3480   if (!key)
3481     return;
3482
3483   if (key->send_iv)
3484     silc_free(key->send_iv);
3485   if (key->receive_iv)
3486     silc_free(key->receive_iv);
3487   if (key->send_enc_key) {
3488     memset(key->send_enc_key, 0, key->enc_key_len / 8);
3489     silc_free(key->send_enc_key);
3490   }
3491   if (key->receive_enc_key) {
3492     memset(key->receive_enc_key, 0, key->enc_key_len / 8);
3493     silc_free(key->receive_enc_key);
3494   }
3495   if (key->send_hmac_key) {
3496     memset(key->send_hmac_key, 0, key->hmac_key_len);
3497     silc_free(key->send_hmac_key);
3498   }
3499   if (key->receive_hmac_key) {
3500     memset(key->receive_hmac_key, 0, key->hmac_key_len);
3501     silc_free(key->receive_hmac_key);
3502   }
3503   silc_free(key);
3504 }
3505
3506 /* Free rekey material */
3507
3508 void silc_ske_free_rekey_material(SilcSKERekeyMaterial rekey)
3509 {
3510   if (!rekey)
3511     return;
3512   if (rekey->send_enc_key) {
3513     memset(rekey->send_enc_key, 0, rekey->enc_key_len / 8);
3514     silc_free(rekey->send_enc_key);
3515   }
3516   silc_free(rekey->hash);
3517   silc_free(rekey);
3518 }
3519
3520 /* Set keys into use */
3521
3522 SilcBool silc_ske_set_keys(SilcSKE ske,
3523                            SilcSKEKeyMaterial keymat,
3524                            SilcSKESecurityProperties prop,
3525                            SilcCipher *ret_send_key,
3526                            SilcCipher *ret_receive_key,
3527                            SilcHmac *ret_hmac_send,
3528                            SilcHmac *ret_hmac_receive,
3529                            SilcHash *ret_hash)
3530 {
3531   unsigned char iv[SILC_HASH_MAXLEN];
3532   SilcBool iv_included = (prop->flags & SILC_SKE_SP_FLAG_IV_INCLUDED);
3533
3534   /* Allocate ciphers to be used in the communication */
3535   if (ret_send_key) {
3536     if (!silc_cipher_alloc((char *)silc_cipher_get_name(prop->cipher),
3537                            ret_send_key))
3538       return FALSE;
3539   }
3540   if (ret_receive_key) {
3541     if (!silc_cipher_alloc((char *)silc_cipher_get_name(prop->cipher),
3542                            ret_receive_key))
3543       return FALSE;
3544   }
3545
3546   /* Allocate HMACs */
3547   if (ret_hmac_send) {
3548     if (!silc_hmac_alloc((char *)silc_hmac_get_name(prop->hmac), NULL,
3549                          ret_hmac_send))
3550       return FALSE;
3551   }
3552   if (ret_hmac_receive) {
3553     if (!silc_hmac_alloc((char *)silc_hmac_get_name(prop->hmac), NULL,
3554                          ret_hmac_receive))
3555       return FALSE;
3556   }
3557
3558   /* Allocate hash */
3559   if (ret_hash) {
3560     if (!silc_hash_alloc(silc_hash_get_name(prop->hash), ret_hash))
3561       return FALSE;
3562   }
3563
3564   /* Set key material */
3565   memset(iv, 0, sizeof(iv));
3566   if (ske->responder) {
3567     if (ret_send_key) {
3568       silc_cipher_set_key(*ret_send_key, keymat->receive_enc_key,
3569                           keymat->enc_key_len, TRUE);
3570
3571       if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) {
3572         /* Counter mode */
3573         if (!ske->rekeying) {
3574           /* Set IV. */
3575           memcpy(iv, ske->hash, 4);
3576           if (!iv_included)
3577             memcpy(iv + 4, keymat->receive_iv, 8);
3578         } else {
3579           /* Rekey, recompute the truncated hash value. */
3580           silc_hash_make(prop->hash, keymat->receive_iv, 8, iv);
3581           if (!iv_included)
3582             memcpy(iv + 4, keymat->receive_iv, 8);
3583           else
3584             memset(iv + 4, 0, 12);
3585         }
3586
3587         silc_cipher_set_iv(*ret_send_key, iv);
3588       } else {
3589         /* Other modes */
3590         silc_cipher_set_iv(*ret_send_key, keymat->receive_iv);
3591       }
3592     }
3593     if (ret_receive_key) {
3594       silc_cipher_set_key(*ret_receive_key, keymat->send_enc_key,
3595                           keymat->enc_key_len, FALSE);
3596
3597       if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) {
3598         /* Counter mode */
3599         if (!ske->rekeying) {
3600           /* Set IV. */
3601           memcpy(iv, ske->hash, 4);
3602           if (!iv_included)
3603             memcpy(iv + 4, keymat->send_iv, 8);
3604         } else {
3605           /* Rekey, recompute the truncated hash value. */
3606           silc_hash_make(prop->hash, keymat->send_iv, 8, iv);
3607           if (!iv_included)
3608             memcpy(iv + 4, keymat->send_iv, 8);
3609           else
3610             memset(iv + 4, 0, 12);
3611         }
3612
3613         silc_cipher_set_iv(*ret_receive_key, iv);
3614       } else {
3615         /* Other modes */
3616         silc_cipher_set_iv(*ret_receive_key, keymat->send_iv);
3617       }
3618     }
3619     if (ret_hmac_send)
3620       silc_hmac_set_key(*ret_hmac_send, keymat->receive_hmac_key,
3621                         keymat->hmac_key_len);
3622     if (ret_hmac_receive)
3623       silc_hmac_set_key(*ret_hmac_receive, keymat->send_hmac_key,
3624                         keymat->hmac_key_len);
3625   } else {
3626     if (ret_send_key) {
3627       silc_cipher_set_key(*ret_send_key, keymat->send_enc_key,
3628                           keymat->enc_key_len, TRUE);
3629
3630       if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) {
3631         /* Counter mode */
3632         if (!ske->rekeying) {
3633           /* Set IV. */
3634           memcpy(iv, ske->hash, 4);
3635           if (!iv_included)
3636             memcpy(iv + 4, keymat->send_iv, 8);
3637         } else {
3638           /* Rekey, recompute the truncated hash value. */
3639           silc_hash_make(prop->hash, keymat->send_iv, 8, iv);
3640           if (!iv_included)
3641             memcpy(iv + 4, keymat->send_iv, 8);
3642           else
3643             memset(iv + 4, 0, 12);
3644         }
3645
3646         silc_cipher_set_iv(*ret_send_key, iv);
3647       } else {
3648         /* Other modes */
3649         silc_cipher_set_iv(*ret_send_key, keymat->send_iv);
3650       }
3651     }
3652     if (ret_receive_key) {
3653       silc_cipher_set_key(*ret_receive_key, keymat->receive_enc_key,
3654                           keymat->enc_key_len, FALSE);
3655
3656       if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) {
3657         /* Counter mode */
3658         if (!ske->rekeying) {
3659           /* Set IV.  If IV Included flag was negotiated we only set the
3660              truncated hash value. */
3661           memcpy(iv, ske->hash, 4);
3662           if (!iv_included)
3663             memcpy(iv + 4, keymat->receive_iv, 8);
3664         } else {
3665           /* Rekey, recompute the truncated hash value. */
3666           silc_hash_make(prop->hash, keymat->receive_iv, 8, iv);
3667           if (!iv_included)
3668             memcpy(iv + 4, keymat->receive_iv, 8);
3669           else
3670             memset(iv + 4, 0, 12);
3671         }
3672
3673         silc_cipher_set_iv(*ret_receive_key, iv);
3674       } else {
3675         /* Other modes */
3676         silc_cipher_set_iv(*ret_receive_key, keymat->receive_iv);
3677       }
3678     }
3679     if (ret_hmac_send)
3680       silc_hmac_set_key(*ret_hmac_send, keymat->send_hmac_key,
3681                         keymat->hmac_key_len);
3682     if (ret_hmac_receive)
3683       silc_hmac_set_key(*ret_hmac_receive, keymat->receive_hmac_key,
3684                         keymat->hmac_key_len);
3685   }
3686
3687   return TRUE;
3688 }
3689
3690 const char *silc_ske_status_string[] =
3691 {
3692   /* Official */
3693   "Ok",
3694   "Unexpected error occurred",
3695   "Bad payload in packet",
3696   "Unsupported group",
3697   "Unsupported cipher",
3698   "Unsupported PKCS",
3699   "Unsupported hash function",
3700   "Unsupported HMAC",
3701   "Public key not accepted",
3702   "Incorrect signature",
3703   "Bad or unsupported version",
3704   "Invalid cookie",
3705
3706   /* Other errors */
3707   "Remote did not provide public key",
3708   "Bad reserved field in packet",
3709   "Bad payload length in packet",
3710   "Error computing signature",
3711   "System out of memory",
3712   "Key exchange timeout",
3713   "Key exchange timeout",
3714
3715   NULL
3716 };
3717
3718 /* Maps status to readable string and returns the string. If string is not
3719    found and empty character string ("") is returned. */
3720
3721 const char *silc_ske_map_status(SilcSKEStatus status)
3722 {
3723   int i;
3724
3725   for (i = 0; silc_ske_status_string[i]; i++)
3726     if (status == i)
3727       return silc_ske_status_string[i];
3728
3729   return "";
3730 }
3731
3732 /* Parses remote host's version string. */
3733
3734 SilcBool silc_ske_parse_version(SilcSKE ske,
3735                                 SilcUInt32 *protocol_version,
3736                                 char **protocol_version_string,
3737                                 SilcUInt32 *software_version,
3738                                 char **software_version_string,
3739                                 char **vendor_version)
3740 {
3741   return silc_parse_version_string(ske->remote_version,
3742                                    protocol_version,
3743                                    protocol_version_string,
3744                                    software_version,
3745                                    software_version_string,
3746                                    vendor_version);
3747 }
3748
3749 /* Get security properties */
3750
3751 SilcSKESecurityProperties silc_ske_get_security_properties(SilcSKE ske)
3752 {
3753   return ske->prop;
3754 }
3755
3756 /* Get key material */
3757
3758 SilcSKEKeyMaterial silc_ske_get_key_material(SilcSKE ske)
3759 {
3760   return ske->keymat;
3761 }