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);
73 silc_ske_payload_ke_free(ske->ke2_payload);
78 silc_ske_group_free(ske->prop->group);
80 silc_pkcs_free(ske->prop->pkcs);
81 if (ske->prop->cipher)
82 silc_cipher_free(ske->prop->cipher);
84 silc_hash_free(ske->prop->hash);
86 silc_hmac_free(ske->prop->hmac);
89 if (ske->start_payload_copy)
90 silc_buffer_free(ske->start_payload_copy);
92 silc_mp_uninit(ske->x);
96 silc_mp_uninit(ske->KEY);
100 silc_free(ske->callbacks);
105 /* Sets the callback functions for the SKE session.
107 The `send_packet' callback is a function that sends the packet to
108 network. The SKE library will call it at any time packet needs to
109 be sent to the remote host.
111 The `payload_receive' callback is called when the remote host's Key
112 Exchange Start Payload has been processed. The payload is saved
113 to ske->start_payload if the application would need it. The application
114 must also provide the payload to the next state of the SKE.
116 The `verify_key' callback is called to verify the received public key
117 or certificate. The verification process is most likely asynchronous.
118 That is why the application must call the completion callback when the
119 verification process has been completed. The library then calls the user
120 callback (`proto_continue'), if it is provided to indicate that the SKE
121 protocol may continue.
123 The `proto_continue' callback is called to indicate that it is
124 safe to continue the execution of the SKE protocol after executing
125 an asynchronous operation, such as calling the `verify_key' callback
126 function, which is asynchronous. The application should check the
127 ske->status in this function to check whether it is Ok to continue
128 the execution of the protocol.
130 The `check_version' callback is called to verify the remote host's
131 version. The application may check its own version against the remote
132 host's version and determine whether supporting the remote host
135 The `context' is passed as argument to all of the above callback
138 void silc_ske_set_callbacks(SilcSKE ske,
139 SilcSKESendPacketCb send_packet,
140 SilcSKECb payload_receive,
141 SilcSKEVerifyCb verify_key,
142 SilcSKECb proto_continue,
143 SilcSKECheckVersion check_version,
147 silc_free(ske->callbacks);
148 ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
149 ske->callbacks->send_packet = send_packet;
150 ske->callbacks->payload_receive = payload_receive;
151 ske->callbacks->verify_key = verify_key;
152 ske->callbacks->proto_continue = proto_continue;
153 ske->callbacks->check_version = check_version;
154 ske->callbacks->context = context;
157 /* Starts the SILC Key Exchange protocol for initiator. The connection
158 to the remote end must be established before calling this function
159 and the connecting socket must be sent as argument. This function
160 creates the Key Exchange Start Payload which includes all our
161 configured security properties. This payload is then sent to the
162 remote end for further processing. This payload must be sent as
163 argument to the function, however, it must not be encoded
164 already, it is done by this function. The caller must not free
165 the `start_payload' since the SKE library will save it.
167 The packet sending is done by calling a callback function. Caller
168 must provide a routine to send the packet. */
170 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
171 SilcSocketConnection sock,
172 SilcSKEStartPayload *start_payload)
174 SilcSKEStatus status = SILC_SKE_STATUS_OK;
175 SilcBuffer payload_buf;
177 SILC_LOG_DEBUG(("Start"));
182 /* Encode the payload */
183 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
184 if (status != SILC_SKE_STATUS_OK)
187 /* Take a copy of the payload buffer for future use. It is used to
188 compute the HASH value. */
189 ske->start_payload_copy = silc_buffer_copy(payload_buf);
190 ske->start_payload = start_payload;
192 /* Send the packet. */
193 if (ske->callbacks->send_packet)
194 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
195 ske->callbacks->context);
197 silc_buffer_free(payload_buf);
202 /* Function called after ske_initiator_start fuction. This receives
203 the remote ends Key Exchange Start payload which includes the
204 security properties selected by the responder from our payload
205 sent in the silc_ske_initiator_start function. */
207 SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
208 SilcBuffer start_payload)
210 SilcSKEStatus status = SILC_SKE_STATUS_OK;
211 SilcSKEStartPayload *payload;
212 SilcSKESecurityProperties prop;
213 SilcSKEDiffieHellmanGroup group;
215 SILC_LOG_DEBUG(("Start"));
217 /* Decode the payload */
218 status = silc_ske_payload_start_decode(ske, start_payload, &payload);
219 if (status != SILC_SKE_STATUS_OK) {
220 ske->status = status;
221 silc_ske_payload_start_free(ske->start_payload);
225 /* Check that the cookie is returned unmodified */
226 if (memcmp(ske->start_payload->cookie, payload->cookie,
227 ske->start_payload->cookie_len)) {
228 SILC_LOG_DEBUG(("Responder modified our cookie and it must not do it"));
229 ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
230 silc_ske_payload_start_free(ske->start_payload);
234 /* Check version string */
235 if (ske->callbacks->check_version) {
236 status = ske->callbacks->check_version(ske, payload->version,
237 payload->version_len,
238 ske->callbacks->context);
239 if (status != SILC_SKE_STATUS_OK) {
240 ske->status = status;
241 silc_ske_payload_start_free(ske->start_payload);
246 /* Free our KE Start Payload context, we don't need it anymore. */
247 silc_ske_payload_start_free(ske->start_payload);
249 /* Take the selected security properties into use while doing
250 the key exchange. This is used only while doing the key
251 exchange. The same data is returned to upper levels by calling
252 the callback function. */
253 ske->prop = prop = silc_calloc(1, sizeof(*prop));
254 prop->flags = payload->flags;
255 status = silc_ske_group_get_by_name(payload->ke_grp_list, &group);
256 if (status != SILC_SKE_STATUS_OK)
261 if (silc_pkcs_alloc(payload->pkcs_alg_list, &prop->pkcs) == FALSE) {
262 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
266 if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
267 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
271 if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
272 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
276 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
277 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
281 /* Save remote's KE Start Payload */
282 ske->start_payload = payload;
284 /* Return the received payload by calling the callback function. */
285 if (ske->callbacks->payload_receive)
286 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
292 silc_ske_payload_start_free(payload);
294 silc_ske_group_free(group);
297 silc_pkcs_free(prop->pkcs);
299 silc_cipher_free(prop->cipher);
301 silc_hash_free(prop->hash);
303 silc_hmac_free(prop->hmac);
307 if (status == SILC_SKE_STATUS_OK)
308 return SILC_SKE_STATUS_ERROR;
310 ske->status = status;
314 /* This function creates random number x, such that 1 < x < q and
315 computes e = g ^ x mod p and sends the result to the remote end in
316 Key Exchange Payload. */
318 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
319 SilcPublicKey public_key,
320 SilcPrivateKey private_key)
322 SilcSKEStatus status = SILC_SKE_STATUS_OK;
323 SilcBuffer payload_buf;
325 SilcSKEKEPayload *payload;
328 SILC_LOG_DEBUG(("Start"));
330 /* Create the random number x, 1 < x < q. */
331 x = silc_calloc(1, sizeof(*x));
334 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
335 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
337 if (status != SILC_SKE_STATUS_OK) {
340 ske->status = status;
344 /* Encode the result to Key Exchange Payload. */
346 payload = silc_calloc(1, sizeof(*payload));
347 ske->ke1_payload = payload;
349 SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
351 /* Do the Diffie Hellman computation, e = g ^ x mod p */
352 silc_mp_init(&payload->x);
353 silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
354 &ske->prop->group->group);
358 payload->pk_data = silc_pkcs_public_key_encode(public_key, &pk_len);
359 if (!payload->pk_data) {
362 silc_mp_uninit(&payload->x);
364 ske->status = SILC_SKE_STATUS_OK;
367 payload->pk_len = pk_len;
369 payload->pk_type = SILC_SKE_PK_TYPE_SILC;
371 /* Compute signature data if we are doing mutual authentication */
372 if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
373 unsigned char hash[32], sign[1024];
374 uint32 hash_len, sign_len;
376 SILC_LOG_DEBUG(("We are doing mutual authentication"));
377 SILC_LOG_DEBUG(("Computing HASH_i value"));
379 /* Compute the hash value */
380 memset(hash, 0, sizeof(hash));
381 silc_ske_make_hash(ske, hash, &hash_len, TRUE);
383 SILC_LOG_DEBUG(("Signing HASH_i value"));
385 /* Sign the hash value */
386 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
387 private_key->prv_len);
388 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
389 payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
390 memcpy(payload->sign_data, sign, sign_len);
391 memset(sign, 0, sizeof(sign));
392 payload->sign_len = sign_len;
395 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
396 if (status != SILC_SKE_STATUS_OK) {
399 silc_mp_uninit(&payload->x);
400 silc_free(payload->pk_data);
402 ske->status = status;
408 /* Send the packet. */
409 if (ske->callbacks->send_packet)
410 (*ske->callbacks->send_packet)(ske, payload_buf,
411 SILC_PACKET_KEY_EXCHANGE_1,
412 ske->callbacks->context);
414 silc_buffer_free(payload_buf);
419 /* An initiator finish final callback that is called to indicate that
420 the SKE protocol may continue. */
422 static void silc_ske_initiator_finish_final(SilcSKE ske,
423 SilcSKEStatus status,
426 SilcSKEKEPayload *payload;
427 unsigned char hash[32];
429 SilcPublicKey public_key = NULL;
431 /* If the SKE was freed during the async call then free it really now,
432 otherwise just decrement the reference counter. */
433 if (ske->status == SILC_SKE_STATUS_FREED) {
438 /* If the caller returns PENDING status SKE library will assume that
439 the caller will re-call this callback when it is not anymore in
441 if (status == SILC_SKE_STATUS_PENDING)
445 payload = ske->ke2_payload;
447 /* If the status is an error then the public key that was verified
448 by the caller is not authentic. */
449 if (status != SILC_SKE_STATUS_OK) {
450 ske->status = status;
451 if (ske->callbacks->proto_continue)
452 ske->callbacks->proto_continue(ske, ske->callbacks->context);
456 if (payload->pk_data) {
457 /* Decode the public key */
458 if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
460 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
461 if (ske->callbacks->proto_continue)
462 ske->callbacks->proto_continue(ske, ske->callbacks->context);
466 SILC_LOG_DEBUG(("Public key is authentic"));
468 /* Compute the hash value */
469 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
470 if (status != SILC_SKE_STATUS_OK)
473 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
474 memcpy(ske->hash, hash, hash_len);
475 ske->hash_len = hash_len;
477 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
479 /* Verify signature */
480 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
481 if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
482 payload->sign_len, hash, hash_len) == FALSE) {
484 SILC_LOG_DEBUG(("Signature don't match"));
486 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
490 SILC_LOG_DEBUG(("Signature is Ok"));
492 silc_pkcs_public_key_free(public_key);
493 memset(hash, 'F', hash_len);
496 ske->status = SILC_SKE_STATUS_OK;
498 /* Call the callback. The caller may now continue the SKE protocol. */
499 if (ske->callbacks->proto_continue)
500 ske->callbacks->proto_continue(ske, ske->callbacks->context);
505 memset(hash, 'F', sizeof(hash));
506 silc_ske_payload_ke_free(payload);
507 ske->ke2_payload = NULL;
509 silc_mp_uninit(ske->KEY);
514 silc_pkcs_public_key_free(public_key);
517 memset(ske->hash, 'F', hash_len);
518 silc_free(ske->hash);
522 if (status == SILC_SKE_STATUS_OK)
523 ske->status = SILC_SKE_STATUS_ERROR;
525 ske->status = status;
527 /* Call the callback. */
528 if (ske->callbacks->proto_continue)
529 ske->callbacks->proto_continue(ske, ske->callbacks->context);
532 /* Receives Key Exchange Payload from responder consisting responders
533 public key, f, and signature. This function verifies the public key,
534 computes the secret shared key and verifies the signature.
536 The `callback' will be called to indicate that the caller may
537 continue with the SKE protocol. The caller must not continue
538 before the SKE libary has called that callback. If this function
539 returns an error the callback will not be called. It is called
540 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
541 However, note that when the library calls the callback the ske->status
544 This calls the `verify_key' callback to verify the received public
545 key or certificate. If the `verify_key' is provided then the remote
546 must send public key and it is considered to be an error if remote
547 does not send its public key. If caller is performing a re-key with
548 SKE then the `verify_key' is usually not provided when it is not also
549 required for the remote to send its public key. */
551 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
552 SilcBuffer ke_payload)
554 SilcSKEStatus status = SILC_SKE_STATUS_OK;
555 SilcSKEKEPayload *payload;
558 SILC_LOG_DEBUG(("Start"));
560 /* Decode the payload */
561 status = silc_ske_payload_ke_decode(ske, ke_payload, &payload);
562 if (status != SILC_SKE_STATUS_OK) {
563 ske->status = status;
566 ske->ke2_payload = payload;
568 if (!payload->pk_data && ske->callbacks->verify_key) {
569 SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
570 "even though we require it"));
571 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
575 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
577 /* Compute the shared secret key */
578 KEY = silc_calloc(1, sizeof(*KEY));
580 silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
583 if (payload->pk_data && ske->callbacks->verify_key) {
584 SILC_LOG_DEBUG(("Verifying public key"));
587 (*ske->callbacks->verify_key)(ske, payload->pk_data, payload->pk_len,
588 payload->pk_type, ske->callbacks->context,
589 silc_ske_initiator_finish_final, NULL);
591 /* We will continue to the final state after the public key has
592 been verified by the caller. */
593 return SILC_SKE_STATUS_PENDING;
596 /* Continue to final state */
598 silc_ske_initiator_finish_final(ske, SILC_SKE_STATUS_OK, NULL);
600 return SILC_SKE_STATUS_OK;
603 silc_ske_payload_ke_free(payload);
604 ske->ke2_payload = NULL;
606 silc_mp_uninit(ske->KEY);
610 if (status == SILC_SKE_STATUS_OK)
611 return SILC_SKE_STATUS_ERROR;
613 ske->status = status;
617 /* Starts Key Exchange protocol for responder. Responder receives
618 Key Exchange Start Payload from initiator consisting of all the
619 security properties the initiator supports. This function decodes
620 the payload and parses the payload further and selects the right
621 security properties. */
623 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
624 SilcSocketConnection sock,
626 SilcBuffer start_payload,
629 SilcSKEStatus status = SILC_SKE_STATUS_OK;
630 SilcSKEStartPayload *remote_payload = NULL, *payload = NULL;
632 SILC_LOG_DEBUG(("Start"));
637 /* Decode the payload */
638 status = silc_ske_payload_start_decode(ske, start_payload, &remote_payload);
639 if (status != SILC_SKE_STATUS_OK) {
640 ske->status = status;
644 /* Take a copy of the payload buffer for future use. It is used to
645 compute the HASH value. */
646 ske->start_payload_copy = silc_buffer_copy(start_payload);
648 /* Force the mutual authentication flag if we want to do it. */
650 SILC_LOG_DEBUG(("Force mutual authentication"));
651 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
654 /* Parse and select the security properties from the payload */
655 payload = silc_calloc(1, sizeof(*payload));
656 status = silc_ske_select_security_properties(ske, version,
657 payload, remote_payload);
658 if (status != SILC_SKE_STATUS_OK)
661 ske->start_payload = payload;
663 /* Call the callback function. */
664 if (ske->callbacks->payload_receive)
665 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
667 silc_ske_payload_start_free(remote_payload);
673 silc_ske_payload_start_free(remote_payload);
677 if (status == SILC_SKE_STATUS_OK)
678 return SILC_SKE_STATUS_ERROR;
680 ske->status = status;
684 /* The selected security properties from the initiator payload is now
685 encoded into Key Exchange Start Payload and sent to the initiator. */
687 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske,
688 SilcSKEStartPayload *start_payload)
690 SilcSKEStatus status = SILC_SKE_STATUS_OK;
691 SilcBuffer payload_buf;
692 SilcSKESecurityProperties prop;
693 SilcSKEDiffieHellmanGroup group = NULL;
695 SILC_LOG_DEBUG(("Start"));
697 /* Allocate security properties from the payload. These are allocated
698 only for this negotiation and will be free'd after KE is over. */
699 ske->prop = prop = silc_calloc(1, sizeof(*prop));
700 prop->flags = start_payload->flags;
701 status = silc_ske_group_get_by_name(start_payload->ke_grp_list, &group);
702 if (status != SILC_SKE_STATUS_OK)
707 if (silc_pkcs_alloc(start_payload->pkcs_alg_list,
708 &prop->pkcs) == FALSE) {
709 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
713 if (silc_cipher_alloc(start_payload->enc_alg_list,
714 &prop->cipher) == FALSE) {
715 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
719 if (silc_hash_alloc(start_payload->hash_alg_list,
720 &prop->hash) == FALSE) {
721 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
725 if (silc_hmac_alloc(start_payload->hmac_alg_list, NULL,
726 &prop->hmac) == FALSE) {
727 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
731 /* Encode the payload */
732 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
733 if (status != SILC_SKE_STATUS_OK)
736 /* Send the packet. */
737 if (ske->callbacks->send_packet)
738 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
739 ske->callbacks->context);
741 silc_buffer_free(payload_buf);
747 silc_ske_group_free(group);
750 silc_pkcs_free(prop->pkcs);
752 silc_cipher_free(prop->cipher);
754 silc_hash_free(prop->hash);
756 silc_hmac_free(prop->hmac);
760 if (status == SILC_SKE_STATUS_OK)
761 return SILC_SKE_STATUS_ERROR;
763 ske->status = status;
767 /* An responder phase 2 final callback that is called to indicate that
768 the SKE protocol may continue. */
770 static void silc_ske_responder_phase2_final(SilcSKE ske,
771 SilcSKEStatus status,
774 SilcSKEKEPayload *recv_payload, *send_payload;
777 /* If the SKE was freed during the async call then free it really now,
778 otherwise just decrement the reference counter. */
779 if (ske->status == SILC_SKE_STATUS_FREED) {
784 /* If the caller returns PENDING status SKE library will assume that
785 the caller will re-call this callback when it is not anymore in
787 if (status == SILC_SKE_STATUS_PENDING)
791 recv_payload = ske->ke1_payload;
793 /* If the status is an error then the public key that was verified
794 by the caller is not authentic. */
795 if (status != SILC_SKE_STATUS_OK) {
796 ske->status = status;
797 if (ske->callbacks->proto_continue)
798 ske->callbacks->proto_continue(ske, ske->callbacks->context);
802 /* The public key verification was performed only if the Mutual
803 Authentication flag is set. */
804 if (ske->start_payload &&
805 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
806 SilcPublicKey public_key = NULL;
807 unsigned char hash[32];
810 /* Decode the public key */
811 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
812 recv_payload->pk_len,
814 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
815 if (ske->callbacks->proto_continue)
816 ske->callbacks->proto_continue(ske, ske->callbacks->context);
820 SILC_LOG_DEBUG(("Public key is authentic"));
822 /* Compute the hash value */
823 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
824 if (status != SILC_SKE_STATUS_OK) {
825 ske->status = status;
826 if (ske->callbacks->proto_continue)
827 ske->callbacks->proto_continue(ske, ske->callbacks->context);
831 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
833 /* Verify signature */
834 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
835 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
836 recv_payload->sign_len, hash, hash_len) == FALSE) {
838 SILC_LOG_DEBUG(("Signature don't match"));
840 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
841 if (ske->callbacks->proto_continue)
842 ske->callbacks->proto_continue(ske, ske->callbacks->context);
846 SILC_LOG_DEBUG(("Signature is Ok"));
848 silc_pkcs_public_key_free(public_key);
849 memset(hash, 'F', hash_len);
852 /* Create the random number x, 1 < x < q. */
853 x = silc_calloc(1, sizeof(*x));
856 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
857 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
859 if (status != SILC_SKE_STATUS_OK) {
862 ske->status = status;
863 if (ske->callbacks->proto_continue)
864 ske->callbacks->proto_continue(ske, ske->callbacks->context);
868 /* Save the results for later processing */
869 send_payload = silc_calloc(1, sizeof(*send_payload));
871 ske->ke2_payload = send_payload;
873 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
875 /* Do the Diffie Hellman computation, f = g ^ x mod p */
876 silc_mp_init(&send_payload->x);
877 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
878 &ske->prop->group->group);
880 /* Call the callback. The caller may now continue with the SKE protocol. */
881 ske->status = SILC_SKE_STATUS_OK;
882 if (ske->callbacks->proto_continue)
883 ske->callbacks->proto_continue(ske, ske->callbacks->context);
886 /* This function receives the Key Exchange Payload from the initiator.
887 This also performs the mutual authentication if required. Then, this
888 function first generated a random number x, such that 1 < x < q
889 and computes f = g ^ x mod p. This then puts the result f to a Key
892 The `callback' will be called to indicate that the caller may
893 continue with the SKE protocol. The caller must not continue
894 before the SKE libary has called that callback. If this function
895 returns an error the callback will not be called. It is called
896 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
897 However, note that when the library calls the callback the ske->status
900 This calls the `verify_key' callback to verify the received public
901 key or certificate if the Mutual Authentication flag is set. If the
902 `verify_key' is provided then the remote must send public key and it
903 is considered to be an error if remote does not send its public key. */
905 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
906 SilcBuffer ke_payload)
908 SilcSKEStatus status = SILC_SKE_STATUS_OK;
909 SilcSKEKEPayload *recv_payload;
911 SILC_LOG_DEBUG(("Start"));
913 /* Decode Key Exchange Payload */
914 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
915 if (status != SILC_SKE_STATUS_OK) {
916 ske->status = status;
920 ske->ke1_payload = recv_payload;
922 /* Verify the received public key and verify the signature if we are
923 doing mutual authentication. */
924 if (ske->start_payload &&
925 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
927 SILC_LOG_DEBUG(("We are doing mutual authentication"));
929 if (!recv_payload->pk_data && ske->callbacks->verify_key) {
930 SILC_LOG_DEBUG(("Remote end did not send its public key (or "
931 "certificate), even though we require it"));
932 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
936 if (recv_payload->pk_data && ske->callbacks->verify_key) {
937 SILC_LOG_DEBUG(("Verifying public key"));
940 (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
941 recv_payload->pk_len,
942 recv_payload->pk_type,
943 ske->callbacks->context,
944 silc_ske_responder_phase2_final, NULL);
946 /* We will continue to the final state after the public key has
947 been verified by the caller. */
948 return SILC_SKE_STATUS_PENDING;
952 /* Continue to final state */
954 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
956 return SILC_SKE_STATUS_OK;
959 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
960 value to be signed and sent to the other end. This then encodes Key
961 Exchange Payload and sends it to the other end. */
963 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
964 SilcPublicKey public_key,
965 SilcPrivateKey private_key,
966 SilcSKEPKType pk_type)
968 SilcSKEStatus status = SILC_SKE_STATUS_OK;
969 SilcBuffer payload_buf;
971 unsigned char hash[32], sign[1024], *pk;
972 uint32 hash_len, sign_len, pk_len;
974 SILC_LOG_DEBUG(("Start"));
976 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
978 /* Compute the shared secret key */
979 KEY = silc_calloc(1, sizeof(*KEY));
981 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
982 &ske->prop->group->group);
985 if (public_key && private_key) {
986 SILC_LOG_DEBUG(("Getting public key"));
988 /* Get the public key */
989 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
991 status = SILC_SKE_STATUS_ERROR;
994 ske->ke2_payload->pk_data = pk;
995 ske->ke2_payload->pk_len = pk_len;
997 SILC_LOG_DEBUG(("Computing HASH value"));
999 /* Compute the hash value */
1000 memset(hash, 0, sizeof(hash));
1001 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1002 if (status != SILC_SKE_STATUS_OK)
1005 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
1006 memcpy(ske->hash, hash, hash_len);
1007 ske->hash_len = hash_len;
1009 SILC_LOG_DEBUG(("Signing HASH value"));
1011 /* Sign the hash value */
1012 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
1013 private_key->prv_len);
1014 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
1015 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
1016 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
1017 memset(sign, 0, sizeof(sign));
1018 ske->ke2_payload->sign_len = sign_len;
1020 ske->ke2_payload->pk_type = pk_type;
1022 /* Encode the Key Exchange Payload */
1023 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
1025 if (status != SILC_SKE_STATUS_OK)
1028 /* Send the packet. */
1029 if (ske->callbacks->send_packet)
1030 (*ske->callbacks->send_packet)(ske, payload_buf,
1031 SILC_PACKET_KEY_EXCHANGE_2,
1032 ske->callbacks->context);
1034 silc_buffer_free(payload_buf);
1039 silc_mp_uninit(ske->KEY);
1040 silc_free(ske->KEY);
1042 silc_ske_payload_ke_free(ske->ke2_payload);
1044 if (status == SILC_SKE_STATUS_OK)
1045 return SILC_SKE_STATUS_ERROR;
1047 ske->status = status;
1051 /* The Key Exchange protocol is ended by calling this function. This
1052 must not be called until the keys are processed like the protocol
1053 defines. This function is for both initiator and responder. */
1055 SilcSKEStatus silc_ske_end(SilcSKE ske)
1059 SILC_LOG_DEBUG(("Start"));
1061 packet = silc_buffer_alloc(4);
1062 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1063 silc_buffer_format(packet,
1064 SILC_STR_UI_INT((uint32)SILC_SKE_STATUS_OK),
1067 if (ske->callbacks->send_packet)
1068 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS,
1069 ske->callbacks->context);
1071 silc_buffer_free(packet);
1073 return SILC_SKE_STATUS_OK;
1076 /* Aborts the Key Exchange protocol. This is called if error occurs
1077 while performing the protocol. The status argument is the error
1078 status and it is sent to the remote end. */
1080 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
1084 SILC_LOG_DEBUG(("Start"));
1086 packet = silc_buffer_alloc(4);
1087 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1088 silc_buffer_format(packet,
1089 SILC_STR_UI_INT((uint32)status),
1092 if (ske->callbacks->send_packet)
1093 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
1094 ske->callbacks->context);
1096 silc_buffer_free(packet);
1098 return SILC_SKE_STATUS_OK;
1101 /* Assembles security properties to Key Exchange Start Payload to be
1102 sent to the remote end. This checks system wide (SILC system, that is)
1103 settings and chooses from those. However, if other properties
1104 should be used this function is easy to replace by another function,
1105 as, this function is called by the caller of the protocol and not
1106 by the protocol itself. */
1109 silc_ske_assemble_security_properties(SilcSKE ske,
1110 unsigned char flags,
1112 SilcSKEStartPayload **return_payload)
1114 SilcSKEStartPayload *rp;
1117 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1119 rp = silc_calloc(1, sizeof(*rp));
1124 /* Set random cookie */
1125 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1126 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1127 rp->cookie[i] = silc_rng_get_byte(ske->rng);
1128 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1131 rp->version = strdup(version);
1132 rp->version_len = strlen(version);
1134 /* Get supported Key Exhange groups */
1135 rp->ke_grp_list = silc_ske_get_supported_groups();
1136 rp->ke_grp_len = strlen(rp->ke_grp_list);
1138 /* Get supported PKCS algorithms */
1139 rp->pkcs_alg_list = silc_pkcs_get_supported();
1140 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1142 /* Get supported encryption algorithms */
1143 rp->enc_alg_list = silc_cipher_get_supported();
1144 rp->enc_alg_len = strlen(rp->enc_alg_list);
1146 /* Get supported hash algorithms */
1147 rp->hash_alg_list = silc_hash_get_supported();
1148 rp->hash_alg_len = strlen(rp->hash_alg_list);
1150 /* Get supported HMACs */
1151 rp->hmac_alg_list = silc_hmac_get_supported();
1152 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1155 /* Get supported compression algorithms */
1156 rp->comp_alg_list = strdup("");
1157 rp->comp_alg_len = 0;
1159 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1160 2 + rp->version_len +
1161 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1162 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1163 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1165 *return_payload = rp;
1167 return SILC_SKE_STATUS_OK;
1170 /* Selects the supported security properties from the remote end's Key
1171 Exchange Start Payload. */
1174 silc_ske_select_security_properties(SilcSKE ske,
1176 SilcSKEStartPayload *payload,
1177 SilcSKEStartPayload *remote_payload)
1179 SilcSKEStatus status;
1180 SilcSKEStartPayload *rp;
1184 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1186 rp = remote_payload;
1188 /* Check version string */
1189 if (ske->callbacks->check_version) {
1190 status = ske->callbacks->check_version(ske, rp->version,
1192 ske->callbacks->context);
1193 if (status != SILC_SKE_STATUS_OK) {
1194 ske->status = status;
1199 /* Flags are returned unchanged. */
1200 payload->flags = rp->flags;
1202 /* Take cookie, we must return it to sender unmodified. */
1203 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1204 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1205 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1207 /* Put our version to our reply */
1208 payload->version = strdup(version);
1209 payload->version_len = strlen(version);
1211 /* Get supported Key Exchange groups */
1212 cp = rp->ke_grp_list;
1213 if (cp && strchr(cp, ',')) {
1217 len = strcspn(cp, ",");
1218 item = silc_calloc(len + 1, sizeof(char));
1219 memcpy(item, cp, len);
1221 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1223 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1224 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1226 payload->ke_grp_len = len;
1227 payload->ke_grp_list = item;
1232 if (strlen(cp) == 0)
1241 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1242 SILC_LOG_DEBUG(("Could not find supported KE group"));
1244 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1248 if (!rp->ke_grp_len) {
1249 SILC_LOG_DEBUG(("KE group not defined in payload"));
1251 return SILC_SKE_STATUS_BAD_PAYLOAD;
1254 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1255 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1257 payload->ke_grp_len = rp->ke_grp_len;
1258 payload->ke_grp_list = strdup(rp->ke_grp_list);
1261 /* Get supported PKCS algorithms */
1262 cp = rp->pkcs_alg_list;
1263 if (cp && strchr(cp, ',')) {
1267 len = strcspn(cp, ",");
1268 item = silc_calloc(len + 1, sizeof(char));
1269 memcpy(item, cp, len);
1271 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1273 if (silc_pkcs_is_supported(item) == TRUE) {
1274 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1276 payload->pkcs_alg_len = len;
1277 payload->pkcs_alg_list = item;
1282 if (strlen(cp) == 0)
1291 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1292 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1293 silc_free(payload->ke_grp_list);
1295 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1299 if (!rp->pkcs_alg_len) {
1300 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1301 silc_free(payload->ke_grp_list);
1303 return SILC_SKE_STATUS_BAD_PAYLOAD;
1306 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1307 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1309 payload->pkcs_alg_len = rp->pkcs_alg_len;
1310 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1313 /* Get supported encryption algorithms */
1314 cp = rp->enc_alg_list;
1315 if (cp && strchr(cp, ',')) {
1319 len = strcspn(cp, ",");
1320 item = silc_calloc(len + 1, sizeof(char));
1321 memcpy(item, cp, len);
1323 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1325 if (silc_cipher_is_supported(item) == TRUE) {
1326 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1328 payload->enc_alg_len = len;
1329 payload->enc_alg_list = item;
1334 if (strlen(cp) == 0)
1343 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1344 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1345 silc_free(payload->ke_grp_list);
1346 silc_free(payload->pkcs_alg_list);
1348 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1352 if (!rp->enc_alg_len) {
1353 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1354 silc_free(payload->ke_grp_list);
1355 silc_free(payload->pkcs_alg_list);
1357 return SILC_SKE_STATUS_BAD_PAYLOAD;
1360 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1363 payload->enc_alg_len = rp->enc_alg_len;
1364 payload->enc_alg_list = strdup(rp->enc_alg_list);
1367 /* Get supported hash algorithms */
1368 cp = rp->hash_alg_list;
1369 if (cp && strchr(cp, ',')) {
1373 len = strcspn(cp, ",");
1374 item = silc_calloc(len + 1, sizeof(char));
1375 memcpy(item, cp, len);
1377 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1379 if (silc_hash_is_supported(item) == TRUE) {
1380 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1382 payload->hash_alg_len = len;
1383 payload->hash_alg_list = item;
1388 if (strlen(cp) == 0)
1397 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1398 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1399 silc_free(payload->ke_grp_list);
1400 silc_free(payload->pkcs_alg_list);
1401 silc_free(payload->enc_alg_list);
1403 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1407 if (!rp->hash_alg_len) {
1408 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1409 silc_free(payload->ke_grp_list);
1410 silc_free(payload->pkcs_alg_list);
1411 silc_free(payload->enc_alg_list);
1413 return SILC_SKE_STATUS_BAD_PAYLOAD;
1416 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1417 rp->hash_alg_list));
1419 payload->hash_alg_len = rp->hash_alg_len;
1420 payload->hash_alg_list = strdup(rp->hash_alg_list);
1423 /* Get supported HMACs */
1424 cp = rp->hmac_alg_list;
1425 if (cp && strchr(cp, ',')) {
1429 len = strcspn(cp, ",");
1430 item = silc_calloc(len + 1, sizeof(char));
1431 memcpy(item, cp, len);
1433 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1435 if (silc_hmac_is_supported(item) == TRUE) {
1436 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1438 payload->hmac_alg_len = len;
1439 payload->hmac_alg_list = item;
1444 if (strlen(cp) == 0)
1453 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1454 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1455 silc_free(payload->ke_grp_list);
1456 silc_free(payload->pkcs_alg_list);
1457 silc_free(payload->enc_alg_list);
1458 silc_free(payload->hash_alg_list);
1460 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1464 if (!rp->hmac_alg_len) {
1465 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1466 silc_free(payload->ke_grp_list);
1467 silc_free(payload->pkcs_alg_list);
1468 silc_free(payload->enc_alg_list);
1469 silc_free(payload->hash_alg_list);
1471 return SILC_SKE_STATUS_BAD_PAYLOAD;
1474 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1475 rp->hmac_alg_list));
1477 payload->hmac_alg_len = rp->hmac_alg_len;
1478 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1482 /* Get supported compression algorithms */
1483 cp = rp->hash_alg_list;
1484 if (cp && strchr(cp, ',')) {
1488 len = strcspn(cp, ",");
1489 item = silc_calloc(len + 1, sizeof(char));
1490 memcpy(item, cp, len);
1492 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1494 if (silc_hash_is_supported(item) == TRUE) {
1495 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1497 payload->hash_alg_len = len;
1498 payload->hash_alg_list = item;
1503 if (strlen(cp) == 0)
1512 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1513 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1514 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1515 silc_free(payload->ke_grp_list);
1516 silc_free(payload->pkcs_alg_list);
1517 silc_free(payload->enc_alg_list);
1526 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1527 2 + payload->version_len +
1528 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1529 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1530 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1532 return SILC_SKE_STATUS_OK;
1535 /* Creates random number such that 1 < rnd < n and at most length
1536 of len bits. The rnd sent as argument must be initialized. */
1538 SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1542 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1543 unsigned char *string;
1545 SILC_LOG_DEBUG(("Creating random number"));
1547 /* Get the random number as string */
1548 string = silc_rng_get_rn_data(ske->rng, (len / 8));
1550 return SILC_SKE_STATUS_ERROR;
1552 /* Decode the string into a MP integer */
1553 silc_mp_bin2mp(string, (len / 8), rnd);
1554 silc_mp_mod_2exp(rnd, rnd, len);
1557 if (silc_mp_cmp_ui(rnd, 1) < 0)
1558 status = SILC_SKE_STATUS_ERROR;
1560 if (silc_mp_cmp(rnd, n) >= 0)
1561 status = SILC_SKE_STATUS_ERROR;
1563 memset(string, 'F', (len / 8));
1569 /* Creates a hash value HASH as defined in the SKE protocol. If the
1570 `initiator' is TRUE then this function is used to create the HASH_i
1571 hash value defined in the protocol. If it is FALSE then this is used
1572 to create the HASH value defined by the protocol. */
1574 SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1575 unsigned char *return_hash,
1576 uint32 *return_hash_len,
1579 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1581 unsigned char *e, *f, *KEY;
1582 uint32 e_len, f_len, KEY_len;
1585 SILC_LOG_DEBUG(("Start"));
1587 if (initiator == FALSE) {
1588 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1589 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1590 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1592 /* Format the buffer used to compute the hash value */
1593 /* XXX Backward support for 0.6.1 */
1594 if (ske->backward_version == 1) {
1595 SILC_LOG_DEBUG(("*********** Using old KE payload"));
1596 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1597 ske->ke2_payload->pk_len + e_len +
1599 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1602 silc_buffer_format(buf,
1603 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1604 ske->start_payload_copy->len),
1605 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1606 ske->ke2_payload->pk_len),
1607 SILC_STR_UI_XNSTRING(e, e_len),
1608 SILC_STR_UI_XNSTRING(f, f_len),
1609 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1612 /* Initiator is not required to send its public key */
1613 SILC_LOG_DEBUG(("*********** Using new KE payload"));
1614 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1615 ske->ke2_payload->pk_len +
1616 ske->ke1_payload->pk_len +
1617 e_len + f_len + KEY_len);
1618 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1620 if (!ske->ke1_payload->pk_data) {
1622 silc_buffer_format(buf,
1623 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1625 ske->start_payload_copy->
1627 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1628 ske->ke2_payload->pk_len),
1629 SILC_STR_UI_XNSTRING(e, e_len),
1630 SILC_STR_UI_XNSTRING(f, f_len),
1631 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1635 silc_buffer_format(buf,
1636 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1638 ske->start_payload_copy->
1640 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1641 ske->ke2_payload->pk_len),
1642 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1643 ske->ke1_payload->pk_len),
1644 SILC_STR_UI_XNSTRING(e, e_len),
1645 SILC_STR_UI_XNSTRING(f, f_len),
1646 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1651 silc_buffer_free(buf);
1652 memset(e, 0, e_len);
1653 memset(f, 0, f_len);
1654 memset(KEY, 0, KEY_len);
1658 return SILC_SKE_STATUS_ERROR;
1661 memset(e, 0, e_len);
1662 memset(f, 0, f_len);
1663 memset(KEY, 0, KEY_len);
1668 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1670 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1671 ske->ke1_payload->pk_len + e_len);
1672 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1674 /* Format the buffer used to compute the hash value */
1676 silc_buffer_format(buf,
1677 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1678 ske->start_payload_copy->len),
1679 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1680 ske->ke1_payload->pk_len),
1681 SILC_STR_UI_XNSTRING(e, e_len),
1684 silc_buffer_free(buf);
1685 memset(e, 0, e_len);
1687 return SILC_SKE_STATUS_ERROR;
1690 memset(e, 0, e_len);
1695 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1696 *return_hash_len = ske->prop->hash->hash->hash_len;
1698 if (initiator == FALSE) {
1699 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1701 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1704 silc_buffer_free(buf);
1709 /* Processes the provided key material `data' as the SILC protocol
1710 specification defines. */
1713 silc_ske_process_key_material_data(unsigned char *data,
1716 uint32 req_enc_key_len,
1717 uint32 req_hmac_key_len,
1719 SilcSKEKeyMaterial *key)
1722 unsigned char hashd[32];
1723 uint32 hash_len = req_hmac_key_len;
1724 uint32 enc_key_len = req_enc_key_len / 8;
1726 SILC_LOG_DEBUG(("Start"));
1728 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1729 return SILC_SKE_STATUS_ERROR;
1731 buf = silc_buffer_alloc(1 + data_len);
1732 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1733 silc_buffer_format(buf,
1734 SILC_STR_UI_CHAR(0),
1735 SILC_STR_UI_XNSTRING(data, data_len),
1739 memset(hashd, 0, sizeof(hashd));
1741 silc_hash_make(hash, buf->data, buf->len, hashd);
1742 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1743 memcpy(key->send_iv, hashd, req_iv_len);
1744 memset(hashd, 0, sizeof(hashd));
1746 silc_hash_make(hash, buf->data, buf->len, hashd);
1747 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1748 memcpy(key->receive_iv, hashd, req_iv_len);
1749 key->iv_len = req_iv_len;
1751 /* Take the encryption keys. If requested key size is more than
1752 the size of hash length we will distribute more key material
1753 as protocol defines. */
1755 if (enc_key_len > hash_len) {
1757 unsigned char k1[32], k2[32], k3[32];
1758 unsigned char *dtmp;
1761 if (enc_key_len > (3 * hash_len))
1762 return SILC_SKE_STATUS_ERROR;
1764 /* Take first round */
1765 memset(k1, 0, sizeof(k1));
1766 silc_hash_make(hash, buf->data, buf->len, k1);
1768 /* Take second round */
1769 dist = silc_buffer_alloc(data_len + hash_len);
1770 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1771 silc_buffer_format(dist,
1772 SILC_STR_UI_XNSTRING(data, data_len),
1773 SILC_STR_UI_XNSTRING(k1, hash_len),
1775 memset(k2, 0, sizeof(k2));
1776 silc_hash_make(hash, dist->data, dist->len, k2);
1778 /* Take third round */
1779 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1780 silc_buffer_pull_tail(dist, hash_len);
1781 silc_buffer_pull(dist, data_len + hash_len);
1782 silc_buffer_format(dist,
1783 SILC_STR_UI_XNSTRING(k2, hash_len),
1785 silc_buffer_push(dist, data_len + hash_len);
1786 memset(k3, 0, sizeof(k3));
1787 silc_hash_make(hash, dist->data, dist->len, k3);
1789 /* Then, save the keys */
1790 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1791 memcpy(dtmp, k1, hash_len);
1792 memcpy(dtmp + hash_len, k2, hash_len);
1793 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1795 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1796 memcpy(key->send_enc_key, dtmp, enc_key_len);
1797 key->enc_key_len = req_enc_key_len;
1799 memset(dtmp, 0, (3 * hash_len));
1800 memset(k1, 0, sizeof(k1));
1801 memset(k2, 0, sizeof(k2));
1802 memset(k3, 0, sizeof(k3));
1804 silc_buffer_free(dist);
1806 /* Take normal hash as key */
1807 memset(hashd, 0, sizeof(hashd));
1808 silc_hash_make(hash, buf->data, buf->len, hashd);
1809 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1810 memcpy(key->send_enc_key, hashd, enc_key_len);
1811 key->enc_key_len = req_enc_key_len;
1815 if (enc_key_len > hash_len) {
1817 unsigned char k1[32], k2[32], k3[32];
1818 unsigned char *dtmp;
1821 if (enc_key_len > (3 * hash_len))
1822 return SILC_SKE_STATUS_ERROR;
1824 /* Take first round */
1825 memset(k1, 0, sizeof(k1));
1826 silc_hash_make(hash, buf->data, buf->len, k1);
1828 /* Take second round */
1829 dist = silc_buffer_alloc(data_len + hash_len);
1830 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1831 silc_buffer_format(dist,
1832 SILC_STR_UI_XNSTRING(data, data_len),
1833 SILC_STR_UI_XNSTRING(k1, hash_len),
1835 memset(k2, 0, sizeof(k2));
1836 silc_hash_make(hash, dist->data, dist->len, k2);
1838 /* Take third round */
1839 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1840 silc_buffer_pull_tail(dist, hash_len);
1841 silc_buffer_pull(dist, data_len + hash_len);
1842 silc_buffer_format(dist,
1843 SILC_STR_UI_XNSTRING(k2, hash_len),
1845 silc_buffer_push(dist, data_len + hash_len);
1846 memset(k3, 0, sizeof(k3));
1847 silc_hash_make(hash, dist->data, dist->len, k3);
1849 /* Then, save the keys */
1850 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1851 memcpy(dtmp, k1, hash_len);
1852 memcpy(dtmp + hash_len, k2, hash_len);
1853 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1855 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1856 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1857 key->enc_key_len = req_enc_key_len;
1859 memset(dtmp, 0, (3 * hash_len));
1860 memset(k1, 0, sizeof(k1));
1861 memset(k2, 0, sizeof(k2));
1862 memset(k3, 0, sizeof(k3));
1864 silc_buffer_free(dist);
1866 /* Take normal hash as key */
1867 memset(hashd, 0, sizeof(hashd));
1868 silc_hash_make(hash, buf->data, buf->len, hashd);
1869 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1870 memcpy(key->receive_enc_key, hashd, enc_key_len);
1871 key->enc_key_len = req_enc_key_len;
1874 /* Take HMAC keys */
1875 memset(hashd, 0, sizeof(hashd));
1877 silc_hash_make(hash, buf->data, buf->len, hashd);
1878 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1879 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1880 memset(hashd, 0, sizeof(hashd));
1882 silc_hash_make(hash, buf->data, buf->len, hashd);
1883 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1884 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1885 key->hmac_key_len = req_hmac_key_len;
1886 memset(hashd, 0, sizeof(hashd));
1888 silc_buffer_free(buf);
1890 return SILC_SKE_STATUS_OK;
1893 /* Processes negotiated key material as protocol specifies. This returns
1894 the actual keys to be used in the SILC. */
1896 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1898 uint32 req_enc_key_len,
1899 uint32 req_hmac_key_len,
1900 SilcSKEKeyMaterial *key)
1902 SilcSKEStatus status;
1904 unsigned char *tmpbuf;
1907 /* Encode KEY to binary data */
1908 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1910 buf = silc_buffer_alloc(klen + ske->hash_len);
1911 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1912 silc_buffer_format(buf,
1913 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1914 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1917 /* Process the key material */
1918 status = silc_ske_process_key_material_data(buf->data, buf->len,
1919 req_iv_len, req_enc_key_len,
1921 ske->prop->hash, key);
1923 memset(tmpbuf, 0, klen);
1925 silc_buffer_free(buf);
1930 /* Free key material structure */
1932 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1938 silc_free(key->send_iv);
1939 if (key->receive_iv)
1940 silc_free(key->receive_iv);
1941 if (key->send_enc_key) {
1942 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1943 silc_free(key->send_enc_key);
1945 if (key->receive_enc_key) {
1946 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1947 silc_free(key->receive_enc_key);
1949 if (key->send_hmac_key) {
1950 memset(key->send_hmac_key, 0, key->hmac_key_len);
1951 silc_free(key->send_hmac_key);
1953 if (key->receive_hmac_key) {
1954 memset(key->receive_hmac_key, 0, key->hmac_key_len);
1955 silc_free(key->receive_hmac_key);
1960 const char *silc_ske_status_string[] =
1964 "Unkown error occurred",
1965 "Bad payload in packet",
1966 "Unsupported group",
1967 "Unsupported cipher",
1969 "Unsupported hash function",
1971 "Unsupported public key (or certificate)",
1972 "Incorrect signature",
1973 "Bad or unsupported version",
1978 "Remote did not provide public key",
1979 "Key exchange protocol is not active",
1980 "Bad reserved field in packet",
1981 "Bad payload length in packet",
1987 /* Maps status to readable string and returns the string. If string is not
1988 found and empty character string ("") is returned. */
1990 const char *silc_ske_map_status(SilcSKEStatus status)
1994 for (i = 0; silc_ske_status_string[i]; i++)
1996 return silc_ske_status_string[i];