5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2000 - 2002 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "silcincludes.h"
23 #include "groups_internal.h"
25 /* Static functions */
26 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
29 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
30 unsigned char *return_hash,
31 SilcUInt32 *return_hash_len,
34 /* Structure to hold all SKE callbacks. */
35 struct SilcSKECallbacksStruct {
36 SilcSKESendPacketCb send_packet;
37 SilcSKECb payload_receive;
38 SilcSKEVerifyCb verify_key;
39 SilcSKECb proto_continue;
40 SilcSKECheckVersion check_version;
44 /* Allocates new SKE object. */
46 SilcSKE silc_ske_alloc(SilcRng rng, void *context)
50 SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
52 ske = silc_calloc(1, sizeof(*ske));
55 ske->status = SILC_SKE_STATUS_OK;
57 ske->user_data = context;
63 /* Free's SKE object. */
65 void silc_ske_free(SilcSKE ske)
69 SILC_LOG_DEBUG(("Key Exchange set to FREED status"));
70 ske->status = SILC_SKE_STATUS_FREED;
74 SILC_LOG_DEBUG(("Freeing Key Exchange object"));
77 /* Free start payload */
78 if (ske->start_payload)
79 silc_ske_payload_start_free(ske->start_payload);
83 silc_ske_payload_ke_free(ske->ke1_payload);
85 silc_ske_payload_ke_free(ske->ke2_payload);
86 silc_free(ske->remote_version);
91 silc_ske_group_free(ske->prop->group);
93 silc_pkcs_free(ske->prop->pkcs);
94 if (ske->prop->cipher)
95 silc_cipher_free(ske->prop->cipher);
97 silc_hash_free(ske->prop->hash);
99 silc_hmac_free(ske->prop->hmac);
100 silc_free(ske->prop);
102 if (ske->start_payload_copy)
103 silc_buffer_free(ske->start_payload_copy);
105 silc_mp_uninit(ske->x);
109 silc_mp_uninit(ske->KEY);
112 silc_free(ske->hash);
113 silc_free(ske->callbacks);
118 /* Sets the callback functions for the SKE session.
120 The `send_packet' callback is a function that sends the packet to
121 network. The SKE library will call it at any time packet needs to
122 be sent to the remote host.
124 The `payload_receive' callback is called when the remote host's Key
125 Exchange Start Payload has been processed. The payload is saved
126 to ske->start_payload if the application would need it. The application
127 must also provide the payload to the next state of the SKE.
129 The `verify_key' callback is called to verify the received public key
130 or certificate. The verification process is most likely asynchronous.
131 That is why the application must call the completion callback when the
132 verification process has been completed. The library then calls the user
133 callback (`proto_continue'), if it is provided to indicate that the SKE
134 protocol may continue.
136 The `proto_continue' callback is called to indicate that it is
137 safe to continue the execution of the SKE protocol after executing
138 an asynchronous operation, such as calling the `verify_key' callback
139 function, which is asynchronous. The application should check the
140 ske->status in this function to check whether it is Ok to continue
141 the execution of the protocol.
143 The `check_version' callback is called to verify the remote host's
144 version. The application may check its own version against the remote
145 host's version and determine whether supporting the remote host
148 The `context' is passed as argument to all of the above callback
151 void silc_ske_set_callbacks(SilcSKE ske,
152 SilcSKESendPacketCb send_packet,
153 SilcSKECb payload_receive,
154 SilcSKEVerifyCb verify_key,
155 SilcSKECb proto_continue,
156 SilcSKECheckVersion check_version,
160 silc_free(ske->callbacks);
161 ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
164 ske->callbacks->send_packet = send_packet;
165 ske->callbacks->payload_receive = payload_receive;
166 ske->callbacks->verify_key = verify_key;
167 ske->callbacks->proto_continue = proto_continue;
168 ske->callbacks->check_version = check_version;
169 ske->callbacks->context = context;
172 /* Starts the SILC Key Exchange protocol for initiator. The connection
173 to the remote end must be established before calling this function
174 and the connecting socket must be sent as argument. This function
175 creates the Key Exchange Start Payload which includes all our
176 configured security properties. This payload is then sent to the
177 remote end for further processing. This payload must be sent as
178 argument to the function, however, it must not be encoded
179 already, it is done by this function. The caller must not free
180 the `start_payload' since the SKE library will save it.
182 The packet sending is done by calling a callback function. Caller
183 must provide a routine to send the packet. */
185 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
186 SilcSocketConnection sock,
187 SilcSKEStartPayload *start_payload)
189 SilcSKEStatus status = SILC_SKE_STATUS_OK;
190 SilcBuffer payload_buf;
192 SILC_LOG_DEBUG(("Start"));
197 /* Encode the payload */
198 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
199 if (status != SILC_SKE_STATUS_OK)
202 /* Take a copy of the payload buffer for future use. It is used to
203 compute the HASH value. */
204 ske->start_payload_copy = silc_buffer_copy(payload_buf);
205 ske->start_payload = start_payload;
207 /* Send the packet. */
208 if (ske->callbacks->send_packet)
209 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
210 ske->callbacks->context);
212 silc_buffer_free(payload_buf);
217 /* Function called after ske_initiator_start fuction. This receives
218 the remote ends Key Exchange Start payload which includes the
219 security properties selected by the responder from our payload
220 sent in the silc_ske_initiator_start function. */
222 SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
223 SilcBuffer start_payload)
225 SilcSKEStatus status = SILC_SKE_STATUS_OK;
226 SilcSKEStartPayload *payload;
227 SilcSKESecurityProperties prop;
228 SilcSKEDiffieHellmanGroup group;
230 SILC_LOG_DEBUG(("Start"));
232 /* Decode the payload */
233 status = silc_ske_payload_start_decode(ske, start_payload, &payload);
234 if (status != SILC_SKE_STATUS_OK) {
235 ske->status = status;
236 silc_ske_payload_start_free(ske->start_payload);
240 /* Check that the cookie is returned unmodified */
241 if (memcmp(ske->start_payload->cookie, payload->cookie,
242 ske->start_payload->cookie_len)) {
243 SILC_LOG_ERROR(("Responder modified our cookie and it must not do it"));
244 ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
245 silc_ske_payload_start_free(ske->start_payload);
249 /* Check version string */
250 if (ske->callbacks->check_version) {
251 status = ske->callbacks->check_version(ske, payload->version,
252 payload->version_len,
253 ske->callbacks->context);
254 if (status != SILC_SKE_STATUS_OK) {
255 ske->status = status;
256 silc_ske_payload_start_free(ske->start_payload);
261 /* Free our KE Start Payload context, we don't need it anymore. */
262 silc_ske_payload_start_free(ske->start_payload);
264 /* Take the selected security properties into use while doing
265 the key exchange. This is used only while doing the key
266 exchange. The same data is returned to upper levels by calling
267 the callback function. */
268 ske->prop = prop = silc_calloc(1, sizeof(*prop));
271 prop->flags = payload->flags;
272 status = silc_ske_group_get_by_name(payload->ke_grp_list, &group);
273 if (status != SILC_SKE_STATUS_OK)
278 if (silc_pkcs_alloc(payload->pkcs_alg_list, &prop->pkcs) == FALSE) {
279 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
283 if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
284 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
288 if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
289 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
293 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
294 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
298 /* Save remote's KE Start Payload */
299 ske->start_payload = payload;
301 /* Return the received payload by calling the callback function. */
302 if (ske->callbacks->payload_receive)
303 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
309 silc_ske_payload_start_free(payload);
311 silc_ske_group_free(group);
314 silc_pkcs_free(prop->pkcs);
316 silc_cipher_free(prop->cipher);
318 silc_hash_free(prop->hash);
320 silc_hmac_free(prop->hmac);
324 if (status == SILC_SKE_STATUS_OK)
325 return SILC_SKE_STATUS_ERROR;
327 ske->status = status;
331 /* This function creates random number x, such that 1 < x < q and
332 computes e = g ^ x mod p and sends the result to the remote end in
333 Key Exchange Payload. */
335 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
336 SilcPublicKey public_key,
337 SilcPrivateKey private_key,
338 SilcSKEPKType pk_type)
340 SilcSKEStatus status = SILC_SKE_STATUS_OK;
341 SilcBuffer payload_buf;
343 SilcSKEKEPayload *payload;
346 SILC_LOG_DEBUG(("Start"));
348 /* Create the random number x, 1 < x < q. */
349 x = silc_calloc(1, sizeof(*x));
351 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
356 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
357 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
359 if (status != SILC_SKE_STATUS_OK) {
362 ske->status = status;
366 /* Encode the result to Key Exchange Payload. */
368 payload = silc_calloc(1, sizeof(*payload));
372 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
375 ske->ke1_payload = payload;
377 SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
379 /* Do the Diffie Hellman computation, e = g ^ x mod p */
380 silc_mp_init(&payload->x);
381 silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
382 &ske->prop->group->group);
386 payload->pk_data = silc_pkcs_public_key_encode(public_key, &pk_len);
387 if (!payload->pk_data) {
390 silc_mp_uninit(&payload->x);
392 ske->status = SILC_SKE_STATUS_OK;
395 payload->pk_len = pk_len;
397 payload->pk_type = pk_type;
399 /* Compute signature data if we are doing mutual authentication */
400 if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
401 unsigned char hash[32], sign[2048];
402 SilcUInt32 hash_len, sign_len;
404 SILC_LOG_DEBUG(("We are doing mutual authentication"));
405 SILC_LOG_DEBUG(("Computing HASH_i value"));
407 /* Compute the hash value */
408 memset(hash, 0, sizeof(hash));
409 silc_ske_make_hash(ske, hash, &hash_len, TRUE);
411 SILC_LOG_DEBUG(("Signing HASH_i value"));
413 /* Sign the hash value */
414 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
415 private_key->prv_len);
416 if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
417 !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
420 silc_mp_uninit(&payload->x);
421 silc_free(payload->pk_data);
423 ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
426 payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
427 memcpy(payload->sign_data, sign, sign_len);
428 memset(sign, 0, sizeof(sign));
429 payload->sign_len = sign_len;
432 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
433 if (status != SILC_SKE_STATUS_OK) {
436 silc_mp_uninit(&payload->x);
437 silc_free(payload->pk_data);
439 ske->status = status;
445 /* Send the packet. */
446 if (ske->callbacks->send_packet)
447 (*ske->callbacks->send_packet)(ske, payload_buf,
448 SILC_PACKET_KEY_EXCHANGE_1,
449 ske->callbacks->context);
451 silc_buffer_free(payload_buf);
456 /* An initiator finish final callback that is called to indicate that
457 the SKE protocol may continue. */
459 static void silc_ske_initiator_finish_final(SilcSKE ske,
460 SilcSKEStatus status,
463 SilcSKEKEPayload *payload;
464 unsigned char hash[32];
466 SilcPublicKey public_key = NULL;
468 /* If the SKE was freed during the async call then free it really now,
469 otherwise just decrement the reference counter. */
470 if (ske->status == SILC_SKE_STATUS_FREED) {
475 /* If the caller returns PENDING status SKE library will assume that
476 the caller will re-call this callback when it is not anymore in
478 if (status == SILC_SKE_STATUS_PENDING)
482 payload = ske->ke2_payload;
484 /* If the status is an error then the public key that was verified
485 by the caller is not authentic. */
486 if (status != SILC_SKE_STATUS_OK) {
487 ske->status = status;
488 if (ske->callbacks->proto_continue)
489 ske->callbacks->proto_continue(ske, ske->callbacks->context);
493 if (payload->pk_data) {
494 /* Decode the public key */
495 if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
497 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
498 SILC_LOG_ERROR(("Unsupported/malformed public key received"));
499 if (ske->callbacks->proto_continue)
500 ske->callbacks->proto_continue(ske, ske->callbacks->context);
504 SILC_LOG_DEBUG(("Public key is authentic"));
506 /* Compute the hash value */
507 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
508 if (status != SILC_SKE_STATUS_OK)
511 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
512 memcpy(ske->hash, hash, hash_len);
513 ske->hash_len = hash_len;
515 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
517 /* Verify signature */
518 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
519 if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
520 payload->sign_len, hash, hash_len) == FALSE) {
521 SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
522 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
526 SILC_LOG_DEBUG(("Signature is Ok"));
528 silc_pkcs_public_key_free(public_key);
529 memset(hash, 'F', hash_len);
532 ske->status = SILC_SKE_STATUS_OK;
534 /* Call the callback. The caller may now continue the SKE protocol. */
535 if (ske->callbacks->proto_continue)
536 ske->callbacks->proto_continue(ske, ske->callbacks->context);
541 memset(hash, 'F', sizeof(hash));
542 silc_ske_payload_ke_free(payload);
543 ske->ke2_payload = NULL;
545 silc_mp_uninit(ske->KEY);
550 silc_pkcs_public_key_free(public_key);
553 memset(ske->hash, 'F', hash_len);
554 silc_free(ske->hash);
558 if (status == SILC_SKE_STATUS_OK)
559 ske->status = SILC_SKE_STATUS_ERROR;
561 ske->status = status;
563 /* Call the callback. */
564 if (ske->callbacks->proto_continue)
565 ske->callbacks->proto_continue(ske, ske->callbacks->context);
568 /* Receives Key Exchange Payload from responder consisting responders
569 public key, f, and signature. This function verifies the public key,
570 computes the secret shared key and verifies the signature.
572 The `proto_continue' will be called to indicate that the caller may
573 continue with the SKE protocol. The caller must not continue
574 before the SKE libary has called that callback. If this function
575 returns an error the callback will not be called. It is called
576 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
577 However, note that when the library calls the callback the ske->status
580 This calls the `verify_key' callback to verify the received public
581 key or certificate. If the `verify_key' is provided then the remote
582 must send public key and it is considered to be an error if remote
583 does not send its public key. If caller is performing a re-key with
584 SKE then the `verify_key' is usually not provided when it is not also
585 required for the remote to send its public key. */
587 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
588 SilcBuffer ke_payload)
590 SilcSKEStatus status = SILC_SKE_STATUS_OK;
591 SilcSKEKEPayload *payload;
594 SILC_LOG_DEBUG(("Start"));
596 /* Decode the payload */
597 status = silc_ske_payload_ke_decode(ske, ke_payload, &payload);
598 if (status != SILC_SKE_STATUS_OK) {
599 ske->status = status;
602 ske->ke2_payload = payload;
604 if (!payload->pk_data && ske->callbacks->verify_key) {
605 SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
606 "even though we require it"));
607 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
611 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
613 /* Compute the shared secret key */
614 KEY = silc_calloc(1, sizeof(*KEY));
616 silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
619 if (payload->pk_data && ske->callbacks->verify_key) {
620 SILC_LOG_DEBUG(("Verifying public key"));
623 (*ske->callbacks->verify_key)(ske, payload->pk_data, payload->pk_len,
624 payload->pk_type, ske->callbacks->context,
625 silc_ske_initiator_finish_final, NULL);
627 /* We will continue to the final state after the public key has
628 been verified by the caller. */
629 return SILC_SKE_STATUS_PENDING;
632 /* Continue to final state */
634 silc_ske_initiator_finish_final(ske, SILC_SKE_STATUS_OK, NULL);
636 return SILC_SKE_STATUS_OK;
639 silc_ske_payload_ke_free(payload);
640 ske->ke2_payload = NULL;
642 silc_mp_uninit(ske->KEY);
646 if (status == SILC_SKE_STATUS_OK)
647 return SILC_SKE_STATUS_ERROR;
649 ske->status = status;
653 /* Starts Key Exchange protocol for responder. Responder receives
654 Key Exchange Start Payload from initiator consisting of all the
655 security properties the initiator supports. This function decodes
656 the payload and parses the payload further and selects the right
657 security properties. */
659 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
660 SilcSocketConnection sock,
662 SilcBuffer start_payload,
663 SilcSKESecurityPropertyFlag flags)
665 SilcSKEStatus status = SILC_SKE_STATUS_OK;
666 SilcSKEStartPayload *remote_payload = NULL, *payload = NULL;
668 SILC_LOG_DEBUG(("Start"));
673 /* Decode the payload */
674 status = silc_ske_payload_start_decode(ske, start_payload, &remote_payload);
675 if (status != SILC_SKE_STATUS_OK) {
676 ske->status = status;
680 /* Take a copy of the payload buffer for future use. It is used to
681 compute the HASH value. */
682 ske->start_payload_copy = silc_buffer_copy(start_payload);
684 /* Force the mutual authentication flag if we want to do it. */
685 if (flags & SILC_SKE_SP_FLAG_MUTUAL) {
686 SILC_LOG_DEBUG(("Force mutual authentication"));
687 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
690 /* Force PFS flag if we require it */
691 if (flags & SILC_SKE_SP_FLAG_PFS) {
692 SILC_LOG_DEBUG(("Force PFS"));
693 remote_payload->flags |= SILC_SKE_SP_FLAG_PFS;
696 /* Parse and select the security properties from the payload */
697 payload = silc_calloc(1, sizeof(*payload));
698 status = silc_ske_select_security_properties(ske, version,
699 payload, remote_payload);
700 if (status != SILC_SKE_STATUS_OK)
703 ske->start_payload = payload;
705 /* Call the callback function. */
706 if (ske->callbacks->payload_receive)
707 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
709 silc_ske_payload_start_free(remote_payload);
715 silc_ske_payload_start_free(remote_payload);
719 if (status == SILC_SKE_STATUS_OK)
720 return SILC_SKE_STATUS_ERROR;
722 ske->status = status;
726 /* The selected security properties from the initiator payload is now
727 encoded into Key Exchange Start Payload and sent to the initiator. */
729 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske)
731 SilcSKEStatus status = SILC_SKE_STATUS_OK;
732 SilcBuffer payload_buf;
733 SilcSKESecurityProperties prop;
734 SilcSKEDiffieHellmanGroup group = NULL;
736 SILC_LOG_DEBUG(("Start"));
738 /* Allocate security properties from the payload. These are allocated
739 only for this negotiation and will be free'd after KE is over. */
740 ske->prop = prop = silc_calloc(1, sizeof(*prop));
741 prop->flags = ske->start_payload->flags;
742 status = silc_ske_group_get_by_name(ske->start_payload->ke_grp_list, &group);
743 if (status != SILC_SKE_STATUS_OK)
748 if (silc_pkcs_alloc(ske->start_payload->pkcs_alg_list,
749 &prop->pkcs) == FALSE) {
750 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
754 if (silc_cipher_alloc(ske->start_payload->enc_alg_list,
755 &prop->cipher) == FALSE) {
756 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
760 if (silc_hash_alloc(ske->start_payload->hash_alg_list,
761 &prop->hash) == FALSE) {
762 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
766 if (silc_hmac_alloc(ske->start_payload->hmac_alg_list, NULL,
767 &prop->hmac) == FALSE) {
768 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
772 /* Encode the payload */
773 status = silc_ske_payload_start_encode(ske, ske->start_payload,
775 if (status != SILC_SKE_STATUS_OK)
778 /* Send the packet. */
779 if (ske->callbacks->send_packet)
780 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
781 ske->callbacks->context);
783 silc_buffer_free(payload_buf);
789 silc_ske_group_free(group);
792 silc_pkcs_free(prop->pkcs);
794 silc_cipher_free(prop->cipher);
796 silc_hash_free(prop->hash);
798 silc_hmac_free(prop->hmac);
802 if (status == SILC_SKE_STATUS_OK)
803 return SILC_SKE_STATUS_ERROR;
805 ske->status = status;
809 /* An responder phase 2 final callback that is called to indicate that
810 the SKE protocol may continue. */
812 static void silc_ske_responder_phase2_final(SilcSKE ske,
813 SilcSKEStatus status,
816 SilcSKEKEPayload *recv_payload, *send_payload;
819 /* If the SKE was freed during the async call then free it really now,
820 otherwise just decrement the reference counter. */
821 if (ske->status == SILC_SKE_STATUS_FREED) {
826 /* If the caller returns PENDING status SKE library will assume that
827 the caller will re-call this callback when it is not anymore in
829 if (status == SILC_SKE_STATUS_PENDING)
833 recv_payload = ske->ke1_payload;
835 /* If the status is an error then the public key that was verified
836 by the caller is not authentic. */
837 if (status != SILC_SKE_STATUS_OK) {
838 ske->status = status;
839 if (ske->callbacks->proto_continue)
840 ske->callbacks->proto_continue(ske, ske->callbacks->context);
844 /* The public key verification was performed only if the Mutual
845 Authentication flag is set. */
846 if (ske->start_payload &&
847 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
848 SilcPublicKey public_key = NULL;
849 unsigned char hash[32];
852 /* Decode the public key */
853 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
854 recv_payload->pk_len,
856 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
857 SILC_LOG_ERROR(("Unsupported/malformed public key received"));
858 if (ske->callbacks->proto_continue)
859 ske->callbacks->proto_continue(ske, ske->callbacks->context);
863 SILC_LOG_DEBUG(("Public key is authentic"));
865 /* Compute the hash value */
866 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
867 if (status != SILC_SKE_STATUS_OK) {
868 ske->status = status;
869 if (ske->callbacks->proto_continue)
870 ske->callbacks->proto_continue(ske, ske->callbacks->context);
874 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
876 /* Verify signature */
877 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
878 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
879 recv_payload->sign_len, hash, hash_len) == FALSE) {
880 SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
881 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
882 if (ske->callbacks->proto_continue)
883 ske->callbacks->proto_continue(ske, ske->callbacks->context);
887 SILC_LOG_DEBUG(("Signature is Ok"));
889 silc_pkcs_public_key_free(public_key);
890 memset(hash, 'F', hash_len);
893 /* Create the random number x, 1 < x < q. */
894 x = silc_calloc(1, sizeof(*x));
897 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
898 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
900 if (status != SILC_SKE_STATUS_OK) {
903 ske->status = status;
904 if (ske->callbacks->proto_continue)
905 ske->callbacks->proto_continue(ske, ske->callbacks->context);
909 /* Save the results for later processing */
910 send_payload = silc_calloc(1, sizeof(*send_payload));
912 ske->ke2_payload = send_payload;
914 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
916 /* Do the Diffie Hellman computation, f = g ^ x mod p */
917 silc_mp_init(&send_payload->x);
918 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
919 &ske->prop->group->group);
921 /* Call the callback. The caller may now continue with the SKE protocol. */
922 ske->status = SILC_SKE_STATUS_OK;
923 if (ske->callbacks->proto_continue)
924 ske->callbacks->proto_continue(ske, ske->callbacks->context);
927 /* This function receives the Key Exchange Payload from the initiator.
928 This also performs the mutual authentication if required. Then, this
929 function first generated a random number x, such that 1 < x < q
930 and computes f = g ^ x mod p. This then puts the result f to a Key
933 The `proto_continue' will be called to indicate that the caller may
934 continue with the SKE protocol. The caller must not continue
935 before the SKE libary has called that callback. If this function
936 returns an error the callback will not be called. It is called
937 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
938 However, note that when the library calls the callback the ske->status
941 This calls the `verify_key' callback to verify the received public
942 key or certificate if the Mutual Authentication flag is set. If the
943 `verify_key' is provided then the remote must send public key and it
944 is considered to be an error if remote does not send its public key. */
946 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
947 SilcBuffer ke_payload)
949 SilcSKEStatus status = SILC_SKE_STATUS_OK;
950 SilcSKEKEPayload *recv_payload;
952 SILC_LOG_DEBUG(("Start"));
954 /* Decode Key Exchange Payload */
955 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
956 if (status != SILC_SKE_STATUS_OK) {
957 ske->status = status;
961 ske->ke1_payload = recv_payload;
963 /* Verify the received public key and verify the signature if we are
964 doing mutual authentication. */
965 if (ske->start_payload &&
966 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
968 SILC_LOG_DEBUG(("We are doing mutual authentication"));
970 if (!recv_payload->pk_data && ske->callbacks->verify_key) {
971 SILC_LOG_ERROR(("Remote end did not send its public key (or "
972 "certificate), even though we require it"));
973 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
977 if (recv_payload->pk_data && ske->callbacks->verify_key) {
978 SILC_LOG_DEBUG(("Verifying public key"));
981 (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
982 recv_payload->pk_len,
983 recv_payload->pk_type,
984 ske->callbacks->context,
985 silc_ske_responder_phase2_final, NULL);
987 /* We will continue to the final state after the public key has
988 been verified by the caller. */
989 return SILC_SKE_STATUS_PENDING;
993 /* Continue to final state */
995 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
997 return SILC_SKE_STATUS_OK;
1000 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
1001 value to be signed and sent to the other end. This then encodes Key
1002 Exchange Payload and sends it to the other end. */
1004 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
1005 SilcPublicKey public_key,
1006 SilcPrivateKey private_key,
1007 SilcSKEPKType pk_type)
1009 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1010 SilcBuffer payload_buf;
1012 unsigned char hash[32], sign[2048], *pk;
1013 SilcUInt32 hash_len, sign_len, pk_len;
1015 SILC_LOG_DEBUG(("Start"));
1017 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
1019 /* Compute the shared secret key */
1020 KEY = silc_calloc(1, sizeof(*KEY));
1022 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
1023 &ske->prop->group->group);
1026 if (public_key && private_key) {
1027 SILC_LOG_DEBUG(("Getting public key"));
1029 /* Get the public key */
1030 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
1032 status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1035 ske->ke2_payload->pk_data = pk;
1036 ske->ke2_payload->pk_len = pk_len;
1038 SILC_LOG_DEBUG(("Computing HASH value"));
1040 /* Compute the hash value */
1041 memset(hash, 0, sizeof(hash));
1042 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1043 if (status != SILC_SKE_STATUS_OK)
1046 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
1047 memcpy(ske->hash, hash, hash_len);
1048 ske->hash_len = hash_len;
1050 SILC_LOG_DEBUG(("Signing HASH value"));
1052 /* Sign the hash value */
1053 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
1054 private_key->prv_len);
1055 if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
1056 !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
1057 status = SILC_SKE_STATUS_SIGNATURE_ERROR;
1060 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
1061 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
1062 memset(sign, 0, sizeof(sign));
1063 ske->ke2_payload->sign_len = sign_len;
1065 ske->ke2_payload->pk_type = pk_type;
1067 /* Encode the Key Exchange Payload */
1068 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
1070 if (status != SILC_SKE_STATUS_OK)
1073 /* Send the packet. */
1074 if (ske->callbacks->send_packet)
1075 (*ske->callbacks->send_packet)(ske, payload_buf,
1076 SILC_PACKET_KEY_EXCHANGE_2,
1077 ske->callbacks->context);
1079 silc_buffer_free(payload_buf);
1084 silc_mp_uninit(ske->KEY);
1085 silc_free(ske->KEY);
1087 silc_ske_payload_ke_free(ske->ke2_payload);
1089 if (status == SILC_SKE_STATUS_OK)
1090 return SILC_SKE_STATUS_ERROR;
1092 ske->status = status;
1096 /* The Key Exchange protocol is ended by calling this function. This
1097 must not be called until the keys are processed like the protocol
1098 defines. This function is for both initiator and responder. */
1100 SilcSKEStatus silc_ske_end(SilcSKE ske)
1104 SILC_LOG_DEBUG(("Start"));
1106 packet = silc_buffer_alloc_size(4);
1108 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1109 silc_buffer_format(packet,
1110 SILC_STR_UI_INT((SilcUInt32)SILC_SKE_STATUS_OK),
1113 if (ske->callbacks->send_packet)
1114 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS,
1115 ske->callbacks->context);
1117 silc_buffer_free(packet);
1119 return SILC_SKE_STATUS_OK;
1122 /* Aborts the Key Exchange protocol. This is called if error occurs
1123 while performing the protocol. The status argument is the error
1124 status and it is sent to the remote end. */
1126 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
1130 SILC_LOG_DEBUG(("Start"));
1132 if (status > SILC_SKE_STATUS_INVALID_COOKIE)
1133 status = SILC_SKE_STATUS_BAD_PAYLOAD;
1135 packet = silc_buffer_alloc_size(4);
1137 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1138 silc_buffer_format(packet,
1139 SILC_STR_UI_INT((SilcUInt32)status),
1142 if (ske->callbacks->send_packet)
1143 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
1144 ske->callbacks->context);
1146 silc_buffer_free(packet);
1148 return SILC_SKE_STATUS_OK;
1151 /* Assembles security properties to Key Exchange Start Payload to be
1152 sent to the remote end. This checks system wide (SILC system, that is)
1153 settings and chooses from those. However, if other properties
1154 should be used this function is easy to replace by another function,
1155 as, this function is called by the caller of the protocol and not
1156 by the protocol itself. */
1159 silc_ske_assemble_security_properties(SilcSKE ske,
1160 SilcSKESecurityPropertyFlag flags,
1161 const char *version,
1162 SilcSKEStartPayload **return_payload)
1164 SilcSKEStartPayload *rp;
1167 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1169 rp = silc_calloc(1, sizeof(*rp));
1172 rp->flags = (unsigned char)flags;
1174 /* Set random cookie */
1175 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1176 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1177 rp->cookie[i] = silc_rng_get_byte(ske->rng);
1178 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1181 rp->version = strdup(version);
1182 rp->version_len = strlen(version);
1184 /* Get supported Key Exhange groups */
1185 rp->ke_grp_list = silc_ske_get_supported_groups();
1186 rp->ke_grp_len = strlen(rp->ke_grp_list);
1188 /* Get supported PKCS algorithms */
1189 rp->pkcs_alg_list = silc_pkcs_get_supported();
1190 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1192 /* Get supported encryption algorithms */
1193 rp->enc_alg_list = silc_cipher_get_supported();
1194 rp->enc_alg_len = strlen(rp->enc_alg_list);
1196 /* Get supported hash algorithms */
1197 rp->hash_alg_list = silc_hash_get_supported();
1198 rp->hash_alg_len = strlen(rp->hash_alg_list);
1200 /* Get supported HMACs */
1201 rp->hmac_alg_list = silc_hmac_get_supported();
1202 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1205 /* Get supported compression algorithms */
1206 rp->comp_alg_list = strdup("");
1207 rp->comp_alg_len = 0;
1209 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1210 2 + rp->version_len +
1211 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1212 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1213 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1215 *return_payload = rp;
1217 return SILC_SKE_STATUS_OK;
1220 /* Selects the supported security properties from the remote end's Key
1221 Exchange Start Payload. */
1224 silc_ske_select_security_properties(SilcSKE ske,
1225 const char *version,
1226 SilcSKEStartPayload *payload,
1227 SilcSKEStartPayload *remote_payload)
1229 SilcSKEStatus status;
1230 SilcSKEStartPayload *rp;
1234 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1236 rp = remote_payload;
1238 /* Check version string */
1239 if (ske->callbacks->check_version) {
1240 status = ske->callbacks->check_version(ske, rp->version,
1242 ske->callbacks->context);
1243 if (status != SILC_SKE_STATUS_OK) {
1244 ske->status = status;
1249 ske->remote_version = silc_memdup(rp->version, rp->version_len);
1251 /* Flags are returned unchanged. */
1252 payload->flags = rp->flags;
1254 /* Take cookie, we must return it to sender unmodified. */
1255 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1256 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1257 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1259 /* Put our version to our reply */
1260 payload->version = strdup(version);
1261 payload->version_len = strlen(version);
1263 /* Get supported Key Exchange groups */
1264 cp = rp->ke_grp_list;
1265 if (cp && strchr(cp, ',')) {
1269 len = strcspn(cp, ",");
1270 item = silc_calloc(len + 1, sizeof(char));
1271 memcpy(item, cp, len);
1273 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1275 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1276 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1278 payload->ke_grp_len = len;
1279 payload->ke_grp_list = item;
1284 if (strlen(cp) == 0)
1293 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1294 SILC_LOG_DEBUG(("Could not find supported KE group"));
1296 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1300 if (!rp->ke_grp_len) {
1301 SILC_LOG_DEBUG(("KE group not defined in payload"));
1303 return SILC_SKE_STATUS_BAD_PAYLOAD;
1306 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1307 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1309 payload->ke_grp_len = rp->ke_grp_len;
1310 payload->ke_grp_list = strdup(rp->ke_grp_list);
1313 /* Get supported PKCS algorithms */
1314 cp = rp->pkcs_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 PKCS alg `%s'", item));
1325 if (silc_pkcs_is_supported(item) == TRUE) {
1326 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1328 payload->pkcs_alg_len = len;
1329 payload->pkcs_alg_list = item;
1334 if (strlen(cp) == 0)
1343 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1344 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1345 silc_free(payload->ke_grp_list);
1347 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1351 if (!rp->pkcs_alg_len) {
1352 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1353 silc_free(payload->ke_grp_list);
1355 return SILC_SKE_STATUS_BAD_PAYLOAD;
1358 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1359 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1361 payload->pkcs_alg_len = rp->pkcs_alg_len;
1362 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1365 /* Get supported encryption algorithms */
1366 cp = rp->enc_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 encryption alg `%s'", item));
1377 if (silc_cipher_is_supported(item) == TRUE) {
1378 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1380 payload->enc_alg_len = len;
1381 payload->enc_alg_list = item;
1386 if (strlen(cp) == 0)
1395 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1396 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1397 silc_free(payload->ke_grp_list);
1398 silc_free(payload->pkcs_alg_list);
1400 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1404 if (!rp->enc_alg_len) {
1405 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1406 silc_free(payload->ke_grp_list);
1407 silc_free(payload->pkcs_alg_list);
1409 return SILC_SKE_STATUS_BAD_PAYLOAD;
1412 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1415 payload->enc_alg_len = rp->enc_alg_len;
1416 payload->enc_alg_list = strdup(rp->enc_alg_list);
1419 /* Get supported hash algorithms */
1420 cp = rp->hash_alg_list;
1421 if (cp && strchr(cp, ',')) {
1425 len = strcspn(cp, ",");
1426 item = silc_calloc(len + 1, sizeof(char));
1427 memcpy(item, cp, len);
1429 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1431 if (silc_hash_is_supported(item) == TRUE) {
1432 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1434 payload->hash_alg_len = len;
1435 payload->hash_alg_list = item;
1440 if (strlen(cp) == 0)
1449 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1450 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1451 silc_free(payload->ke_grp_list);
1452 silc_free(payload->pkcs_alg_list);
1453 silc_free(payload->enc_alg_list);
1455 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1459 if (!rp->hash_alg_len) {
1460 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1461 silc_free(payload->ke_grp_list);
1462 silc_free(payload->pkcs_alg_list);
1463 silc_free(payload->enc_alg_list);
1465 return SILC_SKE_STATUS_BAD_PAYLOAD;
1468 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1469 rp->hash_alg_list));
1471 payload->hash_alg_len = rp->hash_alg_len;
1472 payload->hash_alg_list = strdup(rp->hash_alg_list);
1475 /* Get supported HMACs */
1476 cp = rp->hmac_alg_list;
1477 if (cp && strchr(cp, ',')) {
1481 len = strcspn(cp, ",");
1482 item = silc_calloc(len + 1, sizeof(char));
1483 memcpy(item, cp, len);
1485 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1487 if (silc_hmac_is_supported(item) == TRUE) {
1488 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1490 payload->hmac_alg_len = len;
1491 payload->hmac_alg_list = item;
1496 if (strlen(cp) == 0)
1505 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1506 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1507 silc_free(payload->ke_grp_list);
1508 silc_free(payload->pkcs_alg_list);
1509 silc_free(payload->enc_alg_list);
1510 silc_free(payload->hash_alg_list);
1512 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1516 if (!rp->hmac_alg_len) {
1517 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1518 silc_free(payload->ke_grp_list);
1519 silc_free(payload->pkcs_alg_list);
1520 silc_free(payload->enc_alg_list);
1521 silc_free(payload->hash_alg_list);
1523 return SILC_SKE_STATUS_BAD_PAYLOAD;
1526 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1527 rp->hmac_alg_list));
1529 payload->hmac_alg_len = rp->hmac_alg_len;
1530 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1534 /* Get supported compression algorithms */
1535 cp = rp->hash_alg_list;
1536 if (cp && strchr(cp, ',')) {
1540 len = strcspn(cp, ",");
1541 item = silc_calloc(len + 1, sizeof(char));
1542 memcpy(item, cp, len);
1544 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1546 if (silc_hash_is_supported(item) == TRUE) {
1547 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1549 payload->hash_alg_len = len;
1550 payload->hash_alg_list = item;
1555 if (strlen(cp) == 0)
1564 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1565 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1566 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1567 silc_free(payload->ke_grp_list);
1568 silc_free(payload->pkcs_alg_list);
1569 silc_free(payload->enc_alg_list);
1578 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1579 2 + payload->version_len +
1580 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1581 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1582 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1584 return SILC_SKE_STATUS_OK;
1587 /* Creates random number such that 1 < rnd < n and at most length
1588 of len bits. The rnd sent as argument must be initialized. */
1590 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1594 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1595 unsigned char *string;
1597 SILC_LOG_DEBUG(("Creating random number"));
1599 /* Get the random number as string */
1600 string = silc_rng_get_rn_data(ske->rng, (len / 8));
1602 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1604 /* Decode the string into a MP integer */
1605 silc_mp_bin2mp(string, (len / 8), rnd);
1606 silc_mp_mod_2exp(rnd, rnd, len);
1609 if (silc_mp_cmp_ui(rnd, 1) < 0)
1610 status = SILC_SKE_STATUS_ERROR;
1612 if (silc_mp_cmp(rnd, n) >= 0)
1613 status = SILC_SKE_STATUS_ERROR;
1615 memset(string, 'F', (len / 8));
1621 /* Creates a hash value HASH as defined in the SKE protocol. If the
1622 `initiator' is TRUE then this function is used to create the HASH_i
1623 hash value defined in the protocol. If it is FALSE then this is used
1624 to create the HASH value defined by the protocol. */
1626 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1627 unsigned char *return_hash,
1628 SilcUInt32 *return_hash_len,
1631 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1633 unsigned char *e, *f, *KEY;
1634 SilcUInt32 e_len, f_len, KEY_len;
1637 SILC_LOG_DEBUG(("Start"));
1639 if (initiator == FALSE) {
1640 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1641 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1642 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1644 /* Format the buffer used to compute the hash value */
1645 buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
1646 ske->ke2_payload->pk_len +
1647 ske->ke1_payload->pk_len +
1648 e_len + f_len + KEY_len);
1650 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1652 /* Initiator is not required to send its public key */
1653 if (!ske->ke1_payload->pk_data) {
1655 silc_buffer_format(buf,
1656 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1658 ske->start_payload_copy->
1660 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1661 ske->ke2_payload->pk_len),
1662 SILC_STR_UI_XNSTRING(e, e_len),
1663 SILC_STR_UI_XNSTRING(f, f_len),
1664 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1668 silc_buffer_format(buf,
1669 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1671 ske->start_payload_copy->
1673 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1674 ske->ke2_payload->pk_len),
1675 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1676 ske->ke1_payload->pk_len),
1677 SILC_STR_UI_XNSTRING(e, e_len),
1678 SILC_STR_UI_XNSTRING(f, f_len),
1679 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1683 silc_buffer_free(buf);
1684 memset(e, 0, e_len);
1685 memset(f, 0, f_len);
1686 memset(KEY, 0, KEY_len);
1690 return SILC_SKE_STATUS_ERROR;
1693 memset(e, 0, e_len);
1694 memset(f, 0, f_len);
1695 memset(KEY, 0, KEY_len);
1700 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1702 buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
1703 ske->ke1_payload->pk_len + e_len);
1705 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1707 /* Format the buffer used to compute the hash value */
1709 silc_buffer_format(buf,
1710 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1711 ske->start_payload_copy->len),
1712 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1713 ske->ke1_payload->pk_len),
1714 SILC_STR_UI_XNSTRING(e, e_len),
1717 silc_buffer_free(buf);
1718 memset(e, 0, e_len);
1720 return SILC_SKE_STATUS_ERROR;
1723 memset(e, 0, e_len);
1728 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1729 *return_hash_len = silc_hash_len(ske->prop->hash);
1731 if (initiator == FALSE) {
1732 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1734 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1737 silc_buffer_free(buf);
1742 /* Processes the provided key material `data' as the SILC protocol
1743 specification defines. */
1746 silc_ske_process_key_material_data(unsigned char *data,
1747 SilcUInt32 data_len,
1748 SilcUInt32 req_iv_len,
1749 SilcUInt32 req_enc_key_len,
1750 SilcUInt32 req_hmac_key_len,
1752 SilcSKEKeyMaterial *key)
1755 unsigned char hashd[32];
1756 SilcUInt32 hash_len = req_hmac_key_len;
1757 SilcUInt32 enc_key_len = req_enc_key_len / 8;
1759 SILC_LOG_DEBUG(("Start"));
1761 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1762 return SILC_SKE_STATUS_ERROR;
1764 buf = silc_buffer_alloc_size(1 + data_len);
1766 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1767 silc_buffer_format(buf,
1768 SILC_STR_UI_CHAR(0),
1769 SILC_STR_UI_XNSTRING(data, data_len),
1773 memset(hashd, 0, sizeof(hashd));
1775 silc_hash_make(hash, buf->data, buf->len, hashd);
1776 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1777 memcpy(key->send_iv, hashd, req_iv_len);
1778 memset(hashd, 0, sizeof(hashd));
1780 silc_hash_make(hash, buf->data, buf->len, hashd);
1781 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1782 memcpy(key->receive_iv, hashd, req_iv_len);
1783 key->iv_len = req_iv_len;
1785 /* Take the encryption keys. If requested key size is more than
1786 the size of hash length we will distribute more key material
1787 as protocol defines. */
1789 if (enc_key_len > hash_len) {
1791 unsigned char k1[32], k2[32], k3[32];
1792 unsigned char *dtmp;
1795 if (enc_key_len > (3 * hash_len))
1796 return SILC_SKE_STATUS_ERROR;
1798 /* Take first round */
1799 memset(k1, 0, sizeof(k1));
1800 silc_hash_make(hash, buf->data, buf->len, k1);
1802 /* Take second round */
1803 dist = silc_buffer_alloc_size(data_len + hash_len);
1805 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1806 silc_buffer_format(dist,
1807 SILC_STR_UI_XNSTRING(data, data_len),
1808 SILC_STR_UI_XNSTRING(k1, hash_len),
1810 memset(k2, 0, sizeof(k2));
1811 silc_hash_make(hash, dist->data, dist->len, k2);
1813 /* Take third round */
1814 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1815 silc_buffer_pull_tail(dist, hash_len);
1816 silc_buffer_pull(dist, data_len + hash_len);
1817 silc_buffer_format(dist,
1818 SILC_STR_UI_XNSTRING(k2, hash_len),
1820 silc_buffer_push(dist, data_len + hash_len);
1821 memset(k3, 0, sizeof(k3));
1822 silc_hash_make(hash, dist->data, dist->len, k3);
1824 /* Then, save the keys */
1825 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1826 memcpy(dtmp, k1, hash_len);
1827 memcpy(dtmp + hash_len, k2, hash_len);
1828 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1830 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1831 memcpy(key->send_enc_key, dtmp, enc_key_len);
1832 key->enc_key_len = req_enc_key_len;
1834 memset(dtmp, 0, (3 * hash_len));
1835 memset(k1, 0, sizeof(k1));
1836 memset(k2, 0, sizeof(k2));
1837 memset(k3, 0, sizeof(k3));
1839 silc_buffer_clear(dist);
1840 silc_buffer_free(dist);
1842 /* Take normal hash as key */
1843 memset(hashd, 0, sizeof(hashd));
1844 silc_hash_make(hash, buf->data, buf->len, hashd);
1845 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1846 memcpy(key->send_enc_key, hashd, enc_key_len);
1847 key->enc_key_len = req_enc_key_len;
1851 if (enc_key_len > hash_len) {
1853 unsigned char k1[32], k2[32], k3[32];
1854 unsigned char *dtmp;
1857 if (enc_key_len > (3 * hash_len))
1858 return SILC_SKE_STATUS_ERROR;
1860 /* Take first round */
1861 memset(k1, 0, sizeof(k1));
1862 silc_hash_make(hash, buf->data, buf->len, k1);
1864 /* Take second round */
1865 dist = silc_buffer_alloc_size(data_len + hash_len);
1867 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1868 silc_buffer_format(dist,
1869 SILC_STR_UI_XNSTRING(data, data_len),
1870 SILC_STR_UI_XNSTRING(k1, hash_len),
1872 memset(k2, 0, sizeof(k2));
1873 silc_hash_make(hash, dist->data, dist->len, k2);
1875 /* Take third round */
1876 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1877 silc_buffer_pull_tail(dist, hash_len);
1878 silc_buffer_pull(dist, data_len + hash_len);
1879 silc_buffer_format(dist,
1880 SILC_STR_UI_XNSTRING(k2, hash_len),
1882 silc_buffer_push(dist, data_len + hash_len);
1883 memset(k3, 0, sizeof(k3));
1884 silc_hash_make(hash, dist->data, dist->len, k3);
1886 /* Then, save the keys */
1887 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1888 memcpy(dtmp, k1, hash_len);
1889 memcpy(dtmp + hash_len, k2, hash_len);
1890 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1892 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1893 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1894 key->enc_key_len = req_enc_key_len;
1896 memset(dtmp, 0, (3 * hash_len));
1897 memset(k1, 0, sizeof(k1));
1898 memset(k2, 0, sizeof(k2));
1899 memset(k3, 0, sizeof(k3));
1901 silc_buffer_clear(dist);
1902 silc_buffer_free(dist);
1904 /* Take normal hash as key */
1905 memset(hashd, 0, sizeof(hashd));
1906 silc_hash_make(hash, buf->data, buf->len, hashd);
1907 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1908 memcpy(key->receive_enc_key, hashd, enc_key_len);
1909 key->enc_key_len = req_enc_key_len;
1912 /* Take HMAC keys */
1913 memset(hashd, 0, sizeof(hashd));
1915 silc_hash_make(hash, buf->data, buf->len, hashd);
1916 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1917 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1918 memset(hashd, 0, sizeof(hashd));
1920 silc_hash_make(hash, buf->data, buf->len, hashd);
1921 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1922 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1923 key->hmac_key_len = req_hmac_key_len;
1924 memset(hashd, 0, sizeof(hashd));
1926 silc_buffer_clear(buf);
1927 silc_buffer_free(buf);
1929 return SILC_SKE_STATUS_OK;
1932 /* Processes negotiated key material as protocol specifies. This returns
1933 the actual keys to be used in the SILC. */
1935 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1936 SilcUInt32 req_iv_len,
1937 SilcUInt32 req_enc_key_len,
1938 SilcUInt32 req_hmac_key_len,
1939 SilcSKEKeyMaterial *key)
1941 SilcSKEStatus status;
1943 unsigned char *tmpbuf;
1946 /* Encode KEY to binary data */
1947 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1949 buf = silc_buffer_alloc_size(klen + ske->hash_len);
1951 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1952 silc_buffer_format(buf,
1953 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1954 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1957 /* Process the key material */
1958 status = silc_ske_process_key_material_data(buf->data, buf->len,
1959 req_iv_len, req_enc_key_len,
1961 ske->prop->hash, key);
1963 memset(tmpbuf, 0, klen);
1965 silc_buffer_clear(buf);
1966 silc_buffer_free(buf);
1971 /* Free key material structure */
1973 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1979 silc_free(key->send_iv);
1980 if (key->receive_iv)
1981 silc_free(key->receive_iv);
1982 if (key->send_enc_key) {
1983 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1984 silc_free(key->send_enc_key);
1986 if (key->receive_enc_key) {
1987 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1988 silc_free(key->receive_enc_key);
1990 if (key->send_hmac_key) {
1991 memset(key->send_hmac_key, 0, key->hmac_key_len);
1992 silc_free(key->send_hmac_key);
1994 if (key->receive_hmac_key) {
1995 memset(key->receive_hmac_key, 0, key->hmac_key_len);
1996 silc_free(key->receive_hmac_key);
2001 const char *silc_ske_status_string[] =
2005 "Unkown error occurred",
2006 "Bad payload in packet",
2007 "Unsupported group",
2008 "Unsupported cipher",
2010 "Unsupported hash function",
2012 "Unsupported public key (or certificate)",
2013 "Incorrect signature",
2014 "Bad or unsupported version",
2019 "Remote did not provide public key",
2020 "Key exchange protocol is not active",
2021 "Bad reserved field in packet",
2022 "Bad payload length in packet",
2023 "Error computing signature",
2024 "System out of memory",
2029 /* Maps status to readable string and returns the string. If string is not
2030 found and empty character string ("") is returned. */
2032 const char *silc_ske_map_status(SilcSKEStatus status)
2036 for (i = 0; silc_ske_status_string[i]; i++)
2038 return silc_ske_status_string[i];
2043 /* Parses remote host's version string. */
2045 bool silc_ske_parse_version(SilcSKE ske,
2046 SilcUInt32 *protocol_version,
2047 char **protocol_version_string,
2048 SilcUInt32 *software_version,
2049 char **software_version_string,
2050 char **vendor_version)
2052 return silc_parse_version_string(ske->remote_version,
2054 protocol_version_string,
2056 software_version_string,