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_ske_group_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);
98 silc_free(ske->callbacks);
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_group_get_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);
292 silc_ske_group_free(group);
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);
665 silc_ske_payload_start_free(remote_payload);
671 silc_ske_payload_start_free(remote_payload);
675 if (status == SILC_SKE_STATUS_OK)
676 return SILC_SKE_STATUS_ERROR;
678 ske->status = status;
682 /* The selected security properties from the initiator payload is now
683 encoded into Key Exchange Start Payload and sent to the initiator. */
685 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske,
686 SilcSKEStartPayload *start_payload)
688 SilcSKEStatus status = SILC_SKE_STATUS_OK;
689 SilcBuffer payload_buf;
690 SilcSKESecurityProperties prop;
691 SilcSKEDiffieHellmanGroup group = NULL;
693 SILC_LOG_DEBUG(("Start"));
695 /* Allocate security properties from the payload. These are allocated
696 only for this negotiation and will be free'd after KE is over. */
697 ske->prop = prop = silc_calloc(1, sizeof(*prop));
698 prop->flags = start_payload->flags;
699 status = silc_ske_group_get_by_name(start_payload->ke_grp_list, &group);
700 if (status != SILC_SKE_STATUS_OK)
705 if (silc_pkcs_alloc(start_payload->pkcs_alg_list,
706 &prop->pkcs) == FALSE) {
707 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
711 if (silc_cipher_alloc(start_payload->enc_alg_list,
712 &prop->cipher) == FALSE) {
713 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
717 if (silc_hash_alloc(start_payload->hash_alg_list,
718 &prop->hash) == FALSE) {
719 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
723 if (silc_hmac_alloc(start_payload->hmac_alg_list, NULL,
724 &prop->hmac) == FALSE) {
725 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
729 /* Encode the payload */
730 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
731 if (status != SILC_SKE_STATUS_OK)
734 /* Send the packet. */
735 if (ske->callbacks->send_packet)
736 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
737 ske->callbacks->context);
739 silc_buffer_free(payload_buf);
745 silc_ske_group_free(group);
748 silc_pkcs_free(prop->pkcs);
750 silc_cipher_free(prop->cipher);
752 silc_hash_free(prop->hash);
754 silc_hmac_free(prop->hmac);
758 if (status == SILC_SKE_STATUS_OK)
759 return SILC_SKE_STATUS_ERROR;
761 ske->status = status;
765 /* An responder phase 2 final callback that is called to indicate that
766 the SKE protocol may continue. */
768 static void silc_ske_responder_phase2_final(SilcSKE ske,
769 SilcSKEStatus status,
772 SilcSKEKEPayload *recv_payload, *send_payload;
775 /* If the SKE was freed during the async call then free it really now,
776 otherwise just decrement the reference counter. */
777 if (ske->status == SILC_SKE_STATUS_FREED) {
782 /* If the caller returns PENDING status SKE library will assume that
783 the caller will re-call this callback when it is not anymore in
785 if (status == SILC_SKE_STATUS_PENDING)
789 recv_payload = ske->ke1_payload;
791 /* If the status is an error then the public key that was verified
792 by the caller is not authentic. */
793 if (status != SILC_SKE_STATUS_OK) {
794 ske->status = status;
795 if (ske->callbacks->proto_continue)
796 ske->callbacks->proto_continue(ske, ske->callbacks->context);
800 /* The public key verification was performed only if the Mutual
801 Authentication flag is set. */
802 if (ske->start_payload &&
803 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
804 SilcPublicKey public_key = NULL;
805 unsigned char hash[32];
808 /* Decode the public key */
809 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
810 recv_payload->pk_len,
812 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
813 if (ske->callbacks->proto_continue)
814 ske->callbacks->proto_continue(ske, ske->callbacks->context);
818 SILC_LOG_DEBUG(("Public key is authentic"));
820 /* Compute the hash value */
821 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
822 if (status != SILC_SKE_STATUS_OK) {
823 ske->status = status;
824 if (ske->callbacks->proto_continue)
825 ske->callbacks->proto_continue(ske, ske->callbacks->context);
829 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
831 /* Verify signature */
832 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
833 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
834 recv_payload->sign_len, hash, hash_len) == FALSE) {
836 SILC_LOG_DEBUG(("Signature don't match"));
838 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
839 if (ske->callbacks->proto_continue)
840 ske->callbacks->proto_continue(ske, ske->callbacks->context);
844 SILC_LOG_DEBUG(("Signature is Ok"));
846 silc_pkcs_public_key_free(public_key);
847 memset(hash, 'F', hash_len);
850 /* Create the random number x, 1 < x < q. */
851 x = silc_calloc(1, sizeof(*x));
854 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
855 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
857 if (status != SILC_SKE_STATUS_OK) {
860 ske->status = status;
861 if (ske->callbacks->proto_continue)
862 ske->callbacks->proto_continue(ske, ske->callbacks->context);
866 /* Save the results for later processing */
867 send_payload = silc_calloc(1, sizeof(*send_payload));
869 ske->ke2_payload = send_payload;
871 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
873 /* Do the Diffie Hellman computation, f = g ^ x mod p */
874 silc_mp_init(&send_payload->x);
875 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
876 &ske->prop->group->group);
878 /* Call the callback. The caller may now continue with the SKE protocol. */
879 ske->status = SILC_SKE_STATUS_OK;
880 if (ske->callbacks->proto_continue)
881 ske->callbacks->proto_continue(ske, ske->callbacks->context);
884 /* This function receives the Key Exchange Payload from the initiator.
885 This also performs the mutual authentication if required. Then, this
886 function first generated a random number x, such that 1 < x < q
887 and computes f = g ^ x mod p. This then puts the result f to a Key
890 The `callback' will be called to indicate that the caller may
891 continue with the SKE protocol. The caller must not continue
892 before the SKE libary has called that callback. If this function
893 returns an error the callback will not be called. It is called
894 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
895 However, note that when the library calls the callback the ske->status
898 This calls the `verify_key' callback to verify the received public
899 key or certificate if the Mutual Authentication flag is set. If the
900 `verify_key' is provided then the remote must send public key and it
901 is considered to be an error if remote does not send its public key. */
903 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
904 SilcBuffer ke_payload)
906 SilcSKEStatus status = SILC_SKE_STATUS_OK;
907 SilcSKEKEPayload *recv_payload;
909 SILC_LOG_DEBUG(("Start"));
911 /* Decode Key Exchange Payload */
912 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
913 if (status != SILC_SKE_STATUS_OK) {
914 ske->status = status;
918 ske->ke1_payload = recv_payload;
920 /* Verify the received public key and verify the signature if we are
921 doing mutual authentication. */
922 if (ske->start_payload &&
923 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
925 SILC_LOG_DEBUG(("We are doing mutual authentication"));
927 if (!recv_payload->pk_data && ske->callbacks->verify_key) {
928 SILC_LOG_DEBUG(("Remote end did not send its public key (or "
929 "certificate), even though we require it"));
930 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
934 if (recv_payload->pk_data && ske->callbacks->verify_key) {
935 SILC_LOG_DEBUG(("Verifying public key"));
938 (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
939 recv_payload->pk_len,
940 recv_payload->pk_type,
941 ske->callbacks->context,
942 silc_ske_responder_phase2_final, NULL);
944 /* We will continue to the final state after the public key has
945 been verified by the caller. */
946 return SILC_SKE_STATUS_PENDING;
950 /* Continue to final state */
952 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
954 return SILC_SKE_STATUS_OK;
957 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
958 value to be signed and sent to the other end. This then encodes Key
959 Exchange Payload and sends it to the other end. */
961 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
962 SilcPublicKey public_key,
963 SilcPrivateKey private_key,
964 SilcSKEPKType pk_type)
966 SilcSKEStatus status = SILC_SKE_STATUS_OK;
967 SilcBuffer payload_buf;
969 unsigned char hash[32], sign[1024], *pk;
970 uint32 hash_len, sign_len, pk_len;
972 SILC_LOG_DEBUG(("Start"));
974 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
976 /* Compute the shared secret key */
977 KEY = silc_calloc(1, sizeof(*KEY));
979 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
980 &ske->prop->group->group);
983 if (public_key && private_key) {
984 SILC_LOG_DEBUG(("Getting public key"));
986 /* Get the public key */
987 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
989 status = SILC_SKE_STATUS_ERROR;
992 ske->ke2_payload->pk_data = pk;
993 ske->ke2_payload->pk_len = pk_len;
995 SILC_LOG_DEBUG(("Computing HASH value"));
997 /* Compute the hash value */
998 memset(hash, 0, sizeof(hash));
999 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1000 if (status != SILC_SKE_STATUS_OK)
1003 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
1004 memcpy(ske->hash, hash, hash_len);
1005 ske->hash_len = hash_len;
1007 SILC_LOG_DEBUG(("Signing HASH value"));
1009 /* Sign the hash value */
1010 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
1011 private_key->prv_len);
1012 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
1013 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
1014 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
1015 memset(sign, 0, sizeof(sign));
1016 ske->ke2_payload->sign_len = sign_len;
1018 ske->ke2_payload->pk_type = pk_type;
1020 /* Encode the Key Exchange Payload */
1021 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
1023 if (status != SILC_SKE_STATUS_OK)
1026 /* Send the packet. */
1027 if (ske->callbacks->send_packet)
1028 (*ske->callbacks->send_packet)(ske, payload_buf,
1029 SILC_PACKET_KEY_EXCHANGE_2,
1030 ske->callbacks->context);
1032 silc_buffer_free(payload_buf);
1037 silc_mp_uninit(ske->KEY);
1038 silc_free(ske->KEY);
1040 silc_ske_payload_ke_free(ske->ke2_payload);
1042 if (status == SILC_SKE_STATUS_OK)
1043 return SILC_SKE_STATUS_ERROR;
1045 ske->status = status;
1049 /* The Key Exchange protocol is ended by calling this function. This
1050 must not be called until the keys are processed like the protocol
1051 defines. This function is for both initiator and responder. */
1053 SilcSKEStatus silc_ske_end(SilcSKE ske)
1057 SILC_LOG_DEBUG(("Start"));
1059 packet = silc_buffer_alloc(4);
1060 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1061 silc_buffer_format(packet,
1062 SILC_STR_UI_INT((uint32)SILC_SKE_STATUS_OK),
1065 if (ske->callbacks->send_packet)
1066 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS,
1067 ske->callbacks->context);
1069 silc_buffer_free(packet);
1071 return SILC_SKE_STATUS_OK;
1074 /* Aborts the Key Exchange protocol. This is called if error occurs
1075 while performing the protocol. The status argument is the error
1076 status and it is sent to the remote end. */
1078 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
1082 SILC_LOG_DEBUG(("Start"));
1084 packet = silc_buffer_alloc(4);
1085 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1086 silc_buffer_format(packet,
1087 SILC_STR_UI_INT((uint32)status),
1090 if (ske->callbacks->send_packet)
1091 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
1092 ske->callbacks->context);
1094 silc_buffer_free(packet);
1096 return SILC_SKE_STATUS_OK;
1099 /* Assembles security properties to Key Exchange Start Payload to be
1100 sent to the remote end. This checks system wide (SILC system, that is)
1101 settings and chooses from those. However, if other properties
1102 should be used this function is easy to replace by another function,
1103 as, this function is called by the caller of the protocol and not
1104 by the protocol itself. */
1107 silc_ske_assemble_security_properties(SilcSKE ske,
1108 unsigned char flags,
1110 SilcSKEStartPayload **return_payload)
1112 SilcSKEStartPayload *rp;
1115 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1117 rp = silc_calloc(1, sizeof(*rp));
1122 /* Set random cookie */
1123 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1124 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1125 rp->cookie[i] = silc_rng_get_byte(ske->rng);
1126 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1129 rp->version = strdup(version);
1130 rp->version_len = strlen(version);
1132 /* Get supported Key Exhange groups */
1133 rp->ke_grp_list = silc_ske_get_supported_groups();
1134 rp->ke_grp_len = strlen(rp->ke_grp_list);
1136 /* Get supported PKCS algorithms */
1137 rp->pkcs_alg_list = silc_pkcs_get_supported();
1138 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1140 /* Get supported encryption algorithms */
1141 rp->enc_alg_list = silc_cipher_get_supported();
1142 rp->enc_alg_len = strlen(rp->enc_alg_list);
1144 /* Get supported hash algorithms */
1145 rp->hash_alg_list = silc_hash_get_supported();
1146 rp->hash_alg_len = strlen(rp->hash_alg_list);
1148 /* Get supported HMACs */
1149 rp->hmac_alg_list = silc_hmac_get_supported();
1150 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1153 /* Get supported compression algorithms */
1154 rp->comp_alg_list = strdup("");
1155 rp->comp_alg_len = 0;
1157 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1158 2 + rp->version_len +
1159 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1160 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1161 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1163 *return_payload = rp;
1165 return SILC_SKE_STATUS_OK;
1168 /* Selects the supported security properties from the remote end's Key
1169 Exchange Start Payload. */
1172 silc_ske_select_security_properties(SilcSKE ske,
1174 SilcSKEStartPayload *payload,
1175 SilcSKEStartPayload *remote_payload)
1177 SilcSKEStatus status;
1178 SilcSKEStartPayload *rp;
1182 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1184 rp = remote_payload;
1186 /* Check version string */
1187 if (ske->callbacks->check_version) {
1188 status = ske->callbacks->check_version(ske, rp->version,
1190 ske->callbacks->context);
1191 if (status != SILC_SKE_STATUS_OK) {
1192 ske->status = status;
1197 /* Flags are returned unchanged. */
1198 payload->flags = rp->flags;
1200 /* Take cookie, we must return it to sender unmodified. */
1201 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1202 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1203 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1205 /* Put our version to our reply */
1206 payload->version = strdup(version);
1207 payload->version_len = strlen(version);
1209 /* Get supported Key Exchange groups */
1210 cp = rp->ke_grp_list;
1211 if (cp && strchr(cp, ',')) {
1215 len = strcspn(cp, ",");
1216 item = silc_calloc(len + 1, sizeof(char));
1217 memcpy(item, cp, len);
1219 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1221 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1222 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1224 payload->ke_grp_len = len;
1225 payload->ke_grp_list = item;
1230 if (strlen(cp) == 0)
1239 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1240 SILC_LOG_DEBUG(("Could not find supported KE group"));
1242 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1246 if (!rp->ke_grp_len) {
1247 SILC_LOG_DEBUG(("KE group not defined in payload"));
1249 return SILC_SKE_STATUS_BAD_PAYLOAD;
1252 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1253 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1255 payload->ke_grp_len = rp->ke_grp_len;
1256 payload->ke_grp_list = strdup(rp->ke_grp_list);
1259 /* Get supported PKCS algorithms */
1260 cp = rp->pkcs_alg_list;
1261 if (cp && strchr(cp, ',')) {
1265 len = strcspn(cp, ",");
1266 item = silc_calloc(len + 1, sizeof(char));
1267 memcpy(item, cp, len);
1269 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1271 if (silc_pkcs_is_supported(item) == TRUE) {
1272 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1274 payload->pkcs_alg_len = len;
1275 payload->pkcs_alg_list = item;
1280 if (strlen(cp) == 0)
1289 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1290 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1291 silc_free(payload->ke_grp_list);
1293 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1297 if (!rp->pkcs_alg_len) {
1298 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1299 silc_free(payload->ke_grp_list);
1301 return SILC_SKE_STATUS_BAD_PAYLOAD;
1304 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1305 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1307 payload->pkcs_alg_len = rp->pkcs_alg_len;
1308 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1311 /* Get supported encryption algorithms */
1312 cp = rp->enc_alg_list;
1313 if (cp && strchr(cp, ',')) {
1317 len = strcspn(cp, ",");
1318 item = silc_calloc(len + 1, sizeof(char));
1319 memcpy(item, cp, len);
1321 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1323 if (silc_cipher_is_supported(item) == TRUE) {
1324 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1326 payload->enc_alg_len = len;
1327 payload->enc_alg_list = item;
1332 if (strlen(cp) == 0)
1341 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1342 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1343 silc_free(payload->ke_grp_list);
1344 silc_free(payload->pkcs_alg_list);
1346 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1350 if (!rp->enc_alg_len) {
1351 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1352 silc_free(payload->ke_grp_list);
1353 silc_free(payload->pkcs_alg_list);
1355 return SILC_SKE_STATUS_BAD_PAYLOAD;
1358 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1361 payload->enc_alg_len = rp->enc_alg_len;
1362 payload->enc_alg_list = strdup(rp->enc_alg_list);
1365 /* Get supported hash algorithms */
1366 cp = rp->hash_alg_list;
1367 if (cp && strchr(cp, ',')) {
1371 len = strcspn(cp, ",");
1372 item = silc_calloc(len + 1, sizeof(char));
1373 memcpy(item, cp, len);
1375 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1377 if (silc_hash_is_supported(item) == TRUE) {
1378 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1380 payload->hash_alg_len = len;
1381 payload->hash_alg_list = item;
1386 if (strlen(cp) == 0)
1395 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1396 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1397 silc_free(payload->ke_grp_list);
1398 silc_free(payload->pkcs_alg_list);
1399 silc_free(payload->enc_alg_list);
1401 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1405 if (!rp->hash_alg_len) {
1406 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1407 silc_free(payload->ke_grp_list);
1408 silc_free(payload->pkcs_alg_list);
1409 silc_free(payload->enc_alg_list);
1411 return SILC_SKE_STATUS_BAD_PAYLOAD;
1414 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1415 rp->hash_alg_list));
1417 payload->hash_alg_len = rp->hash_alg_len;
1418 payload->hash_alg_list = strdup(rp->hash_alg_list);
1421 /* Get supported HMACs */
1422 cp = rp->hmac_alg_list;
1423 if (cp && strchr(cp, ',')) {
1427 len = strcspn(cp, ",");
1428 item = silc_calloc(len + 1, sizeof(char));
1429 memcpy(item, cp, len);
1431 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1433 if (silc_hmac_is_supported(item) == TRUE) {
1434 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1436 payload->hmac_alg_len = len;
1437 payload->hmac_alg_list = item;
1442 if (strlen(cp) == 0)
1451 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1452 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1453 silc_free(payload->ke_grp_list);
1454 silc_free(payload->pkcs_alg_list);
1455 silc_free(payload->enc_alg_list);
1456 silc_free(payload->hash_alg_list);
1458 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1462 if (!rp->hmac_alg_len) {
1463 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1464 silc_free(payload->ke_grp_list);
1465 silc_free(payload->pkcs_alg_list);
1466 silc_free(payload->enc_alg_list);
1467 silc_free(payload->hash_alg_list);
1469 return SILC_SKE_STATUS_BAD_PAYLOAD;
1472 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1473 rp->hmac_alg_list));
1475 payload->hmac_alg_len = rp->hmac_alg_len;
1476 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1480 /* Get supported compression algorithms */
1481 cp = rp->hash_alg_list;
1482 if (cp && strchr(cp, ',')) {
1486 len = strcspn(cp, ",");
1487 item = silc_calloc(len + 1, sizeof(char));
1488 memcpy(item, cp, len);
1490 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1492 if (silc_hash_is_supported(item) == TRUE) {
1493 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1495 payload->hash_alg_len = len;
1496 payload->hash_alg_list = item;
1501 if (strlen(cp) == 0)
1510 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1511 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1512 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1513 silc_free(payload->ke_grp_list);
1514 silc_free(payload->pkcs_alg_list);
1515 silc_free(payload->enc_alg_list);
1524 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1525 2 + payload->version_len +
1526 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1527 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1528 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1530 return SILC_SKE_STATUS_OK;
1533 /* Creates random number such that 1 < rnd < n and at most length
1534 of len bits. The rnd sent as argument must be initialized. */
1536 SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1540 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1541 unsigned char *string;
1543 SILC_LOG_DEBUG(("Creating random number"));
1545 /* Get the random number as string */
1546 string = silc_rng_get_rn_data(ske->rng, (len / 8));
1548 return SILC_SKE_STATUS_ERROR;
1550 /* Decode the string into a MP integer */
1551 silc_mp_bin2mp(string, (len / 8), rnd);
1552 silc_mp_mod_2exp(rnd, rnd, len);
1555 if (silc_mp_cmp_ui(rnd, 1) < 0)
1556 status = SILC_SKE_STATUS_ERROR;
1558 if (silc_mp_cmp(rnd, n) >= 0)
1559 status = SILC_SKE_STATUS_ERROR;
1561 memset(string, 'F', (len / 8));
1567 /* Creates a hash value HASH as defined in the SKE protocol. If the
1568 `initiator' is TRUE then this function is used to create the HASH_i
1569 hash value defined in the protocol. If it is FALSE then this is used
1570 to create the HASH value defined by the protocol. */
1572 SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1573 unsigned char *return_hash,
1574 uint32 *return_hash_len,
1577 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1579 unsigned char *e, *f, *KEY;
1580 uint32 e_len, f_len, KEY_len;
1583 SILC_LOG_DEBUG(("Start"));
1585 if (initiator == FALSE) {
1586 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1587 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1588 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1590 /* Format the buffer used to compute the hash value */
1591 /* XXX Backward support for 0.6.1 */
1592 if (ske->backward_version == 1) {
1593 SILC_LOG_DEBUG(("*********** Using old KE payload"));
1594 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1595 ske->ke2_payload->pk_len + e_len +
1597 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1600 silc_buffer_format(buf,
1601 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1602 ske->start_payload_copy->len),
1603 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1604 ske->ke2_payload->pk_len),
1605 SILC_STR_UI_XNSTRING(e, e_len),
1606 SILC_STR_UI_XNSTRING(f, f_len),
1607 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1610 /* Initiator is not required to send its public key */
1611 SILC_LOG_DEBUG(("*********** Using new KE payload"));
1612 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1613 ske->ke2_payload->pk_len +
1614 ske->ke1_payload->pk_len +
1615 e_len + f_len + KEY_len);
1616 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1618 if (!ske->ke1_payload->pk_data) {
1620 silc_buffer_format(buf,
1621 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1623 ske->start_payload_copy->
1625 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1626 ske->ke2_payload->pk_len),
1627 SILC_STR_UI_XNSTRING(e, e_len),
1628 SILC_STR_UI_XNSTRING(f, f_len),
1629 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1633 silc_buffer_format(buf,
1634 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1636 ske->start_payload_copy->
1638 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1639 ske->ke2_payload->pk_len),
1640 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1641 ske->ke1_payload->pk_len),
1642 SILC_STR_UI_XNSTRING(e, e_len),
1643 SILC_STR_UI_XNSTRING(f, f_len),
1644 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1649 silc_buffer_free(buf);
1650 memset(e, 0, e_len);
1651 memset(f, 0, f_len);
1652 memset(KEY, 0, KEY_len);
1656 return SILC_SKE_STATUS_ERROR;
1659 memset(e, 0, e_len);
1660 memset(f, 0, f_len);
1661 memset(KEY, 0, KEY_len);
1666 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1668 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1669 ske->ke1_payload->pk_len + e_len);
1670 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1672 /* Format the buffer used to compute the hash value */
1674 silc_buffer_format(buf,
1675 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1676 ske->start_payload_copy->len),
1677 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1678 ske->ke1_payload->pk_len),
1679 SILC_STR_UI_XNSTRING(e, e_len),
1682 silc_buffer_free(buf);
1683 memset(e, 0, e_len);
1685 return SILC_SKE_STATUS_ERROR;
1688 memset(e, 0, e_len);
1693 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1694 *return_hash_len = ske->prop->hash->hash->hash_len;
1696 if (initiator == FALSE) {
1697 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1699 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1702 silc_buffer_free(buf);
1707 /* Processes the provided key material `data' as the SILC protocol
1708 specification defines. */
1711 silc_ske_process_key_material_data(unsigned char *data,
1714 uint32 req_enc_key_len,
1715 uint32 req_hmac_key_len,
1717 SilcSKEKeyMaterial *key)
1720 unsigned char hashd[32];
1721 uint32 hash_len = req_hmac_key_len;
1722 uint32 enc_key_len = req_enc_key_len / 8;
1724 SILC_LOG_DEBUG(("Start"));
1726 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1727 return SILC_SKE_STATUS_ERROR;
1729 buf = silc_buffer_alloc(1 + data_len);
1730 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1731 silc_buffer_format(buf,
1732 SILC_STR_UI_CHAR(0),
1733 SILC_STR_UI_XNSTRING(data, data_len),
1737 memset(hashd, 0, sizeof(hashd));
1739 silc_hash_make(hash, buf->data, buf->len, hashd);
1740 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1741 memcpy(key->send_iv, hashd, req_iv_len);
1742 memset(hashd, 0, sizeof(hashd));
1744 silc_hash_make(hash, buf->data, buf->len, hashd);
1745 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1746 memcpy(key->receive_iv, hashd, req_iv_len);
1747 key->iv_len = req_iv_len;
1749 /* Take the encryption keys. If requested key size is more than
1750 the size of hash length we will distribute more key material
1751 as protocol defines. */
1753 if (enc_key_len > hash_len) {
1755 unsigned char k1[32], k2[32], k3[32];
1756 unsigned char *dtmp;
1759 if (enc_key_len > (3 * hash_len))
1760 return SILC_SKE_STATUS_ERROR;
1762 /* Take first round */
1763 memset(k1, 0, sizeof(k1));
1764 silc_hash_make(hash, buf->data, buf->len, k1);
1766 /* Take second round */
1767 dist = silc_buffer_alloc(data_len + hash_len);
1768 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1769 silc_buffer_format(dist,
1770 SILC_STR_UI_XNSTRING(data, data_len),
1771 SILC_STR_UI_XNSTRING(k1, hash_len),
1773 memset(k2, 0, sizeof(k2));
1774 silc_hash_make(hash, dist->data, dist->len, k2);
1776 /* Take third round */
1777 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1778 silc_buffer_pull_tail(dist, hash_len);
1779 silc_buffer_pull(dist, data_len + hash_len);
1780 silc_buffer_format(dist,
1781 SILC_STR_UI_XNSTRING(k2, hash_len),
1783 silc_buffer_push(dist, data_len + hash_len);
1784 memset(k3, 0, sizeof(k3));
1785 silc_hash_make(hash, dist->data, dist->len, k3);
1787 /* Then, save the keys */
1788 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1789 memcpy(dtmp, k1, hash_len);
1790 memcpy(dtmp + hash_len, k2, hash_len);
1791 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1793 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1794 memcpy(key->send_enc_key, dtmp, enc_key_len);
1795 key->enc_key_len = req_enc_key_len;
1797 memset(dtmp, 0, (3 * hash_len));
1798 memset(k1, 0, sizeof(k1));
1799 memset(k2, 0, sizeof(k2));
1800 memset(k3, 0, sizeof(k3));
1802 silc_buffer_free(dist);
1804 /* Take normal hash as key */
1805 memset(hashd, 0, sizeof(hashd));
1806 silc_hash_make(hash, buf->data, buf->len, hashd);
1807 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1808 memcpy(key->send_enc_key, hashd, enc_key_len);
1809 key->enc_key_len = req_enc_key_len;
1813 if (enc_key_len > hash_len) {
1815 unsigned char k1[32], k2[32], k3[32];
1816 unsigned char *dtmp;
1819 if (enc_key_len > (3 * hash_len))
1820 return SILC_SKE_STATUS_ERROR;
1822 /* Take first round */
1823 memset(k1, 0, sizeof(k1));
1824 silc_hash_make(hash, buf->data, buf->len, k1);
1826 /* Take second round */
1827 dist = silc_buffer_alloc(data_len + hash_len);
1828 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1829 silc_buffer_format(dist,
1830 SILC_STR_UI_XNSTRING(data, data_len),
1831 SILC_STR_UI_XNSTRING(k1, hash_len),
1833 memset(k2, 0, sizeof(k2));
1834 silc_hash_make(hash, dist->data, dist->len, k2);
1836 /* Take third round */
1837 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1838 silc_buffer_pull_tail(dist, hash_len);
1839 silc_buffer_pull(dist, data_len + hash_len);
1840 silc_buffer_format(dist,
1841 SILC_STR_UI_XNSTRING(k2, hash_len),
1843 silc_buffer_push(dist, data_len + hash_len);
1844 memset(k3, 0, sizeof(k3));
1845 silc_hash_make(hash, dist->data, dist->len, k3);
1847 /* Then, save the keys */
1848 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1849 memcpy(dtmp, k1, hash_len);
1850 memcpy(dtmp + hash_len, k2, hash_len);
1851 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1853 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1854 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1855 key->enc_key_len = req_enc_key_len;
1857 memset(dtmp, 0, (3 * hash_len));
1858 memset(k1, 0, sizeof(k1));
1859 memset(k2, 0, sizeof(k2));
1860 memset(k3, 0, sizeof(k3));
1862 silc_buffer_free(dist);
1864 /* Take normal hash as key */
1865 memset(hashd, 0, sizeof(hashd));
1866 silc_hash_make(hash, buf->data, buf->len, hashd);
1867 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1868 memcpy(key->receive_enc_key, hashd, enc_key_len);
1869 key->enc_key_len = req_enc_key_len;
1872 /* Take HMAC keys */
1873 memset(hashd, 0, sizeof(hashd));
1875 silc_hash_make(hash, buf->data, buf->len, hashd);
1876 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1877 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1878 memset(hashd, 0, sizeof(hashd));
1880 silc_hash_make(hash, buf->data, buf->len, hashd);
1881 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1882 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1883 key->hmac_key_len = req_hmac_key_len;
1884 memset(hashd, 0, sizeof(hashd));
1886 silc_buffer_free(buf);
1888 return SILC_SKE_STATUS_OK;
1891 /* Processes negotiated key material as protocol specifies. This returns
1892 the actual keys to be used in the SILC. */
1894 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1896 uint32 req_enc_key_len,
1897 uint32 req_hmac_key_len,
1898 SilcSKEKeyMaterial *key)
1900 SilcSKEStatus status;
1902 unsigned char *tmpbuf;
1905 /* Encode KEY to binary data */
1906 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1908 buf = silc_buffer_alloc(klen + ske->hash_len);
1909 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1910 silc_buffer_format(buf,
1911 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1912 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1915 /* Process the key material */
1916 status = silc_ske_process_key_material_data(buf->data, buf->len,
1917 req_iv_len, req_enc_key_len,
1919 ske->prop->hash, key);
1921 memset(tmpbuf, 0, klen);
1923 silc_buffer_free(buf);
1928 /* Free key material structure */
1930 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1936 silc_free(key->send_iv);
1937 if (key->receive_iv)
1938 silc_free(key->receive_iv);
1939 if (key->send_enc_key) {
1940 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1941 silc_free(key->send_enc_key);
1943 if (key->receive_enc_key) {
1944 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1945 silc_free(key->receive_enc_key);
1947 if (key->send_hmac_key) {
1948 memset(key->send_hmac_key, 0, key->hmac_key_len);
1949 silc_free(key->send_hmac_key);
1951 if (key->receive_hmac_key) {
1952 memset(key->receive_hmac_key, 0, key->hmac_key_len);
1953 silc_free(key->receive_hmac_key);
1958 const char *silc_ske_status_string[] =
1962 "Unkown error occurred",
1963 "Bad payload in packet",
1964 "Unsupported group",
1965 "Unsupported cipher",
1967 "Unsupported hash function",
1969 "Unsupported public key (or certificate)",
1970 "Incorrect signature",
1971 "Bad or unsupported version",
1976 "Remote did not provide public key",
1977 "Key exchange protocol is not active",
1978 "Bad reserved field in packet",
1979 "Bad payload length in packet",
1985 /* Maps status to readable string and returns the string. If string is not
1986 found and empty character string ("") is returned. */
1988 const char *silc_ske_map_status(SilcSKEStatus status)
1992 for (i = 0; silc_ske_status_string[i]; i++)
1994 return silc_ske_status_string[i];