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