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