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