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