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