5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2000 - 2001 Pekka Riikonen
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.
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.
22 #include "silcincludes.h"
24 #include "groups_internal.h"
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;
36 /* Allocates new SKE object. */
38 SilcSKE silc_ske_alloc()
42 SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
44 ske = silc_calloc(1, sizeof(*ske));
45 ske->status = SILC_SKE_STATUS_OK;
51 /* Free's SKE object. */
53 void silc_ske_free(SilcSKE ske)
57 SILC_LOG_DEBUG(("Key Exchange set to FREED status"));
58 ske->status = SILC_SKE_STATUS_FREED;
62 SILC_LOG_DEBUG(("Freeing Key Exchange object"));
65 /* Free start payload */
66 if (ske->start_payload)
67 silc_ske_payload_start_free(ske->start_payload);
71 silc_ske_payload_ke_free(ske->ke1_payload);
76 silc_free(ske->prop->group);
78 silc_pkcs_free(ske->prop->pkcs);
79 if (ske->prop->cipher)
80 silc_cipher_free(ske->prop->cipher);
82 silc_hash_free(ske->prop->hash);
84 silc_hmac_free(ske->prop->hmac);
87 if (ske->start_payload_copy)
88 silc_buffer_free(ske->start_payload_copy);
90 silc_mp_uninit(ske->x);
94 silc_mp_uninit(ske->KEY);
103 /* Sets the callback functions for the SKE session.
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.
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.
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.
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.
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
133 The `context' is passed as argument to all of the above callback
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,
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;
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.
165 The packet sending is done by calling a callback function. Caller
166 must provide a routine to send the packet. */
168 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
169 SilcSocketConnection sock,
170 SilcSKEStartPayload *start_payload)
172 SilcSKEStatus status = SILC_SKE_STATUS_OK;
173 SilcBuffer payload_buf;
175 SILC_LOG_DEBUG(("Start"));
180 /* Encode the payload */
181 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
182 if (status != SILC_SKE_STATUS_OK)
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;
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);
195 silc_buffer_free(payload_buf);
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. */
205 SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
206 SilcBuffer start_payload)
208 SilcSKEStatus status = SILC_SKE_STATUS_OK;
209 SilcSKEStartPayload *payload;
210 SilcSKESecurityProperties prop;
211 SilcSKEDiffieHellmanGroup group;
213 SILC_LOG_DEBUG(("Start"));
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);
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);
232 /* Check version string */
233 if (ske->callbacks->check_version) {
234 status = ske->callbacks->check_version(ske, payload->version,
235 payload->version_len,
236 ske->callbacks->context);
237 if (status != SILC_SKE_STATUS_OK) {
238 ske->status = status;
239 silc_ske_payload_start_free(ske->start_payload);
244 /* Free our KE Start Payload context, we don't need it anymore. */
245 silc_ske_payload_start_free(ske->start_payload);
247 /* Take the selected security properties into use while doing
248 the key exchange. This is used only while doing the key
249 exchange. The same data is returned to upper levels by calling
250 the callback function. */
251 ske->prop = prop = silc_calloc(1, sizeof(*prop));
252 prop->flags = payload->flags;
253 status = silc_ske_get_group_by_name(payload->ke_grp_list, &group);
254 if (status != SILC_SKE_STATUS_OK)
259 if (silc_pkcs_alloc(payload->pkcs_alg_list, &prop->pkcs) == FALSE) {
260 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
264 if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
265 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
269 if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
270 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
274 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
275 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
279 /* Save remote's KE Start Payload */
280 ske->start_payload = payload;
282 /* Return the received payload by calling the callback function. */
283 if (ske->callbacks->payload_receive)
284 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
290 silc_ske_payload_start_free(payload);
295 silc_pkcs_free(prop->pkcs);
297 silc_cipher_free(prop->cipher);
299 silc_hash_free(prop->hash);
301 silc_hmac_free(prop->hmac);
305 if (status == SILC_SKE_STATUS_OK)
306 return SILC_SKE_STATUS_ERROR;
308 ske->status = status;
312 /* This function creates random number x, such that 1 < x < q and
313 computes e = g ^ x mod p and sends the result to the remote end in
314 Key Exchange Payload. */
316 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
317 SilcPublicKey public_key,
318 SilcPrivateKey private_key)
320 SilcSKEStatus status = SILC_SKE_STATUS_OK;
321 SilcBuffer payload_buf;
323 SilcSKEKEPayload *payload;
326 SILC_LOG_DEBUG(("Start"));
328 /* Create the random number x, 1 < x < q. */
329 x = silc_calloc(1, sizeof(*x));
332 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
333 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
335 if (status != SILC_SKE_STATUS_OK) {
338 ske->status = status;
342 /* Encode the result to Key Exchange Payload. */
344 payload = silc_calloc(1, sizeof(*payload));
345 ske->ke1_payload = payload;
347 SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
349 /* Do the Diffie Hellman computation, e = g ^ x mod p */
350 silc_mp_init(&payload->x);
351 silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
352 &ske->prop->group->group);
356 payload->pk_data = silc_pkcs_public_key_encode(public_key, &pk_len);
357 if (!payload->pk_data) {
360 silc_mp_uninit(&payload->x);
362 ske->status = SILC_SKE_STATUS_OK;
365 payload->pk_len = pk_len;
367 payload->pk_type = SILC_SKE_PK_TYPE_SILC;
369 /* Compute signature data if we are doing mutual authentication */
370 if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
371 unsigned char hash[32], sign[1024];
372 uint32 hash_len, sign_len;
374 SILC_LOG_DEBUG(("We are doing mutual authentication"));
375 SILC_LOG_DEBUG(("Computing HASH_i value"));
377 /* Compute the hash value */
378 memset(hash, 0, sizeof(hash));
379 silc_ske_make_hash(ske, hash, &hash_len, TRUE);
381 SILC_LOG_DEBUG(("Signing HASH_i value"));
383 /* Sign the hash value */
384 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
385 private_key->prv_len);
386 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
387 payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
388 memcpy(payload->sign_data, sign, sign_len);
389 memset(sign, 0, sizeof(sign));
390 payload->sign_len = sign_len;
393 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
394 if (status != SILC_SKE_STATUS_OK) {
397 silc_mp_uninit(&payload->x);
398 silc_free(payload->pk_data);
400 ske->status = status;
406 /* Send the packet. */
407 if (ske->callbacks->send_packet)
408 (*ske->callbacks->send_packet)(ske, payload_buf,
409 SILC_PACKET_KEY_EXCHANGE_1,
410 ske->callbacks->context);
412 silc_buffer_free(payload_buf);
417 /* An initiator finish final callback that is called to indicate that
418 the SKE protocol may continue. */
420 static void silc_ske_initiator_finish_final(SilcSKE ske,
421 SilcSKEStatus status,
424 SilcSKEKEPayload *payload;
425 unsigned char hash[32];
427 SilcPublicKey public_key = NULL;
429 /* If the SKE was freed during the async call then free it really now,
430 otherwise just decrement the reference counter. */
431 if (ske->status == SILC_SKE_STATUS_FREED) {
436 /* If the caller returns PENDING status SKE library will assume that
437 the caller will re-call this callback when it is not anymore in
439 if (status == SILC_SKE_STATUS_PENDING)
443 payload = ske->ke2_payload;
445 /* If the status is an error then the public key that was verified
446 by the caller is not authentic. */
447 if (status != SILC_SKE_STATUS_OK) {
448 ske->status = status;
449 if (ske->callbacks->proto_continue)
450 ske->callbacks->proto_continue(ske, ske->callbacks->context);
454 if (payload->pk_data) {
455 /* Decode the public key */
456 if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
458 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
459 if (ske->callbacks->proto_continue)
460 ske->callbacks->proto_continue(ske, ske->callbacks->context);
464 SILC_LOG_DEBUG(("Public key is authentic"));
466 /* Compute the hash value */
467 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
468 if (status != SILC_SKE_STATUS_OK)
471 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
472 memcpy(ske->hash, hash, hash_len);
473 ske->hash_len = hash_len;
475 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
477 /* Verify signature */
478 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
479 if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
480 payload->sign_len, hash, hash_len) == FALSE) {
482 SILC_LOG_DEBUG(("Signature don't match"));
484 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
488 SILC_LOG_DEBUG(("Signature is Ok"));
490 silc_pkcs_public_key_free(public_key);
491 memset(hash, 'F', hash_len);
494 ske->status = SILC_SKE_STATUS_OK;
496 /* Call the callback. The caller may now continue the SKE protocol. */
497 if (ske->callbacks->proto_continue)
498 ske->callbacks->proto_continue(ske, ske->callbacks->context);
503 memset(hash, 'F', sizeof(hash));
504 silc_ske_payload_ke_free(payload);
505 ske->ke2_payload = NULL;
507 silc_mp_uninit(ske->KEY);
512 silc_pkcs_public_key_free(public_key);
515 memset(ske->hash, 'F', hash_len);
516 silc_free(ske->hash);
520 if (status == SILC_SKE_STATUS_OK)
521 ske->status = SILC_SKE_STATUS_ERROR;
523 ske->status = status;
525 /* Call the callback. */
526 if (ske->callbacks->proto_continue)
527 ske->callbacks->proto_continue(ske, ske->callbacks->context);
530 /* Receives Key Exchange Payload from responder consisting responders
531 public key, f, and signature. This function verifies the public key,
532 computes the secret shared key and verifies the signature.
534 The `callback' will be called to indicate that the caller may
535 continue with the SKE protocol. The caller must not continue
536 before the SKE libary has called that callback. If this function
537 returns an error the callback will not be called. It is called
538 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
539 However, note that when the library calls the callback the ske->status
542 This calls the `verify_key' callback to verify the received public
543 key or certificate. If the `verify_key' is provided then the remote
544 must send public key and it is considered to be an error if remote
545 does not send its public key. If caller is performing a re-key with
546 SKE then the `verify_key' is usually not provided when it is not also
547 required for the remote to send its public key. */
549 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
550 SilcBuffer ke_payload)
552 SilcSKEStatus status = SILC_SKE_STATUS_OK;
553 SilcSKEKEPayload *payload;
556 SILC_LOG_DEBUG(("Start"));
558 /* Decode the payload */
559 status = silc_ske_payload_ke_decode(ske, ke_payload, &payload);
560 if (status != SILC_SKE_STATUS_OK) {
561 ske->status = status;
564 ske->ke2_payload = payload;
566 if (!payload->pk_data && ske->callbacks->verify_key) {
567 SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
568 "even though we require it"));
569 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
573 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
575 /* Compute the shared secret key */
576 KEY = silc_calloc(1, sizeof(*KEY));
578 silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
581 if (payload->pk_data && ske->callbacks->verify_key) {
582 SILC_LOG_DEBUG(("Verifying public key"));
585 (*ske->callbacks->verify_key)(ske, payload->pk_data, payload->pk_len,
586 payload->pk_type, ske->callbacks->context,
587 silc_ske_initiator_finish_final, NULL);
589 /* We will continue to the final state after the public key has
590 been verified by the caller. */
591 return SILC_SKE_STATUS_PENDING;
594 /* Continue to final state */
596 silc_ske_initiator_finish_final(ske, SILC_SKE_STATUS_OK, NULL);
598 return SILC_SKE_STATUS_OK;
601 silc_ske_payload_ke_free(payload);
602 ske->ke2_payload = NULL;
604 silc_mp_uninit(ske->KEY);
608 if (status == SILC_SKE_STATUS_OK)
609 return SILC_SKE_STATUS_ERROR;
611 ske->status = status;
615 /* Starts Key Exchange protocol for responder. Responder receives
616 Key Exchange Start Payload from initiator consisting of all the
617 security properties the initiator supports. This function decodes
618 the payload and parses the payload further and selects the right
619 security properties. */
621 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
622 SilcSocketConnection sock,
624 SilcBuffer start_payload,
627 SilcSKEStatus status = SILC_SKE_STATUS_OK;
628 SilcSKEStartPayload *remote_payload = NULL, *payload = NULL;
630 SILC_LOG_DEBUG(("Start"));
635 /* Decode the payload */
636 status = silc_ske_payload_start_decode(ske, start_payload, &remote_payload);
637 if (status != SILC_SKE_STATUS_OK) {
638 ske->status = status;
642 /* Take a copy of the payload buffer for future use. It is used to
643 compute the HASH value. */
644 ske->start_payload_copy = silc_buffer_copy(start_payload);
646 /* Force the mutual authentication flag if we want to do it. */
648 SILC_LOG_DEBUG(("Force mutual authentication"));
649 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
652 /* Parse and select the security properties from the payload */
653 payload = silc_calloc(1, sizeof(*payload));
654 status = silc_ske_select_security_properties(ske, version,
655 payload, remote_payload);
656 if (status != SILC_SKE_STATUS_OK)
659 ske->start_payload = payload;
661 /* Call the callback function. */
662 if (ske->callbacks->payload_receive)
663 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
669 silc_ske_payload_start_free(remote_payload);
673 if (status == SILC_SKE_STATUS_OK)
674 return SILC_SKE_STATUS_ERROR;
676 ske->status = status;
680 /* The selected security properties from the initiator payload is now
681 encoded into Key Exchange Start Payload and sent to the initiator. */
683 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske,
684 SilcSKEStartPayload *start_payload)
686 SilcSKEStatus status = SILC_SKE_STATUS_OK;
687 SilcBuffer payload_buf;
688 SilcSKESecurityProperties prop;
689 SilcSKEDiffieHellmanGroup group = NULL;
691 SILC_LOG_DEBUG(("Start"));
693 /* Allocate security properties from the payload. These are allocated
694 only for this negotiation and will be free'd after KE is over. */
695 ske->prop = prop = silc_calloc(1, sizeof(*prop));
696 prop->flags = start_payload->flags;
697 status = silc_ske_get_group_by_name(start_payload->ke_grp_list, &group);
698 if (status != SILC_SKE_STATUS_OK)
703 if (silc_pkcs_alloc(start_payload->pkcs_alg_list,
704 &prop->pkcs) == FALSE) {
705 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
709 if (silc_cipher_alloc(start_payload->enc_alg_list,
710 &prop->cipher) == FALSE) {
711 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
715 if (silc_hash_alloc(start_payload->hash_alg_list,
716 &prop->hash) == FALSE) {
717 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
721 if (silc_hmac_alloc(start_payload->hmac_alg_list, NULL,
722 &prop->hmac) == FALSE) {
723 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
727 /* Encode the payload */
728 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
729 if (status != SILC_SKE_STATUS_OK)
732 /* Send the packet. */
733 if (ske->callbacks->send_packet)
734 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
735 ske->callbacks->context);
737 silc_buffer_free(payload_buf);
746 silc_pkcs_free(prop->pkcs);
748 silc_cipher_free(prop->cipher);
750 silc_hash_free(prop->hash);
752 silc_hmac_free(prop->hmac);
756 if (status == SILC_SKE_STATUS_OK)
757 return SILC_SKE_STATUS_ERROR;
759 ske->status = status;
763 /* An responder phase 2 final callback that is called to indicate that
764 the SKE protocol may continue. */
766 static void silc_ske_responder_phase2_final(SilcSKE ske,
767 SilcSKEStatus status,
770 SilcSKEKEPayload *recv_payload, *send_payload;
773 /* If the SKE was freed during the async call then free it really now,
774 otherwise just decrement the reference counter. */
775 if (ske->status == SILC_SKE_STATUS_FREED) {
780 /* If the caller returns PENDING status SKE library will assume that
781 the caller will re-call this callback when it is not anymore in
783 if (status == SILC_SKE_STATUS_PENDING)
787 recv_payload = ske->ke1_payload;
789 /* If the status is an error then the public key that was verified
790 by the caller is not authentic. */
791 if (status != SILC_SKE_STATUS_OK) {
792 ske->status = status;
793 if (ske->callbacks->proto_continue)
794 ske->callbacks->proto_continue(ske, ske->callbacks->context);
798 /* The public key verification was performed only if the Mutual
799 Authentication flag is set. */
800 if (ske->start_payload &&
801 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
802 SilcPublicKey public_key = NULL;
803 unsigned char hash[32];
806 /* Decode the public key */
807 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
808 recv_payload->pk_len,
810 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
811 if (ske->callbacks->proto_continue)
812 ske->callbacks->proto_continue(ske, ske->callbacks->context);
816 SILC_LOG_DEBUG(("Public key is authentic"));
818 /* Compute the hash value */
819 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
820 if (status != SILC_SKE_STATUS_OK) {
821 ske->status = status;
822 if (ske->callbacks->proto_continue)
823 ske->callbacks->proto_continue(ske, ske->callbacks->context);
827 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
829 /* Verify signature */
830 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
831 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
832 recv_payload->sign_len, hash, hash_len) == FALSE) {
834 SILC_LOG_DEBUG(("Signature don't match"));
836 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
837 if (ske->callbacks->proto_continue)
838 ske->callbacks->proto_continue(ske, ske->callbacks->context);
842 SILC_LOG_DEBUG(("Signature is Ok"));
844 silc_pkcs_public_key_free(public_key);
845 memset(hash, 'F', hash_len);
848 /* Create the random number x, 1 < x < q. */
849 x = silc_calloc(1, sizeof(*x));
852 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
853 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
855 if (status != SILC_SKE_STATUS_OK) {
858 ske->status = status;
859 if (ske->callbacks->proto_continue)
860 ske->callbacks->proto_continue(ske, ske->callbacks->context);
864 /* Save the results for later processing */
865 send_payload = silc_calloc(1, sizeof(*send_payload));
867 ske->ke2_payload = send_payload;
869 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
871 /* Do the Diffie Hellman computation, f = g ^ x mod p */
872 silc_mp_init(&send_payload->x);
873 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
874 &ske->prop->group->group);
876 /* Call the callback. The caller may now continue with the SKE protocol. */
877 ske->status = SILC_SKE_STATUS_OK;
878 if (ske->callbacks->proto_continue)
879 ske->callbacks->proto_continue(ske, ske->callbacks->context);
882 /* This function receives the Key Exchange Payload from the initiator.
883 This also performs the mutual authentication if required. Then, this
884 function first generated a random number x, such that 1 < x < q
885 and computes f = g ^ x mod p. This then puts the result f to a Key
888 The `callback' will be called to indicate that the caller may
889 continue with the SKE protocol. The caller must not continue
890 before the SKE libary has called that callback. If this function
891 returns an error the callback will not be called. It is called
892 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
893 However, note that when the library calls the callback the ske->status
896 This calls the `verify_key' callback to verify the received public
897 key or certificate if the Mutual Authentication flag is set. If the
898 `verify_key' is provided then the remote must send public key and it
899 is considered to be an error if remote does not send its public key. */
901 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
902 SilcBuffer ke_payload)
904 SilcSKEStatus status = SILC_SKE_STATUS_OK;
905 SilcSKEKEPayload *recv_payload;
907 SILC_LOG_DEBUG(("Start"));
909 /* Decode Key Exchange Payload */
910 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
911 if (status != SILC_SKE_STATUS_OK) {
912 ske->status = status;
916 ske->ke1_payload = recv_payload;
918 /* Verify the received public key and verify the signature if we are
919 doing mutual authentication. */
920 if (ske->start_payload &&
921 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
923 SILC_LOG_DEBUG(("We are doing mutual authentication"));
925 if (!recv_payload->pk_data && ske->callbacks->verify_key) {
926 SILC_LOG_DEBUG(("Remote end did not send its public key (or "
927 "certificate), even though we require it"));
928 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
932 if (recv_payload->pk_data && ske->callbacks->verify_key) {
933 SILC_LOG_DEBUG(("Verifying public key"));
936 (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
937 recv_payload->pk_len,
938 recv_payload->pk_type,
939 ske->callbacks->context,
940 silc_ske_responder_phase2_final, NULL);
942 /* We will continue to the final state after the public key has
943 been verified by the caller. */
944 return SILC_SKE_STATUS_PENDING;
948 /* Continue to final state */
950 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
952 return SILC_SKE_STATUS_OK;
955 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
956 value to be signed and sent to the other end. This then encodes Key
957 Exchange Payload and sends it to the other end. */
959 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
960 SilcPublicKey public_key,
961 SilcPrivateKey private_key,
962 SilcSKEPKType pk_type)
964 SilcSKEStatus status = SILC_SKE_STATUS_OK;
965 SilcBuffer payload_buf;
967 unsigned char hash[32], sign[1024], *pk;
968 uint32 hash_len, sign_len, pk_len;
970 SILC_LOG_DEBUG(("Start"));
972 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
974 /* Compute the shared secret key */
975 KEY = silc_calloc(1, sizeof(*KEY));
977 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
978 &ske->prop->group->group);
981 if (public_key && private_key) {
982 SILC_LOG_DEBUG(("Getting public key"));
984 /* Get the public key */
985 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
987 status = SILC_SKE_STATUS_ERROR;
990 ske->ke2_payload->pk_data = pk;
991 ske->ke2_payload->pk_len = pk_len;
993 SILC_LOG_DEBUG(("Computing HASH value"));
995 /* Compute the hash value */
996 memset(hash, 0, sizeof(hash));
997 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
998 if (status != SILC_SKE_STATUS_OK)
1001 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
1002 memcpy(ske->hash, hash, hash_len);
1003 ske->hash_len = hash_len;
1005 SILC_LOG_DEBUG(("Signing HASH value"));
1007 /* Sign the hash value */
1008 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
1009 private_key->prv_len);
1010 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
1011 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
1012 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
1013 memset(sign, 0, sizeof(sign));
1014 ske->ke2_payload->sign_len = sign_len;
1016 ske->ke2_payload->pk_type = pk_type;
1018 /* Encode the Key Exchange Payload */
1019 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
1021 if (status != SILC_SKE_STATUS_OK)
1024 /* Send the packet. */
1025 if (ske->callbacks->send_packet)
1026 (*ske->callbacks->send_packet)(ske, payload_buf,
1027 SILC_PACKET_KEY_EXCHANGE_2,
1028 ske->callbacks->context);
1030 silc_buffer_free(payload_buf);
1035 silc_mp_uninit(ske->KEY);
1036 silc_free(ske->KEY);
1038 silc_ske_payload_ke_free(ske->ke2_payload);
1040 if (status == SILC_SKE_STATUS_OK)
1041 return SILC_SKE_STATUS_ERROR;
1043 ske->status = status;
1047 /* The Key Exchange protocol is ended by calling this function. This
1048 must not be called until the keys are processed like the protocol
1049 defines. This function is for both initiator and responder. */
1051 SilcSKEStatus silc_ske_end(SilcSKE ske)
1055 SILC_LOG_DEBUG(("Start"));
1057 packet = silc_buffer_alloc(4);
1058 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1059 silc_buffer_format(packet,
1060 SILC_STR_UI_INT((uint32)SILC_SKE_STATUS_OK),
1063 if (ske->callbacks->send_packet)
1064 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS,
1065 ske->callbacks->context);
1067 silc_buffer_free(packet);
1069 return SILC_SKE_STATUS_OK;
1072 /* Aborts the Key Exchange protocol. This is called if error occurs
1073 while performing the protocol. The status argument is the error
1074 status and it is sent to the remote end. */
1076 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
1080 SILC_LOG_DEBUG(("Start"));
1082 packet = silc_buffer_alloc(4);
1083 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1084 silc_buffer_format(packet,
1085 SILC_STR_UI_INT((uint32)status),
1088 if (ske->callbacks->send_packet)
1089 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
1090 ske->callbacks->context);
1092 silc_buffer_free(packet);
1094 return SILC_SKE_STATUS_OK;
1097 /* Assembles security properties to Key Exchange Start Payload to be
1098 sent to the remote end. This checks system wide (SILC system, that is)
1099 settings and chooses from those. However, if other properties
1100 should be used this function is easy to replace by another function,
1101 as, this function is called by the caller of the protocol and not
1102 by the protocol itself. */
1105 silc_ske_assemble_security_properties(SilcSKE ske,
1106 unsigned char flags,
1108 SilcSKEStartPayload **return_payload)
1110 SilcSKEStartPayload *rp;
1113 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1115 rp = silc_calloc(1, sizeof(*rp));
1120 /* Set random cookie */
1121 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1122 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1123 rp->cookie[i] = silc_rng_get_byte(ske->rng);
1124 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1127 rp->version = strdup(version);
1128 rp->version_len = strlen(version);
1130 /* Get supported Key Exhange groups */
1131 rp->ke_grp_list = silc_ske_get_supported_groups();
1132 rp->ke_grp_len = strlen(rp->ke_grp_list);
1134 /* Get supported PKCS algorithms */
1135 rp->pkcs_alg_list = silc_pkcs_get_supported();
1136 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1138 /* Get supported encryption algorithms */
1139 rp->enc_alg_list = silc_cipher_get_supported();
1140 rp->enc_alg_len = strlen(rp->enc_alg_list);
1142 /* Get supported hash algorithms */
1143 rp->hash_alg_list = silc_hash_get_supported();
1144 rp->hash_alg_len = strlen(rp->hash_alg_list);
1146 /* Get supported HMACs */
1147 rp->hmac_alg_list = silc_hmac_get_supported();
1148 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1151 /* Get supported compression algorithms */
1152 rp->comp_alg_list = strdup("");
1153 rp->comp_alg_len = 0;
1155 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1156 2 + rp->version_len +
1157 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1158 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1159 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1161 *return_payload = rp;
1163 return SILC_SKE_STATUS_OK;
1166 /* Selects the supported security properties from the remote end's Key
1167 Exchange Start Payload. */
1170 silc_ske_select_security_properties(SilcSKE ske,
1172 SilcSKEStartPayload *payload,
1173 SilcSKEStartPayload *remote_payload)
1175 SilcSKEStatus status;
1176 SilcSKEStartPayload *rp;
1180 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1182 rp = remote_payload;
1184 /* Check version string */
1185 if (ske->callbacks->check_version) {
1186 status = ske->callbacks->check_version(ske, rp->version,
1188 ske->callbacks->context);
1189 if (status != SILC_SKE_STATUS_OK) {
1190 ske->status = status;
1195 /* Flags are returned unchanged. */
1196 payload->flags = rp->flags;
1198 /* Take cookie, we must return it to sender unmodified. */
1199 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1200 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1201 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1203 /* Put our version to our reply */
1204 payload->version = strdup(version);
1205 payload->version_len = strlen(version);
1207 /* Get supported Key Exchange groups */
1208 cp = rp->ke_grp_list;
1209 if (cp && strchr(cp, ',')) {
1213 len = strcspn(cp, ",");
1214 item = silc_calloc(len + 1, sizeof(char));
1215 memcpy(item, cp, len);
1217 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1219 if (silc_ske_get_group_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1220 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1222 payload->ke_grp_len = len;
1223 payload->ke_grp_list = item;
1228 if (strlen(cp) == 0)
1237 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1238 SILC_LOG_DEBUG(("Could not find supported KE group"));
1240 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1244 if (!rp->ke_grp_len) {
1245 SILC_LOG_DEBUG(("KE group not defined in payload"));
1247 return SILC_SKE_STATUS_BAD_PAYLOAD;
1250 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1251 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1253 payload->ke_grp_len = rp->ke_grp_len;
1254 payload->ke_grp_list = strdup(rp->ke_grp_list);
1257 /* Get supported PKCS algorithms */
1258 cp = rp->pkcs_alg_list;
1259 if (cp && strchr(cp, ',')) {
1263 len = strcspn(cp, ",");
1264 item = silc_calloc(len + 1, sizeof(char));
1265 memcpy(item, cp, len);
1267 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1269 if (silc_pkcs_is_supported(item) == TRUE) {
1270 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1272 payload->pkcs_alg_len = len;
1273 payload->pkcs_alg_list = item;
1278 if (strlen(cp) == 0)
1287 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1288 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1289 silc_free(payload->ke_grp_list);
1291 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1295 if (!rp->pkcs_alg_len) {
1296 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1297 silc_free(payload->ke_grp_list);
1299 return SILC_SKE_STATUS_BAD_PAYLOAD;
1302 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1303 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1305 payload->pkcs_alg_len = rp->pkcs_alg_len;
1306 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1309 /* Get supported encryption algorithms */
1310 cp = rp->enc_alg_list;
1311 if (cp && strchr(cp, ',')) {
1315 len = strcspn(cp, ",");
1316 item = silc_calloc(len + 1, sizeof(char));
1317 memcpy(item, cp, len);
1319 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1321 if (silc_cipher_is_supported(item) == TRUE) {
1322 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1324 payload->enc_alg_len = len;
1325 payload->enc_alg_list = item;
1330 if (strlen(cp) == 0)
1339 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1340 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1341 silc_free(payload->ke_grp_list);
1342 silc_free(payload->pkcs_alg_list);
1344 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1348 if (!rp->enc_alg_len) {
1349 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1350 silc_free(payload->ke_grp_list);
1351 silc_free(payload->pkcs_alg_list);
1353 return SILC_SKE_STATUS_BAD_PAYLOAD;
1356 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1359 payload->enc_alg_len = rp->enc_alg_len;
1360 payload->enc_alg_list = strdup(rp->enc_alg_list);
1363 /* Get supported hash algorithms */
1364 cp = rp->hash_alg_list;
1365 if (cp && strchr(cp, ',')) {
1369 len = strcspn(cp, ",");
1370 item = silc_calloc(len + 1, sizeof(char));
1371 memcpy(item, cp, len);
1373 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1375 if (silc_hash_is_supported(item) == TRUE) {
1376 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1378 payload->hash_alg_len = len;
1379 payload->hash_alg_list = item;
1384 if (strlen(cp) == 0)
1393 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1394 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1395 silc_free(payload->ke_grp_list);
1396 silc_free(payload->pkcs_alg_list);
1397 silc_free(payload->enc_alg_list);
1399 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1403 if (!rp->hash_alg_len) {
1404 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1405 silc_free(payload->ke_grp_list);
1406 silc_free(payload->pkcs_alg_list);
1407 silc_free(payload->enc_alg_list);
1409 return SILC_SKE_STATUS_BAD_PAYLOAD;
1412 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1413 rp->hash_alg_list));
1415 payload->hash_alg_len = rp->hash_alg_len;
1416 payload->hash_alg_list = strdup(rp->hash_alg_list);
1419 /* Get supported HMACs */
1420 cp = rp->hmac_alg_list;
1421 if (cp && strchr(cp, ',')) {
1425 len = strcspn(cp, ",");
1426 item = silc_calloc(len + 1, sizeof(char));
1427 memcpy(item, cp, len);
1429 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1431 if (silc_hmac_is_supported(item) == TRUE) {
1432 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1434 payload->hmac_alg_len = len;
1435 payload->hmac_alg_list = item;
1440 if (strlen(cp) == 0)
1449 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1450 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1451 silc_free(payload->ke_grp_list);
1452 silc_free(payload->pkcs_alg_list);
1453 silc_free(payload->enc_alg_list);
1454 silc_free(payload->hash_alg_list);
1456 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1460 if (!rp->hmac_alg_len) {
1461 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1462 silc_free(payload->ke_grp_list);
1463 silc_free(payload->pkcs_alg_list);
1464 silc_free(payload->enc_alg_list);
1465 silc_free(payload->hash_alg_list);
1467 return SILC_SKE_STATUS_BAD_PAYLOAD;
1470 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1471 rp->hmac_alg_list));
1473 payload->hmac_alg_len = rp->hmac_alg_len;
1474 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1478 /* Get supported compression algorithms */
1479 cp = rp->hash_alg_list;
1480 if (cp && strchr(cp, ',')) {
1484 len = strcspn(cp, ",");
1485 item = silc_calloc(len + 1, sizeof(char));
1486 memcpy(item, cp, len);
1488 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1490 if (silc_hash_is_supported(item) == TRUE) {
1491 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1493 payload->hash_alg_len = len;
1494 payload->hash_alg_list = item;
1499 if (strlen(cp) == 0)
1508 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1509 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1510 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1511 silc_free(payload->ke_grp_list);
1512 silc_free(payload->pkcs_alg_list);
1513 silc_free(payload->enc_alg_list);
1522 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1523 2 + payload->version_len +
1524 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1525 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1526 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1528 return SILC_SKE_STATUS_OK;
1531 /* Creates random number such that 1 < rnd < n and at most length
1532 of len bits. The rnd sent as argument must be initialized. */
1534 SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1538 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1539 unsigned char *string;
1541 SILC_LOG_DEBUG(("Creating random number"));
1543 /* Get the random number as string */
1544 string = silc_rng_get_rn_data(ske->rng, (len / 8));
1546 return SILC_SKE_STATUS_ERROR;
1548 /* Decode the string into a MP integer */
1549 silc_mp_bin2mp(string, (len / 8), rnd);
1550 silc_mp_mod_2exp(rnd, rnd, len);
1553 if (silc_mp_cmp_ui(rnd, 1) < 0)
1554 status = SILC_SKE_STATUS_ERROR;
1556 if (silc_mp_cmp(rnd, n) >= 0)
1557 status = SILC_SKE_STATUS_ERROR;
1559 memset(string, 'F', (len / 8));
1565 /* Creates a hash value HASH as defined in the SKE protocol. If the
1566 `initiator' is TRUE then this function is used to create the HASH_i
1567 hash value defined in the protocol. If it is FALSE then this is used
1568 to create the HASH value defined by the protocol. */
1570 SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1571 unsigned char *return_hash,
1572 uint32 *return_hash_len,
1575 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1577 unsigned char *e, *f, *KEY;
1578 uint32 e_len, f_len, KEY_len;
1581 SILC_LOG_DEBUG(("Start"));
1583 if (initiator == FALSE) {
1584 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1585 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1586 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1588 /* Format the buffer used to compute the hash value */
1589 /* XXX Backward support for 0.6.1 */
1590 if (ske->backward_version == 1) {
1591 SILC_LOG_DEBUG(("*********** Using old KE payload"));
1592 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1593 ske->ke2_payload->pk_len + e_len +
1595 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1598 silc_buffer_format(buf,
1599 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1600 ske->start_payload_copy->len),
1601 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1602 ske->ke2_payload->pk_len),
1603 SILC_STR_UI_XNSTRING(e, e_len),
1604 SILC_STR_UI_XNSTRING(f, f_len),
1605 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1608 /* Initiator is not required to send its public key */
1609 SILC_LOG_DEBUG(("*********** Using new KE payload"));
1610 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1611 ske->ke2_payload->pk_len +
1612 ske->ke1_payload->pk_len +
1613 e_len + f_len + KEY_len);
1614 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1616 if (!ske->ke1_payload->pk_data) {
1618 silc_buffer_format(buf,
1619 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1621 ske->start_payload_copy->
1623 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1624 ske->ke2_payload->pk_len),
1625 SILC_STR_UI_XNSTRING(e, e_len),
1626 SILC_STR_UI_XNSTRING(f, f_len),
1627 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1631 silc_buffer_format(buf,
1632 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1634 ske->start_payload_copy->
1636 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1637 ske->ke2_payload->pk_len),
1638 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1639 ske->ke1_payload->pk_len),
1640 SILC_STR_UI_XNSTRING(e, e_len),
1641 SILC_STR_UI_XNSTRING(f, f_len),
1642 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1647 silc_buffer_free(buf);
1648 memset(e, 0, e_len);
1649 memset(f, 0, f_len);
1650 memset(KEY, 0, KEY_len);
1654 return SILC_SKE_STATUS_ERROR;
1657 memset(e, 0, e_len);
1658 memset(f, 0, f_len);
1659 memset(KEY, 0, KEY_len);
1664 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1666 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1667 ske->ke1_payload->pk_len + e_len);
1668 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1670 /* Format the buffer used to compute the hash value */
1672 silc_buffer_format(buf,
1673 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1674 ske->start_payload_copy->len),
1675 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1676 ske->ke1_payload->pk_len),
1677 SILC_STR_UI_XNSTRING(e, e_len),
1680 silc_buffer_free(buf);
1681 memset(e, 0, e_len);
1683 return SILC_SKE_STATUS_ERROR;
1686 memset(e, 0, e_len);
1691 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1692 *return_hash_len = ske->prop->hash->hash->hash_len;
1694 if (initiator == FALSE) {
1695 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1697 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1700 silc_buffer_free(buf);
1705 /* Processes the provided key material `data' as the SILC protocol
1706 specification defines. */
1709 silc_ske_process_key_material_data(unsigned char *data,
1712 uint32 req_enc_key_len,
1713 uint32 req_hmac_key_len,
1715 SilcSKEKeyMaterial *key)
1718 unsigned char hashd[32];
1719 uint32 hash_len = req_hmac_key_len;
1720 uint32 enc_key_len = req_enc_key_len / 8;
1722 SILC_LOG_DEBUG(("Start"));
1724 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1725 return SILC_SKE_STATUS_ERROR;
1727 buf = silc_buffer_alloc(1 + data_len);
1728 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1729 silc_buffer_format(buf,
1730 SILC_STR_UI_CHAR(0),
1731 SILC_STR_UI_XNSTRING(data, data_len),
1735 memset(hashd, 0, sizeof(hashd));
1737 silc_hash_make(hash, buf->data, buf->len, hashd);
1738 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1739 memcpy(key->send_iv, hashd, req_iv_len);
1740 memset(hashd, 0, sizeof(hashd));
1742 silc_hash_make(hash, buf->data, buf->len, hashd);
1743 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1744 memcpy(key->receive_iv, hashd, req_iv_len);
1745 key->iv_len = req_iv_len;
1747 /* Take the encryption keys. If requested key size is more than
1748 the size of hash length we will distribute more key material
1749 as protocol defines. */
1751 if (enc_key_len > hash_len) {
1753 unsigned char k1[32], k2[32], k3[32];
1754 unsigned char *dtmp;
1757 if (enc_key_len > (3 * hash_len))
1758 return SILC_SKE_STATUS_ERROR;
1760 /* Take first round */
1761 memset(k1, 0, sizeof(k1));
1762 silc_hash_make(hash, buf->data, buf->len, k1);
1764 /* Take second round */
1765 dist = silc_buffer_alloc(data_len + hash_len);
1766 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1767 silc_buffer_format(dist,
1768 SILC_STR_UI_XNSTRING(data, data_len),
1769 SILC_STR_UI_XNSTRING(k1, hash_len),
1771 memset(k2, 0, sizeof(k2));
1772 silc_hash_make(hash, dist->data, dist->len, k2);
1774 /* Take third round */
1775 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1776 silc_buffer_pull_tail(dist, hash_len);
1777 silc_buffer_pull(dist, data_len + hash_len);
1778 silc_buffer_format(dist,
1779 SILC_STR_UI_XNSTRING(k2, hash_len),
1781 silc_buffer_push(dist, data_len + hash_len);
1782 memset(k3, 0, sizeof(k3));
1783 silc_hash_make(hash, dist->data, dist->len, k3);
1785 /* Then, save the keys */
1786 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1787 memcpy(dtmp, k1, hash_len);
1788 memcpy(dtmp + hash_len, k2, hash_len);
1789 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1791 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1792 memcpy(key->send_enc_key, dtmp, enc_key_len);
1793 key->enc_key_len = req_enc_key_len;
1795 memset(dtmp, 0, (3 * hash_len));
1796 memset(k1, 0, sizeof(k1));
1797 memset(k2, 0, sizeof(k2));
1798 memset(k3, 0, sizeof(k3));
1800 silc_buffer_free(dist);
1802 /* Take normal hash as key */
1803 memset(hashd, 0, sizeof(hashd));
1804 silc_hash_make(hash, buf->data, buf->len, hashd);
1805 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1806 memcpy(key->send_enc_key, hashd, enc_key_len);
1807 key->enc_key_len = req_enc_key_len;
1811 if (enc_key_len > hash_len) {
1813 unsigned char k1[32], k2[32], k3[32];
1814 unsigned char *dtmp;
1817 if (enc_key_len > (3 * hash_len))
1818 return SILC_SKE_STATUS_ERROR;
1820 /* Take first round */
1821 memset(k1, 0, sizeof(k1));
1822 silc_hash_make(hash, buf->data, buf->len, k1);
1824 /* Take second round */
1825 dist = silc_buffer_alloc(data_len + hash_len);
1826 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1827 silc_buffer_format(dist,
1828 SILC_STR_UI_XNSTRING(data, data_len),
1829 SILC_STR_UI_XNSTRING(k1, hash_len),
1831 memset(k2, 0, sizeof(k2));
1832 silc_hash_make(hash, dist->data, dist->len, k2);
1834 /* Take third round */
1835 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1836 silc_buffer_pull_tail(dist, hash_len);
1837 silc_buffer_pull(dist, data_len + hash_len);
1838 silc_buffer_format(dist,
1839 SILC_STR_UI_XNSTRING(k2, hash_len),
1841 silc_buffer_push(dist, data_len + hash_len);
1842 memset(k3, 0, sizeof(k3));
1843 silc_hash_make(hash, dist->data, dist->len, k3);
1845 /* Then, save the keys */
1846 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1847 memcpy(dtmp, k1, hash_len);
1848 memcpy(dtmp + hash_len, k2, hash_len);
1849 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1851 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1852 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1853 key->enc_key_len = req_enc_key_len;
1855 memset(dtmp, 0, (3 * hash_len));
1856 memset(k1, 0, sizeof(k1));
1857 memset(k2, 0, sizeof(k2));
1858 memset(k3, 0, sizeof(k3));
1860 silc_buffer_free(dist);
1862 /* Take normal hash as key */
1863 memset(hashd, 0, sizeof(hashd));
1864 silc_hash_make(hash, buf->data, buf->len, hashd);
1865 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1866 memcpy(key->receive_enc_key, hashd, enc_key_len);
1867 key->enc_key_len = req_enc_key_len;
1870 /* Take HMAC keys */
1871 memset(hashd, 0, sizeof(hashd));
1873 silc_hash_make(hash, buf->data, buf->len, hashd);
1874 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1875 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1876 memset(hashd, 0, sizeof(hashd));
1878 silc_hash_make(hash, buf->data, buf->len, hashd);
1879 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1880 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1881 key->hmac_key_len = req_hmac_key_len;
1882 memset(hashd, 0, sizeof(hashd));
1884 silc_buffer_free(buf);
1886 return SILC_SKE_STATUS_OK;
1889 /* Processes negotiated key material as protocol specifies. This returns
1890 the actual keys to be used in the SILC. */
1892 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1894 uint32 req_enc_key_len,
1895 uint32 req_hmac_key_len,
1896 SilcSKEKeyMaterial *key)
1898 SilcSKEStatus status;
1900 unsigned char *tmpbuf;
1903 /* Encode KEY to binary data */
1904 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1906 buf = silc_buffer_alloc(klen + ske->hash_len);
1907 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1908 silc_buffer_format(buf,
1909 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1910 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1913 /* Process the key material */
1914 status = silc_ske_process_key_material_data(buf->data, buf->len,
1915 req_iv_len, req_enc_key_len,
1917 ske->prop->hash, key);
1919 memset(tmpbuf, 0, klen);
1921 silc_buffer_free(buf);
1926 /* Free key material structure */
1928 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1934 silc_free(key->send_iv);
1935 if (key->receive_iv)
1936 silc_free(key->receive_iv);
1937 if (key->send_enc_key) {
1938 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1939 silc_free(key->send_enc_key);
1941 if (key->receive_enc_key) {
1942 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1943 silc_free(key->receive_enc_key);
1945 if (key->send_hmac_key) {
1946 memset(key->send_hmac_key, 0, key->hmac_key_len);
1947 silc_free(key->send_hmac_key);
1949 if (key->receive_hmac_key) {
1950 memset(key->receive_hmac_key, 0, key->hmac_key_len);
1951 silc_free(key->receive_hmac_key);
1956 const char *silc_ske_status_string[] =
1960 "Unkown error occurred",
1961 "Bad payload in packet",
1962 "Unsupported group",
1963 "Unsupported cipher",
1965 "Unsupported hash function",
1967 "Unsupported public key (or certificate)",
1968 "Incorrect signature",
1969 "Bad or unsupported version",
1974 "Remote did not provide public key",
1975 "Key exchange protocol is not active",
1976 "Bad reserved field in packet",
1977 "Bad payload length in packet",
1983 /* Maps status to readable string and returns the string. If string is not
1984 found and empty character string ("") is returned. */
1986 const char *silc_ske_map_status(SilcSKEStatus status)
1990 for (i = 0; silc_ske_status_string[i]; i++)
1992 return silc_ske_status_string[i];