Search keys from repository with KEY_AGREEMENT usage.
[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     ske->status = SILC_SKE_STATUS_ERROR;
954     silc_fsm_next(fsm, silc_ske_st_initiator_error);
955     return SILC_FSM_CONTINUE;
956   }
957
958   /* XXX timeout */
959
960   /** Wait for responder proposal */
961   SILC_LOG_DEBUG(("Waiting for reponder proposal"));
962   silc_fsm_next(fsm, silc_ske_st_initiator_phase1);
963   return SILC_FSM_WAIT;
964 }
965
966 /* Phase-1.  Receives responder's proposal */
967
968 SILC_FSM_STATE(silc_ske_st_initiator_phase1)
969 {
970   SilcSKE ske = fsm_context;
971   SilcSKEStatus status;
972   SilcSKEStartPayload payload;
973   SilcSKESecurityProperties prop;
974   SilcSKEDiffieHellmanGroup group;
975   SilcBuffer packet_buf = &ske->packet->buffer;
976   SilcUInt16 remote_port = 0;
977   SilcID id;
978   int coff = 0;
979
980   SILC_LOG_DEBUG(("Start"));
981
982   if (ske->aborted) {
983     /** Aborted */
984     silc_packet_free(ske->packet);
985     silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
986     return SILC_FSM_CONTINUE;
987   }
988
989   /* Decode the payload */
990   status = silc_ske_payload_start_decode(ske, packet_buf, &payload);
991   if (status != SILC_SKE_STATUS_OK) {
992     /** Error decoding Start Payload */
993     silc_packet_free(ske->packet);
994     ske->status = status;
995     silc_fsm_next(fsm, silc_ske_st_initiator_error);
996     return SILC_FSM_CONTINUE;
997   }
998
999   /* Get remote ID and set it to stream */
1000   if (ske->packet->src_id_len) {
1001     silc_id_str2id(ske->packet->src_id, ske->packet->src_id_len,
1002                    ske->packet->src_id_type,
1003                    (ske->packet->src_id_type == SILC_ID_SERVER ?
1004                     (void *)&id.u.server_id : (void *)&id.u.client_id),
1005                    (ske->packet->src_id_type == SILC_ID_SERVER ?
1006                     sizeof(id.u.server_id) : sizeof(id.u.client_id)));
1007     silc_packet_set_ids(ske->stream, 0, NULL, ske->packet->src_id_type,
1008                         (ske->packet->src_id_type == SILC_ID_SERVER ?
1009                          (void *)&id.u.server_id : (void *)&id.u.client_id));
1010   }
1011
1012   silc_packet_free(ske->packet);
1013
1014   /* Check that the cookie is returned unmodified.  In case IV included
1015      flag and session port has been set, the first two bytes of cookie
1016      are the session port and we ignore them in this check. */
1017   if (payload->flags & SILC_SKE_SP_FLAG_IV_INCLUDED && ske->session_port) {
1018     /* Take remote port */
1019     SILC_GET16_MSB(remote_port, ske->start_payload->cookie);
1020     coff = 2;
1021   }
1022   if (memcmp(ske->start_payload->cookie + coff, payload->cookie + coff,
1023              SILC_SKE_COOKIE_LEN - coff)) {
1024     /** Invalid cookie */
1025     SILC_LOG_ERROR(("Invalid cookie, modified or unsupported feature"));
1026     ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
1027     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1028     return SILC_FSM_CONTINUE;
1029   }
1030
1031   /* Check version string */
1032   ske->remote_version = silc_memdup(payload->version, payload->version_len);
1033   status = silc_ske_check_version(ske);
1034   if (status != SILC_SKE_STATUS_OK) {
1035     /** Version mismatch */
1036     ske->status = status;
1037     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1038     return SILC_FSM_CONTINUE;
1039   }
1040
1041   /* Free our KE Start Payload context, we don't need it anymore. */
1042   silc_ske_payload_start_free(ske->start_payload);
1043   ske->start_payload = NULL;
1044
1045   /* Take the selected security properties into use while doing
1046      the key exchange.  This is used only while doing the key
1047      exchange. */
1048   ske->prop = prop = silc_calloc(1, sizeof(*prop));
1049   if (!ske->prop)
1050     goto err;
1051   prop->flags = payload->flags;
1052   status = silc_ske_group_get_by_name(payload->ke_grp_list, &group);
1053   if (status != SILC_SKE_STATUS_OK)
1054     goto err;
1055
1056   prop->group = group;
1057   prop->remote_port = remote_port;
1058
1059   if (silc_pkcs_find_algorithm(payload->pkcs_alg_list, NULL) == NULL) {
1060     status = SILC_SKE_STATUS_UNKNOWN_PKCS;
1061     goto err;
1062   }
1063   if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
1064     status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
1065     goto err;
1066   }
1067   if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
1068     status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1069     goto err;
1070   }
1071   if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
1072     status = SILC_SKE_STATUS_UNKNOWN_HMAC;
1073     goto err;
1074   }
1075
1076   /* Save remote's KE Start Payload */
1077   ske->start_payload = payload;
1078
1079   /** Send KE Payload */
1080   silc_fsm_next(fsm, silc_ske_st_initiator_phase2);
1081   return SILC_FSM_CONTINUE;
1082
1083  err:
1084   if (payload)
1085     silc_ske_payload_start_free(payload);
1086
1087   silc_ske_group_free(group);
1088
1089   if (prop->cipher)
1090     silc_cipher_free(prop->cipher);
1091   if (prop->hash)
1092     silc_hash_free(prop->hash);
1093   if (prop->hmac)
1094     silc_hmac_free(prop->hmac);
1095   silc_free(prop);
1096   ske->prop = NULL;
1097
1098   if (status == SILC_SKE_STATUS_OK)
1099     status = SILC_SKE_STATUS_ERROR;
1100
1101   /** Error */
1102   ske->status = status;
1103   silc_fsm_next(fsm, silc_ske_st_initiator_error);
1104   return SILC_FSM_CONTINUE;
1105 }
1106
1107 /* Phase-2.  Send KE payload */
1108
1109 SILC_FSM_STATE(silc_ske_st_initiator_phase2)
1110 {
1111   SilcSKE ske = fsm_context;
1112   SilcSKEStatus status;
1113   SilcBuffer payload_buf;
1114   SilcMPInt *x;
1115   SilcSKEKEPayload payload;
1116   SilcUInt32 pk_len;
1117
1118   SILC_LOG_DEBUG(("Start"));
1119
1120   /* Create the random number x, 1 < x < q. */
1121   x = silc_calloc(1, sizeof(*x));
1122   if (!x){
1123     /** Out of memory */
1124     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1125     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1126     return SILC_FSM_CONTINUE;
1127   }
1128   silc_mp_init(x);
1129   status =
1130     silc_ske_create_rnd(ske, &ske->prop->group->group_order,
1131                         silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
1132                         x);
1133   if (status != SILC_SKE_STATUS_OK) {
1134     /** Error generating random number */
1135     silc_mp_uninit(x);
1136     silc_free(x);
1137     ske->status = status;
1138     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1139     return SILC_FSM_CONTINUE;
1140   }
1141
1142   /* Encode the result to Key Exchange Payload. */
1143
1144   payload = silc_calloc(1, sizeof(*payload));
1145   if (!payload) {
1146     /** Out of memory */
1147     silc_mp_uninit(x);
1148     silc_free(x);
1149     ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1150     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1151     return SILC_FSM_CONTINUE;
1152   }
1153   ske->ke1_payload = payload;
1154
1155   SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
1156
1157   /* Do the Diffie Hellman computation, e = g ^ x mod p */
1158   silc_mp_init(&payload->x);
1159   silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
1160                   &ske->prop->group->group);
1161
1162   /* Get public key */
1163   payload->pk_data = silc_pkcs_public_key_encode(ske->public_key, &pk_len);
1164   if (!payload->pk_data) {
1165     /** Error encoding public key */
1166     silc_mp_uninit(x);
1167     silc_free(x);
1168     silc_mp_uninit(&payload->x);
1169     silc_free(payload);
1170     ske->ke1_payload = NULL;
1171     ske->status = SILC_SKE_STATUS_ERROR;
1172     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1173     return SILC_FSM_CONTINUE;
1174   }
1175   payload->pk_len = pk_len;
1176   payload->pk_type = silc_pkcs_get_type(ske->public_key);
1177
1178   /* Compute signature data if we are doing mutual authentication */
1179   if (ske->private_key &&
1180       ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
1181     unsigned char hash[SILC_HASH_MAXLEN], sign[2048 + 1];
1182     SilcUInt32 hash_len, sign_len;
1183
1184     SILC_LOG_DEBUG(("We are doing mutual authentication"));
1185     SILC_LOG_DEBUG(("Computing HASH_i value"));
1186
1187     /* Compute the hash value */
1188     memset(hash, 0, sizeof(hash));
1189     silc_ske_make_hash(ske, hash, &hash_len, TRUE);
1190
1191     SILC_LOG_DEBUG(("Signing HASH_i value"));
1192
1193     /* Sign the hash value */
1194     if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
1195                         sizeof(sign) - 1, &sign_len, NULL)) {
1196       /** Error computing signature */
1197       silc_mp_uninit(x);
1198       silc_free(x);
1199       silc_mp_uninit(&payload->x);
1200       silc_free(payload->pk_data);
1201       silc_free(payload);
1202       ske->ke1_payload = NULL;
1203       ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
1204       silc_fsm_next(fsm, silc_ske_st_initiator_error);
1205       return SILC_FSM_CONTINUE;
1206     }
1207     payload->sign_data = silc_memdup(sign, sign_len);
1208     if (payload->sign_data)
1209       payload->sign_len = sign_len;
1210     memset(sign, 0, sizeof(sign));
1211   }
1212
1213   status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
1214   if (status != SILC_SKE_STATUS_OK) {
1215     /** Error encoding KE payload */
1216     silc_mp_uninit(x);
1217     silc_free(x);
1218     silc_mp_uninit(&payload->x);
1219     silc_free(payload->pk_data);
1220     silc_free(payload->sign_data);
1221     silc_free(payload);
1222     ske->ke1_payload = NULL;
1223     ske->status = status;
1224     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1225     return SILC_FSM_CONTINUE;
1226   }
1227
1228   ske->x = x;
1229
1230   /* Check for backwards compatibility */
1231
1232   /* Send the packet. */
1233   if (!silc_packet_send(ske->stream, SILC_PACKET_KEY_EXCHANGE_1, 0,
1234                         silc_buffer_data(payload_buf),
1235                         silc_buffer_len(payload_buf))) {
1236     /** Error sending packet */
1237     ske->status = SILC_SKE_STATUS_ERROR;
1238     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1239     return SILC_FSM_CONTINUE;
1240   }
1241
1242   silc_buffer_free(payload_buf);
1243
1244   /** Waiting responder's KE payload */
1245   silc_fsm_next(fsm, silc_ske_st_initiator_phase3);
1246   return SILC_FSM_WAIT;
1247 }
1248
1249 /* Phase-3.  Process responder's KE payload */
1250
1251 SILC_FSM_STATE(silc_ske_st_initiator_phase3)
1252 {
1253   SilcSKE ske = fsm_context;
1254   SilcSKEStatus status;
1255   SilcSKEKEPayload payload;
1256   SilcMPInt *KEY;
1257   SilcBuffer packet_buf = &ske->packet->buffer;
1258
1259   SILC_LOG_DEBUG(("Start"));
1260
1261   if (ske->aborted) {
1262     /** Aborted */
1263     silc_packet_free(ske->packet);
1264     silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
1265     return SILC_FSM_CONTINUE;
1266   }
1267
1268   /* Decode the payload */
1269   status = silc_ske_payload_ke_decode(ske, packet_buf, &payload);
1270   if (status != SILC_SKE_STATUS_OK) {
1271     /** Error decoding KE payload */
1272     silc_packet_free(ske->packet);
1273     ske->status = status;
1274     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1275     return SILC_FSM_CONTINUE;
1276   }
1277   silc_packet_free(ske->packet);
1278   ske->ke2_payload = payload;
1279
1280   if (!payload->pk_data && (ske->callbacks->verify_key || ske->repository)) {
1281     SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
1282                     "even though we require it"));
1283     ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
1284     goto err;
1285   }
1286
1287   SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
1288
1289   /* Compute the shared secret key */
1290   KEY = silc_calloc(1, sizeof(*KEY));
1291   silc_mp_init(KEY);
1292   silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
1293   ske->KEY = KEY;
1294
1295   /* Decode the remote's public key */
1296   if (payload->pk_data &&
1297       !silc_pkcs_public_key_alloc(payload->pk_type,
1298                                   payload->pk_data, payload->pk_len,
1299                                   &ske->prop->public_key)) {
1300     SILC_LOG_ERROR(("Unsupported/malformed public key received"));
1301     status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
1302     goto err;
1303   }
1304
1305   if (ske->prop->public_key && (ske->callbacks->verify_key ||
1306                                 ske->repository)) {
1307     SILC_LOG_DEBUG(("Verifying public key"));
1308
1309     /** Waiting public key verification */
1310     silc_fsm_next(fsm, silc_ske_st_initiator_phase4);
1311
1312     /* If repository is provided, verify the key from there. */
1313     if (ske->repository) {
1314       SilcSKRFind find;
1315
1316       find = silc_skr_find_alloc();
1317       if (!find) {
1318         status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1319         goto err;
1320       }
1321       silc_skr_find_set_pkcs_type(find,
1322                                   silc_pkcs_get_type(ske->prop->public_key));
1323       silc_skr_find_set_public_key(find, ske->prop->public_key);
1324       silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT);
1325
1326       /* Find key from repository */
1327       SILC_FSM_CALL(silc_skr_find(ske->repository, find,
1328                                   silc_ske_skr_callback, ske));
1329     } else {
1330       /* Verify from application */
1331       SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key,
1332                                                ske->callbacks->context,
1333                                                silc_ske_pk_verified, NULL));
1334     }
1335     /* NOT REACHED */
1336   }
1337
1338   /** Process key material */
1339   silc_fsm_next(fsm, silc_ske_st_initiator_phase4);
1340   return SILC_FSM_CONTINUE;
1341
1342  err:
1343   silc_ske_payload_ke_free(payload);
1344   ske->ke2_payload = NULL;
1345
1346   silc_mp_uninit(ske->KEY);
1347   silc_free(ske->KEY);
1348   ske->KEY = NULL;
1349
1350   if (status == SILC_SKE_STATUS_OK)
1351     return SILC_SKE_STATUS_ERROR;
1352
1353   /** Error */
1354   ske->status = status;
1355   silc_fsm_next(fsm, silc_ske_st_initiator_error);
1356   return SILC_FSM_CONTINUE;
1357 }
1358
1359 /* Process key material */
1360
1361 SILC_FSM_STATE(silc_ske_st_initiator_phase4)
1362 {
1363   SilcSKE ske = fsm_context;
1364   SilcSKEStatus status;
1365   SilcSKEKEPayload payload;
1366   unsigned char hash[SILC_HASH_MAXLEN];
1367   SilcUInt32 hash_len;
1368   int key_len, block_len;
1369
1370   if (ske->aborted) {
1371     /** Aborted */
1372     silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
1373     return SILC_FSM_CONTINUE;
1374   }
1375
1376   /* Check result of public key verification */
1377   if (ske->status != SILC_SKE_STATUS_OK) {
1378     /** Public key not verified */
1379     SILC_LOG_DEBUG(("Public key verification failed"));
1380     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1381     return SILC_FSM_CONTINUE;
1382   }
1383
1384   payload = ske->ke2_payload;
1385
1386   if (ske->prop->public_key) {
1387     SILC_LOG_DEBUG(("Public key is authentic"));
1388
1389     /* Compute the hash value */
1390     status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1391     if (status != SILC_SKE_STATUS_OK)
1392       goto err;
1393
1394     SILC_LOG_DEBUG(("Verifying signature (HASH)"));
1395
1396     /* Verify signature */
1397     if (!silc_pkcs_verify(ske->prop->public_key, payload->sign_data,
1398                           payload->sign_len, hash, hash_len, NULL)) {
1399       SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
1400       status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
1401       goto err;
1402     }
1403
1404     SILC_LOG_DEBUG(("Signature is Ok"));
1405
1406     ske->hash = silc_memdup(hash, hash_len);
1407     ske->hash_len = hash_len;
1408     memset(hash, 'F', hash_len);
1409   }
1410
1411   ske->status = SILC_SKE_STATUS_OK;
1412
1413   /* Process key material */
1414   key_len = silc_cipher_get_key_len(ske->prop->cipher);
1415   block_len = silc_cipher_get_key_len(ske->prop->cipher);
1416   hash_len = silc_hash_len(ske->prop->hash);
1417   ske->keymat = silc_ske_process_key_material(ske, block_len,
1418                                               key_len, hash_len);
1419   if (!ske->keymat) {
1420     SILC_LOG_ERROR(("Error processing key material"));
1421     status = SILC_SKE_STATUS_ERROR;
1422     goto err;
1423   }
1424
1425   /* Send SUCCESS packet */
1426   SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, hash);
1427   if (!silc_packet_send(ske->stream, SILC_PACKET_SUCCESS, 0, hash, 4)) {
1428     /** Error sending packet */
1429     ske->status = SILC_SKE_STATUS_ERROR;
1430     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1431     return SILC_FSM_CONTINUE;
1432   }
1433
1434   /** Waiting completion */
1435   silc_fsm_next(fsm, silc_ske_st_initiator_end);
1436   return SILC_FSM_WAIT;
1437
1438  err:
1439   memset(hash, 'F', sizeof(hash));
1440   silc_ske_payload_ke_free(payload);
1441   ske->ke2_payload = NULL;
1442
1443   silc_mp_uninit(ske->KEY);
1444   silc_free(ske->KEY);
1445   ske->KEY = NULL;
1446
1447   if (ske->hash) {
1448     memset(ske->hash, 'F', hash_len);
1449     silc_free(ske->hash);
1450     ske->hash = NULL;
1451   }
1452
1453   if (status == SILC_SKE_STATUS_OK)
1454     status = SILC_SKE_STATUS_ERROR;
1455
1456   /** Error */
1457   ske->status = status;
1458   silc_fsm_next(fsm, silc_ske_st_initiator_error);
1459   return SILC_FSM_CONTINUE;
1460 }
1461
1462 /* Protocol completed */
1463
1464 SILC_FSM_STATE(silc_ske_st_initiator_end)
1465 {
1466   SilcSKE ske = fsm_context;
1467
1468   SILC_LOG_DEBUG(("Start"));
1469
1470   if (ske->aborted) {
1471     /** Aborted */
1472     silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
1473     return SILC_FSM_CONTINUE;
1474   }
1475
1476   /* See if received failure from remote */
1477   if (ske->packet->type == SILC_PACKET_FAILURE) {
1478     silc_packet_free(ske->packet);
1479     silc_fsm_next(fsm, silc_ske_st_initiator_failure);
1480     return SILC_FSM_CONTINUE;
1481   }
1482
1483   SILC_LOG_DEBUG(("Key exchange completed successfully"));
1484
1485   /* Call the completion callback */
1486   if (ske->callbacks->completed)
1487     ske->callbacks->completed(ske, ske->status, ske->prop, ske->keymat,
1488                               ske->rekey, ske->user_data);
1489
1490   silc_packet_free(ske->packet);
1491
1492   return SILC_FSM_FINISH;
1493 }
1494
1495 /* Aborted by application */
1496
1497 SILC_FSM_STATE(silc_ske_st_initiator_aborted)
1498 {
1499   SilcSKE ske = fsm_context;
1500   unsigned char data[4];
1501
1502   SILC_LOG_DEBUG(("Aborted by caller"));
1503
1504   /* Send FAILURE packet */
1505   SILC_PUT32_MSB(SILC_SKE_STATUS_ERROR, data);
1506   silc_packet_send(ske->stream, SILC_PACKET_FAILURE, 0, data, 4);
1507
1508   return SILC_FSM_FINISH;
1509 }
1510
1511 /* Error occurred.  Send error to remote host */
1512
1513 SILC_FSM_STATE(silc_ske_st_initiator_error)
1514 {
1515   SilcSKE ske = fsm_context;
1516   SilcSKEStatus status;
1517   unsigned char data[4];
1518
1519   SILC_LOG_DEBUG(("Error %s (%d) occurred during key exchange",
1520                   silc_ske_map_status(ske->status), ske->status));
1521
1522   status = ske->status;
1523   if (status > SILC_SKE_STATUS_INVALID_COOKIE)
1524     status = SILC_SKE_STATUS_ERROR;
1525
1526   /* Send FAILURE packet */
1527   SILC_PUT32_MSB((SilcUInt32)status, data);
1528   silc_packet_send(ske->stream, SILC_PACKET_FAILURE, 0, data, 4);
1529
1530   /* Call the completion callback */
1531   if (ske->callbacks->completed)
1532     ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL, NULL);
1533
1534   return SILC_FSM_FINISH;
1535 }
1536
1537 /* Failure received from remote */
1538
1539 SILC_FSM_STATE(silc_ske_st_initiator_failure)
1540 {
1541   SilcSKE ske = fsm_context;
1542
1543   SILC_LOG_DEBUG(("Error %s (%d) received during key exchange",
1544                   silc_ske_map_status(ske->status), ske->status));
1545
1546   /* Call the completion callback */
1547   if (ske->callbacks->completed)
1548     ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL, NULL);
1549
1550   return SILC_FSM_FINISH;
1551 }
1552
1553 /* FSM destructor */
1554
1555 static void silc_ske_initiator_finished(SilcFSM fsm, void *fsm_context,
1556                                         void *destructor_context)
1557 {
1558   SilcSKE ske = fsm_context;
1559   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1560 }
1561
1562 /* Starts the protocol as initiator */
1563
1564 SilcAsyncOperation
1565 silc_ske_initiator(SilcSKE ske,
1566                    SilcPacketStream stream,
1567                    SilcSKEParams params,
1568                    SilcSKEStartPayload start_payload)
1569 {
1570   SILC_LOG_DEBUG(("Start SKE as initiator"));
1571
1572   if (!ske || !stream || !params || !params->version)
1573     return NULL;
1574
1575   if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
1576     return NULL;
1577
1578   if (!silc_fsm_init(&ske->fsm, ske, silc_ske_initiator_finished, ske,
1579                      ske->schedule))
1580     return NULL;
1581
1582   if (params->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)
1583     ske->session_port = params->session_port;
1584
1585   /* Generate security properties if not provided */
1586   if (!start_payload) {
1587     start_payload = silc_ske_assemble_security_properties(ske,
1588                                                           params->flags,
1589                                                           params->version);
1590     if (!start_payload)
1591       return NULL;
1592   }
1593
1594   ske->start_payload = start_payload;
1595   ske->version = params->version;
1596
1597   /* Link to packet stream to get key exchange packets */
1598   ske->stream = stream;
1599   silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
1600                           SILC_PACKET_KEY_EXCHANGE,
1601                           SILC_PACKET_KEY_EXCHANGE_2,
1602                           SILC_PACKET_SUCCESS,
1603                           SILC_PACKET_FAILURE, -1);
1604
1605   /* Start SKE as initiator */
1606   silc_fsm_start(&ske->fsm, silc_ske_st_initiator_start);
1607
1608   return &ske->op;
1609 }
1610
1611
1612 /******************************** Responder *********************************/
1613
1614 SILC_FSM_STATE(silc_ske_st_responder_start);
1615 SILC_FSM_STATE(silc_ske_st_responder_phase1);
1616 SILC_FSM_STATE(silc_ske_st_responder_phase2);
1617 SILC_FSM_STATE(silc_ske_st_responder_phase4);
1618 SILC_FSM_STATE(silc_ske_st_responder_phase5);
1619 SILC_FSM_STATE(silc_ske_st_responder_end);
1620 SILC_FSM_STATE(silc_ske_st_responder_aborted);
1621 SILC_FSM_STATE(silc_ske_st_responder_failure);
1622 SILC_FSM_STATE(silc_ske_st_responder_error);
1623
1624 /* Start protocol as responder.  Wait initiator's start payload */
1625
1626 SILC_FSM_STATE(silc_ske_st_responder_start)
1627 {
1628   SilcSKE ske = fsm_context;
1629
1630   SILC_LOG_DEBUG(("Start"));
1631
1632   if (ske->aborted) {
1633     /** Aborted */
1634     silc_fsm_next(fsm, silc_ske_st_responder_aborted);
1635     return SILC_FSM_CONTINUE;
1636   }
1637
1638   /* Start timeout */
1639   /* XXX */
1640
1641   /** Wait for initiator */
1642   silc_fsm_next(fsm, silc_ske_st_responder_phase1);
1643   return SILC_FSM_WAIT;
1644 }
1645
1646 /* Decode initiator's start payload.  Select the security properties from
1647    the initiator's start payload and send our reply start payload back. */
1648
1649 SILC_FSM_STATE(silc_ske_st_responder_phase1)
1650 {
1651   SilcSKE ske = fsm_context;
1652   SilcSKEStatus status;
1653   SilcSKEStartPayload remote_payload = NULL;
1654   SilcBuffer packet_buf = &ske->packet->buffer;
1655
1656   SILC_LOG_DEBUG(("Start"));
1657
1658   if (ske->aborted) {
1659     /** Aborted */
1660     silc_packet_free(ske->packet);
1661     silc_fsm_next(fsm, silc_ske_st_responder_aborted);
1662     return SILC_FSM_CONTINUE;
1663   }
1664
1665   /* See if received failure from remote */
1666   if (ske->packet->type == SILC_PACKET_FAILURE) {
1667     silc_packet_free(ske->packet);
1668     silc_fsm_next(fsm, silc_ske_st_responder_failure);
1669     return SILC_FSM_CONTINUE;
1670   }
1671
1672   /* Decode the payload */
1673   status = silc_ske_payload_start_decode(ske, packet_buf, &remote_payload);
1674   if (status != SILC_SKE_STATUS_OK) {
1675     /** Error decoding Start Payload */
1676     silc_packet_free(ske->packet);
1677     ske->status = status;
1678     silc_fsm_next(fsm, silc_ske_st_responder_error);
1679     return SILC_FSM_CONTINUE;
1680   }
1681
1682   /* Take a copy of the payload buffer for future use. It is used to
1683      compute the HASH value. */
1684   ske->start_payload_copy = silc_buffer_copy(packet_buf);
1685
1686   silc_packet_free(ske->packet);
1687
1688   /* Force the mutual authentication flag if we want to do it. */
1689   if (ske->flags & SILC_SKE_SP_FLAG_MUTUAL) {
1690     SILC_LOG_DEBUG(("Force mutual authentication"));
1691     remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
1692   }
1693
1694   /* Force PFS flag if we require it */
1695   if (ske->flags & SILC_SKE_SP_FLAG_PFS) {
1696     SILC_LOG_DEBUG(("Force PFS"));
1697     remote_payload->flags |= SILC_SKE_SP_FLAG_PFS;
1698   }
1699
1700   /* Disable IV Included flag if requested */
1701   if (remote_payload->flags & SILC_SKE_SP_FLAG_IV_INCLUDED &&
1702       !(ske->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)) {
1703     SILC_LOG_DEBUG(("We do not support IV Included flag"));
1704     remote_payload->flags &= ~SILC_SKE_SP_FLAG_IV_INCLUDED;
1705   }
1706
1707   /* Check and select security properties */
1708   status = silc_ske_select_security_properties(ske, remote_payload,
1709                                                &ske->prop);
1710   if (status != SILC_SKE_STATUS_OK) {
1711     /** Error selecting proposal */
1712     silc_ske_payload_start_free(remote_payload);
1713     ske->status = status;
1714     silc_fsm_next(fsm, silc_ske_st_responder_error);
1715     return SILC_FSM_CONTINUE;
1716   }
1717
1718   silc_ske_payload_start_free(remote_payload);
1719
1720   /* Encode our reply payload to send the selected security properties */
1721   status = silc_ske_payload_start_encode(ske, ske->start_payload,
1722                                          &packet_buf);
1723   if (status != SILC_SKE_STATUS_OK)
1724     goto err;
1725
1726   /* Send the packet. */
1727   if (!silc_packet_send(ske->stream, SILC_PACKET_KEY_EXCHANGE, 0,
1728                         silc_buffer_data(packet_buf),
1729                         silc_buffer_len(packet_buf)))
1730     goto err;
1731
1732   silc_buffer_free(packet_buf);
1733
1734   /** Waiting initiator's KE payload */
1735   silc_fsm_next(fsm, silc_ske_st_responder_phase2);
1736   return SILC_FSM_WAIT;
1737
1738  err:
1739   if (ske->prop->group)
1740     silc_ske_group_free(ske->prop->group);
1741   if (ske->prop->cipher)
1742     silc_cipher_free(ske->prop->cipher);
1743   if (ske->prop->hash)
1744     silc_hash_free(ske->prop->hash);
1745   if (ske->prop->hmac)
1746     silc_hmac_free(ske->prop->hmac);
1747   silc_free(ske->prop);
1748   ske->prop = NULL;
1749
1750   if (status == SILC_SKE_STATUS_OK)
1751     status = SILC_SKE_STATUS_ERROR;
1752
1753   /** Error */
1754   ske->status = status;
1755   silc_fsm_next(fsm, silc_ske_st_responder_error);
1756   return SILC_FSM_CONTINUE;
1757 }
1758
1759 /* Phase-2.  Decode initiator's KE payload */
1760
1761 SILC_FSM_STATE(silc_ske_st_responder_phase2)
1762 {
1763   SilcSKE ske = fsm_context;
1764   SilcSKEStatus status;
1765   SilcSKEKEPayload recv_payload;
1766   SilcBuffer packet_buf = &ske->packet->buffer;
1767
1768   SILC_LOG_DEBUG(("Start"));
1769
1770   if (ske->aborted) {
1771     /** Aborted */
1772     silc_fsm_next(fsm, silc_ske_st_responder_aborted);
1773     return SILC_FSM_CONTINUE;
1774   }
1775
1776   /* See if received failure from remote */
1777   if (ske->packet->type == SILC_PACKET_FAILURE) {
1778     silc_fsm_next(fsm, silc_ske_st_responder_failure);
1779     return SILC_FSM_CONTINUE;
1780   }
1781
1782   /* Decode Key Exchange Payload */
1783   status = silc_ske_payload_ke_decode(ske, packet_buf, &recv_payload);
1784   if (status != SILC_SKE_STATUS_OK) {
1785     /** Error decoding KE payload */
1786     silc_packet_free(ske->packet);
1787     ske->status = status;
1788     silc_fsm_next(fsm, silc_ske_st_responder_error);
1789     return SILC_FSM_CONTINUE;
1790   }
1791
1792   ske->ke1_payload = recv_payload;
1793
1794   silc_packet_free(ske->packet);
1795
1796   /* Verify the received public key and verify the signature if we are
1797      doing mutual authentication. */
1798   if (ske->start_payload &&
1799       ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
1800
1801     SILC_LOG_DEBUG(("We are doing mutual authentication"));
1802
1803     if (!recv_payload->pk_data && (ske->callbacks->verify_key ||
1804                                    ske->repository)) {
1805       /** Public key not provided */
1806       SILC_LOG_ERROR(("Remote end did not send its public key (or "
1807                       "certificate), even though we require it"));
1808       ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
1809       silc_fsm_next(fsm, silc_ske_st_responder_error);
1810       return SILC_FSM_CONTINUE;
1811     }
1812
1813     /* Decode the remote's public key */
1814     if (recv_payload->pk_data &&
1815         !silc_pkcs_public_key_alloc(recv_payload->pk_type,
1816                                     recv_payload->pk_data,
1817                                     recv_payload->pk_len,
1818                                     &ske->prop->public_key)) {
1819       /** Error decoding public key */
1820       SILC_LOG_ERROR(("Unsupported/malformed public key received"));
1821       ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
1822       silc_fsm_next(fsm, silc_ske_st_responder_error);
1823       return SILC_FSM_CONTINUE;
1824     }
1825
1826     if (ske->prop->public_key && (ske->callbacks->verify_key ||
1827                                   ske->repository)) {
1828       SILC_LOG_DEBUG(("Verifying public key"));
1829
1830       /** Waiting public key verification */
1831       silc_fsm_next(fsm, silc_ske_st_responder_phase4);
1832
1833       /* If repository is provided, verify the key from there. */
1834       if (ske->repository) {
1835         SilcSKRFind find;
1836
1837         find = silc_skr_find_alloc();
1838         if (!find) {
1839           ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1840           silc_fsm_next(fsm, silc_ske_st_responder_error);
1841           return SILC_FSM_CONTINUE;
1842         }
1843         silc_skr_find_set_pkcs_type(find,
1844                                     silc_pkcs_get_type(ske->prop->public_key));
1845         silc_skr_find_set_public_key(find, ske->prop->public_key);
1846         silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT);
1847
1848         /* Find key from repository */
1849         SILC_FSM_CALL(silc_skr_find(ske->repository, find,
1850                                     silc_ske_skr_callback, ske));
1851       } else {
1852         /* Verify from application */
1853         SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key,
1854                                                  ske->callbacks->context,
1855                                                  silc_ske_pk_verified, NULL));
1856       }
1857       /* NOT REACHED */
1858     }
1859   }
1860
1861   /** Generate KE2 payload */
1862   silc_fsm_next(fsm, silc_ske_st_responder_phase4);
1863   return SILC_FSM_CONTINUE;
1864 }
1865
1866 /* Phase-4. Generate KE2 payload */
1867
1868 SILC_FSM_STATE(silc_ske_st_responder_phase4)
1869 {
1870   SilcSKE ske = fsm_context;
1871   SilcSKEStatus status;
1872   SilcSKEKEPayload recv_payload, send_payload;
1873   SilcMPInt *x, *KEY;
1874
1875   if (ske->aborted) {
1876     /** Aborted */
1877     silc_fsm_next(fsm, silc_ske_st_responder_aborted);
1878     return SILC_FSM_CONTINUE;
1879   }
1880
1881   /* Check result of public key verification */
1882   if (ske->status != SILC_SKE_STATUS_OK) {
1883     /** Public key not verified */
1884     SILC_LOG_DEBUG(("Public key verification failed"));
1885     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1886     return SILC_FSM_CONTINUE;
1887   }
1888
1889   recv_payload = ske->ke1_payload;
1890
1891   /* The public key verification was performed only if the Mutual
1892      Authentication flag is set. */
1893   if (ske->start_payload &&
1894       ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
1895     unsigned char hash[SILC_HASH_MAXLEN];
1896     SilcUInt32 hash_len;
1897
1898     SILC_LOG_DEBUG(("Public key is authentic"));
1899
1900     /* Compute the hash value */
1901     status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
1902     if (status != SILC_SKE_STATUS_OK) {
1903       /** Error computing hash */
1904       ske->status = status;
1905       silc_fsm_next(fsm, silc_ske_st_responder_error);
1906       return SILC_FSM_CONTINUE;
1907     }
1908
1909     SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
1910
1911     /* Verify signature */
1912     if (!silc_pkcs_verify(ske->prop->public_key, recv_payload->sign_data,
1913                           recv_payload->sign_len, hash, hash_len, NULL)) {
1914       /** Incorrect signature */
1915       SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
1916       ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
1917       silc_fsm_next(fsm, silc_ske_st_responder_error);
1918       return SILC_FSM_CONTINUE;
1919     }
1920
1921     SILC_LOG_DEBUG(("Signature is Ok"));
1922
1923     memset(hash, 'F', hash_len);
1924   }
1925
1926   /* Create the random number x, 1 < x < q. */
1927   x = silc_calloc(1, sizeof(*x));
1928   silc_mp_init(x);
1929   status =
1930     silc_ske_create_rnd(ske, &ske->prop->group->group_order,
1931                         silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
1932                         x);
1933   if (status != SILC_SKE_STATUS_OK) {
1934     /** Error generating random number */
1935     silc_mp_uninit(x);
1936     silc_free(x);
1937     ske->status = status;
1938     silc_fsm_next(fsm, silc_ske_st_responder_error);
1939     return SILC_FSM_CONTINUE;
1940   }
1941
1942   /* Save the results for later processing */
1943   send_payload = silc_calloc(1, sizeof(*send_payload));
1944   ske->x = x;
1945   ske->ke2_payload = send_payload;
1946
1947   SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
1948
1949   /* Do the Diffie Hellman computation, f = g ^ x mod p */
1950   silc_mp_init(&send_payload->x);
1951   silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
1952                   &ske->prop->group->group);
1953
1954   SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
1955
1956   /* Compute the shared secret key */
1957   KEY = silc_calloc(1, sizeof(*KEY));
1958   silc_mp_init(KEY);
1959   silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
1960                   &ske->prop->group->group);
1961   ske->KEY = KEY;
1962
1963   /** Send KE2 payload */
1964   silc_fsm_next(fsm, silc_ske_st_responder_phase5);
1965   return SILC_FSM_CONTINUE;
1966 }
1967
1968 /* Phase-5.  Send KE2 payload */
1969
1970 SILC_FSM_STATE(silc_ske_st_responder_phase5)
1971 {
1972   SilcSKE ske = fsm_context;
1973   SilcSKEStatus status;
1974   SilcBuffer payload_buf;
1975   unsigned char hash[SILC_HASH_MAXLEN], sign[2048 + 1], *pk;
1976   SilcUInt32 hash_len, sign_len, pk_len;
1977
1978   SILC_LOG_DEBUG(("Start"));
1979
1980   if (ske->public_key && ske->private_key) {
1981     SILC_LOG_DEBUG(("Getting public key"));
1982
1983     /* Get the public key */
1984     pk = silc_pkcs_public_key_encode(ske->public_key, &pk_len);
1985     if (!pk) {
1986       /** Error encoding public key */
1987       status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1988       silc_fsm_next(fsm, silc_ske_st_responder_error);
1989       return SILC_FSM_CONTINUE;
1990     }
1991     ske->ke2_payload->pk_data = pk;
1992     ske->ke2_payload->pk_len = pk_len;
1993
1994     SILC_LOG_DEBUG(("Computing HASH value"));
1995
1996     /* Compute the hash value */
1997     memset(hash, 0, sizeof(hash));
1998     status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1999     if (status != SILC_SKE_STATUS_OK) {
2000       /** Error computing hash */
2001       ske->status = status;
2002       silc_fsm_next(fsm, silc_ske_st_responder_error);
2003       return SILC_FSM_CONTINUE;
2004     }
2005
2006     ske->hash = silc_memdup(hash, hash_len);
2007     ske->hash_len = hash_len;
2008
2009     SILC_LOG_DEBUG(("Signing HASH value"));
2010
2011     /* Sign the hash value */
2012     if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
2013                         sizeof(sign) - 1, &sign_len, NULL)) {
2014       /** Error computing signature */
2015       status = SILC_SKE_STATUS_SIGNATURE_ERROR;
2016       silc_fsm_next(fsm, silc_ske_st_responder_error);
2017       return SILC_FSM_CONTINUE;
2018     }
2019     ske->ke2_payload->sign_data = silc_memdup(sign, sign_len);
2020     ske->ke2_payload->sign_len = sign_len;
2021     memset(sign, 0, sizeof(sign));
2022   }
2023   ske->ke2_payload->pk_type = silc_pkcs_get_type(ske->public_key);
2024
2025   /* Encode the Key Exchange Payload */
2026   status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
2027                                       &payload_buf);
2028   if (status != SILC_SKE_STATUS_OK) {
2029     /** Error encoding KE payload */
2030     ske->status = status;
2031     silc_fsm_next(fsm, silc_ske_st_responder_error);
2032     return SILC_FSM_CONTINUE;
2033   }
2034
2035   /* Send the packet. */
2036   if (!silc_packet_send(ske->stream, SILC_PACKET_KEY_EXCHANGE_2, 0,
2037                         payload_buf->data, silc_buffer_len(payload_buf))) {
2038     ske->status = SILC_SKE_STATUS_ERROR;
2039     silc_fsm_next(fsm, silc_ske_st_responder_error);
2040     return SILC_FSM_CONTINUE;
2041   }
2042
2043   silc_buffer_free(payload_buf);
2044
2045   /** Waiting completion */
2046   silc_fsm_next(fsm, silc_ske_st_responder_end);
2047   return SILC_FSM_WAIT;
2048 }
2049
2050 /* Protocol completed */
2051
2052 SILC_FSM_STATE(silc_ske_st_responder_end)
2053 {
2054   SilcSKE ske = fsm_context;
2055   unsigned char tmp[4];
2056   SilcUInt32 hash_len, key_len, block_len;
2057
2058   if (ske->aborted) {
2059     /** Aborted */
2060     silc_fsm_next(fsm, silc_ske_st_responder_aborted);
2061     return SILC_FSM_CONTINUE;
2062   }
2063
2064   /* Check the result of the protocol */
2065   if (ske->packet->type == SILC_PACKET_FAILURE) {
2066     silc_fsm_next(fsm, silc_ske_st_responder_failure);
2067     return SILC_FSM_CONTINUE;
2068   }
2069   silc_packet_free(ske->packet);
2070
2071   /* Process key material */
2072   key_len = silc_cipher_get_key_len(ske->prop->cipher);
2073   block_len = silc_cipher_get_key_len(ske->prop->cipher);
2074   hash_len = silc_hash_len(ske->prop->hash);
2075   ske->keymat = silc_ske_process_key_material(ske, block_len,
2076                                               key_len, hash_len);
2077   if (!ske->keymat) {
2078     /** Error processing key material */
2079     ske->status = SILC_SKE_STATUS_ERROR;
2080     silc_fsm_next(fsm, silc_ske_st_responder_error);
2081     return SILC_FSM_CONTINUE;
2082   }
2083
2084   /* Send SUCCESS packet */
2085   SILC_PUT32_MSB(SILC_SKE_STATUS_OK, tmp);
2086   silc_packet_send(ske->stream, SILC_PACKET_SUCCESS, 0, tmp, 4);
2087
2088   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2089
2090   /* Call the completion callback */
2091   if (ske->callbacks->completed)
2092     ske->callbacks->completed(ske, ske->status, ske->prop, ske->keymat,
2093                               ske->rekey, ske->callbacks->context);
2094
2095   return SILC_FSM_FINISH;
2096 }
2097
2098 /* Aborted by application */
2099
2100 SILC_FSM_STATE(silc_ske_st_responder_aborted)
2101 {
2102   SilcSKE ske = fsm_context;
2103   unsigned char tmp[4];
2104
2105   SILC_LOG_DEBUG(("Key exchange protocol aborted"));
2106
2107   /* Send FAILURE packet */
2108   SILC_PUT32_MSB(SILC_SKE_STATUS_ERROR, tmp);
2109   silc_packet_send(ske->stream, SILC_PACKET_FAILURE, 0, tmp, 4);
2110
2111   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2112
2113   return SILC_FSM_FINISH;
2114 }
2115
2116 /* Failure received from remote */
2117
2118 SILC_FSM_STATE(silc_ske_st_responder_failure)
2119 {
2120   SilcSKE ske = fsm_context;
2121   SilcUInt32 error = SILC_SKE_STATUS_ERROR;
2122
2123   SILC_LOG_DEBUG(("Key exchange protocol failed"));
2124
2125   if (silc_buffer_len(&ske->packet->buffer) == 4)
2126     SILC_GET32_MSB(error, ske->packet->buffer.data);
2127   ske->status = error;
2128
2129   /* Call the completion callback */
2130   if (ske->callbacks->completed)
2131     ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL,
2132                               ske->callbacks->context);
2133
2134   silc_packet_free(ske->packet);
2135   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2136
2137   return SILC_FSM_FINISH;
2138 }
2139
2140 /* Error occurred */
2141
2142 SILC_FSM_STATE(silc_ske_st_responder_error)
2143 {
2144   SilcSKE ske = fsm_context;
2145   unsigned char tmp[4];
2146
2147   SILC_LOG_DEBUG(("Error %d (%s) during key exchange protocol",
2148                   ske->status, silc_ske_map_status(ske->status)));
2149
2150   /* Send FAILURE packet */
2151   if (ske->status > SILC_SKE_STATUS_INVALID_COOKIE)
2152     ske->status = SILC_SKE_STATUS_BAD_PAYLOAD;
2153   SILC_PUT32_MSB(ske->status, tmp);
2154   silc_packet_send(ske->stream, SILC_PACKET_FAILURE, 0, tmp, 4);
2155
2156   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2157
2158   return SILC_FSM_FINISH;
2159 }
2160
2161
2162 static void silc_ske_responder_finished(SilcFSM fsm, void *fsm_context,
2163                                         void *destructor_context)
2164 {
2165
2166 }
2167
2168 /* Starts the protocol as responder. */
2169
2170 SilcAsyncOperation
2171 silc_ske_responder(SilcSKE ske,
2172                    SilcPacketStream stream,
2173                    SilcSKEParams params)
2174 {
2175   SILC_LOG_DEBUG(("Start SKE as responder"));
2176
2177   if (!ske || !stream || !params || !params->version) {
2178     return NULL;
2179   }
2180
2181   if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
2182     return NULL;
2183
2184   if (!silc_fsm_init(&ske->fsm, ske, silc_ske_responder_finished, ske,
2185                      ske->schedule))
2186     return NULL;
2187
2188   ske->responder = TRUE;
2189   ske->flags = params->flags;
2190   if (ske->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)
2191     ske->session_port = params->session_port;
2192   ske->version = strdup(params->version);
2193   if (!ske->version)
2194     return NULL;
2195
2196   /* Link to packet stream to get key exchange packets */
2197   ske->stream = stream;
2198   silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
2199                           SILC_PACKET_KEY_EXCHANGE,
2200                           SILC_PACKET_KEY_EXCHANGE_1,
2201                           SILC_PACKET_SUCCESS,
2202                           SILC_PACKET_FAILURE, -1);
2203
2204   /* Start SKE as responder */
2205   silc_fsm_start(&ske->fsm, silc_ske_st_responder_start);
2206
2207   return &ske->op;
2208 }
2209
2210 SILC_FSM_STATE(silc_ske_st_rekey_initiator_start);
2211
2212 SILC_FSM_STATE(silc_ske_st_rekey_initiator_start)
2213 {
2214   return SILC_FSM_FINISH;
2215 }
2216
2217 /* Starts rekey protocol as initiator */
2218
2219 SilcAsyncOperation
2220 silc_ske_rekey_initiator(SilcSKE ske,
2221                          SilcPacketStream stream,
2222                          SilcSKERekeyMaterial rekey)
2223 {
2224   SILC_LOG_DEBUG(("Start SKE rekey as initator"));
2225
2226   if (!ske || !stream || !rekey)
2227     return NULL;
2228
2229   if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
2230     return NULL;
2231
2232   if (!silc_fsm_init(&ske->fsm, ske, NULL, NULL, ske->schedule))
2233     return NULL;
2234
2235   ske->rekey = rekey;
2236
2237   /* Link to packet stream to get key exchange packets */
2238   ske->stream = stream;
2239
2240   /* Start SKE rekey as initiator */
2241   silc_fsm_start(&ske->fsm, silc_ske_st_rekey_initiator_start);
2242
2243   return &ske->op;
2244 }
2245
2246 SILC_FSM_STATE(silc_ske_st_rekey_responder_start);
2247
2248 SILC_FSM_STATE(silc_ske_st_rekey_responder_start)
2249 {
2250   return SILC_FSM_FINISH;
2251 }
2252
2253 /* Starts rekey protocol as responder */
2254
2255 SilcAsyncOperation
2256 silc_ske_rekey_responder(SilcSKE ske,
2257                          SilcPacketStream stream,
2258                          SilcBuffer ke_payload,
2259                          SilcSKERekeyMaterial rekey)
2260 {
2261   SILC_LOG_DEBUG(("Start SKE rekey as responder"));
2262
2263   if (!ske || !stream || !rekey)
2264     return NULL;
2265   if (rekey->pfs && !ke_payload)
2266     return NULL;
2267
2268   if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
2269     return NULL;
2270
2271   if (!silc_fsm_init(&ske->fsm, ske, NULL, NULL, ske->schedule))
2272     return NULL;
2273
2274   //  ske->packet_buf = ke_payload;
2275   ske->rekey = rekey;
2276
2277   /* Link to packet stream to get key exchange packets */
2278   ske->stream = stream;
2279
2280   /* Start SKE rekey as responder */
2281   silc_fsm_start(&ske->fsm, silc_ske_st_rekey_responder_start);
2282
2283   return &ske->op;
2284 }
2285
2286 /* Processes the provided key material `data' as the SILC protocol
2287    specification defines. */
2288
2289 SilcSKEKeyMaterial
2290 silc_ske_process_key_material_data(unsigned char *data,
2291                                    SilcUInt32 data_len,
2292                                    SilcUInt32 req_iv_len,
2293                                    SilcUInt32 req_enc_key_len,
2294                                    SilcUInt32 req_hmac_key_len,
2295                                    SilcHash hash)
2296 {
2297   SilcBuffer buf;
2298   unsigned char hashd[SILC_HASH_MAXLEN];
2299   SilcUInt32 hash_len = req_hmac_key_len;
2300   SilcUInt32 enc_key_len = req_enc_key_len / 8;
2301   SilcSKEKeyMaterial key;
2302
2303   SILC_LOG_DEBUG(("Start"));
2304
2305   if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
2306     return NULL;
2307
2308   key = silc_calloc(1, sizeof(*key));
2309   if (!key)
2310     return NULL;
2311
2312   buf = silc_buffer_alloc_size(1 + data_len);
2313   if (!buf)
2314     return NULL;
2315   silc_buffer_format(buf,
2316                      SILC_STR_UI_CHAR(0),
2317                      SILC_STR_UI_XNSTRING(data, data_len),
2318                      SILC_STR_END);
2319
2320   /* Take IVs */
2321   memset(hashd, 0, sizeof(hashd));
2322   buf->data[0] = 0;
2323   silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2324   key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
2325   memcpy(key->send_iv, hashd, req_iv_len);
2326   memset(hashd, 0, sizeof(hashd));
2327   buf->data[0] = 1;
2328   silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2329   key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
2330   memcpy(key->receive_iv, hashd, req_iv_len);
2331   key->iv_len = req_iv_len;
2332
2333   /* Take the encryption keys. If requested key size is more than
2334      the size of hash length we will distribute more key material
2335      as protocol defines. */
2336   buf->data[0] = 2;
2337   if (enc_key_len > hash_len) {
2338     SilcBuffer dist;
2339     unsigned char k1[SILC_HASH_MAXLEN], k2[SILC_HASH_MAXLEN],
2340         k3[SILC_HASH_MAXLEN];
2341     unsigned char *dtmp;
2342
2343     /* XXX */
2344     if (enc_key_len > (3 * hash_len))
2345       return NULL;
2346
2347     /* Take first round */
2348     memset(k1, 0, sizeof(k1));
2349     silc_hash_make(hash, buf->data, silc_buffer_len(buf), k1);
2350
2351     /* Take second round */
2352     dist = silc_buffer_alloc_size(data_len + hash_len);
2353     if (!dist)
2354       return NULL;
2355     silc_buffer_format(dist,
2356                        SILC_STR_UI_XNSTRING(data, data_len),
2357                        SILC_STR_UI_XNSTRING(k1, hash_len),
2358                        SILC_STR_END);
2359     memset(k2, 0, sizeof(k2));
2360     silc_hash_make(hash, dist->data, silc_buffer_len(dist), k2);
2361
2362     /* Take third round */
2363     dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
2364     silc_buffer_pull_tail(dist, hash_len);
2365     silc_buffer_pull(dist, data_len + hash_len);
2366     silc_buffer_format(dist,
2367                        SILC_STR_UI_XNSTRING(k2, hash_len),
2368                        SILC_STR_END);
2369     silc_buffer_push(dist, data_len + hash_len);
2370     memset(k3, 0, sizeof(k3));
2371     silc_hash_make(hash, dist->data, silc_buffer_len(dist), k3);
2372
2373     /* Then, save the keys */
2374     dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
2375     memcpy(dtmp, k1, hash_len);
2376     memcpy(dtmp + hash_len, k2, hash_len);
2377     memcpy(dtmp + hash_len + hash_len, k3, hash_len);
2378
2379     key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
2380     memcpy(key->send_enc_key, dtmp, enc_key_len);
2381     key->enc_key_len = req_enc_key_len;
2382
2383     memset(dtmp, 0, (3 * hash_len));
2384     memset(k1, 0, sizeof(k1));
2385     memset(k2, 0, sizeof(k2));
2386     memset(k3, 0, sizeof(k3));
2387     silc_free(dtmp);
2388     silc_buffer_clear(dist);
2389     silc_buffer_free(dist);
2390   } else {
2391     /* Take normal hash as key */
2392     memset(hashd, 0, sizeof(hashd));
2393     silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2394     key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
2395     memcpy(key->send_enc_key, hashd, enc_key_len);
2396     key->enc_key_len = req_enc_key_len;
2397   }
2398
2399   buf->data[0] = 3;
2400   if (enc_key_len > hash_len) {
2401     SilcBuffer dist;
2402     unsigned char k1[SILC_HASH_MAXLEN], k2[SILC_HASH_MAXLEN],
2403         k3[SILC_HASH_MAXLEN];
2404     unsigned char *dtmp;
2405
2406     /* XXX */
2407     if (enc_key_len > (3 * hash_len))
2408       return NULL;
2409
2410     /* Take first round */
2411     memset(k1, 0, sizeof(k1));
2412     silc_hash_make(hash, buf->data, silc_buffer_len(buf), k1);
2413
2414     /* Take second round */
2415     dist = silc_buffer_alloc_size(data_len + hash_len);
2416     if (!dist)
2417       return NULL;
2418     silc_buffer_format(dist,
2419                        SILC_STR_UI_XNSTRING(data, data_len),
2420                        SILC_STR_UI_XNSTRING(k1, hash_len),
2421                        SILC_STR_END);
2422     memset(k2, 0, sizeof(k2));
2423     silc_hash_make(hash, dist->data, silc_buffer_len(dist), k2);
2424
2425     /* Take third round */
2426     dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
2427     silc_buffer_pull_tail(dist, hash_len);
2428     silc_buffer_pull(dist, data_len + hash_len);
2429     silc_buffer_format(dist,
2430                        SILC_STR_UI_XNSTRING(k2, hash_len),
2431                        SILC_STR_END);
2432     silc_buffer_push(dist, data_len + hash_len);
2433     memset(k3, 0, sizeof(k3));
2434     silc_hash_make(hash, dist->data, silc_buffer_len(dist), k3);
2435
2436     /* Then, save the keys */
2437     dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
2438     memcpy(dtmp, k1, hash_len);
2439     memcpy(dtmp + hash_len, k2, hash_len);
2440     memcpy(dtmp + hash_len + hash_len, k3, hash_len);
2441
2442     key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
2443     memcpy(key->receive_enc_key, dtmp, enc_key_len);
2444     key->enc_key_len = req_enc_key_len;
2445
2446     memset(dtmp, 0, (3 * hash_len));
2447     memset(k1, 0, sizeof(k1));
2448     memset(k2, 0, sizeof(k2));
2449     memset(k3, 0, sizeof(k3));
2450     silc_free(dtmp);
2451     silc_buffer_clear(dist);
2452     silc_buffer_free(dist);
2453   } else {
2454     /* Take normal hash as key */
2455     memset(hashd, 0, sizeof(hashd));
2456     silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2457     key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
2458     memcpy(key->receive_enc_key, hashd, enc_key_len);
2459     key->enc_key_len = req_enc_key_len;
2460   }
2461
2462   /* Take HMAC keys */
2463   memset(hashd, 0, sizeof(hashd));
2464   buf->data[0] = 4;
2465   silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2466   key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
2467   memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
2468   memset(hashd, 0, sizeof(hashd));
2469   buf->data[0] = 5;
2470   silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2471   key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
2472   memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
2473   key->hmac_key_len = req_hmac_key_len;
2474   memset(hashd, 0, sizeof(hashd));
2475
2476   silc_buffer_clear(buf);
2477   silc_buffer_free(buf);
2478
2479   return key;
2480 }
2481
2482 /* Processes negotiated key material as protocol specifies. This returns
2483    the actual keys to be used in the SILC. */
2484
2485 SilcSKEKeyMaterial
2486 silc_ske_process_key_material(SilcSKE ske,
2487                               SilcUInt32 req_iv_len,
2488                               SilcUInt32 req_enc_key_len,
2489                               SilcUInt32 req_hmac_key_len)
2490 {
2491   SilcBuffer buf;
2492   unsigned char *tmpbuf;
2493   SilcUInt32 klen;
2494   SilcSKEKeyMaterial key;
2495
2496   /* Encode KEY to binary data */
2497   tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
2498
2499   buf = silc_buffer_alloc_size(klen + ske->hash_len);
2500   if (!buf)
2501     return NULL;
2502   silc_buffer_format(buf,
2503                      SILC_STR_UI_XNSTRING(tmpbuf, klen),
2504                      SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
2505                      SILC_STR_END);
2506
2507   /* Process the key material */
2508   key = silc_ske_process_key_material_data(buf->data, silc_buffer_len(buf),
2509                                            req_iv_len, req_enc_key_len,
2510                                            req_hmac_key_len,
2511                                            ske->prop->hash);
2512
2513   memset(tmpbuf, 0, klen);
2514   silc_free(tmpbuf);
2515   silc_buffer_clear(buf);
2516   silc_buffer_free(buf);
2517
2518   return key;
2519 }
2520
2521 /* Free key material structure */
2522
2523 void silc_ske_free_key_material(SilcSKEKeyMaterial key)
2524 {
2525   if (!key)
2526     return;
2527
2528   if (key->send_iv)
2529     silc_free(key->send_iv);
2530   if (key->receive_iv)
2531     silc_free(key->receive_iv);
2532   if (key->send_enc_key) {
2533     memset(key->send_enc_key, 0, key->enc_key_len / 8);
2534     silc_free(key->send_enc_key);
2535   }
2536   if (key->receive_enc_key) {
2537     memset(key->receive_enc_key, 0, key->enc_key_len / 8);
2538     silc_free(key->receive_enc_key);
2539   }
2540   if (key->send_hmac_key) {
2541     memset(key->send_hmac_key, 0, key->hmac_key_len);
2542     silc_free(key->send_hmac_key);
2543   }
2544   if (key->receive_hmac_key) {
2545     memset(key->receive_hmac_key, 0, key->hmac_key_len);
2546     silc_free(key->receive_hmac_key);
2547   }
2548   silc_free(key);
2549 }
2550
2551 /* Set keys into use */
2552
2553 SilcBool silc_ske_set_keys(SilcSKE ske,
2554                            SilcSKEKeyMaterial keymat,
2555                            SilcSKESecurityProperties prop,
2556                            SilcCipher *ret_send_key,
2557                            SilcCipher *ret_receive_key,
2558                            SilcHmac *ret_hmac_send,
2559                            SilcHmac *ret_hmac_receive,
2560                            SilcHash *ret_hash)
2561 {
2562   /* Allocate ciphers to be used in the communication */
2563   if (ret_send_key) {
2564     if (!silc_cipher_alloc((char *)silc_cipher_get_name(prop->cipher),
2565                            ret_send_key))
2566       return FALSE;
2567   }
2568   if (ret_receive_key) {
2569     if (!silc_cipher_alloc((char *)silc_cipher_get_name(prop->cipher),
2570                            ret_receive_key))
2571       return FALSE;
2572   }
2573
2574   /* Allocate HMACs */
2575   if (ret_hmac_send) {
2576     if (!silc_hmac_alloc((char *)silc_hmac_get_name(prop->hmac), NULL,
2577                          ret_hmac_send))
2578       return FALSE;
2579   }
2580   if (ret_hmac_receive) {
2581     if (!silc_hmac_alloc((char *)silc_hmac_get_name(prop->hmac), NULL,
2582                          ret_hmac_receive))
2583       return FALSE;
2584   }
2585
2586   /* Set key material */
2587   if (ske->responder) {
2588     silc_cipher_set_key(*ret_send_key, keymat->receive_enc_key,
2589                         keymat->enc_key_len);
2590     silc_cipher_set_iv(*ret_send_key, keymat->receive_iv);
2591     silc_cipher_set_key(*ret_receive_key, keymat->send_enc_key,
2592                         keymat->enc_key_len);
2593     silc_cipher_set_iv(*ret_receive_key, keymat->send_iv);
2594     silc_hmac_set_key(*ret_hmac_send, keymat->receive_hmac_key,
2595                       keymat->hmac_key_len);
2596     silc_hmac_set_key(*ret_hmac_receive, keymat->send_hmac_key,
2597                       keymat->hmac_key_len);
2598   } else {
2599     silc_cipher_set_key(*ret_send_key, keymat->send_enc_key,
2600                         keymat->enc_key_len);
2601     silc_cipher_set_iv(*ret_send_key, keymat->send_iv);
2602     silc_cipher_set_key(*ret_receive_key, keymat->receive_enc_key,
2603                         keymat->enc_key_len);
2604     silc_cipher_set_iv(*ret_receive_key, keymat->receive_iv);
2605     silc_hmac_set_key(*ret_hmac_send, keymat->send_hmac_key,
2606                       keymat->hmac_key_len);
2607     silc_hmac_set_key(*ret_hmac_receive, keymat->receive_hmac_key,
2608                       keymat->hmac_key_len);
2609   }
2610
2611   /* Allocate hash */
2612   if (ret_hash) {
2613     if (!silc_hash_alloc(silc_hash_get_name(prop->hash), ret_hash))
2614       return FALSE;
2615   }
2616
2617   SILC_LOG_INFO(("Security properties: %s %s %s %s",
2618                  ret_send_key ? silc_cipher_get_name(*ret_send_key) : "??",
2619                  ret_hmac_send ? silc_hmac_get_name(*ret_hmac_send) : "??",
2620                  ret_hash ? silc_hash_get_name(*ret_hash) : "??",
2621                  ske->prop->flags & SILC_SKE_SP_FLAG_PFS ? "PFS" : ""));
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 }