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