updates.
[silc.git] / lib / silcske / silcske.c
1 /*
2
3   silcske.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 2000 - 2001 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; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "silcincludes.h"
23 #include "payload_internal.h"
24 #include "groups_internal.h"
25
26 /* Allocates new SKE object. */
27
28 SilcSKE silc_ske_alloc()
29 {
30   SilcSKE ske;
31
32   SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
33
34   ske = silc_calloc(1, sizeof(*ske));
35   ske->status = SILC_SKE_STATUS_OK;
36
37   return ske;
38 }
39
40 /* Free's SKE object. */
41
42 void silc_ske_free(SilcSKE ske)
43 {
44   SILC_LOG_DEBUG(("Freeing Key Exchange object"));
45
46   if (ske) {
47     /* Free start payload */
48     if (ske->start_payload)
49       silc_ske_payload_start_free(ske->start_payload);
50
51     /* Free KE payload */
52     if (ske->ke1_payload)
53       silc_ske_payload_ke_free(ske->ke1_payload);
54
55     /* Free rest */
56     if (ske->prop) {
57       if (ske->prop->group)
58         silc_free(ske->prop->group);
59       if (ske->prop->pkcs)
60         silc_pkcs_free(ske->prop->pkcs);
61       if (ske->prop->cipher)
62         silc_cipher_free(ske->prop->cipher);
63       if (ske->prop->hash)
64         silc_hash_free(ske->prop->hash);
65       if (ske->prop->hmac)
66         silc_hmac_free(ske->prop->hmac);
67       silc_free(ske->prop);
68     }
69     if (ske->start_payload_copy)
70       silc_buffer_free(ske->start_payload_copy);
71     if (ske->pk)
72       silc_free(ske->pk);
73     if (ske->x) {
74       silc_mp_uninit(ske->x);
75       silc_free(ske->x);
76     }
77     if (ske->KEY) {
78       silc_mp_uninit(ske->KEY);
79       silc_free(ske->KEY);
80     }
81     if (ske->hash)
82       silc_free(ske->hash);
83     silc_free(ske);
84   }
85 }
86
87 /* Starts the SILC Key Exchange protocol for initiator. The connection
88    to the remote end must be established before calling this function
89    and the connecting socket must be sent as argument. This function
90    creates the Key Exchange Start Paload which includes all our
91    configured security properties. This payload is then sent to the
92    remote end for further processing. This payload must be sent as
93    argument to the function, however, it must not be encoded
94    already, it is done by this function.
95
96    The packet sending is done by calling a callback function. Caller
97    must provide a routine to send the packet. */
98
99 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
100                                        SilcSocketConnection sock,
101                                        SilcSKEStartPayload *start_payload,
102                                        SilcSKESendPacketCb send_packet,
103                                        void *context)
104 {
105   SilcSKEStatus status = SILC_SKE_STATUS_OK;
106   SilcBuffer payload_buf;
107
108   SILC_LOG_DEBUG(("Start"));
109
110   ske->sock = sock;
111   ske->rng = rng;
112
113   /* Encode the payload */
114   status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
115   if (status != SILC_SKE_STATUS_OK)
116     return status;
117
118   /* Take a copy of the payload buffer for future use. It is used to
119      compute the HASH value. */
120   ske->start_payload_copy = silc_buffer_copy(payload_buf);
121
122   /* Send the packet. */
123   if (send_packet)
124     (*send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE, context);
125
126   silc_buffer_free(payload_buf);
127
128   return status;
129 }
130
131 /* Function called after ske_initiator_start fuction. This receives
132    the remote ends Key Exchange Start payload which includes the
133    security properties selected by the responder from our payload
134    sent in the silc_ske_initiator_start function. */
135
136 SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske, 
137                                          SilcBuffer start_payload,
138                                          SilcSKECb callback,
139                                          void *context)
140 {
141   SilcSKEStatus status = SILC_SKE_STATUS_OK;
142   SilcSKEStartPayload *payload;
143   SilcSKESecurityProperties prop;
144   SilcSKEDiffieHellmanGroup group;
145
146   SILC_LOG_DEBUG(("Start"));
147
148   /* Decode the payload */
149   status = silc_ske_payload_start_decode(ske, start_payload, &payload);
150   if (status != SILC_SKE_STATUS_OK) {
151     ske->status = status;
152     return status;
153   }
154
155   /* Take the selected security properties into use while doing
156      the key exchange. This is used only while doing the key 
157      exchange. The same data is returned to upper levels by calling
158      the callback function. */
159   ske->prop = prop = silc_calloc(1, sizeof(*prop));
160   prop->flags = payload->flags;
161   status = silc_ske_get_group_by_name(payload->ke_grp_list, &group);
162   if (status != SILC_SKE_STATUS_OK)
163     goto err;
164
165   prop->group = group;
166
167   if (silc_pkcs_alloc(payload->pkcs_alg_list, &prop->pkcs) == FALSE) {
168     status = SILC_SKE_STATUS_UNKNOWN_PKCS;
169     goto err;
170   }
171
172   if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
173     status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
174     goto err;
175   }
176
177   if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
178     status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
179     goto err;
180   }
181
182   if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
183     status = SILC_SKE_STATUS_UNKNOWN_HMAC;
184     goto err;
185   }
186
187   ske->start_payload = payload;
188
189   /* Return the received payload by calling the callback function. */
190   if (callback)
191     (*callback)(ske, context);
192
193   return status;
194
195  err:
196   if (payload)
197     silc_ske_payload_start_free(payload);
198
199   silc_free(group);
200
201   if (prop->pkcs)
202     silc_pkcs_free(prop->pkcs);
203   if (prop->cipher)
204     silc_cipher_free(prop->cipher);
205   if (prop->hash)
206     silc_hash_free(prop->hash);
207   if (prop->hmac)
208     silc_hmac_free(prop->hmac);
209   silc_free(prop);
210   ske->prop = NULL;
211
212   if (status == SILC_SKE_STATUS_OK)
213     return SILC_SKE_STATUS_ERROR;
214
215   ske->status = status;
216   return status;
217 }
218
219 /* This function creates random number x, such that 1 < x < q and 
220    computes e = g ^ x mod p and sends the result to the remote end in 
221    Key Exchange Payload. */
222
223 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
224                                          SilcPublicKey public_key,
225                                          SilcPrivateKey private_key,
226                                          SilcSKESendPacketCb send_packet,
227                                          void *context)
228 {
229   SilcSKEStatus status = SILC_SKE_STATUS_OK;
230   SilcBuffer payload_buf;
231   SilcMPInt *x, e;
232   SilcSKEKEPayload *payload;
233   uint32 pk_len;
234
235   SILC_LOG_DEBUG(("Start"));
236
237   /* Create the random number x, 1 < x < q. */
238   x = silc_calloc(1, sizeof(*x));
239   silc_mp_init(x);
240   status = 
241     silc_ske_create_rnd(ske, ske->prop->group->group_order,
242                         silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
243                         x);
244   if (status != SILC_SKE_STATUS_OK) {
245     silc_mp_uninit(x);
246     silc_free(x);
247     ske->status = status;
248     return status;
249   }
250
251   SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
252
253   /* Do the Diffie Hellman computation, e = g ^ x mod p */
254   silc_mp_init(&e);
255   silc_mp_pow_mod(&e, &ske->prop->group->generator, x, 
256                   &ske->prop->group->group);
257
258   /* Encode the result to Key Exchange Payload. */
259
260   payload = silc_calloc(1, sizeof(*payload));
261   ske->ke1_payload = payload;
262
263   payload->x = e;
264
265   /* Get public key */
266   if (public_key) {
267     payload->pk_data = silc_pkcs_public_key_encode(public_key, &pk_len);
268     if (!payload->pk_data) {
269       silc_mp_uninit(x);
270       silc_free(x);
271       silc_mp_uninit(&e);
272       silc_free(payload);
273       ske->status = SILC_SKE_STATUS_OK;
274       return ske->status;
275     }
276     payload->pk_len = pk_len;
277   }
278   payload->pk_type = SILC_SKE_PK_TYPE_SILC;
279
280   /* Compute signature data if we are doing mutual authentication */
281   if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
282     unsigned char hash[32], sign[1024];
283     uint32 hash_len, sign_len;
284
285     SILC_LOG_DEBUG(("We are doing mutual authentication"));
286     SILC_LOG_DEBUG(("Computing HASH_i value"));
287
288     /* Compute the hash value */
289     memset(hash, 0, sizeof(hash));
290     silc_ske_make_hash(ske, hash, &hash_len, TRUE);
291
292     SILC_LOG_DEBUG(("Signing HASH_i value"));
293     
294     /* Sign the hash value */
295     silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv, 
296                                    private_key->prv_len);
297     silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
298     payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
299     memcpy(payload->sign_data, sign, sign_len);
300     memset(sign, 0, sizeof(sign));
301     payload->sign_len = sign_len;
302   }
303
304   status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
305   if (status != SILC_SKE_STATUS_OK) {
306     silc_mp_uninit(x);
307     silc_free(x);
308     silc_mp_uninit(&e);
309     silc_free(payload->pk_data);
310     silc_free(payload);
311     ske->status = status;
312     return status;
313   }
314
315   ske->x = x;
316
317   /* Send the packet. */
318   if (send_packet)
319     (*send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE_1, context);
320
321   silc_buffer_free(payload_buf);
322
323   return status;
324 }
325
326 /* An initiator finish final callback that is called to indicate that
327    the SKE protocol may continue. */
328
329 typedef struct {
330   SilcSKECb callback;
331   void *context;
332 } *SKEInitiatorFinish;
333
334 static void silc_ske_initiator_finish_final(SilcSKE ske,
335                                             SilcSKEStatus status,
336                                             void *context)
337 {
338   SKEInitiatorFinish finish = (SKEInitiatorFinish)context;
339   SilcSKEKEPayload *payload = ske->ke2_payload;
340   unsigned char hash[32];
341   uint32 hash_len;
342   SilcPublicKey public_key = NULL;
343
344   /* If the caller returns PENDING status SKE library will assume that
345      the caller will re-call this callback when it is not anymore in
346      PENDING status. */
347   if (status == SILC_SKE_STATUS_PENDING)
348     return;
349
350   /* If the status is an error then the public key that was verified
351      by the caller is not authentic. */
352   if (status != SILC_SKE_STATUS_OK) {
353     ske->status = status;
354     if (finish->callback)
355       finish->callback(ske, finish->context);
356     silc_free(finish);
357     return;
358   }
359
360   if (payload->pk_data) {
361     /* Decode the public key */
362     if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len, 
363                                      &public_key)) {
364       status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
365       if (finish->callback)
366         finish->callback(ske, finish->context);
367       silc_free(finish);
368       return;
369     }
370
371     SILC_LOG_DEBUG(("Public key is authentic"));
372
373     /* Compute the hash value */
374     status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
375     if (status != SILC_SKE_STATUS_OK)
376       goto err;
377
378     ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
379     memcpy(ske->hash, hash, hash_len);
380     ske->hash_len = hash_len;
381
382     SILC_LOG_DEBUG(("Verifying signature (HASH)"));
383
384     /* Verify signature */
385     silc_pkcs_public_key_data_set(ske->prop->pkcs, public_key->pk, 
386                                   public_key->pk_len);
387     if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data, 
388                          payload->sign_len, hash, hash_len) == FALSE) {
389       
390       SILC_LOG_DEBUG(("Signature don't match"));
391       
392       status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
393       goto err;
394     }
395
396     SILC_LOG_DEBUG(("Signature is Ok"));
397     
398     silc_pkcs_public_key_free(public_key);
399     memset(hash, 'F', hash_len);
400   }
401
402   ske->status = SILC_SKE_STATUS_OK;
403
404   /* Call the callback. The caller may now continue the SKE protocol. */
405   if (finish->callback)
406     finish->callback(ske, finish->context);
407
408   silc_free(finish);
409   return;
410
411  err:
412   memset(hash, 'F', sizeof(hash));
413   silc_ske_payload_ke_free(payload);
414   ske->ke2_payload = NULL;
415
416   silc_mp_uninit(ske->KEY);
417   silc_free(ske->KEY);
418   ske->KEY = NULL;
419
420   if (public_key)
421     silc_pkcs_public_key_free(public_key);
422
423   if (ske->hash) {
424     memset(ske->hash, 'F', hash_len);
425     silc_free(ske->hash);
426     ske->hash = NULL;
427   }
428
429   if (status == SILC_SKE_STATUS_OK)
430     ske->status = SILC_SKE_STATUS_ERROR;
431
432   ske->status = status;
433
434   /* Call the callback. */
435   if (finish->callback)
436     finish->callback(ske, finish->context);
437   silc_free(finish);
438 }
439
440 /* Receives Key Exchange Payload from responder consisting responders
441    public key, f, and signature. This function verifies the public key,
442    computes the secret shared key and verifies the signature. 
443
444    The `callback' will be called to indicate that the caller may
445    continue with the SKE protocol.  The caller must not continue
446    before the SKE libary has called that callback.  If this function
447    returns an error the callback will not be called.  It is called
448    if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
449    However, note that when the library calls the callback the ske->status
450    may be error.
451
452    This calls the `verify_key' callback to verify the received public
453    key or certificate. If the `verify_key' is provided then the remote
454    must send public key and it is considered to be an error if remote 
455    does not send its public key. If caller is performing a re-key with
456    SKE then the `verify_key' is usually not provided when it is not also
457    required for the remote to send its public key. */
458
459 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
460                                         SilcBuffer ke_payload,
461                                         SilcSKEVerifyCb verify_key,
462                                         void *verify_context,
463                                         SilcSKECb callback,
464                                         void *context)
465 {
466   SilcSKEStatus status = SILC_SKE_STATUS_OK;
467   SilcSKEKEPayload *payload;
468   SilcMPInt *KEY;
469   SKEInitiatorFinish finish;
470
471   SILC_LOG_DEBUG(("Start"));
472
473   /* Decode the payload */
474   status = silc_ske_payload_ke_decode(ske, ke_payload, &payload);
475   if (status != SILC_SKE_STATUS_OK) {
476     ske->status = status;
477     return status;
478   }
479   ske->ke2_payload = payload;
480
481   if (!payload->pk_data && verify_key) {
482     SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
483                     "even though we require it"));
484     ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
485     goto err;
486   }
487
488   SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
489
490   /* Compute the shared secret key */
491   KEY = silc_calloc(1, sizeof(*KEY));
492   silc_mp_init(KEY);
493   silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
494   ske->KEY = KEY;
495
496   finish = silc_calloc(1, sizeof(*finish));
497   finish->callback = callback;
498   finish->context = context;
499
500   if (payload->pk_data && verify_key) {
501     SILC_LOG_DEBUG(("Verifying public key"));
502     
503     (*verify_key)(ske, payload->pk_data, payload->pk_len,
504                   payload->pk_type, verify_context,
505                   silc_ske_initiator_finish_final, finish);
506     
507     /* We will continue to the final state after the public key has
508        been verified by the caller. */
509     return SILC_SKE_STATUS_PENDING;
510   }
511
512   /* Continue to final state */
513   silc_ske_initiator_finish_final(ske, SILC_SKE_STATUS_OK, finish);
514
515   return SILC_SKE_STATUS_OK;
516
517  err:
518   silc_ske_payload_ke_free(payload);
519   ske->ke2_payload = NULL;
520
521   silc_mp_uninit(ske->KEY);
522   silc_free(ske->KEY);
523   ske->KEY = NULL;
524
525   if (status == SILC_SKE_STATUS_OK)
526     return SILC_SKE_STATUS_ERROR;
527
528   ske->status = status;
529   return status;
530 }
531
532 /* Starts Key Exchange protocol for responder. Responder receives
533    Key Exchange Start Payload from initiator consisting of all the
534    security properties the initiator supports. This function decodes
535    the payload and parses the payload further and selects the right 
536    security properties. */
537
538 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
539                                        SilcSocketConnection sock,
540                                        char *version,
541                                        SilcBuffer start_payload,
542                                        int mutual_auth,
543                                        SilcSKECb callback,
544                                        void *context)
545 {
546   SilcSKEStatus status = SILC_SKE_STATUS_OK;
547   SilcSKEStartPayload *remote_payload = NULL, *payload = NULL;
548
549   SILC_LOG_DEBUG(("Start"));
550
551   ske->sock = sock;
552   ske->rng = rng;
553
554   /* Decode the payload */
555   status = silc_ske_payload_start_decode(ske, start_payload, &remote_payload);
556   if (status != SILC_SKE_STATUS_OK) {
557     ske->status = status;
558     return status;
559   }
560
561   /* Take a copy of the payload buffer for future use. It is used to
562      compute the HASH value. */
563   ske->start_payload_copy = silc_buffer_copy(start_payload);
564
565   /* Force the mutual authentication flag if we want to do it. */
566   if (mutual_auth) {
567     SILC_LOG_DEBUG(("Force mutual authentication"));
568     remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
569   }
570
571   /* Parse and select the security properties from the payload */
572   payload = silc_calloc(1, sizeof(*payload));
573   status = silc_ske_select_security_properties(ske, version,
574                                                payload, remote_payload);
575   if (status != SILC_SKE_STATUS_OK)
576     goto err;
577
578   ske->start_payload = payload;
579
580   /* Call the callback function. */
581   if (callback)
582     (*callback)(ske, context);
583
584   return status;
585
586  err:
587   if (remote_payload)
588     silc_ske_payload_start_free(remote_payload);
589   if (payload)
590     silc_free(payload);
591
592   if (status == SILC_SKE_STATUS_OK)
593     return SILC_SKE_STATUS_ERROR;
594
595   ske->status = status;
596   return status;
597 }
598
599 /* The selected security properties from the initiator payload is now 
600    encoded into Key Exchange Start Payload and sent to the initiator. */
601
602 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske, 
603                                          SilcSKEStartPayload *start_payload,
604                                          SilcSKESendPacketCb send_packet,
605                                          void *context)
606 {
607   SilcSKEStatus status = SILC_SKE_STATUS_OK;
608   SilcBuffer payload_buf;
609   SilcSKESecurityProperties prop;
610   SilcSKEDiffieHellmanGroup group = NULL;
611
612   SILC_LOG_DEBUG(("Start"));
613
614   /* Allocate security properties from the payload. These are allocated
615      only for this negotiation and will be free'd after KE is over. */
616   ske->prop = prop = silc_calloc(1, sizeof(*prop));
617   prop->flags = start_payload->flags;
618   status = silc_ske_get_group_by_name(start_payload->ke_grp_list, &group);
619   if (status != SILC_SKE_STATUS_OK)
620     goto err;
621
622   prop->group = group;
623
624   if (silc_pkcs_alloc(start_payload->pkcs_alg_list, 
625                       &prop->pkcs) == FALSE) {
626     status = SILC_SKE_STATUS_UNKNOWN_PKCS;
627     goto err;
628   }
629
630   if (silc_cipher_alloc(start_payload->enc_alg_list, 
631                         &prop->cipher) == FALSE) {
632     status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
633     goto err;
634   }
635
636   if (silc_hash_alloc(start_payload->hash_alg_list,
637                       &prop->hash) == FALSE) {
638     status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
639     goto err;
640   }
641
642   if (silc_hmac_alloc(start_payload->hmac_alg_list, NULL,
643                       &prop->hmac) == FALSE) {
644     status = SILC_SKE_STATUS_UNKNOWN_HMAC;
645     goto err;
646   }
647
648   /* Encode the payload */
649   status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
650   if (status != SILC_SKE_STATUS_OK)
651     goto err;
652
653   /* Send the packet. */
654   if (send_packet)
655     (*send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE, context);
656
657   silc_buffer_free(payload_buf);
658
659   return status;
660
661  err:
662   if (group)
663     silc_free(group);
664
665   if (prop->pkcs)
666     silc_pkcs_free(prop->pkcs);
667   if (prop->cipher)
668     silc_cipher_free(prop->cipher);
669   if (prop->hash)
670     silc_hash_free(prop->hash);
671   if (prop->hmac)
672     silc_hmac_free(prop->hmac);
673   silc_free(prop);
674   ske->prop = NULL;
675
676   if (status == SILC_SKE_STATUS_OK)
677     return SILC_SKE_STATUS_ERROR;
678
679   ske->status = status;
680   return status;
681 }
682
683 /* An responder phase 2 final callback that is called to indicate that
684    the SKE protocol may continue. */
685
686 typedef struct {
687   SilcSKECb callback;
688   void *context;
689 } *SKEResponderPhaseII;
690
691 static void silc_ske_responder_phase2_final(SilcSKE ske,
692                                             SilcSKEStatus status,
693                                             void *context)
694 {
695   SKEResponderPhaseII finish = (SKEResponderPhaseII)context;
696   SilcSKEKEPayload *recv_payload, *send_payload;
697   SilcMPInt *x, f;
698
699   recv_payload = ske->ke1_payload;
700
701   /* If the caller returns PENDING status SKE library will assume that
702      the caller will re-call this callback when it is not anymore in
703      PENDING status. */
704   if (status == SILC_SKE_STATUS_PENDING)
705     return;
706
707   /* If the status is an error then the public key that was verified
708      by the caller is not authentic. */
709   if (status != SILC_SKE_STATUS_OK) {
710     ske->status = status;
711     if (finish->callback)
712       finish->callback(ske, finish->context);
713     silc_free(finish);
714     return;
715   }
716
717   /* The public key verification was performed only if the Mutual
718      Authentication flag is set. */
719   if (ske->start_payload && 
720       ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
721     SilcPublicKey public_key = NULL;
722     unsigned char hash[32];
723     uint32 hash_len;
724
725     /* Decode the public key */
726     if (!silc_pkcs_public_key_decode(recv_payload->pk_data, 
727                                      recv_payload->pk_len, 
728                                      &public_key)) {
729       ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
730       if (finish->callback)
731         finish->callback(ske, finish->context);
732       silc_free(finish);
733       return;
734     }
735
736     SILC_LOG_DEBUG(("Public key is authentic"));
737
738     /* Compute the hash value */
739     status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
740     if (status != SILC_SKE_STATUS_OK) {
741       ske->status = status;
742       if (finish->callback)
743         finish->callback(ske, finish->context);
744       silc_free(finish);
745       return;
746     }
747
748     SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
749     
750     /* Verify signature */
751     silc_pkcs_public_key_data_set(ske->prop->pkcs, public_key->pk, 
752                                   public_key->pk_len);
753     if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data, 
754                          recv_payload->sign_len, hash, hash_len) == FALSE) {
755       
756       SILC_LOG_DEBUG(("Signature don't match"));
757       
758       ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
759       if (finish->callback)
760         finish->callback(ske, finish->context);
761       silc_free(finish);
762       return;
763     }
764     
765     SILC_LOG_DEBUG(("Signature is Ok"));
766     
767     silc_pkcs_public_key_free(public_key);
768     memset(hash, 'F', hash_len);
769   }
770
771   /* Create the random number x, 1 < x < q. */
772   x = silc_calloc(1, sizeof(*x));
773   silc_mp_init(x);
774   status = 
775     silc_ske_create_rnd(ske, ske->prop->group->group_order,
776                         silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
777                         x);
778   if (status != SILC_SKE_STATUS_OK) {
779     silc_mp_uninit(x);
780     silc_free(x);
781     ske->status = status;
782     if (finish->callback)
783       finish->callback(ske, finish->context);
784     silc_free(finish);
785     return;
786   }
787
788   SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
789
790   /* Do the Diffie Hellman computation, f = g ^ x mod p */
791   silc_mp_init(&f);
792   silc_mp_pow_mod(&f, &ske->prop->group->generator, x, 
793                   &ske->prop->group->group);
794   
795   /* Save the results for later processing */
796   send_payload = silc_calloc(1, sizeof(*send_payload));
797   send_payload->x = f;
798   ske->x = x;
799   ske->ke2_payload = send_payload;
800
801   /* Call the callback. The caller may now continue with the SKE protocol. */
802   ske->status = SILC_SKE_STATUS_OK;
803   if (finish->callback)
804     finish->callback(ske, finish->context);
805   silc_free(finish);
806 }
807
808 /* This function receives the Key Exchange Payload from the initiator.
809    This also performs the mutual authentication if required. Then, this 
810    function first generated a random number x, such that 1 < x < q
811    and computes f = g ^ x mod p. This then puts the result f to a Key
812    Exchange Payload. 
813
814    The `callback' will be called to indicate that the caller may
815    continue with the SKE protocol.  The caller must not continue
816    before the SKE libary has called that callback.  If this function
817    returns an error the callback will not be called.  It is called
818    if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
819    However, note that when the library calls the callback the ske->status
820    may be error.
821
822    This calls the `verify_key' callback to verify the received public
823    key or certificate if the Mutual Authentication flag is set. If the
824    `verify_key' is provided then the remote must send public key and it
825    is considered to be an error if remote does not send its public key. */
826
827 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
828                                          SilcBuffer ke_payload,
829                                          SilcSKEVerifyCb verify_key,
830                                          void *verify_context,
831                                          SilcSKECb callback,
832                                          void *context)
833 {
834   SilcSKEStatus status = SILC_SKE_STATUS_OK;
835   SilcSKEKEPayload *recv_payload;
836   SKEResponderPhaseII finish;
837
838   SILC_LOG_DEBUG(("Start"));
839
840   /* Decode Key Exchange Payload */
841   status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
842   if (status != SILC_SKE_STATUS_OK) {
843     ske->status = status;
844     return status;
845   }
846
847   ske->ke1_payload = recv_payload;
848
849   finish = silc_calloc(1, sizeof(*finish));
850   finish->callback = callback;
851   finish->context = context;
852
853   /* Verify the received public key and verify the signature if we are
854      doing mutual authentication. */
855   if (ske->start_payload && 
856       ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
857
858     SILC_LOG_DEBUG(("We are doing mutual authentication"));
859     
860     if (!recv_payload->pk_data && verify_key) {
861       SILC_LOG_DEBUG(("Remote end did not send its public key (or "
862                       "certificate), even though we require it"));
863       ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
864       return status;
865     }
866
867     if (recv_payload->pk_data && verify_key) {
868       SILC_LOG_DEBUG(("Verifying public key"));
869
870       (*verify_key)(ske, recv_payload->pk_data, recv_payload->pk_len,
871                     recv_payload->pk_type, verify_context,
872                     silc_ske_responder_phase2_final, finish);
873
874       /* We will continue to the final state after the public key has
875          been verified by the caller. */
876       return SILC_SKE_STATUS_PENDING;
877     }
878   }
879
880   /* Continue to final state */
881   silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, finish);
882
883   return SILC_SKE_STATUS_OK;
884 }
885
886 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
887    value to be signed and sent to the other end. This then encodes Key
888    Exchange Payload and sends it to the other end. */
889
890 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
891                                         SilcPublicKey public_key,
892                                         SilcPrivateKey private_key,
893                                         SilcSKEPKType pk_type,
894                                         SilcSKESendPacketCb send_packet,
895                                         void *context)
896 {
897   SilcSKEStatus status = SILC_SKE_STATUS_OK;
898   SilcBuffer payload_buf;
899   SilcMPInt *KEY;
900   unsigned char hash[32], sign[1024], *pk;
901   uint32 hash_len, sign_len, pk_len;
902
903   SILC_LOG_DEBUG(("Start"));
904
905   SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
906
907   /* Compute the shared secret key */
908   KEY = silc_calloc(1, sizeof(*KEY));
909   silc_mp_init(KEY);
910   silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x, 
911                   &ske->prop->group->group);
912   ske->KEY = KEY;
913
914   if (public_key && private_key) {
915     SILC_LOG_DEBUG(("Getting public key"));
916     
917     /* Get the public key */
918     pk = silc_pkcs_public_key_encode(public_key, &pk_len);
919     if (!pk) {
920       status = SILC_SKE_STATUS_ERROR;
921       goto err;
922     }
923     ske->ke2_payload->pk_data = pk;
924     ske->ke2_payload->pk_len = pk_len;
925     
926     SILC_LOG_DEBUG(("Computing HASH value"));
927     
928     /* Compute the hash value */
929     memset(hash, 0, sizeof(hash));
930     status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
931     if (status != SILC_SKE_STATUS_OK)
932       goto err;
933
934     ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
935     memcpy(ske->hash, hash, hash_len);
936     ske->hash_len = hash_len;
937     
938     SILC_LOG_DEBUG(("Signing HASH value"));
939     
940     /* Sign the hash value */
941     silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv, 
942                                    private_key->prv_len);
943     silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
944     ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
945     memcpy(ske->ke2_payload->sign_data, sign, sign_len);
946     memset(sign, 0, sizeof(sign));
947     ske->ke2_payload->sign_len = sign_len;
948   }
949   ske->ke2_payload->pk_type = pk_type;
950
951   /* Encode the Key Exchange Payload */
952   status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
953                                       &payload_buf);
954   if (status != SILC_SKE_STATUS_OK)
955     goto err;
956
957   /* Send the packet. */
958   if (send_packet)
959     (*send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE_2, context);
960
961   silc_buffer_free(payload_buf);
962
963   return status;
964
965  err:
966   silc_mp_uninit(ske->KEY);
967   silc_free(ske->KEY);
968   ske->KEY = NULL;
969   silc_ske_payload_ke_free(ske->ke2_payload);
970
971   if (status == SILC_SKE_STATUS_OK)
972     return SILC_SKE_STATUS_ERROR;
973
974   ske->status = status;
975   return status;
976 }
977
978 /* The Key Exchange protocol is ended by calling this function. This
979    must not be called until the keys are processed like the protocol
980    defines. This function is for both initiator and responder. */
981
982 SilcSKEStatus silc_ske_end(SilcSKE ske,
983                            SilcSKESendPacketCb send_packet,
984                            void *context)
985 {
986   SilcBuffer packet;
987
988   SILC_LOG_DEBUG(("Start"));
989
990   packet = silc_buffer_alloc(4);
991   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
992   silc_buffer_format(packet,
993                      SILC_STR_UI_INT((uint32)SILC_SKE_STATUS_OK),
994                      SILC_STR_END);
995
996   if (send_packet)
997     (*send_packet)(ske, packet, SILC_PACKET_SUCCESS, context);
998
999   silc_buffer_free(packet);
1000
1001   return SILC_SKE_STATUS_OK;
1002 }
1003
1004 /* Aborts the Key Exchange protocol. This is called if error occurs
1005    while performing the protocol. The status argument is the error
1006    status and it is sent to the remote end. */
1007
1008 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status,
1009                              SilcSKESendPacketCb send_packet,
1010                              void *context)
1011 {
1012   SilcBuffer packet;
1013
1014   SILC_LOG_DEBUG(("Start"));
1015
1016   packet = silc_buffer_alloc(4);
1017   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1018   silc_buffer_format(packet,
1019                      SILC_STR_UI_INT((uint32)status),
1020                      SILC_STR_END);
1021
1022   if (send_packet)
1023     (*send_packet)(ske, packet, SILC_PACKET_FAILURE, context);
1024
1025   silc_buffer_free(packet);
1026
1027   return SILC_SKE_STATUS_OK;
1028 }
1029
1030 /* Assembles security properties to Key Exchange Start Payload to be
1031    sent to the remote end. This checks system wide (SILC system, that is)
1032    settings and chooses from those. However, if other properties
1033    should be used this function is easy to replace by another function,
1034    as, this function is called by the caller of the protocol and not
1035    by the protocol itself. */
1036
1037 SilcSKEStatus 
1038 silc_ske_assemble_security_properties(SilcSKE ske,
1039                                       unsigned char flags,
1040                                       char *version,
1041                                       SilcSKEStartPayload **return_payload)
1042 {
1043   SilcSKEStartPayload *rp;
1044   int i;
1045
1046   SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1047
1048   rp = silc_calloc(1, sizeof(*rp));
1049
1050   /* Set flags */
1051   rp->flags = flags;
1052
1053   /* Set random cookie */
1054   rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1055   for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1056     rp->cookie[i] = silc_rng_get_byte(ske->rng);
1057   rp->cookie_len = SILC_SKE_COOKIE_LEN;
1058
1059   /* Put version */
1060   rp->version = strdup(version);
1061   rp->version_len = strlen(version);
1062
1063   /* Get supported Key Exhange groups */
1064   rp->ke_grp_list = silc_ske_get_supported_groups();
1065   rp->ke_grp_len = strlen(rp->ke_grp_list);
1066
1067   /* Get supported PKCS algorithms */
1068   rp->pkcs_alg_list = silc_pkcs_get_supported();
1069   rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1070
1071   /* Get supported encryption algorithms */
1072   rp->enc_alg_list = silc_cipher_get_supported();
1073   rp->enc_alg_len = strlen(rp->enc_alg_list);
1074
1075   /* Get supported hash algorithms */
1076   rp->hash_alg_list = silc_hash_get_supported();
1077   rp->hash_alg_len = strlen(rp->hash_alg_list);
1078
1079   /* Get supported HMACs */
1080   rp->hmac_alg_list = silc_hmac_get_supported();
1081   rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1082
1083   /* XXX */
1084   /* Get supported compression algorithms */
1085   rp->comp_alg_list = "";
1086   rp->comp_alg_len = 0;
1087
1088   rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN + 
1089     2 + rp->version_len +
1090     2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len + 
1091     2 + rp->enc_alg_len + 2 + rp->hash_alg_len + 
1092     2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1093
1094   *return_payload = rp;
1095
1096   return SILC_SKE_STATUS_OK;
1097 }
1098
1099 /* Selects the supported security properties from the remote end's Key 
1100    Exchange Start Payload. */
1101
1102 SilcSKEStatus 
1103 silc_ske_select_security_properties(SilcSKE ske,
1104                                     char *version,
1105                                     SilcSKEStartPayload *payload,
1106                                     SilcSKEStartPayload *remote_payload)
1107 {
1108   SilcSKEStatus status;
1109   SilcSKEStartPayload *rp;
1110   char *cp;
1111   int len;
1112
1113   SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1114
1115   rp = remote_payload;
1116
1117   /* Check version string */
1118   status = silc_ske_check_version(ske, rp->version, rp->version_len);
1119   if (status != SILC_SKE_STATUS_OK) {
1120     ske->status = status;
1121     return status;
1122   }
1123
1124   /* Flags are returned unchanged. */
1125   payload->flags = rp->flags;
1126
1127   /* Take cookie */
1128   payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1129   payload->cookie_len = SILC_SKE_COOKIE_LEN;
1130   memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1131
1132   /* Put our version to our reply */
1133   payload->version = strdup(version);
1134   payload->version_len = strlen(version);
1135
1136   /* Get supported Key Exchange groups */
1137   cp = rp->ke_grp_list;
1138   if (cp && strchr(cp, ',')) {
1139     while(cp) {
1140       char *item;
1141
1142       len = strcspn(cp, ",");
1143       item = silc_calloc(len + 1, sizeof(char));
1144       memcpy(item, cp, len);
1145
1146       SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1147
1148       if (silc_ske_get_group_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1149         SILC_LOG_DEBUG(("Found KE group `%s'", item));
1150
1151         payload->ke_grp_len = len;
1152         payload->ke_grp_list = item;
1153         break;
1154       }
1155
1156       cp += len;
1157       if (strlen(cp) == 0)
1158         cp = NULL;
1159       else
1160         cp++;
1161
1162       if (item)
1163         silc_free(item);
1164     }
1165
1166     if (!payload->ke_grp_len && !payload->ke_grp_list) {
1167       SILC_LOG_DEBUG(("Could not find supported KE group"));
1168       silc_free(payload);
1169       return SILC_SKE_STATUS_UNKNOWN_GROUP;
1170     }
1171   } else {
1172
1173     if (!rp->ke_grp_len) {
1174       SILC_LOG_DEBUG(("KE group not defined in payload"));
1175       silc_free(payload);
1176       return SILC_SKE_STATUS_BAD_PAYLOAD;
1177     }
1178
1179     SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1180     SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1181
1182     payload->ke_grp_len = rp->ke_grp_len;
1183     payload->ke_grp_list = strdup(rp->ke_grp_list);
1184   }
1185
1186   /* Get supported PKCS algorithms */
1187   cp = rp->pkcs_alg_list;
1188   if (cp && strchr(cp, ',')) {
1189     while(cp) {
1190       char *item;
1191
1192       len = strcspn(cp, ",");
1193       item = silc_calloc(len + 1, sizeof(char));
1194       memcpy(item, cp, len);
1195
1196       SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1197
1198       if (silc_pkcs_is_supported(item) == TRUE) {
1199         SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1200
1201         payload->pkcs_alg_len = len;
1202         payload->pkcs_alg_list = item;
1203         break;
1204       }
1205
1206       cp += len;
1207       if (strlen(cp) == 0)
1208         cp = NULL;
1209       else
1210         cp++;
1211
1212       if (item)
1213         silc_free(item);
1214     }
1215
1216     if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1217       SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1218       silc_free(payload->ke_grp_list);
1219       silc_free(payload);
1220       return SILC_SKE_STATUS_UNKNOWN_PKCS;
1221     }
1222   } else {
1223
1224     if (!rp->pkcs_alg_len) {
1225       SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1226       silc_free(payload->ke_grp_list);
1227       silc_free(payload);
1228       return SILC_SKE_STATUS_BAD_PAYLOAD;
1229     }
1230
1231     SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1232     SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1233
1234     payload->pkcs_alg_len = rp->pkcs_alg_len;
1235     payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1236   }
1237
1238   /* Get supported encryption algorithms */
1239   cp = rp->enc_alg_list;
1240   if (cp && strchr(cp, ',')) {
1241     while(cp) {
1242       char *item;
1243
1244       len = strcspn(cp, ",");
1245       item = silc_calloc(len + 1, sizeof(char));
1246       memcpy(item, cp, len);
1247
1248       SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1249
1250       if (silc_cipher_is_supported(item) == TRUE) {
1251         SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1252
1253         payload->enc_alg_len = len;
1254         payload->enc_alg_list = item;
1255         break;
1256       }
1257
1258       cp += len;
1259       if (strlen(cp) == 0)
1260         cp = NULL;
1261       else
1262         cp++;
1263
1264       if (item)
1265         silc_free(item);
1266     }
1267
1268     if (!payload->enc_alg_len && !payload->enc_alg_list) {
1269       SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1270       silc_free(payload->ke_grp_list);
1271       silc_free(payload->pkcs_alg_list);
1272       silc_free(payload);
1273       return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1274     }
1275   } else {
1276
1277     if (!rp->enc_alg_len) {
1278       SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1279       silc_free(payload->ke_grp_list);
1280       silc_free(payload->pkcs_alg_list);
1281       silc_free(payload);
1282       return SILC_SKE_STATUS_BAD_PAYLOAD;
1283     }
1284
1285     SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1286                     rp->enc_alg_list));
1287
1288     payload->enc_alg_len = rp->enc_alg_len;
1289     payload->enc_alg_list = strdup(rp->enc_alg_list);
1290   }
1291
1292   /* Get supported hash algorithms */
1293   cp = rp->hash_alg_list;
1294   if (cp && strchr(cp, ',')) {
1295     while(cp) {
1296       char *item;
1297
1298       len = strcspn(cp, ",");
1299       item = silc_calloc(len + 1, sizeof(char));
1300       memcpy(item, cp, len);
1301
1302       SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1303
1304       if (silc_hash_is_supported(item) == TRUE) {
1305         SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1306
1307         payload->hash_alg_len = len;
1308         payload->hash_alg_list = item;
1309         break;
1310       }
1311
1312       cp += len;
1313       if (strlen(cp) == 0)
1314         cp = NULL;
1315       else
1316         cp++;
1317
1318       if (item)
1319         silc_free(item);
1320     }
1321
1322     if (!payload->hash_alg_len && !payload->hash_alg_list) {
1323       SILC_LOG_DEBUG(("Could not find supported hash alg"));
1324       silc_free(payload->ke_grp_list);
1325       silc_free(payload->pkcs_alg_list);
1326       silc_free(payload->enc_alg_list);
1327       silc_free(payload);
1328       return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1329     }
1330   } else {
1331
1332     if (!rp->hash_alg_len) {
1333       SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1334       silc_free(payload->ke_grp_list);
1335       silc_free(payload->pkcs_alg_list);
1336       silc_free(payload->enc_alg_list);
1337       silc_free(payload);
1338       return SILC_SKE_STATUS_BAD_PAYLOAD;
1339     }
1340
1341     SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1342                     rp->hash_alg_list));
1343
1344     payload->hash_alg_len = rp->hash_alg_len;
1345     payload->hash_alg_list = strdup(rp->hash_alg_list);
1346   }
1347
1348   /* Get supported HMACs */
1349   cp = rp->hmac_alg_list;
1350   if (cp && strchr(cp, ',')) {
1351     while(cp) {
1352       char *item;
1353
1354       len = strcspn(cp, ",");
1355       item = silc_calloc(len + 1, sizeof(char));
1356       memcpy(item, cp, len);
1357
1358       SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1359
1360       if (silc_hmac_is_supported(item) == TRUE) {
1361         SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1362
1363         payload->hmac_alg_len = len;
1364         payload->hmac_alg_list = item;
1365         break;
1366       }
1367
1368       cp += len;
1369       if (strlen(cp) == 0)
1370         cp = NULL;
1371       else
1372         cp++;
1373
1374       if (item)
1375         silc_free(item);
1376     }
1377
1378     if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1379       SILC_LOG_DEBUG(("Could not find supported HMAC"));
1380       silc_free(payload->ke_grp_list);
1381       silc_free(payload->pkcs_alg_list);
1382       silc_free(payload->enc_alg_list);
1383       silc_free(payload->hash_alg_list);
1384       silc_free(payload);
1385       return SILC_SKE_STATUS_UNKNOWN_HMAC;
1386     }
1387   } else {
1388
1389     if (!rp->hmac_alg_len) {
1390       SILC_LOG_DEBUG(("HMAC not defined in payload"));
1391       silc_free(payload->ke_grp_list);
1392       silc_free(payload->pkcs_alg_list);
1393       silc_free(payload->enc_alg_list);
1394       silc_free(payload->hash_alg_list);
1395       silc_free(payload);
1396       return SILC_SKE_STATUS_BAD_PAYLOAD;
1397     }
1398
1399     SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1400                     rp->hmac_alg_list));
1401
1402     payload->hmac_alg_len = rp->hmac_alg_len;
1403     payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1404   }
1405
1406 #if 0
1407   /* Get supported compression algorithms */
1408   cp = rp->hash_alg_list;
1409   if (cp && strchr(cp, ',')) {
1410     while(cp) {
1411       char *item;
1412
1413       len = strcspn(cp, ",");
1414       item = silc_calloc(len + 1, sizeof(char));
1415       memcpy(item, cp, len);
1416
1417       SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1418
1419       if (silc_hash_is_supported(item) == TRUE) {
1420         SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1421
1422         payload->hash_alg_len = len;
1423         payload->hash_alg_list = item;
1424         break;
1425       }
1426
1427       cp += len;
1428       if (strlen(cp) == 0)
1429         cp = NULL;
1430       else
1431         cp++;
1432
1433       if (item)
1434         silc_free(item);
1435     }
1436
1437     if (!payload->hash_alg_len && !payload->hash_alg_list) {
1438       SILC_LOG_DEBUG(("Could not find supported hash alg"));
1439       silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1440       silc_free(payload->ke_grp_list);
1441       silc_free(payload->pkcs_alg_list);
1442       silc_free(payload->enc_alg_list);
1443       silc_free(payload);
1444       return;
1445     }
1446   } else {
1447
1448   }
1449 #endif
1450
1451   payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN + 
1452     2 + payload->version_len + 
1453     2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len + 
1454     2 + payload->enc_alg_len + 2 + payload->hash_alg_len + 
1455     2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1456
1457   return SILC_SKE_STATUS_OK;
1458 }
1459
1460 /* Creates random number such that 1 < rnd < n and at most length
1461    of len bits. The rnd sent as argument must be initialized. */
1462
1463 SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt n, 
1464                                   uint32 len, 
1465                                   SilcMPInt *rnd)
1466 {
1467   SilcSKEStatus status = SILC_SKE_STATUS_OK;
1468   unsigned char *string;
1469
1470   SILC_LOG_DEBUG(("Creating random number"));
1471
1472   /* Get the random number as string */
1473   string = silc_rng_get_rn_data(ske->rng, (len / 8));
1474   if (!string)
1475     return SILC_SKE_STATUS_ERROR;
1476
1477   /* Decode the string into a MP integer */
1478   silc_mp_bin2mp(string, (len / 8), rnd);
1479   silc_mp_mod_2exp(rnd, rnd, len);
1480
1481   /* Checks */
1482   if (silc_mp_cmp_ui(rnd, 1) < 0)
1483     status = SILC_SKE_STATUS_ERROR;
1484
1485   if (silc_mp_cmp(rnd, &n) >= 0)
1486     status = SILC_SKE_STATUS_ERROR;
1487
1488   memset(string, 'F', (len / 8));
1489   silc_free(string);
1490
1491   return status;
1492 }
1493
1494 /* Creates a hash value HASH as defined in the SKE protocol. If the
1495    `initiator' is TRUE then this function is used to create the HASH_i
1496    hash value defined in the protocol. If it is FALSE then this is used
1497    to create the HASH value defined by the protocol. */
1498
1499 SilcSKEStatus silc_ske_make_hash(SilcSKE ske, 
1500                                  unsigned char *return_hash,
1501                                  uint32 *return_hash_len,
1502                                  int initiator)
1503 {
1504   SilcSKEStatus status = SILC_SKE_STATUS_OK;
1505   SilcBuffer buf;
1506   unsigned char *e, *f, *KEY;
1507   uint32 e_len, f_len, KEY_len;
1508   int ret;
1509
1510   SILC_LOG_DEBUG(("Start"));
1511
1512   if (initiator == FALSE) {
1513     e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1514     f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1515     KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1516     
1517     buf = silc_buffer_alloc(ske->start_payload_copy->len + 
1518                             ske->pk_len + e_len + f_len + KEY_len);
1519     silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1520     
1521     /* Format the buffer used to compute the hash value */
1522     ret = 
1523       silc_buffer_format(buf,
1524                          SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1525                                               ske->start_payload_copy->len),
1526                          SILC_STR_UI_XNSTRING(ske->pk, ske->pk_len),
1527                          SILC_STR_UI_XNSTRING(e, e_len),
1528                          SILC_STR_UI_XNSTRING(f, f_len),
1529                          SILC_STR_UI_XNSTRING(KEY, KEY_len),
1530                          SILC_STR_END);
1531     if (ret == -1) {
1532       silc_buffer_free(buf);
1533       memset(e, 0, e_len);
1534       memset(f, 0, f_len);
1535       memset(KEY, 0, KEY_len);
1536       silc_free(e);
1537       silc_free(f);
1538       silc_free(KEY);
1539       return SILC_SKE_STATUS_ERROR;
1540     }
1541
1542     memset(e, 0, e_len);
1543     memset(f, 0, f_len);
1544     memset(KEY, 0, KEY_len);
1545     silc_free(e);
1546     silc_free(f);
1547     silc_free(KEY);
1548   } else {
1549     e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1550
1551     buf = silc_buffer_alloc(ske->start_payload_copy->len + 
1552                             ske->pk_len + e_len);
1553     silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1554     
1555     /* Format the buffer used to compute the hash value */
1556     ret = 
1557       silc_buffer_format(buf,
1558                          SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1559                                               ske->start_payload_copy->len),
1560                          SILC_STR_UI_XNSTRING(ske->pk, ske->pk_len),
1561                          SILC_STR_UI_XNSTRING(e, e_len),
1562                          SILC_STR_END);
1563     if (ret == -1) {
1564       silc_buffer_free(buf);
1565       memset(e, 0, e_len);
1566       silc_free(e);
1567       return SILC_SKE_STATUS_ERROR;
1568     }
1569
1570     memset(e, 0, e_len);
1571     silc_free(e);
1572   }
1573
1574   /* Make the hash */
1575   silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1576   *return_hash_len = ske->prop->hash->hash->hash_len;
1577
1578   if (initiator == FALSE) {
1579     SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1580   } else {
1581     SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1582   }
1583
1584   silc_buffer_free(buf);
1585
1586   return status;
1587 }
1588
1589 /* Processes the provided key material `data' as the SILC protocol 
1590    specification specifies. */
1591
1592 SilcSKEStatus 
1593 silc_ske_process_key_material_data(unsigned char *data,
1594                                    uint32 data_len,
1595                                    uint32 req_iv_len,
1596                                    uint32 req_enc_key_len,
1597                                    uint32 req_hmac_key_len,
1598                                    SilcHash hash,
1599                                    SilcSKEKeyMaterial *key)
1600 {
1601   SilcBuffer buf;
1602   unsigned char hashd[32];
1603   uint32 hash_len = req_hmac_key_len;
1604   uint32 enc_key_len = req_enc_key_len / 8;
1605
1606   SILC_LOG_DEBUG(("Start"));
1607
1608   if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1609     return SILC_SKE_STATUS_ERROR;
1610
1611   buf = silc_buffer_alloc(1 + data_len);
1612   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1613   silc_buffer_format(buf,
1614                      SILC_STR_UI_CHAR(0),
1615                      SILC_STR_UI_XNSTRING(data, data_len),
1616                      SILC_STR_END);
1617
1618   /* Take IVs */
1619   memset(hashd, 0, sizeof(hashd));
1620   buf->data[0] = 0;
1621   silc_hash_make(hash, buf->data, buf->len, hashd);
1622   key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1623   memcpy(key->send_iv, hashd, req_iv_len);
1624   memset(hashd, 0, sizeof(hashd));
1625   buf->data[0] = 1;
1626   silc_hash_make(hash, buf->data, buf->len, hashd);
1627   key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1628   memcpy(key->receive_iv, hashd, req_iv_len);
1629   key->iv_len = req_iv_len;
1630
1631   /* Take the encryption keys. If requested key size is more than
1632      the size of hash length we will distribute more key material
1633      as protocol defines. */
1634   buf->data[0] = 2;
1635   if (enc_key_len > hash_len) {
1636     SilcBuffer dist;
1637     unsigned char k1[32], k2[32], k3[32];
1638     unsigned char *dtmp;
1639     
1640     /* XXX */
1641     if (enc_key_len > (3 * hash_len))
1642       return SILC_SKE_STATUS_ERROR;
1643     
1644     /* Take first round */
1645     memset(k1, 0, sizeof(k1));
1646     silc_hash_make(hash, buf->data, buf->len, k1);
1647     
1648     /* Take second round */
1649     dist = silc_buffer_alloc(data_len + hash_len);
1650     silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1651     silc_buffer_format(dist,
1652                        SILC_STR_UI_XNSTRING(data, data_len),
1653                        SILC_STR_UI_XNSTRING(k1, hash_len),
1654                        SILC_STR_END);
1655     memset(k2, 0, sizeof(k2));
1656     silc_hash_make(hash, dist->data, dist->len, k2);
1657     
1658     /* Take third round */
1659     dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1660     silc_buffer_pull_tail(dist, hash_len);
1661     silc_buffer_pull(dist, data_len + hash_len);
1662     silc_buffer_format(dist,
1663                        SILC_STR_UI_XNSTRING(k2, hash_len),
1664                        SILC_STR_END);
1665     silc_buffer_push(dist, data_len + hash_len);
1666     memset(k3, 0, sizeof(k3));
1667     silc_hash_make(hash, dist->data, dist->len, k3);
1668
1669     /* Then, save the keys */
1670     dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1671     memcpy(dtmp, k1, hash_len);
1672     memcpy(dtmp + hash_len, k2, hash_len);
1673     memcpy(dtmp + hash_len, k3, hash_len);
1674
1675     key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1676     memcpy(key->send_enc_key, dtmp, enc_key_len);
1677     key->enc_key_len = req_enc_key_len;
1678
1679     memset(dtmp, 0, (3 * hash_len));
1680     memset(k1, 0, sizeof(k1));
1681     memset(k2, 0, sizeof(k2));
1682     memset(k3, 0, sizeof(k3));
1683     silc_free(dtmp);
1684     silc_buffer_free(dist);
1685   } else {
1686     /* Take normal hash as key */
1687     memset(hashd, 0, sizeof(hashd));
1688     silc_hash_make(hash, buf->data, buf->len, hashd);
1689     key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1690     memcpy(key->send_enc_key, hashd, enc_key_len);
1691     key->enc_key_len = req_enc_key_len;
1692   }
1693
1694   buf->data[0] = 3;
1695   if (enc_key_len > hash_len) {
1696     SilcBuffer dist;
1697     unsigned char k1[32], k2[32], k3[32];
1698     unsigned char *dtmp;
1699     
1700     /* XXX */
1701     if (enc_key_len > (3 * hash_len))
1702       return SILC_SKE_STATUS_ERROR;
1703     
1704     /* Take first round */
1705     memset(k1, 0, sizeof(k1));
1706     silc_hash_make(hash, buf->data, buf->len, k1);
1707     
1708     /* Take second round */
1709     dist = silc_buffer_alloc(data_len + hash_len);
1710     silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1711     silc_buffer_format(dist,
1712                        SILC_STR_UI_XNSTRING(data, data_len),
1713                        SILC_STR_UI_XNSTRING(k1, hash_len),
1714                        SILC_STR_END);
1715     memset(k2, 0, sizeof(k2));
1716     silc_hash_make(hash, dist->data, dist->len, k2);
1717     
1718     /* Take third round */
1719     dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1720     silc_buffer_pull_tail(dist, hash_len);
1721     silc_buffer_pull(dist, data_len + hash_len);
1722     silc_buffer_format(dist,
1723                        SILC_STR_UI_XNSTRING(k2, hash_len),
1724                        SILC_STR_END);
1725     silc_buffer_push(dist, data_len + hash_len);
1726     memset(k3, 0, sizeof(k3));
1727     silc_hash_make(hash, dist->data, dist->len, k3);
1728
1729     /* Then, save the keys */
1730     dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1731     memcpy(dtmp, k1, hash_len);
1732     memcpy(dtmp + hash_len, k2, hash_len);
1733     memcpy(dtmp + hash_len, k3, hash_len);
1734
1735     key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1736     memcpy(key->receive_enc_key, dtmp, enc_key_len);
1737     key->enc_key_len = req_enc_key_len;
1738
1739     memset(dtmp, 0, (3 * hash_len));
1740     memset(k1, 0, sizeof(k1));
1741     memset(k2, 0, sizeof(k2));
1742     memset(k3, 0, sizeof(k3));
1743     silc_free(dtmp);
1744     silc_buffer_free(dist);
1745   } else {
1746     /* Take normal hash as key */
1747     memset(hashd, 0, sizeof(hashd));
1748     silc_hash_make(hash, buf->data, buf->len, hashd);
1749     key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1750     memcpy(key->receive_enc_key, hashd, enc_key_len);
1751     key->enc_key_len = req_enc_key_len;
1752   }
1753
1754   /* Take HMAC key */
1755   memset(hashd, 0, sizeof(hashd));
1756   buf->data[0] = 4;
1757   silc_hash_make(hash, buf->data, buf->len, hashd);
1758   key->hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1759   memcpy(key->hmac_key, hashd, req_hmac_key_len);
1760   key->hmac_key_len = req_hmac_key_len;
1761
1762   silc_buffer_free(buf);
1763
1764   return SILC_SKE_STATUS_OK;
1765 }
1766
1767 /* Processes negotiated key material as protocol specifies. This returns
1768    the actual keys to be used in the SILC. */
1769
1770 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske, 
1771                                             uint32 req_iv_len,
1772                                             uint32 req_enc_key_len,
1773                                             uint32 req_hmac_key_len,
1774                                             SilcSKEKeyMaterial *key)
1775 {
1776   SilcSKEStatus status;
1777   SilcBuffer buf;
1778   unsigned char *tmpbuf;
1779   uint32 klen;
1780
1781   /* Encode KEY to binary data */
1782   tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1783
1784   buf = silc_buffer_alloc(klen + ske->hash_len);
1785   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1786   silc_buffer_format(buf,
1787                      SILC_STR_UI_XNSTRING(tmpbuf, klen),
1788                      SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1789                      SILC_STR_END);
1790
1791   /* Process the key material */
1792   status = silc_ske_process_key_material_data(buf->data, buf->len,
1793                                               req_iv_len, req_enc_key_len,
1794                                               req_hmac_key_len, 
1795                                               ske->prop->hash, key);
1796
1797   memset(tmpbuf, 0, klen);
1798   silc_free(tmpbuf);
1799   silc_buffer_free(buf);
1800
1801   return status;
1802 }
1803
1804 /* Free key material structure */
1805
1806 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1807 {
1808   if (!key)
1809     return;
1810
1811   if (key->send_iv)
1812     silc_free(key->send_iv);
1813   if (key->receive_iv)
1814     silc_free(key->receive_iv);
1815   if (key->send_enc_key) {
1816     memset(key->send_enc_key, 0, key->enc_key_len / 8);
1817     silc_free(key->send_enc_key);
1818   }
1819   if (key->receive_enc_key) {
1820     memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1821     silc_free(key->receive_enc_key);
1822   }
1823   if (key->hmac_key) {
1824     memset(key->hmac_key, 0, key->hmac_key_len);
1825     silc_free(key->hmac_key);
1826   }
1827   silc_free(key);
1828 }