Brought back silc_ske_process_key_material_data.
[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
1325       /* Find key from repository */
1326       SILC_FSM_CALL(silc_skr_find(ske->repository, find,
1327                                   silc_ske_skr_callback, ske));
1328     } else {
1329       /* Verify from application */
1330       SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key,
1331                                                ske->callbacks->context,
1332                                                silc_ske_pk_verified, NULL));
1333     }
1334     /* NOT REACHED */
1335   }
1336
1337   /** Process key material */
1338   silc_fsm_next(fsm, silc_ske_st_initiator_phase4);
1339   return SILC_FSM_CONTINUE;
1340
1341  err:
1342   silc_ske_payload_ke_free(payload);
1343   ske->ke2_payload = NULL;
1344
1345   silc_mp_uninit(ske->KEY);
1346   silc_free(ske->KEY);
1347   ske->KEY = NULL;
1348
1349   if (status == SILC_SKE_STATUS_OK)
1350     return SILC_SKE_STATUS_ERROR;
1351
1352   /** Error */
1353   ske->status = status;
1354   silc_fsm_next(fsm, silc_ske_st_initiator_error);
1355   return SILC_FSM_CONTINUE;
1356 }
1357
1358 /* Process key material */
1359
1360 SILC_FSM_STATE(silc_ske_st_initiator_phase4)
1361 {
1362   SilcSKE ske = fsm_context;
1363   SilcSKEStatus status;
1364   SilcSKEKEPayload payload;
1365   unsigned char hash[SILC_HASH_MAXLEN];
1366   SilcUInt32 hash_len;
1367   int key_len, block_len;
1368
1369   if (ske->aborted) {
1370     /** Aborted */
1371     silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
1372     return SILC_FSM_CONTINUE;
1373   }
1374
1375   /* Check result of public key verification */
1376   if (ske->status != SILC_SKE_STATUS_OK) {
1377     /** Public key not verified */
1378     SILC_LOG_DEBUG(("Public key verification failed"));
1379     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1380     return SILC_FSM_CONTINUE;
1381   }
1382
1383   payload = ske->ke2_payload;
1384
1385   if (ske->prop->public_key) {
1386     SILC_LOG_DEBUG(("Public key is authentic"));
1387
1388     /* Compute the hash value */
1389     status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1390     if (status != SILC_SKE_STATUS_OK)
1391       goto err;
1392
1393     SILC_LOG_DEBUG(("Verifying signature (HASH)"));
1394
1395     /* Verify signature */
1396     if (!silc_pkcs_verify(ske->prop->public_key, payload->sign_data,
1397                           payload->sign_len, hash, hash_len, NULL)) {
1398       SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
1399       status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
1400       goto err;
1401     }
1402
1403     SILC_LOG_DEBUG(("Signature is Ok"));
1404
1405     ske->hash = silc_memdup(hash, hash_len);
1406     ske->hash_len = hash_len;
1407     memset(hash, 'F', hash_len);
1408   }
1409
1410   ske->status = SILC_SKE_STATUS_OK;
1411
1412   /* Process key material */
1413   key_len = silc_cipher_get_key_len(ske->prop->cipher);
1414   block_len = silc_cipher_get_key_len(ske->prop->cipher);
1415   hash_len = silc_hash_len(ske->prop->hash);
1416   ske->keymat = silc_ske_process_key_material(ske, block_len,
1417                                               key_len, hash_len);
1418   if (!ske->keymat) {
1419     SILC_LOG_ERROR(("Error processing key material"));
1420     status = SILC_SKE_STATUS_ERROR;
1421     goto err;
1422   }
1423
1424   /* Send SUCCESS packet */
1425   SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, hash);
1426   if (!silc_packet_send(ske->stream, SILC_PACKET_SUCCESS, 0, hash, 4)) {
1427     /** Error sending packet */
1428     ske->status = SILC_SKE_STATUS_ERROR;
1429     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1430     return SILC_FSM_CONTINUE;
1431   }
1432
1433   /** Waiting completion */
1434   silc_fsm_next(fsm, silc_ske_st_initiator_end);
1435   return SILC_FSM_WAIT;
1436
1437  err:
1438   memset(hash, 'F', sizeof(hash));
1439   silc_ske_payload_ke_free(payload);
1440   ske->ke2_payload = NULL;
1441
1442   silc_mp_uninit(ske->KEY);
1443   silc_free(ske->KEY);
1444   ske->KEY = NULL;
1445
1446   if (ske->hash) {
1447     memset(ske->hash, 'F', hash_len);
1448     silc_free(ske->hash);
1449     ske->hash = NULL;
1450   }
1451
1452   if (status == SILC_SKE_STATUS_OK)
1453     status = SILC_SKE_STATUS_ERROR;
1454
1455   /** Error */
1456   ske->status = status;
1457   silc_fsm_next(fsm, silc_ske_st_initiator_error);
1458   return SILC_FSM_CONTINUE;
1459 }
1460
1461 /* Protocol completed */
1462
1463 SILC_FSM_STATE(silc_ske_st_initiator_end)
1464 {
1465   SilcSKE ske = fsm_context;
1466
1467   SILC_LOG_DEBUG(("Start"));
1468
1469   if (ske->aborted) {
1470     /** Aborted */
1471     silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
1472     return SILC_FSM_CONTINUE;
1473   }
1474
1475   /* See if received failure from remote */
1476   if (ske->packet->type == SILC_PACKET_FAILURE) {
1477     silc_packet_free(ske->packet);
1478     silc_fsm_next(fsm, silc_ske_st_initiator_failure);
1479     return SILC_FSM_CONTINUE;
1480   }
1481
1482   SILC_LOG_DEBUG(("Key exchange completed successfully"));
1483
1484   /* Call the completion callback */
1485   if (ske->callbacks->completed)
1486     ske->callbacks->completed(ske, ske->status, ske->prop, ske->keymat,
1487                               ske->rekey, ske->user_data);
1488
1489   silc_packet_free(ske->packet);
1490
1491   return SILC_FSM_FINISH;
1492 }
1493
1494 /* Aborted by application */
1495
1496 SILC_FSM_STATE(silc_ske_st_initiator_aborted)
1497 {
1498   SilcSKE ske = fsm_context;
1499   unsigned char data[4];
1500
1501   SILC_LOG_DEBUG(("Aborted by caller"));
1502
1503   /* Send FAILURE packet */
1504   SILC_PUT32_MSB(SILC_SKE_STATUS_ERROR, data);
1505   silc_packet_send(ske->stream, SILC_PACKET_FAILURE, 0, data, 4);
1506
1507   return SILC_FSM_FINISH;
1508 }
1509
1510 /* Error occurred.  Send error to remote host */
1511
1512 SILC_FSM_STATE(silc_ske_st_initiator_error)
1513 {
1514   SilcSKE ske = fsm_context;
1515   SilcSKEStatus status;
1516   unsigned char data[4];
1517
1518   SILC_LOG_DEBUG(("Error %s (%d) occurred during key exchange",
1519                   silc_ske_map_status(ske->status), ske->status));
1520
1521   status = ske->status;
1522   if (status > SILC_SKE_STATUS_INVALID_COOKIE)
1523     status = SILC_SKE_STATUS_ERROR;
1524
1525   /* Send FAILURE packet */
1526   SILC_PUT32_MSB((SilcUInt32)status, data);
1527   silc_packet_send(ske->stream, SILC_PACKET_FAILURE, 0, data, 4);
1528
1529   /* Call the completion callback */
1530   if (ske->callbacks->completed)
1531     ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL, NULL);
1532
1533   return SILC_FSM_FINISH;
1534 }
1535
1536 /* Failure received from remote */
1537
1538 SILC_FSM_STATE(silc_ske_st_initiator_failure)
1539 {
1540   SilcSKE ske = fsm_context;
1541
1542   SILC_LOG_DEBUG(("Error %s (%d) received during key exchange",
1543                   silc_ske_map_status(ske->status), ske->status));
1544
1545   /* Call the completion callback */
1546   if (ske->callbacks->completed)
1547     ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL, NULL);
1548
1549   return SILC_FSM_FINISH;
1550 }
1551
1552 /* FSM destructor */
1553
1554 static void silc_ske_initiator_finished(SilcFSM fsm, void *fsm_context,
1555                                         void *destructor_context)
1556 {
1557   SilcSKE ske = fsm_context;
1558   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1559 }
1560
1561 /* Starts the protocol as initiator */
1562
1563 SilcAsyncOperation
1564 silc_ske_initiator(SilcSKE ske,
1565                    SilcPacketStream stream,
1566                    SilcSKEParams params,
1567                    SilcSKEStartPayload start_payload)
1568 {
1569   SILC_LOG_DEBUG(("Start SKE as initiator"));
1570
1571   if (!ske || !stream || !params || !params->version)
1572     return NULL;
1573
1574   if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
1575     return NULL;
1576
1577   if (!silc_fsm_init(&ske->fsm, ske, silc_ske_initiator_finished, ske,
1578                      ske->schedule))
1579     return NULL;
1580
1581   if (params->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)
1582     ske->session_port = params->session_port;
1583
1584   /* Generate security properties if not provided */
1585   if (!start_payload) {
1586     start_payload = silc_ske_assemble_security_properties(ske,
1587                                                           params->flags,
1588                                                           params->version);
1589     if (!start_payload)
1590       return NULL;
1591   }
1592
1593   ske->start_payload = start_payload;
1594   ske->version = params->version;
1595
1596   /* Link to packet stream to get key exchange packets */
1597   ske->stream = stream;
1598   silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
1599                           SILC_PACKET_KEY_EXCHANGE,
1600                           SILC_PACKET_KEY_EXCHANGE_2,
1601                           SILC_PACKET_SUCCESS,
1602                           SILC_PACKET_FAILURE, -1);
1603
1604   /* Start SKE as initiator */
1605   silc_fsm_start(&ske->fsm, silc_ske_st_initiator_start);
1606
1607   return &ske->op;
1608 }
1609
1610
1611 /******************************** Responder *********************************/
1612
1613 SILC_FSM_STATE(silc_ske_st_responder_start);
1614 SILC_FSM_STATE(silc_ske_st_responder_phase1);
1615 SILC_FSM_STATE(silc_ske_st_responder_phase2);
1616 SILC_FSM_STATE(silc_ske_st_responder_phase4);
1617 SILC_FSM_STATE(silc_ske_st_responder_phase5);
1618 SILC_FSM_STATE(silc_ske_st_responder_end);
1619 SILC_FSM_STATE(silc_ske_st_responder_aborted);
1620 SILC_FSM_STATE(silc_ske_st_responder_failure);
1621 SILC_FSM_STATE(silc_ske_st_responder_error);
1622
1623 /* Start protocol as responder.  Wait initiator's start payload */
1624
1625 SILC_FSM_STATE(silc_ske_st_responder_start)
1626 {
1627   SilcSKE ske = fsm_context;
1628
1629   SILC_LOG_DEBUG(("Start"));
1630
1631   if (ske->aborted) {
1632     /** Aborted */
1633     silc_fsm_next(fsm, silc_ske_st_responder_aborted);
1634     return SILC_FSM_CONTINUE;
1635   }
1636
1637   /* Start timeout */
1638   /* XXX */
1639
1640   /** Wait for initiator */
1641   silc_fsm_next(fsm, silc_ske_st_responder_phase1);
1642   return SILC_FSM_WAIT;
1643 }
1644
1645 /* Decode initiator's start payload.  Select the security properties from
1646    the initiator's start payload and send our reply start payload back. */
1647
1648 SILC_FSM_STATE(silc_ske_st_responder_phase1)
1649 {
1650   SilcSKE ske = fsm_context;
1651   SilcSKEStatus status;
1652   SilcSKEStartPayload remote_payload = NULL;
1653   SilcBuffer packet_buf = &ske->packet->buffer;
1654
1655   SILC_LOG_DEBUG(("Start"));
1656
1657   if (ske->aborted) {
1658     /** Aborted */
1659     silc_packet_free(ske->packet);
1660     silc_fsm_next(fsm, silc_ske_st_responder_aborted);
1661     return SILC_FSM_CONTINUE;
1662   }
1663
1664   /* See if received failure from remote */
1665   if (ske->packet->type == SILC_PACKET_FAILURE) {
1666     silc_packet_free(ske->packet);
1667     silc_fsm_next(fsm, silc_ske_st_responder_failure);
1668     return SILC_FSM_CONTINUE;
1669   }
1670
1671   /* Decode the payload */
1672   status = silc_ske_payload_start_decode(ske, packet_buf, &remote_payload);
1673   if (status != SILC_SKE_STATUS_OK) {
1674     /** Error decoding Start Payload */
1675     silc_packet_free(ske->packet);
1676     ske->status = status;
1677     silc_fsm_next(fsm, silc_ske_st_responder_error);
1678     return SILC_FSM_CONTINUE;
1679   }
1680
1681   /* Take a copy of the payload buffer for future use. It is used to
1682      compute the HASH value. */
1683   ske->start_payload_copy = silc_buffer_copy(packet_buf);
1684
1685   silc_packet_free(ske->packet);
1686
1687   /* Force the mutual authentication flag if we want to do it. */
1688   if (ske->flags & SILC_SKE_SP_FLAG_MUTUAL) {
1689     SILC_LOG_DEBUG(("Force mutual authentication"));
1690     remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
1691   }
1692
1693   /* Force PFS flag if we require it */
1694   if (ske->flags & SILC_SKE_SP_FLAG_PFS) {
1695     SILC_LOG_DEBUG(("Force PFS"));
1696     remote_payload->flags |= SILC_SKE_SP_FLAG_PFS;
1697   }
1698
1699   /* Disable IV Included flag if requested */
1700   if (remote_payload->flags & SILC_SKE_SP_FLAG_IV_INCLUDED &&
1701       !(ske->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)) {
1702     SILC_LOG_DEBUG(("We do not support IV Included flag"));
1703     remote_payload->flags &= ~SILC_SKE_SP_FLAG_IV_INCLUDED;
1704   }
1705
1706   /* Check and select security properties */
1707   status = silc_ske_select_security_properties(ske, remote_payload,
1708                                                &ske->prop);
1709   if (status != SILC_SKE_STATUS_OK) {
1710     /** Error selecting proposal */
1711     silc_ske_payload_start_free(remote_payload);
1712     ske->status = status;
1713     silc_fsm_next(fsm, silc_ske_st_responder_error);
1714     return SILC_FSM_CONTINUE;
1715   }
1716
1717   silc_ske_payload_start_free(remote_payload);
1718
1719   /* Encode our reply payload to send the selected security properties */
1720   status = silc_ske_payload_start_encode(ske, ske->start_payload,
1721                                          &packet_buf);
1722   if (status != SILC_SKE_STATUS_OK)
1723     goto err;
1724
1725   /* Send the packet. */
1726   if (!silc_packet_send(ske->stream, SILC_PACKET_KEY_EXCHANGE, 0,
1727                         silc_buffer_data(packet_buf),
1728                         silc_buffer_len(packet_buf)))
1729     goto err;
1730
1731   silc_buffer_free(packet_buf);
1732
1733   /** Waiting initiator's KE payload */
1734   silc_fsm_next(fsm, silc_ske_st_responder_phase2);
1735   return SILC_FSM_WAIT;
1736
1737  err:
1738   if (ske->prop->group)
1739     silc_ske_group_free(ske->prop->group);
1740   if (ske->prop->cipher)
1741     silc_cipher_free(ske->prop->cipher);
1742   if (ske->prop->hash)
1743     silc_hash_free(ske->prop->hash);
1744   if (ske->prop->hmac)
1745     silc_hmac_free(ske->prop->hmac);
1746   silc_free(ske->prop);
1747   ske->prop = NULL;
1748
1749   if (status == SILC_SKE_STATUS_OK)
1750     status = SILC_SKE_STATUS_ERROR;
1751
1752   /** Error */
1753   ske->status = status;
1754   silc_fsm_next(fsm, silc_ske_st_responder_error);
1755   return SILC_FSM_CONTINUE;
1756 }
1757
1758 /* Phase-2.  Decode initiator's KE payload */
1759
1760 SILC_FSM_STATE(silc_ske_st_responder_phase2)
1761 {
1762   SilcSKE ske = fsm_context;
1763   SilcSKEStatus status;
1764   SilcSKEKEPayload recv_payload;
1765   SilcBuffer packet_buf = &ske->packet->buffer;
1766
1767   SILC_LOG_DEBUG(("Start"));
1768
1769   if (ske->aborted) {
1770     /** Aborted */
1771     silc_fsm_next(fsm, silc_ske_st_responder_aborted);
1772     return SILC_FSM_CONTINUE;
1773   }
1774
1775   /* See if received failure from remote */
1776   if (ske->packet->type == SILC_PACKET_FAILURE) {
1777     silc_fsm_next(fsm, silc_ske_st_responder_failure);
1778     return SILC_FSM_CONTINUE;
1779   }
1780
1781   /* Decode Key Exchange Payload */
1782   status = silc_ske_payload_ke_decode(ske, packet_buf, &recv_payload);
1783   if (status != SILC_SKE_STATUS_OK) {
1784     /** Error decoding KE payload */
1785     silc_packet_free(ske->packet);
1786     ske->status = status;
1787     silc_fsm_next(fsm, silc_ske_st_responder_error);
1788     return SILC_FSM_CONTINUE;
1789   }
1790
1791   ske->ke1_payload = recv_payload;
1792
1793   silc_packet_free(ske->packet);
1794
1795   /* Verify the received public key and verify the signature if we are
1796      doing mutual authentication. */
1797   if (ske->start_payload &&
1798       ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
1799
1800     SILC_LOG_DEBUG(("We are doing mutual authentication"));
1801
1802     if (!recv_payload->pk_data && (ske->callbacks->verify_key ||
1803                                    ske->repository)) {
1804       /** Public key not provided */
1805       SILC_LOG_ERROR(("Remote end did not send its public key (or "
1806                       "certificate), even though we require it"));
1807       ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
1808       silc_fsm_next(fsm, silc_ske_st_responder_error);
1809       return SILC_FSM_CONTINUE;
1810     }
1811
1812     /* Decode the remote's public key */
1813     if (recv_payload->pk_data &&
1814         !silc_pkcs_public_key_alloc(recv_payload->pk_type,
1815                                     recv_payload->pk_data,
1816                                     recv_payload->pk_len,
1817                                     &ske->prop->public_key)) {
1818       /** Error decoding public key */
1819       SILC_LOG_ERROR(("Unsupported/malformed public key received"));
1820       ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
1821       silc_fsm_next(fsm, silc_ske_st_responder_error);
1822       return SILC_FSM_CONTINUE;
1823     }
1824
1825     if (ske->prop->public_key && (ske->callbacks->verify_key ||
1826                                   ske->repository)) {
1827       SILC_LOG_DEBUG(("Verifying public key"));
1828
1829       /** Waiting public key verification */
1830       silc_fsm_next(fsm, silc_ske_st_responder_phase4);
1831
1832       /* If repository is provided, verify the key from there. */
1833       if (ske->repository) {
1834         SilcSKRFind find;
1835
1836         find = silc_skr_find_alloc();
1837         if (!find) {
1838           ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1839           silc_fsm_next(fsm, silc_ske_st_responder_error);
1840           return SILC_FSM_CONTINUE;
1841         }
1842         silc_skr_find_set_pkcs_type(find,
1843                                     silc_pkcs_get_type(ske->prop->public_key));
1844         silc_skr_find_set_public_key(find, ske->prop->public_key);
1845
1846         /* Find key from repository */
1847         SILC_FSM_CALL(silc_skr_find(ske->repository, find,
1848                                     silc_ske_skr_callback, ske));
1849       } else {
1850         /* Verify from application */
1851         SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key,
1852                                                  ske->callbacks->context,
1853                                                  silc_ske_pk_verified, NULL));
1854       }
1855       /* NOT REACHED */
1856     }
1857   }
1858
1859   /** Generate KE2 payload */
1860   silc_fsm_next(fsm, silc_ske_st_responder_phase4);
1861   return SILC_FSM_CONTINUE;
1862 }
1863
1864 /* Phase-4. Generate KE2 payload */
1865
1866 SILC_FSM_STATE(silc_ske_st_responder_phase4)
1867 {
1868   SilcSKE ske = fsm_context;
1869   SilcSKEStatus status;
1870   SilcSKEKEPayload recv_payload, send_payload;
1871   SilcMPInt *x, *KEY;
1872
1873   if (ske->aborted) {
1874     /** Aborted */
1875     silc_fsm_next(fsm, silc_ske_st_responder_aborted);
1876     return SILC_FSM_CONTINUE;
1877   }
1878
1879   /* Check result of public key verification */
1880   if (ske->status != SILC_SKE_STATUS_OK) {
1881     /** Public key not verified */
1882     SILC_LOG_DEBUG(("Public key verification failed"));
1883     silc_fsm_next(fsm, silc_ske_st_initiator_error);
1884     return SILC_FSM_CONTINUE;
1885   }
1886
1887   recv_payload = ske->ke1_payload;
1888
1889   /* The public key verification was performed only if the Mutual
1890      Authentication flag is set. */
1891   if (ske->start_payload &&
1892       ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
1893     unsigned char hash[SILC_HASH_MAXLEN];
1894     SilcUInt32 hash_len;
1895
1896     SILC_LOG_DEBUG(("Public key is authentic"));
1897
1898     /* Compute the hash value */
1899     status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
1900     if (status != SILC_SKE_STATUS_OK) {
1901       /** Error computing hash */
1902       ske->status = status;
1903       silc_fsm_next(fsm, silc_ske_st_responder_error);
1904       return SILC_FSM_CONTINUE;
1905     }
1906
1907     SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
1908
1909     /* Verify signature */
1910     if (!silc_pkcs_verify(ske->prop->public_key, recv_payload->sign_data,
1911                           recv_payload->sign_len, hash, hash_len, NULL)) {
1912       /** Incorrect signature */
1913       SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
1914       ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
1915       silc_fsm_next(fsm, silc_ske_st_responder_error);
1916       return SILC_FSM_CONTINUE;
1917     }
1918
1919     SILC_LOG_DEBUG(("Signature is Ok"));
1920
1921     memset(hash, 'F', hash_len);
1922   }
1923
1924   /* Create the random number x, 1 < x < q. */
1925   x = silc_calloc(1, sizeof(*x));
1926   silc_mp_init(x);
1927   status =
1928     silc_ske_create_rnd(ske, &ske->prop->group->group_order,
1929                         silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
1930                         x);
1931   if (status != SILC_SKE_STATUS_OK) {
1932     /** Error generating random number */
1933     silc_mp_uninit(x);
1934     silc_free(x);
1935     ske->status = status;
1936     silc_fsm_next(fsm, silc_ske_st_responder_error);
1937     return SILC_FSM_CONTINUE;
1938   }
1939
1940   /* Save the results for later processing */
1941   send_payload = silc_calloc(1, sizeof(*send_payload));
1942   ske->x = x;
1943   ske->ke2_payload = send_payload;
1944
1945   SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
1946
1947   /* Do the Diffie Hellman computation, f = g ^ x mod p */
1948   silc_mp_init(&send_payload->x);
1949   silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
1950                   &ske->prop->group->group);
1951
1952   SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
1953
1954   /* Compute the shared secret key */
1955   KEY = silc_calloc(1, sizeof(*KEY));
1956   silc_mp_init(KEY);
1957   silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
1958                   &ske->prop->group->group);
1959   ske->KEY = KEY;
1960
1961   /** Send KE2 payload */
1962   silc_fsm_next(fsm, silc_ske_st_responder_phase5);
1963   return SILC_FSM_CONTINUE;
1964 }
1965
1966 /* Phase-5.  Send KE2 payload */
1967
1968 SILC_FSM_STATE(silc_ske_st_responder_phase5)
1969 {
1970   SilcSKE ske = fsm_context;
1971   SilcSKEStatus status;
1972   SilcBuffer payload_buf;
1973   unsigned char hash[SILC_HASH_MAXLEN], sign[2048 + 1], *pk;
1974   SilcUInt32 hash_len, sign_len, pk_len;
1975
1976   SILC_LOG_DEBUG(("Start"));
1977
1978   if (ske->public_key && ske->private_key) {
1979     SILC_LOG_DEBUG(("Getting public key"));
1980
1981     /* Get the public key */
1982     pk = silc_pkcs_public_key_encode(ske->public_key, &pk_len);
1983     if (!pk) {
1984       /** Error encoding public key */
1985       status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1986       silc_fsm_next(fsm, silc_ske_st_responder_error);
1987       return SILC_FSM_CONTINUE;
1988     }
1989     ske->ke2_payload->pk_data = pk;
1990     ske->ke2_payload->pk_len = pk_len;
1991
1992     SILC_LOG_DEBUG(("Computing HASH value"));
1993
1994     /* Compute the hash value */
1995     memset(hash, 0, sizeof(hash));
1996     status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1997     if (status != SILC_SKE_STATUS_OK) {
1998       /** Error computing hash */
1999       ske->status = status;
2000       silc_fsm_next(fsm, silc_ske_st_responder_error);
2001       return SILC_FSM_CONTINUE;
2002     }
2003
2004     ske->hash = silc_memdup(hash, hash_len);
2005     ske->hash_len = hash_len;
2006
2007     SILC_LOG_DEBUG(("Signing HASH value"));
2008
2009     /* Sign the hash value */
2010     if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
2011                         sizeof(sign) - 1, &sign_len, NULL)) {
2012       /** Error computing signature */
2013       status = SILC_SKE_STATUS_SIGNATURE_ERROR;
2014       silc_fsm_next(fsm, silc_ske_st_responder_error);
2015       return SILC_FSM_CONTINUE;
2016     }
2017     ske->ke2_payload->sign_data = silc_memdup(sign, sign_len);
2018     ske->ke2_payload->sign_len = sign_len;
2019     memset(sign, 0, sizeof(sign));
2020   }
2021   ske->ke2_payload->pk_type = silc_pkcs_get_type(ske->public_key);
2022
2023   /* Encode the Key Exchange Payload */
2024   status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
2025                                       &payload_buf);
2026   if (status != SILC_SKE_STATUS_OK) {
2027     /** Error encoding KE payload */
2028     ske->status = status;
2029     silc_fsm_next(fsm, silc_ske_st_responder_error);
2030     return SILC_FSM_CONTINUE;
2031   }
2032
2033   /* Send the packet. */
2034   if (!silc_packet_send(ske->stream, SILC_PACKET_KEY_EXCHANGE_2, 0,
2035                         payload_buf->data, silc_buffer_len(payload_buf))) {
2036     ske->status = SILC_SKE_STATUS_ERROR;
2037     silc_fsm_next(fsm, silc_ske_st_responder_error);
2038     return SILC_FSM_CONTINUE;
2039   }
2040
2041   silc_buffer_free(payload_buf);
2042
2043   /** Waiting completion */
2044   silc_fsm_next(fsm, silc_ske_st_responder_end);
2045   return SILC_FSM_WAIT;
2046 }
2047
2048 /* Protocol completed */
2049
2050 SILC_FSM_STATE(silc_ske_st_responder_end)
2051 {
2052   SilcSKE ske = fsm_context;
2053   unsigned char tmp[4];
2054   SilcUInt32 hash_len, key_len, block_len;
2055
2056   if (ske->aborted) {
2057     /** Aborted */
2058     silc_fsm_next(fsm, silc_ske_st_responder_aborted);
2059     return SILC_FSM_CONTINUE;
2060   }
2061
2062   /* Check the result of the protocol */
2063   if (ske->packet->type == SILC_PACKET_FAILURE) {
2064     silc_fsm_next(fsm, silc_ske_st_responder_failure);
2065     return SILC_FSM_CONTINUE;
2066   }
2067   silc_packet_free(ske->packet);
2068
2069   /* Process key material */
2070   key_len = silc_cipher_get_key_len(ske->prop->cipher);
2071   block_len = silc_cipher_get_key_len(ske->prop->cipher);
2072   hash_len = silc_hash_len(ske->prop->hash);
2073   ske->keymat = silc_ske_process_key_material(ske, block_len,
2074                                               key_len, hash_len);
2075   if (!ske->keymat) {
2076     /** Error processing key material */
2077     ske->status = SILC_SKE_STATUS_ERROR;
2078     silc_fsm_next(fsm, silc_ske_st_responder_error);
2079     return SILC_FSM_CONTINUE;
2080   }
2081
2082   /* Send SUCCESS packet */
2083   SILC_PUT32_MSB(SILC_SKE_STATUS_OK, tmp);
2084   silc_packet_send(ske->stream, SILC_PACKET_SUCCESS, 0, tmp, 4);
2085
2086   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2087
2088   /* Call the completion callback */
2089   if (ske->callbacks->completed)
2090     ske->callbacks->completed(ske, ske->status, ske->prop, ske->keymat,
2091                               ske->rekey, ske->callbacks->context);
2092
2093   return SILC_FSM_FINISH;
2094 }
2095
2096 /* Aborted by application */
2097
2098 SILC_FSM_STATE(silc_ske_st_responder_aborted)
2099 {
2100   SilcSKE ske = fsm_context;
2101   unsigned char tmp[4];
2102
2103   SILC_LOG_DEBUG(("Key exchange protocol aborted"));
2104
2105   /* Send FAILURE packet */
2106   SILC_PUT32_MSB(SILC_SKE_STATUS_ERROR, tmp);
2107   silc_packet_send(ske->stream, SILC_PACKET_FAILURE, 0, tmp, 4);
2108
2109   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2110
2111   return SILC_FSM_FINISH;
2112 }
2113
2114 /* Failure received from remote */
2115
2116 SILC_FSM_STATE(silc_ske_st_responder_failure)
2117 {
2118   SilcSKE ske = fsm_context;
2119   SilcUInt32 error = SILC_SKE_STATUS_ERROR;
2120
2121   SILC_LOG_DEBUG(("Key exchange protocol failed"));
2122
2123   if (silc_buffer_len(&ske->packet->buffer) == 4)
2124     SILC_GET32_MSB(error, ske->packet->buffer.data);
2125   ske->status = error;
2126
2127   /* Call the completion callback */
2128   if (ske->callbacks->completed)
2129     ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL,
2130                               ske->callbacks->context);
2131
2132   silc_packet_free(ske->packet);
2133   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2134
2135   return SILC_FSM_FINISH;
2136 }
2137
2138 /* Error occurred */
2139
2140 SILC_FSM_STATE(silc_ske_st_responder_error)
2141 {
2142   SilcSKE ske = fsm_context;
2143   unsigned char tmp[4];
2144
2145   SILC_LOG_DEBUG(("Error %d (%s) during key exchange protocol",
2146                   ske->status, silc_ske_map_status(ske->status)));
2147
2148   /* Send FAILURE packet */
2149   if (ske->status > SILC_SKE_STATUS_INVALID_COOKIE)
2150     ske->status = SILC_SKE_STATUS_BAD_PAYLOAD;
2151   SILC_PUT32_MSB(ske->status, tmp);
2152   silc_packet_send(ske->stream, SILC_PACKET_FAILURE, 0, tmp, 4);
2153
2154   silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2155
2156   return SILC_FSM_FINISH;
2157 }
2158
2159
2160 static void silc_ske_responder_finished(SilcFSM fsm, void *fsm_context,
2161                                         void *destructor_context)
2162 {
2163
2164 }
2165
2166 /* Starts the protocol as responder. */
2167
2168 SilcAsyncOperation
2169 silc_ske_responder(SilcSKE ske,
2170                    SilcPacketStream stream,
2171                    SilcSKEParams params)
2172 {
2173   SILC_LOG_DEBUG(("Start SKE as responder"));
2174
2175   if (!ske || !stream || !params || !params->version) {
2176     return NULL;
2177   }
2178
2179   if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
2180     return NULL;
2181
2182   if (!silc_fsm_init(&ske->fsm, ske, silc_ske_responder_finished, ske,
2183                      ske->schedule))
2184     return NULL;
2185
2186   ske->responder = TRUE;
2187   ske->flags = params->flags;
2188   if (ske->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)
2189     ske->session_port = params->session_port;
2190   ske->version = strdup(params->version);
2191   if (!ske->version)
2192     return NULL;
2193
2194   /* Link to packet stream to get key exchange packets */
2195   ske->stream = stream;
2196   silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
2197                           SILC_PACKET_KEY_EXCHANGE,
2198                           SILC_PACKET_KEY_EXCHANGE_1,
2199                           SILC_PACKET_SUCCESS,
2200                           SILC_PACKET_FAILURE, -1);
2201
2202   /* Start SKE as responder */
2203   silc_fsm_start(&ske->fsm, silc_ske_st_responder_start);
2204
2205   return &ske->op;
2206 }
2207
2208 SILC_FSM_STATE(silc_ske_st_rekey_initiator_start);
2209
2210 SILC_FSM_STATE(silc_ske_st_rekey_initiator_start)
2211 {
2212   return SILC_FSM_FINISH;
2213 }
2214
2215 /* Starts rekey protocol as initiator */
2216
2217 SilcAsyncOperation
2218 silc_ske_rekey_initiator(SilcSKE ske,
2219                          SilcPacketStream stream,
2220                          SilcSKERekeyMaterial rekey)
2221 {
2222   SILC_LOG_DEBUG(("Start SKE rekey as initator"));
2223
2224   if (!ske || !stream || !rekey)
2225     return NULL;
2226
2227   if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
2228     return NULL;
2229
2230   if (!silc_fsm_init(&ske->fsm, ske, NULL, NULL, ske->schedule))
2231     return NULL;
2232
2233   ske->rekey = rekey;
2234
2235   /* Link to packet stream to get key exchange packets */
2236   ske->stream = stream;
2237
2238   /* Start SKE rekey as initiator */
2239   silc_fsm_start(&ske->fsm, silc_ske_st_rekey_initiator_start);
2240
2241   return &ske->op;
2242 }
2243
2244 SILC_FSM_STATE(silc_ske_st_rekey_responder_start);
2245
2246 SILC_FSM_STATE(silc_ske_st_rekey_responder_start)
2247 {
2248   return SILC_FSM_FINISH;
2249 }
2250
2251 /* Starts rekey protocol as responder */
2252
2253 SilcAsyncOperation
2254 silc_ske_rekey_responder(SilcSKE ske,
2255                          SilcPacketStream stream,
2256                          SilcBuffer ke_payload,
2257                          SilcSKERekeyMaterial rekey)
2258 {
2259   SILC_LOG_DEBUG(("Start SKE rekey as responder"));
2260
2261   if (!ske || !stream || !rekey)
2262     return NULL;
2263   if (rekey->pfs && !ke_payload)
2264     return NULL;
2265
2266   if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
2267     return NULL;
2268
2269   if (!silc_fsm_init(&ske->fsm, ske, NULL, NULL, ske->schedule))
2270     return NULL;
2271
2272   //  ske->packet_buf = ke_payload;
2273   ske->rekey = rekey;
2274
2275   /* Link to packet stream to get key exchange packets */
2276   ske->stream = stream;
2277
2278   /* Start SKE rekey as responder */
2279   silc_fsm_start(&ske->fsm, silc_ske_st_rekey_responder_start);
2280
2281   return &ske->op;
2282 }
2283
2284 /* Processes the provided key material `data' as the SILC protocol
2285    specification defines. */
2286
2287 SilcSKEKeyMaterial
2288 silc_ske_process_key_material_data(unsigned char *data,
2289                                    SilcUInt32 data_len,
2290                                    SilcUInt32 req_iv_len,
2291                                    SilcUInt32 req_enc_key_len,
2292                                    SilcUInt32 req_hmac_key_len,
2293                                    SilcHash hash)
2294 {
2295   SilcBuffer buf;
2296   unsigned char hashd[SILC_HASH_MAXLEN];
2297   SilcUInt32 hash_len = req_hmac_key_len;
2298   SilcUInt32 enc_key_len = req_enc_key_len / 8;
2299   SilcSKEKeyMaterial key;
2300
2301   SILC_LOG_DEBUG(("Start"));
2302
2303   if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
2304     return NULL;
2305
2306   key = silc_calloc(1, sizeof(*key));
2307   if (!key)
2308     return NULL;
2309
2310   buf = silc_buffer_alloc_size(1 + data_len);
2311   if (!buf)
2312     return NULL;
2313   silc_buffer_format(buf,
2314                      SILC_STR_UI_CHAR(0),
2315                      SILC_STR_UI_XNSTRING(data, data_len),
2316                      SILC_STR_END);
2317
2318   /* Take IVs */
2319   memset(hashd, 0, sizeof(hashd));
2320   buf->data[0] = 0;
2321   silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2322   key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
2323   memcpy(key->send_iv, hashd, req_iv_len);
2324   memset(hashd, 0, sizeof(hashd));
2325   buf->data[0] = 1;
2326   silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2327   key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
2328   memcpy(key->receive_iv, hashd, req_iv_len);
2329   key->iv_len = req_iv_len;
2330
2331   /* Take the encryption keys. If requested key size is more than
2332      the size of hash length we will distribute more key material
2333      as protocol defines. */
2334   buf->data[0] = 2;
2335   if (enc_key_len > hash_len) {
2336     SilcBuffer dist;
2337     unsigned char k1[SILC_HASH_MAXLEN], k2[SILC_HASH_MAXLEN],
2338         k3[SILC_HASH_MAXLEN];
2339     unsigned char *dtmp;
2340
2341     /* XXX */
2342     if (enc_key_len > (3 * hash_len))
2343       return NULL;
2344
2345     /* Take first round */
2346     memset(k1, 0, sizeof(k1));
2347     silc_hash_make(hash, buf->data, silc_buffer_len(buf), k1);
2348
2349     /* Take second round */
2350     dist = silc_buffer_alloc_size(data_len + hash_len);
2351     if (!dist)
2352       return NULL;
2353     silc_buffer_format(dist,
2354                        SILC_STR_UI_XNSTRING(data, data_len),
2355                        SILC_STR_UI_XNSTRING(k1, hash_len),
2356                        SILC_STR_END);
2357     memset(k2, 0, sizeof(k2));
2358     silc_hash_make(hash, dist->data, silc_buffer_len(dist), k2);
2359
2360     /* Take third round */
2361     dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
2362     silc_buffer_pull_tail(dist, hash_len);
2363     silc_buffer_pull(dist, data_len + hash_len);
2364     silc_buffer_format(dist,
2365                        SILC_STR_UI_XNSTRING(k2, hash_len),
2366                        SILC_STR_END);
2367     silc_buffer_push(dist, data_len + hash_len);
2368     memset(k3, 0, sizeof(k3));
2369     silc_hash_make(hash, dist->data, silc_buffer_len(dist), k3);
2370
2371     /* Then, save the keys */
2372     dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
2373     memcpy(dtmp, k1, hash_len);
2374     memcpy(dtmp + hash_len, k2, hash_len);
2375     memcpy(dtmp + hash_len + hash_len, k3, hash_len);
2376
2377     key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
2378     memcpy(key->send_enc_key, dtmp, enc_key_len);
2379     key->enc_key_len = req_enc_key_len;
2380
2381     memset(dtmp, 0, (3 * hash_len));
2382     memset(k1, 0, sizeof(k1));
2383     memset(k2, 0, sizeof(k2));
2384     memset(k3, 0, sizeof(k3));
2385     silc_free(dtmp);
2386     silc_buffer_clear(dist);
2387     silc_buffer_free(dist);
2388   } else {
2389     /* Take normal hash as key */
2390     memset(hashd, 0, sizeof(hashd));
2391     silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2392     key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
2393     memcpy(key->send_enc_key, hashd, enc_key_len);
2394     key->enc_key_len = req_enc_key_len;
2395   }
2396
2397   buf->data[0] = 3;
2398   if (enc_key_len > hash_len) {
2399     SilcBuffer dist;
2400     unsigned char k1[SILC_HASH_MAXLEN], k2[SILC_HASH_MAXLEN],
2401         k3[SILC_HASH_MAXLEN];
2402     unsigned char *dtmp;
2403
2404     /* XXX */
2405     if (enc_key_len > (3 * hash_len))
2406       return NULL;
2407
2408     /* Take first round */
2409     memset(k1, 0, sizeof(k1));
2410     silc_hash_make(hash, buf->data, silc_buffer_len(buf), k1);
2411
2412     /* Take second round */
2413     dist = silc_buffer_alloc_size(data_len + hash_len);
2414     if (!dist)
2415       return NULL;
2416     silc_buffer_format(dist,
2417                        SILC_STR_UI_XNSTRING(data, data_len),
2418                        SILC_STR_UI_XNSTRING(k1, hash_len),
2419                        SILC_STR_END);
2420     memset(k2, 0, sizeof(k2));
2421     silc_hash_make(hash, dist->data, silc_buffer_len(dist), k2);
2422
2423     /* Take third round */
2424     dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
2425     silc_buffer_pull_tail(dist, hash_len);
2426     silc_buffer_pull(dist, data_len + hash_len);
2427     silc_buffer_format(dist,
2428                        SILC_STR_UI_XNSTRING(k2, hash_len),
2429                        SILC_STR_END);
2430     silc_buffer_push(dist, data_len + hash_len);
2431     memset(k3, 0, sizeof(k3));
2432     silc_hash_make(hash, dist->data, silc_buffer_len(dist), k3);
2433
2434     /* Then, save the keys */
2435     dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
2436     memcpy(dtmp, k1, hash_len);
2437     memcpy(dtmp + hash_len, k2, hash_len);
2438     memcpy(dtmp + hash_len + hash_len, k3, hash_len);
2439
2440     key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
2441     memcpy(key->receive_enc_key, dtmp, enc_key_len);
2442     key->enc_key_len = req_enc_key_len;
2443
2444     memset(dtmp, 0, (3 * hash_len));
2445     memset(k1, 0, sizeof(k1));
2446     memset(k2, 0, sizeof(k2));
2447     memset(k3, 0, sizeof(k3));
2448     silc_free(dtmp);
2449     silc_buffer_clear(dist);
2450     silc_buffer_free(dist);
2451   } else {
2452     /* Take normal hash as key */
2453     memset(hashd, 0, sizeof(hashd));
2454     silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2455     key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
2456     memcpy(key->receive_enc_key, hashd, enc_key_len);
2457     key->enc_key_len = req_enc_key_len;
2458   }
2459
2460   /* Take HMAC keys */
2461   memset(hashd, 0, sizeof(hashd));
2462   buf->data[0] = 4;
2463   silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2464   key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
2465   memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
2466   memset(hashd, 0, sizeof(hashd));
2467   buf->data[0] = 5;
2468   silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2469   key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
2470   memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
2471   key->hmac_key_len = req_hmac_key_len;
2472   memset(hashd, 0, sizeof(hashd));
2473
2474   silc_buffer_clear(buf);
2475   silc_buffer_free(buf);
2476
2477   return key;
2478 }
2479
2480 /* Processes negotiated key material as protocol specifies. This returns
2481    the actual keys to be used in the SILC. */
2482
2483 SilcSKEKeyMaterial
2484 silc_ske_process_key_material(SilcSKE ske,
2485                               SilcUInt32 req_iv_len,
2486                               SilcUInt32 req_enc_key_len,
2487                               SilcUInt32 req_hmac_key_len)
2488 {
2489   SilcBuffer buf;
2490   unsigned char *tmpbuf;
2491   SilcUInt32 klen;
2492   SilcSKEKeyMaterial key;
2493
2494   /* Encode KEY to binary data */
2495   tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
2496
2497   buf = silc_buffer_alloc_size(klen + ske->hash_len);
2498   if (!buf)
2499     return NULL;
2500   silc_buffer_format(buf,
2501                      SILC_STR_UI_XNSTRING(tmpbuf, klen),
2502                      SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
2503                      SILC_STR_END);
2504
2505   /* Process the key material */
2506   key = silc_ske_process_key_material_data(buf->data, silc_buffer_len(buf),
2507                                            req_iv_len, req_enc_key_len,
2508                                            req_hmac_key_len,
2509                                            ske->prop->hash);
2510
2511   memset(tmpbuf, 0, klen);
2512   silc_free(tmpbuf);
2513   silc_buffer_clear(buf);
2514   silc_buffer_free(buf);
2515
2516   return key;
2517 }
2518
2519 /* Free key material structure */
2520
2521 void silc_ske_free_key_material(SilcSKEKeyMaterial key)
2522 {
2523   if (!key)
2524     return;
2525
2526   if (key->send_iv)
2527     silc_free(key->send_iv);
2528   if (key->receive_iv)
2529     silc_free(key->receive_iv);
2530   if (key->send_enc_key) {
2531     memset(key->send_enc_key, 0, key->enc_key_len / 8);
2532     silc_free(key->send_enc_key);
2533   }
2534   if (key->receive_enc_key) {
2535     memset(key->receive_enc_key, 0, key->enc_key_len / 8);
2536     silc_free(key->receive_enc_key);
2537   }
2538   if (key->send_hmac_key) {
2539     memset(key->send_hmac_key, 0, key->hmac_key_len);
2540     silc_free(key->send_hmac_key);
2541   }
2542   if (key->receive_hmac_key) {
2543     memset(key->receive_hmac_key, 0, key->hmac_key_len);
2544     silc_free(key->receive_hmac_key);
2545   }
2546   silc_free(key);
2547 }
2548
2549 /* Set keys into use */
2550
2551 SilcBool silc_ske_set_keys(SilcSKE ske,
2552                            SilcSKEKeyMaterial keymat,
2553                            SilcSKESecurityProperties prop,
2554                            SilcCipher *ret_send_key,
2555                            SilcCipher *ret_receive_key,
2556                            SilcHmac *ret_hmac_send,
2557                            SilcHmac *ret_hmac_receive,
2558                            SilcHash *ret_hash)
2559 {
2560   /* Allocate ciphers to be used in the communication */
2561   if (ret_send_key) {
2562     if (!silc_cipher_alloc((char *)silc_cipher_get_name(prop->cipher),
2563                            ret_send_key))
2564       return FALSE;
2565   }
2566   if (ret_receive_key) {
2567     if (!silc_cipher_alloc((char *)silc_cipher_get_name(prop->cipher),
2568                            ret_receive_key))
2569       return FALSE;
2570   }
2571
2572   /* Allocate HMACs */
2573   if (ret_hmac_send) {
2574     if (!silc_hmac_alloc((char *)silc_hmac_get_name(prop->hmac), NULL,
2575                          ret_hmac_send))
2576       return FALSE;
2577   }
2578   if (ret_hmac_receive) {
2579     if (!silc_hmac_alloc((char *)silc_hmac_get_name(prop->hmac), NULL,
2580                          ret_hmac_receive))
2581       return FALSE;
2582   }
2583
2584   /* Set key material */
2585   if (ske->responder) {
2586     silc_cipher_set_key(*ret_send_key, keymat->receive_enc_key,
2587                         keymat->enc_key_len);
2588     silc_cipher_set_iv(*ret_send_key, keymat->receive_iv);
2589     silc_cipher_set_key(*ret_receive_key, keymat->send_enc_key,
2590                         keymat->enc_key_len);
2591     silc_cipher_set_iv(*ret_receive_key, keymat->send_iv);
2592     silc_hmac_set_key(*ret_hmac_send, keymat->receive_hmac_key,
2593                       keymat->hmac_key_len);
2594     silc_hmac_set_key(*ret_hmac_receive, keymat->send_hmac_key,
2595                       keymat->hmac_key_len);
2596   } else {
2597     silc_cipher_set_key(*ret_send_key, keymat->send_enc_key,
2598                         keymat->enc_key_len);
2599     silc_cipher_set_iv(*ret_send_key, keymat->send_iv);
2600     silc_cipher_set_key(*ret_receive_key, keymat->receive_enc_key,
2601                         keymat->enc_key_len);
2602     silc_cipher_set_iv(*ret_receive_key, keymat->receive_iv);
2603     silc_hmac_set_key(*ret_hmac_send, keymat->send_hmac_key,
2604                       keymat->hmac_key_len);
2605     silc_hmac_set_key(*ret_hmac_receive, keymat->receive_hmac_key,
2606                       keymat->hmac_key_len);
2607   }
2608
2609   /* Allocate hash */
2610   if (ret_hash) {
2611     if (!silc_hash_alloc(silc_hash_get_name(prop->hash), ret_hash))
2612       return FALSE;
2613   }
2614
2615   SILC_LOG_INFO(("Security properties: %s %s %s %s",
2616                  ret_send_key ? silc_cipher_get_name(*ret_send_key) : "??",
2617                  ret_hmac_send ? silc_hmac_get_name(*ret_hmac_send) : "??",
2618                  ret_hash ? silc_hash_get_name(*ret_hash) : "??",
2619                  ske->prop->flags & SILC_SKE_SP_FLAG_PFS ? "PFS" : ""));
2620
2621   return TRUE;
2622 }
2623
2624 const char *silc_ske_status_string[] =
2625 {
2626   /* Official */
2627   "Ok",
2628   "Unkown error occurred",
2629   "Bad payload in packet",
2630   "Unsupported group",
2631   "Unsupported cipher",
2632   "Unsupported PKCS",
2633   "Unsupported hash function",
2634   "Unsupported HMAC",
2635   "Unsupported public key (or certificate)",
2636   "Incorrect signature",
2637   "Bad or unsupported version",
2638   "Invalid cookie",
2639
2640   /* Other errors */
2641   "Remote did not provide public key",
2642   "Bad reserved field in packet",
2643   "Bad payload length in packet",
2644   "Error computing signature",
2645   "System out of memory",
2646
2647   NULL
2648 };
2649
2650 /* Maps status to readable string and returns the string. If string is not
2651    found and empty character string ("") is returned. */
2652
2653 const char *silc_ske_map_status(SilcSKEStatus status)
2654 {
2655   int i;
2656
2657   for (i = 0; silc_ske_status_string[i]; i++)
2658     if (status == i)
2659       return silc_ske_status_string[i];
2660
2661   return "";
2662 }
2663
2664 /* Parses remote host's version string. */
2665
2666 SilcBool silc_ske_parse_version(SilcSKE ske,
2667                                 SilcUInt32 *protocol_version,
2668                                 char **protocol_version_string,
2669                                 SilcUInt32 *software_version,
2670                                 char **software_version_string,
2671                                 char **vendor_version)
2672 {
2673   return silc_parse_version_string(ske->remote_version,
2674                                    protocol_version,
2675                                    protocol_version_string,
2676                                    software_version,
2677                                    software_version_string,
2678                                    vendor_version);
2679 }
2680
2681 /* Get security properties */
2682
2683 SilcSKESecurityProperties silc_ske_get_security_properties(SilcSKE ske)
2684 {
2685   return ske->prop;
2686 }