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