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