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