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