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 if (ske->callbacks->proto_continue)
499 ske->callbacks->proto_continue(ske, ske->callbacks->context);
503 SILC_LOG_DEBUG(("Public key is authentic"));
505 /* Compute the hash value */
506 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
507 if (status != SILC_SKE_STATUS_OK)
510 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
511 memcpy(ske->hash, hash, hash_len);
512 ske->hash_len = hash_len;
514 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
516 /* Verify signature */
517 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
518 if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
519 payload->sign_len, hash, hash_len) == FALSE) {
521 SILC_LOG_DEBUG(("Signature don't match"));
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 if (ske->callbacks->proto_continue)
858 ske->callbacks->proto_continue(ske, ske->callbacks->context);
862 SILC_LOG_DEBUG(("Public key is authentic"));
864 /* Compute the hash value */
865 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
866 if (status != SILC_SKE_STATUS_OK) {
867 ske->status = status;
868 if (ske->callbacks->proto_continue)
869 ske->callbacks->proto_continue(ske, ske->callbacks->context);
873 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
875 /* Verify signature */
876 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
877 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
878 recv_payload->sign_len, hash, hash_len) == FALSE) {
880 SILC_LOG_DEBUG(("Signature don't match"));
882 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
883 if (ske->callbacks->proto_continue)
884 ske->callbacks->proto_continue(ske, ske->callbacks->context);
888 SILC_LOG_DEBUG(("Signature is Ok"));
890 silc_pkcs_public_key_free(public_key);
891 memset(hash, 'F', hash_len);
894 /* Create the random number x, 1 < x < q. */
895 x = silc_calloc(1, sizeof(*x));
898 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
899 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
901 if (status != SILC_SKE_STATUS_OK) {
904 ske->status = status;
905 if (ske->callbacks->proto_continue)
906 ske->callbacks->proto_continue(ske, ske->callbacks->context);
910 /* Save the results for later processing */
911 send_payload = silc_calloc(1, sizeof(*send_payload));
913 ske->ke2_payload = send_payload;
915 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
917 /* Do the Diffie Hellman computation, f = g ^ x mod p */
918 silc_mp_init(&send_payload->x);
919 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
920 &ske->prop->group->group);
922 /* Call the callback. The caller may now continue with the SKE protocol. */
923 ske->status = SILC_SKE_STATUS_OK;
924 if (ske->callbacks->proto_continue)
925 ske->callbacks->proto_continue(ske, ske->callbacks->context);
928 /* This function receives the Key Exchange Payload from the initiator.
929 This also performs the mutual authentication if required. Then, this
930 function first generated a random number x, such that 1 < x < q
931 and computes f = g ^ x mod p. This then puts the result f to a Key
934 The `proto_continue' will be called to indicate that the caller may
935 continue with the SKE protocol. The caller must not continue
936 before the SKE libary has called that callback. If this function
937 returns an error the callback will not be called. It is called
938 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
939 However, note that when the library calls the callback the ske->status
942 This calls the `verify_key' callback to verify the received public
943 key or certificate if the Mutual Authentication flag is set. If the
944 `verify_key' is provided then the remote must send public key and it
945 is considered to be an error if remote does not send its public key. */
947 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
948 SilcBuffer ke_payload)
950 SilcSKEStatus status = SILC_SKE_STATUS_OK;
951 SilcSKEKEPayload *recv_payload;
953 SILC_LOG_DEBUG(("Start"));
955 /* Decode Key Exchange Payload */
956 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
957 if (status != SILC_SKE_STATUS_OK) {
958 ske->status = status;
962 ske->ke1_payload = recv_payload;
964 /* Verify the received public key and verify the signature if we are
965 doing mutual authentication. */
966 if (ske->start_payload &&
967 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
969 SILC_LOG_DEBUG(("We are doing mutual authentication"));
971 if (!recv_payload->pk_data && ske->callbacks->verify_key) {
972 SILC_LOG_DEBUG(("Remote end did not send its public key (or "
973 "certificate), even though we require it"));
974 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
978 if (recv_payload->pk_data && ske->callbacks->verify_key) {
979 SILC_LOG_DEBUG(("Verifying public key"));
982 (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
983 recv_payload->pk_len,
984 recv_payload->pk_type,
985 ske->callbacks->context,
986 silc_ske_responder_phase2_final, NULL);
988 /* We will continue to the final state after the public key has
989 been verified by the caller. */
990 return SILC_SKE_STATUS_PENDING;
994 /* Continue to final state */
996 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
998 return SILC_SKE_STATUS_OK;
1001 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
1002 value to be signed and sent to the other end. This then encodes Key
1003 Exchange Payload and sends it to the other end. */
1005 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
1006 SilcPublicKey public_key,
1007 SilcPrivateKey private_key,
1008 SilcSKEPKType pk_type)
1010 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1011 SilcBuffer payload_buf;
1013 unsigned char hash[32], sign[2048], *pk;
1014 SilcUInt32 hash_len, sign_len, pk_len;
1016 SILC_LOG_DEBUG(("Start"));
1018 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
1020 /* Compute the shared secret key */
1021 KEY = silc_calloc(1, sizeof(*KEY));
1023 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
1024 &ske->prop->group->group);
1027 if (public_key && private_key) {
1028 SILC_LOG_DEBUG(("Getting public key"));
1030 /* Get the public key */
1031 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
1033 status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1036 ske->ke2_payload->pk_data = pk;
1037 ske->ke2_payload->pk_len = pk_len;
1039 SILC_LOG_DEBUG(("Computing HASH value"));
1041 /* Compute the hash value */
1042 memset(hash, 0, sizeof(hash));
1043 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1044 if (status != SILC_SKE_STATUS_OK)
1047 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
1048 memcpy(ske->hash, hash, hash_len);
1049 ske->hash_len = hash_len;
1051 SILC_LOG_DEBUG(("Signing HASH value"));
1053 /* Sign the hash value */
1054 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
1055 private_key->prv_len);
1056 if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
1057 !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
1058 status = SILC_SKE_STATUS_SIGNATURE_ERROR;
1061 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
1062 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
1063 memset(sign, 0, sizeof(sign));
1064 ske->ke2_payload->sign_len = sign_len;
1066 ske->ke2_payload->pk_type = pk_type;
1068 /* Encode the Key Exchange Payload */
1069 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
1071 if (status != SILC_SKE_STATUS_OK)
1074 /* Send the packet. */
1075 if (ske->callbacks->send_packet)
1076 (*ske->callbacks->send_packet)(ske, payload_buf,
1077 SILC_PACKET_KEY_EXCHANGE_2,
1078 ske->callbacks->context);
1080 silc_buffer_free(payload_buf);
1085 silc_mp_uninit(ske->KEY);
1086 silc_free(ske->KEY);
1088 silc_ske_payload_ke_free(ske->ke2_payload);
1090 if (status == SILC_SKE_STATUS_OK)
1091 return SILC_SKE_STATUS_ERROR;
1093 ske->status = status;
1097 /* The Key Exchange protocol is ended by calling this function. This
1098 must not be called until the keys are processed like the protocol
1099 defines. This function is for both initiator and responder. */
1101 SilcSKEStatus silc_ske_end(SilcSKE ske)
1105 SILC_LOG_DEBUG(("Start"));
1107 packet = silc_buffer_alloc_size(4);
1109 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1110 silc_buffer_format(packet,
1111 SILC_STR_UI_INT((SilcUInt32)SILC_SKE_STATUS_OK),
1114 if (ske->callbacks->send_packet)
1115 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS,
1116 ske->callbacks->context);
1118 silc_buffer_free(packet);
1120 return SILC_SKE_STATUS_OK;
1123 /* Aborts the Key Exchange protocol. This is called if error occurs
1124 while performing the protocol. The status argument is the error
1125 status and it is sent to the remote end. */
1127 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
1131 SILC_LOG_DEBUG(("Start"));
1133 if (status > SILC_SKE_STATUS_INVALID_COOKIE)
1134 status = SILC_SKE_STATUS_BAD_PAYLOAD;
1136 packet = silc_buffer_alloc_size(4);
1138 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1139 silc_buffer_format(packet,
1140 SILC_STR_UI_INT((SilcUInt32)status),
1143 if (ske->callbacks->send_packet)
1144 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
1145 ske->callbacks->context);
1147 silc_buffer_free(packet);
1149 return SILC_SKE_STATUS_OK;
1152 /* Assembles security properties to Key Exchange Start Payload to be
1153 sent to the remote end. This checks system wide (SILC system, that is)
1154 settings and chooses from those. However, if other properties
1155 should be used this function is easy to replace by another function,
1156 as, this function is called by the caller of the protocol and not
1157 by the protocol itself. */
1160 silc_ske_assemble_security_properties(SilcSKE ske,
1161 SilcSKESecurityPropertyFlag flags,
1162 const char *version,
1163 SilcSKEStartPayload **return_payload)
1165 SilcSKEStartPayload *rp;
1168 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1170 rp = silc_calloc(1, sizeof(*rp));
1173 rp->flags = (unsigned char)flags;
1175 /* Set random cookie */
1176 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1177 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1178 rp->cookie[i] = silc_rng_get_byte(ske->rng);
1179 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1182 rp->version = strdup(version);
1183 rp->version_len = strlen(version);
1185 /* Get supported Key Exhange groups */
1186 rp->ke_grp_list = silc_ske_get_supported_groups();
1187 rp->ke_grp_len = strlen(rp->ke_grp_list);
1189 /* Get supported PKCS algorithms */
1190 rp->pkcs_alg_list = silc_pkcs_get_supported();
1191 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1193 /* Get supported encryption algorithms */
1194 rp->enc_alg_list = silc_cipher_get_supported();
1195 rp->enc_alg_len = strlen(rp->enc_alg_list);
1197 /* Get supported hash algorithms */
1198 rp->hash_alg_list = silc_hash_get_supported();
1199 rp->hash_alg_len = strlen(rp->hash_alg_list);
1201 /* Get supported HMACs */
1202 rp->hmac_alg_list = silc_hmac_get_supported();
1203 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1206 /* Get supported compression algorithms */
1207 rp->comp_alg_list = strdup("");
1208 rp->comp_alg_len = 0;
1210 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1211 2 + rp->version_len +
1212 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1213 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1214 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1216 *return_payload = rp;
1218 return SILC_SKE_STATUS_OK;
1221 /* Selects the supported security properties from the remote end's Key
1222 Exchange Start Payload. */
1225 silc_ske_select_security_properties(SilcSKE ske,
1226 const char *version,
1227 SilcSKEStartPayload *payload,
1228 SilcSKEStartPayload *remote_payload)
1230 SilcSKEStatus status;
1231 SilcSKEStartPayload *rp;
1235 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1237 rp = remote_payload;
1239 /* Check version string */
1240 if (ske->callbacks->check_version) {
1241 status = ske->callbacks->check_version(ske, rp->version,
1243 ske->callbacks->context);
1244 if (status != SILC_SKE_STATUS_OK) {
1245 ske->status = status;
1250 ske->remote_version = silc_memdup(rp->version, rp->version_len);
1252 /* Flags are returned unchanged. */
1253 payload->flags = rp->flags;
1255 /* Take cookie, we must return it to sender unmodified. */
1256 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1257 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1258 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1260 /* Put our version to our reply */
1261 payload->version = strdup(version);
1262 payload->version_len = strlen(version);
1264 /* Get supported Key Exchange groups */
1265 cp = rp->ke_grp_list;
1266 if (cp && strchr(cp, ',')) {
1270 len = strcspn(cp, ",");
1271 item = silc_calloc(len + 1, sizeof(char));
1272 memcpy(item, cp, len);
1274 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1276 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1277 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1279 payload->ke_grp_len = len;
1280 payload->ke_grp_list = item;
1285 if (strlen(cp) == 0)
1294 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1295 SILC_LOG_DEBUG(("Could not find supported KE group"));
1297 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1301 if (!rp->ke_grp_len) {
1302 SILC_LOG_DEBUG(("KE group not defined in payload"));
1304 return SILC_SKE_STATUS_BAD_PAYLOAD;
1307 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1308 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1310 payload->ke_grp_len = rp->ke_grp_len;
1311 payload->ke_grp_list = strdup(rp->ke_grp_list);
1314 /* Get supported PKCS algorithms */
1315 cp = rp->pkcs_alg_list;
1316 if (cp && strchr(cp, ',')) {
1320 len = strcspn(cp, ",");
1321 item = silc_calloc(len + 1, sizeof(char));
1322 memcpy(item, cp, len);
1324 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1326 if (silc_pkcs_is_supported(item) == TRUE) {
1327 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1329 payload->pkcs_alg_len = len;
1330 payload->pkcs_alg_list = item;
1335 if (strlen(cp) == 0)
1344 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1345 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1346 silc_free(payload->ke_grp_list);
1348 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1352 if (!rp->pkcs_alg_len) {
1353 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1354 silc_free(payload->ke_grp_list);
1356 return SILC_SKE_STATUS_BAD_PAYLOAD;
1359 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1360 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1362 payload->pkcs_alg_len = rp->pkcs_alg_len;
1363 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1366 /* Get supported encryption algorithms */
1367 cp = rp->enc_alg_list;
1368 if (cp && strchr(cp, ',')) {
1372 len = strcspn(cp, ",");
1373 item = silc_calloc(len + 1, sizeof(char));
1374 memcpy(item, cp, len);
1376 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1378 if (silc_cipher_is_supported(item) == TRUE) {
1379 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1381 payload->enc_alg_len = len;
1382 payload->enc_alg_list = item;
1387 if (strlen(cp) == 0)
1396 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1397 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1398 silc_free(payload->ke_grp_list);
1399 silc_free(payload->pkcs_alg_list);
1401 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1405 if (!rp->enc_alg_len) {
1406 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1407 silc_free(payload->ke_grp_list);
1408 silc_free(payload->pkcs_alg_list);
1410 return SILC_SKE_STATUS_BAD_PAYLOAD;
1413 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1416 payload->enc_alg_len = rp->enc_alg_len;
1417 payload->enc_alg_list = strdup(rp->enc_alg_list);
1420 /* Get supported hash algorithms */
1421 cp = rp->hash_alg_list;
1422 if (cp && strchr(cp, ',')) {
1426 len = strcspn(cp, ",");
1427 item = silc_calloc(len + 1, sizeof(char));
1428 memcpy(item, cp, len);
1430 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1432 if (silc_hash_is_supported(item) == TRUE) {
1433 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1435 payload->hash_alg_len = len;
1436 payload->hash_alg_list = item;
1441 if (strlen(cp) == 0)
1450 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1451 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1452 silc_free(payload->ke_grp_list);
1453 silc_free(payload->pkcs_alg_list);
1454 silc_free(payload->enc_alg_list);
1456 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1460 if (!rp->hash_alg_len) {
1461 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1462 silc_free(payload->ke_grp_list);
1463 silc_free(payload->pkcs_alg_list);
1464 silc_free(payload->enc_alg_list);
1466 return SILC_SKE_STATUS_BAD_PAYLOAD;
1469 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1470 rp->hash_alg_list));
1472 payload->hash_alg_len = rp->hash_alg_len;
1473 payload->hash_alg_list = strdup(rp->hash_alg_list);
1476 /* Get supported HMACs */
1477 cp = rp->hmac_alg_list;
1478 if (cp && strchr(cp, ',')) {
1482 len = strcspn(cp, ",");
1483 item = silc_calloc(len + 1, sizeof(char));
1484 memcpy(item, cp, len);
1486 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1488 if (silc_hmac_is_supported(item) == TRUE) {
1489 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1491 payload->hmac_alg_len = len;
1492 payload->hmac_alg_list = item;
1497 if (strlen(cp) == 0)
1506 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1507 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1508 silc_free(payload->ke_grp_list);
1509 silc_free(payload->pkcs_alg_list);
1510 silc_free(payload->enc_alg_list);
1511 silc_free(payload->hash_alg_list);
1513 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1517 if (!rp->hmac_alg_len) {
1518 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1519 silc_free(payload->ke_grp_list);
1520 silc_free(payload->pkcs_alg_list);
1521 silc_free(payload->enc_alg_list);
1522 silc_free(payload->hash_alg_list);
1524 return SILC_SKE_STATUS_BAD_PAYLOAD;
1527 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1528 rp->hmac_alg_list));
1530 payload->hmac_alg_len = rp->hmac_alg_len;
1531 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1535 /* Get supported compression algorithms */
1536 cp = rp->hash_alg_list;
1537 if (cp && strchr(cp, ',')) {
1541 len = strcspn(cp, ",");
1542 item = silc_calloc(len + 1, sizeof(char));
1543 memcpy(item, cp, len);
1545 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1547 if (silc_hash_is_supported(item) == TRUE) {
1548 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1550 payload->hash_alg_len = len;
1551 payload->hash_alg_list = item;
1556 if (strlen(cp) == 0)
1565 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1566 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1567 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1568 silc_free(payload->ke_grp_list);
1569 silc_free(payload->pkcs_alg_list);
1570 silc_free(payload->enc_alg_list);
1579 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1580 2 + payload->version_len +
1581 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1582 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1583 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1585 return SILC_SKE_STATUS_OK;
1588 /* Creates random number such that 1 < rnd < n and at most length
1589 of len bits. The rnd sent as argument must be initialized. */
1591 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1595 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1596 unsigned char *string;
1598 SILC_LOG_DEBUG(("Creating random number"));
1600 /* Get the random number as string */
1601 string = silc_rng_get_rn_data(ske->rng, (len / 8));
1603 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1605 /* Decode the string into a MP integer */
1606 silc_mp_bin2mp(string, (len / 8), rnd);
1607 silc_mp_mod_2exp(rnd, rnd, len);
1610 if (silc_mp_cmp_ui(rnd, 1) < 0)
1611 status = SILC_SKE_STATUS_ERROR;
1613 if (silc_mp_cmp(rnd, n) >= 0)
1614 status = SILC_SKE_STATUS_ERROR;
1616 memset(string, 'F', (len / 8));
1622 /* Creates a hash value HASH as defined in the SKE protocol. If the
1623 `initiator' is TRUE then this function is used to create the HASH_i
1624 hash value defined in the protocol. If it is FALSE then this is used
1625 to create the HASH value defined by the protocol. */
1627 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1628 unsigned char *return_hash,
1629 SilcUInt32 *return_hash_len,
1632 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1634 unsigned char *e, *f, *KEY;
1635 SilcUInt32 e_len, f_len, KEY_len;
1638 SILC_LOG_DEBUG(("Start"));
1640 if (initiator == FALSE) {
1641 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1642 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1643 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1645 /* Format the buffer used to compute the hash value */
1646 buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
1647 ske->ke2_payload->pk_len +
1648 ske->ke1_payload->pk_len +
1649 e_len + f_len + KEY_len);
1651 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1653 /* Initiator is not required to send its public key */
1654 if (!ske->ke1_payload->pk_data) {
1656 silc_buffer_format(buf,
1657 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1659 ske->start_payload_copy->
1661 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1662 ske->ke2_payload->pk_len),
1663 SILC_STR_UI_XNSTRING(e, e_len),
1664 SILC_STR_UI_XNSTRING(f, f_len),
1665 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1669 silc_buffer_format(buf,
1670 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1672 ske->start_payload_copy->
1674 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1675 ske->ke2_payload->pk_len),
1676 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1677 ske->ke1_payload->pk_len),
1678 SILC_STR_UI_XNSTRING(e, e_len),
1679 SILC_STR_UI_XNSTRING(f, f_len),
1680 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1684 silc_buffer_free(buf);
1685 memset(e, 0, e_len);
1686 memset(f, 0, f_len);
1687 memset(KEY, 0, KEY_len);
1691 return SILC_SKE_STATUS_ERROR;
1694 memset(e, 0, e_len);
1695 memset(f, 0, f_len);
1696 memset(KEY, 0, KEY_len);
1701 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1703 buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
1704 ske->ke1_payload->pk_len + e_len);
1706 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1708 /* Format the buffer used to compute the hash value */
1710 silc_buffer_format(buf,
1711 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1712 ske->start_payload_copy->len),
1713 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1714 ske->ke1_payload->pk_len),
1715 SILC_STR_UI_XNSTRING(e, e_len),
1718 silc_buffer_free(buf);
1719 memset(e, 0, e_len);
1721 return SILC_SKE_STATUS_ERROR;
1724 memset(e, 0, e_len);
1729 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1730 *return_hash_len = silc_hash_len(ske->prop->hash);
1732 if (initiator == FALSE) {
1733 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1735 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1738 silc_buffer_free(buf);
1743 /* Processes the provided key material `data' as the SILC protocol
1744 specification defines. */
1747 silc_ske_process_key_material_data(unsigned char *data,
1748 SilcUInt32 data_len,
1749 SilcUInt32 req_iv_len,
1750 SilcUInt32 req_enc_key_len,
1751 SilcUInt32 req_hmac_key_len,
1753 SilcSKEKeyMaterial *key)
1756 unsigned char hashd[32];
1757 SilcUInt32 hash_len = req_hmac_key_len;
1758 SilcUInt32 enc_key_len = req_enc_key_len / 8;
1760 SILC_LOG_DEBUG(("Start"));
1762 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1763 return SILC_SKE_STATUS_ERROR;
1765 buf = silc_buffer_alloc_size(1 + data_len);
1767 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1768 silc_buffer_format(buf,
1769 SILC_STR_UI_CHAR(0),
1770 SILC_STR_UI_XNSTRING(data, data_len),
1774 memset(hashd, 0, sizeof(hashd));
1776 silc_hash_make(hash, buf->data, buf->len, hashd);
1777 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1778 memcpy(key->send_iv, hashd, req_iv_len);
1779 memset(hashd, 0, sizeof(hashd));
1781 silc_hash_make(hash, buf->data, buf->len, hashd);
1782 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1783 memcpy(key->receive_iv, hashd, req_iv_len);
1784 key->iv_len = req_iv_len;
1786 /* Take the encryption keys. If requested key size is more than
1787 the size of hash length we will distribute more key material
1788 as protocol defines. */
1790 if (enc_key_len > hash_len) {
1792 unsigned char k1[32], k2[32], k3[32];
1793 unsigned char *dtmp;
1796 if (enc_key_len > (3 * hash_len))
1797 return SILC_SKE_STATUS_ERROR;
1799 /* Take first round */
1800 memset(k1, 0, sizeof(k1));
1801 silc_hash_make(hash, buf->data, buf->len, k1);
1803 /* Take second round */
1804 dist = silc_buffer_alloc_size(data_len + hash_len);
1806 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1807 silc_buffer_format(dist,
1808 SILC_STR_UI_XNSTRING(data, data_len),
1809 SILC_STR_UI_XNSTRING(k1, hash_len),
1811 memset(k2, 0, sizeof(k2));
1812 silc_hash_make(hash, dist->data, dist->len, k2);
1814 /* Take third round */
1815 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1816 silc_buffer_pull_tail(dist, hash_len);
1817 silc_buffer_pull(dist, data_len + hash_len);
1818 silc_buffer_format(dist,
1819 SILC_STR_UI_XNSTRING(k2, hash_len),
1821 silc_buffer_push(dist, data_len + hash_len);
1822 memset(k3, 0, sizeof(k3));
1823 silc_hash_make(hash, dist->data, dist->len, k3);
1825 /* Then, save the keys */
1826 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1827 memcpy(dtmp, k1, hash_len);
1828 memcpy(dtmp + hash_len, k2, hash_len);
1829 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1831 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1832 memcpy(key->send_enc_key, dtmp, enc_key_len);
1833 key->enc_key_len = req_enc_key_len;
1835 memset(dtmp, 0, (3 * hash_len));
1836 memset(k1, 0, sizeof(k1));
1837 memset(k2, 0, sizeof(k2));
1838 memset(k3, 0, sizeof(k3));
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_free(dist);
1903 /* Take normal hash as key */
1904 memset(hashd, 0, sizeof(hashd));
1905 silc_hash_make(hash, buf->data, buf->len, hashd);
1906 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1907 memcpy(key->receive_enc_key, hashd, enc_key_len);
1908 key->enc_key_len = req_enc_key_len;
1911 /* Take HMAC keys */
1912 memset(hashd, 0, sizeof(hashd));
1914 silc_hash_make(hash, buf->data, buf->len, hashd);
1915 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1916 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1917 memset(hashd, 0, sizeof(hashd));
1919 silc_hash_make(hash, buf->data, buf->len, hashd);
1920 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1921 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1922 key->hmac_key_len = req_hmac_key_len;
1923 memset(hashd, 0, sizeof(hashd));
1925 silc_buffer_free(buf);
1927 return SILC_SKE_STATUS_OK;
1930 /* Processes negotiated key material as protocol specifies. This returns
1931 the actual keys to be used in the SILC. */
1933 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1934 SilcUInt32 req_iv_len,
1935 SilcUInt32 req_enc_key_len,
1936 SilcUInt32 req_hmac_key_len,
1937 SilcSKEKeyMaterial *key)
1939 SilcSKEStatus status;
1941 unsigned char *tmpbuf;
1944 /* Encode KEY to binary data */
1945 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1947 buf = silc_buffer_alloc_size(klen + ske->hash_len);
1949 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1950 silc_buffer_format(buf,
1951 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1952 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1955 /* Process the key material */
1956 status = silc_ske_process_key_material_data(buf->data, buf->len,
1957 req_iv_len, req_enc_key_len,
1959 ske->prop->hash, key);
1961 memset(tmpbuf, 0, klen);
1963 silc_buffer_free(buf);
1968 /* Free key material structure */
1970 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1976 silc_free(key->send_iv);
1977 if (key->receive_iv)
1978 silc_free(key->receive_iv);
1979 if (key->send_enc_key) {
1980 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1981 silc_free(key->send_enc_key);
1983 if (key->receive_enc_key) {
1984 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1985 silc_free(key->receive_enc_key);
1987 if (key->send_hmac_key) {
1988 memset(key->send_hmac_key, 0, key->hmac_key_len);
1989 silc_free(key->send_hmac_key);
1991 if (key->receive_hmac_key) {
1992 memset(key->receive_hmac_key, 0, key->hmac_key_len);
1993 silc_free(key->receive_hmac_key);
1998 const char *silc_ske_status_string[] =
2002 "Unkown error occurred",
2003 "Bad payload in packet",
2004 "Unsupported group",
2005 "Unsupported cipher",
2007 "Unsupported hash function",
2009 "Unsupported public key (or certificate)",
2010 "Incorrect signature",
2011 "Bad or unsupported version",
2016 "Remote did not provide public key",
2017 "Key exchange protocol is not active",
2018 "Bad reserved field in packet",
2019 "Bad payload length in packet",
2020 "Error computing signature",
2021 "System out of memory",
2026 /* Maps status to readable string and returns the string. If string is not
2027 found and empty character string ("") is returned. */
2029 const char *silc_ske_map_status(SilcSKEStatus status)
2033 for (i = 0; silc_ske_status_string[i]; i++)
2035 return silc_ske_status_string[i];
2040 /* Parses remote host's version string. */
2042 bool silc_ske_parse_version(SilcSKE ske,
2043 SilcUInt32 *protocol_version,
2044 char **protocol_version_string,
2045 SilcUInt32 *software_version,
2046 char **software_version_string,
2047 char **vendor_version)
2049 return silc_parse_version_string(ske->remote_version,
2051 protocol_version_string,
2053 software_version_string,