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 /* Disable IV Included flag if requested */
697 if (remote_payload->flags & SILC_SKE_SP_FLAG_IV_INCLUDED &&
698 !(flags & SILC_SKE_SP_FLAG_IV_INCLUDED)) {
699 SILC_LOG_DEBUG(("We do not support IV Included flag"));
700 remote_payload->flags &= ~SILC_SKE_SP_FLAG_IV_INCLUDED;
703 /* Parse and select the security properties from the payload */
704 payload = silc_calloc(1, sizeof(*payload));
705 status = silc_ske_select_security_properties(ske, version,
706 payload, remote_payload);
707 if (status != SILC_SKE_STATUS_OK)
710 ske->start_payload = payload;
712 /* Call the callback function. */
713 if (ske->callbacks->payload_receive)
714 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
716 silc_ske_payload_start_free(remote_payload);
722 silc_ske_payload_start_free(remote_payload);
726 if (status == SILC_SKE_STATUS_OK)
727 return SILC_SKE_STATUS_ERROR;
729 ske->status = status;
733 /* The selected security properties from the initiator payload is now
734 encoded into Key Exchange Start Payload and sent to the initiator. */
736 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske)
738 SilcSKEStatus status = SILC_SKE_STATUS_OK;
739 SilcBuffer payload_buf;
740 SilcSKESecurityProperties prop;
741 SilcSKEDiffieHellmanGroup group = NULL;
743 SILC_LOG_DEBUG(("Start"));
745 /* Allocate security properties from the payload. These are allocated
746 only for this negotiation and will be free'd after KE is over. */
747 ske->prop = prop = silc_calloc(1, sizeof(*prop));
748 prop->flags = ske->start_payload->flags;
749 status = silc_ske_group_get_by_name(ske->start_payload->ke_grp_list, &group);
750 if (status != SILC_SKE_STATUS_OK)
755 if (silc_pkcs_alloc(ske->start_payload->pkcs_alg_list,
756 &prop->pkcs) == FALSE) {
757 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
761 if (silc_cipher_alloc(ske->start_payload->enc_alg_list,
762 &prop->cipher) == FALSE) {
763 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
767 if (silc_hash_alloc(ske->start_payload->hash_alg_list,
768 &prop->hash) == FALSE) {
769 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
773 if (silc_hmac_alloc(ske->start_payload->hmac_alg_list, NULL,
774 &prop->hmac) == FALSE) {
775 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
779 /* Encode the payload */
780 status = silc_ske_payload_start_encode(ske, ske->start_payload,
782 if (status != SILC_SKE_STATUS_OK)
785 /* Send the packet. */
786 if (ske->callbacks->send_packet)
787 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
788 ske->callbacks->context);
790 silc_buffer_free(payload_buf);
796 silc_ske_group_free(group);
799 silc_pkcs_free(prop->pkcs);
801 silc_cipher_free(prop->cipher);
803 silc_hash_free(prop->hash);
805 silc_hmac_free(prop->hmac);
809 if (status == SILC_SKE_STATUS_OK)
810 return SILC_SKE_STATUS_ERROR;
812 ske->status = status;
816 /* An responder phase 2 final callback that is called to indicate that
817 the SKE protocol may continue. */
819 static void silc_ske_responder_phase2_final(SilcSKE ske,
820 SilcSKEStatus status,
823 SilcSKEKEPayload *recv_payload, *send_payload;
826 /* If the SKE was freed during the async call then free it really now,
827 otherwise just decrement the reference counter. */
828 if (ske->status == SILC_SKE_STATUS_FREED) {
833 /* If the caller returns PENDING status SKE library will assume that
834 the caller will re-call this callback when it is not anymore in
836 if (status == SILC_SKE_STATUS_PENDING)
840 recv_payload = ske->ke1_payload;
842 /* If the status is an error then the public key that was verified
843 by the caller is not authentic. */
844 if (status != SILC_SKE_STATUS_OK) {
845 ske->status = status;
846 if (ske->callbacks->proto_continue)
847 ske->callbacks->proto_continue(ske, ske->callbacks->context);
851 /* The public key verification was performed only if the Mutual
852 Authentication flag is set. */
853 if (ske->start_payload &&
854 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
855 SilcPublicKey public_key = NULL;
856 unsigned char hash[32];
859 /* Decode the public key */
860 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
861 recv_payload->pk_len,
863 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
864 SILC_LOG_ERROR(("Unsupported/malformed public key received"));
865 if (ske->callbacks->proto_continue)
866 ske->callbacks->proto_continue(ske, ske->callbacks->context);
870 SILC_LOG_DEBUG(("Public key is authentic"));
872 /* Compute the hash value */
873 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
874 if (status != SILC_SKE_STATUS_OK) {
875 ske->status = status;
876 if (ske->callbacks->proto_continue)
877 ske->callbacks->proto_continue(ske, ske->callbacks->context);
881 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
883 /* Verify signature */
884 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
885 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
886 recv_payload->sign_len, hash, hash_len) == FALSE) {
887 SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
888 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
889 if (ske->callbacks->proto_continue)
890 ske->callbacks->proto_continue(ske, ske->callbacks->context);
894 SILC_LOG_DEBUG(("Signature is Ok"));
896 silc_pkcs_public_key_free(public_key);
897 memset(hash, 'F', hash_len);
900 /* Create the random number x, 1 < x < q. */
901 x = silc_calloc(1, sizeof(*x));
904 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
905 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
907 if (status != SILC_SKE_STATUS_OK) {
910 ske->status = status;
911 if (ske->callbacks->proto_continue)
912 ske->callbacks->proto_continue(ske, ske->callbacks->context);
916 /* Save the results for later processing */
917 send_payload = silc_calloc(1, sizeof(*send_payload));
919 ske->ke2_payload = send_payload;
921 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
923 /* Do the Diffie Hellman computation, f = g ^ x mod p */
924 silc_mp_init(&send_payload->x);
925 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
926 &ske->prop->group->group);
928 /* Call the callback. The caller may now continue with the SKE protocol. */
929 ske->status = SILC_SKE_STATUS_OK;
930 if (ske->callbacks->proto_continue)
931 ske->callbacks->proto_continue(ske, ske->callbacks->context);
934 /* This function receives the Key Exchange Payload from the initiator.
935 This also performs the mutual authentication if required. Then, this
936 function first generated a random number x, such that 1 < x < q
937 and computes f = g ^ x mod p. This then puts the result f to a Key
940 The `proto_continue' will be called to indicate that the caller may
941 continue with the SKE protocol. The caller must not continue
942 before the SKE libary has called that callback. If this function
943 returns an error the callback will not be called. It is called
944 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
945 However, note that when the library calls the callback the ske->status
948 This calls the `verify_key' callback to verify the received public
949 key or certificate if the Mutual Authentication flag is set. If the
950 `verify_key' is provided then the remote must send public key and it
951 is considered to be an error if remote does not send its public key. */
953 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
954 SilcBuffer ke_payload)
956 SilcSKEStatus status = SILC_SKE_STATUS_OK;
957 SilcSKEKEPayload *recv_payload;
959 SILC_LOG_DEBUG(("Start"));
961 /* Decode Key Exchange Payload */
962 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
963 if (status != SILC_SKE_STATUS_OK) {
964 ske->status = status;
968 ske->ke1_payload = recv_payload;
970 /* Verify the received public key and verify the signature if we are
971 doing mutual authentication. */
972 if (ske->start_payload &&
973 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
975 SILC_LOG_DEBUG(("We are doing mutual authentication"));
977 if (!recv_payload->pk_data && ske->callbacks->verify_key) {
978 SILC_LOG_ERROR(("Remote end did not send its public key (or "
979 "certificate), even though we require it"));
980 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
984 if (recv_payload->pk_data && ske->callbacks->verify_key) {
985 SILC_LOG_DEBUG(("Verifying public key"));
988 (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
989 recv_payload->pk_len,
990 recv_payload->pk_type,
991 ske->callbacks->context,
992 silc_ske_responder_phase2_final, NULL);
994 /* We will continue to the final state after the public key has
995 been verified by the caller. */
996 return SILC_SKE_STATUS_PENDING;
1000 /* Continue to final state */
1002 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
1004 return SILC_SKE_STATUS_OK;
1007 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
1008 value to be signed and sent to the other end. This then encodes Key
1009 Exchange Payload and sends it to the other end. */
1011 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
1012 SilcPublicKey public_key,
1013 SilcPrivateKey private_key,
1014 SilcSKEPKType pk_type)
1016 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1017 SilcBuffer payload_buf;
1019 unsigned char hash[32], sign[2048], *pk;
1020 SilcUInt32 hash_len, sign_len, pk_len;
1022 SILC_LOG_DEBUG(("Start"));
1024 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
1026 /* Compute the shared secret key */
1027 KEY = silc_calloc(1, sizeof(*KEY));
1029 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
1030 &ske->prop->group->group);
1033 if (public_key && private_key) {
1034 SILC_LOG_DEBUG(("Getting public key"));
1036 /* Get the public key */
1037 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
1039 status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1042 ske->ke2_payload->pk_data = pk;
1043 ske->ke2_payload->pk_len = pk_len;
1045 SILC_LOG_DEBUG(("Computing HASH value"));
1047 /* Compute the hash value */
1048 memset(hash, 0, sizeof(hash));
1049 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1050 if (status != SILC_SKE_STATUS_OK)
1053 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
1054 memcpy(ske->hash, hash, hash_len);
1055 ske->hash_len = hash_len;
1057 SILC_LOG_DEBUG(("Signing HASH value"));
1059 /* Sign the hash value */
1060 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
1061 private_key->prv_len);
1062 if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
1063 !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
1064 status = SILC_SKE_STATUS_SIGNATURE_ERROR;
1067 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
1068 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
1069 memset(sign, 0, sizeof(sign));
1070 ske->ke2_payload->sign_len = sign_len;
1072 ske->ke2_payload->pk_type = pk_type;
1074 /* Encode the Key Exchange Payload */
1075 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
1077 if (status != SILC_SKE_STATUS_OK)
1080 /* Send the packet. */
1081 if (ske->callbacks->send_packet)
1082 (*ske->callbacks->send_packet)(ske, payload_buf,
1083 SILC_PACKET_KEY_EXCHANGE_2,
1084 ske->callbacks->context);
1086 silc_buffer_free(payload_buf);
1091 silc_mp_uninit(ske->KEY);
1092 silc_free(ske->KEY);
1094 silc_ske_payload_ke_free(ske->ke2_payload);
1096 if (status == SILC_SKE_STATUS_OK)
1097 return SILC_SKE_STATUS_ERROR;
1099 ske->status = status;
1103 /* The Key Exchange protocol is ended by calling this function. This
1104 must not be called until the keys are processed like the protocol
1105 defines. This function is for both initiator and responder. */
1107 SilcSKEStatus silc_ske_end(SilcSKE ske)
1111 SILC_LOG_DEBUG(("Start"));
1113 packet = silc_buffer_alloc_size(4);
1115 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1116 silc_buffer_format(packet,
1117 SILC_STR_UI_INT((SilcUInt32)SILC_SKE_STATUS_OK),
1120 if (ske->callbacks->send_packet)
1121 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS,
1122 ske->callbacks->context);
1124 silc_buffer_free(packet);
1126 return SILC_SKE_STATUS_OK;
1129 /* Aborts the Key Exchange protocol. This is called if error occurs
1130 while performing the protocol. The status argument is the error
1131 status and it is sent to the remote end. */
1133 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
1137 SILC_LOG_DEBUG(("Start"));
1139 if (status > SILC_SKE_STATUS_INVALID_COOKIE)
1140 status = SILC_SKE_STATUS_BAD_PAYLOAD;
1142 packet = silc_buffer_alloc_size(4);
1144 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1145 silc_buffer_format(packet,
1146 SILC_STR_UI_INT((SilcUInt32)status),
1149 if (ske->callbacks->send_packet)
1150 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
1151 ske->callbacks->context);
1153 silc_buffer_free(packet);
1155 return SILC_SKE_STATUS_OK;
1158 /* Assembles security properties to Key Exchange Start Payload to be
1159 sent to the remote end. This checks system wide (SILC system, that is)
1160 settings and chooses from those. However, if other properties
1161 should be used this function is easy to replace by another function,
1162 as, this function is called by the caller of the protocol and not
1163 by the protocol itself. */
1166 silc_ske_assemble_security_properties(SilcSKE ske,
1167 SilcSKESecurityPropertyFlag flags,
1168 const char *version,
1169 SilcSKEStartPayload **return_payload)
1171 SilcSKEStartPayload *rp;
1174 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1176 rp = silc_calloc(1, sizeof(*rp));
1179 rp->flags = (unsigned char)flags;
1181 /* Set random cookie */
1182 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1183 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1184 rp->cookie[i] = silc_rng_get_byte(ske->rng);
1185 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1188 rp->version = strdup(version);
1189 rp->version_len = strlen(version);
1191 /* Get supported Key Exhange groups */
1192 rp->ke_grp_list = silc_ske_get_supported_groups();
1193 rp->ke_grp_len = strlen(rp->ke_grp_list);
1195 /* Get supported PKCS algorithms */
1196 rp->pkcs_alg_list = silc_pkcs_get_supported();
1197 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1199 /* Get supported encryption algorithms */
1200 rp->enc_alg_list = silc_cipher_get_supported();
1201 rp->enc_alg_len = strlen(rp->enc_alg_list);
1203 /* Get supported hash algorithms */
1204 rp->hash_alg_list = silc_hash_get_supported();
1205 rp->hash_alg_len = strlen(rp->hash_alg_list);
1207 /* Get supported HMACs */
1208 rp->hmac_alg_list = silc_hmac_get_supported();
1209 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1212 /* Get supported compression algorithms */
1213 rp->comp_alg_list = strdup("");
1214 rp->comp_alg_len = 0;
1216 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1217 2 + rp->version_len +
1218 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1219 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1220 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1222 *return_payload = rp;
1224 return SILC_SKE_STATUS_OK;
1227 /* Selects the supported security properties from the remote end's Key
1228 Exchange Start Payload. */
1231 silc_ske_select_security_properties(SilcSKE ske,
1232 const char *version,
1233 SilcSKEStartPayload *payload,
1234 SilcSKEStartPayload *remote_payload)
1236 SilcSKEStatus status;
1237 SilcSKEStartPayload *rp;
1241 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1243 rp = remote_payload;
1245 /* Check version string */
1246 if (ske->callbacks->check_version) {
1247 status = ske->callbacks->check_version(ske, rp->version,
1249 ske->callbacks->context);
1250 if (status != SILC_SKE_STATUS_OK) {
1251 ske->status = status;
1256 ske->remote_version = silc_memdup(rp->version, rp->version_len);
1258 /* Flags are returned unchanged. */
1259 payload->flags = rp->flags;
1261 /* Take cookie, we must return it to sender unmodified. */
1262 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1263 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1264 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1266 /* Put our version to our reply */
1267 payload->version = strdup(version);
1268 payload->version_len = strlen(version);
1270 /* Get supported Key Exchange groups */
1271 cp = rp->ke_grp_list;
1272 if (cp && strchr(cp, ',')) {
1276 len = strcspn(cp, ",");
1277 item = silc_calloc(len + 1, sizeof(char));
1278 memcpy(item, cp, len);
1280 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1282 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1283 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1285 payload->ke_grp_len = len;
1286 payload->ke_grp_list = item;
1291 if (strlen(cp) == 0)
1300 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1301 SILC_LOG_DEBUG(("Could not find supported KE group"));
1303 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1307 if (!rp->ke_grp_len) {
1308 SILC_LOG_DEBUG(("KE group not defined in payload"));
1310 return SILC_SKE_STATUS_BAD_PAYLOAD;
1313 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1314 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1316 payload->ke_grp_len = rp->ke_grp_len;
1317 payload->ke_grp_list = strdup(rp->ke_grp_list);
1320 /* Get supported PKCS algorithms */
1321 cp = rp->pkcs_alg_list;
1322 if (cp && strchr(cp, ',')) {
1326 len = strcspn(cp, ",");
1327 item = silc_calloc(len + 1, sizeof(char));
1328 memcpy(item, cp, len);
1330 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1332 if (silc_pkcs_is_supported(item) == TRUE) {
1333 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1335 payload->pkcs_alg_len = len;
1336 payload->pkcs_alg_list = item;
1341 if (strlen(cp) == 0)
1350 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1351 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1352 silc_free(payload->ke_grp_list);
1354 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1358 if (!rp->pkcs_alg_len) {
1359 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1360 silc_free(payload->ke_grp_list);
1362 return SILC_SKE_STATUS_BAD_PAYLOAD;
1365 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1366 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1368 payload->pkcs_alg_len = rp->pkcs_alg_len;
1369 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1372 /* Get supported encryption algorithms */
1373 cp = rp->enc_alg_list;
1374 if (cp && strchr(cp, ',')) {
1378 len = strcspn(cp, ",");
1379 item = silc_calloc(len + 1, sizeof(char));
1380 memcpy(item, cp, len);
1382 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1384 if (silc_cipher_is_supported(item) == TRUE) {
1385 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1387 payload->enc_alg_len = len;
1388 payload->enc_alg_list = item;
1393 if (strlen(cp) == 0)
1402 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1403 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1404 silc_free(payload->ke_grp_list);
1405 silc_free(payload->pkcs_alg_list);
1407 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1411 if (!rp->enc_alg_len) {
1412 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1413 silc_free(payload->ke_grp_list);
1414 silc_free(payload->pkcs_alg_list);
1416 return SILC_SKE_STATUS_BAD_PAYLOAD;
1419 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1422 payload->enc_alg_len = rp->enc_alg_len;
1423 payload->enc_alg_list = strdup(rp->enc_alg_list);
1426 /* Get supported hash algorithms */
1427 cp = rp->hash_alg_list;
1428 if (cp && strchr(cp, ',')) {
1432 len = strcspn(cp, ",");
1433 item = silc_calloc(len + 1, sizeof(char));
1434 memcpy(item, cp, len);
1436 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1438 if (silc_hash_is_supported(item) == TRUE) {
1439 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1441 payload->hash_alg_len = len;
1442 payload->hash_alg_list = item;
1447 if (strlen(cp) == 0)
1456 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1457 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1458 silc_free(payload->ke_grp_list);
1459 silc_free(payload->pkcs_alg_list);
1460 silc_free(payload->enc_alg_list);
1462 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1466 if (!rp->hash_alg_len) {
1467 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1468 silc_free(payload->ke_grp_list);
1469 silc_free(payload->pkcs_alg_list);
1470 silc_free(payload->enc_alg_list);
1472 return SILC_SKE_STATUS_BAD_PAYLOAD;
1475 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1476 rp->hash_alg_list));
1478 payload->hash_alg_len = rp->hash_alg_len;
1479 payload->hash_alg_list = strdup(rp->hash_alg_list);
1482 /* Get supported HMACs */
1483 cp = rp->hmac_alg_list;
1484 if (cp && strchr(cp, ',')) {
1488 len = strcspn(cp, ",");
1489 item = silc_calloc(len + 1, sizeof(char));
1490 memcpy(item, cp, len);
1492 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1494 if (silc_hmac_is_supported(item) == TRUE) {
1495 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1497 payload->hmac_alg_len = len;
1498 payload->hmac_alg_list = item;
1503 if (strlen(cp) == 0)
1512 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1513 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1514 silc_free(payload->ke_grp_list);
1515 silc_free(payload->pkcs_alg_list);
1516 silc_free(payload->enc_alg_list);
1517 silc_free(payload->hash_alg_list);
1519 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1523 if (!rp->hmac_alg_len) {
1524 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1525 silc_free(payload->ke_grp_list);
1526 silc_free(payload->pkcs_alg_list);
1527 silc_free(payload->enc_alg_list);
1528 silc_free(payload->hash_alg_list);
1530 return SILC_SKE_STATUS_BAD_PAYLOAD;
1533 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1534 rp->hmac_alg_list));
1536 payload->hmac_alg_len = rp->hmac_alg_len;
1537 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1541 /* Get supported compression algorithms */
1542 cp = rp->hash_alg_list;
1543 if (cp && strchr(cp, ',')) {
1547 len = strcspn(cp, ",");
1548 item = silc_calloc(len + 1, sizeof(char));
1549 memcpy(item, cp, len);
1551 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1553 if (silc_hash_is_supported(item) == TRUE) {
1554 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1556 payload->hash_alg_len = len;
1557 payload->hash_alg_list = item;
1562 if (strlen(cp) == 0)
1571 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1572 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1573 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1574 silc_free(payload->ke_grp_list);
1575 silc_free(payload->pkcs_alg_list);
1576 silc_free(payload->enc_alg_list);
1585 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1586 2 + payload->version_len +
1587 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1588 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1589 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1591 return SILC_SKE_STATUS_OK;
1594 /* Creates random number such that 1 < rnd < n and at most length
1595 of len bits. The rnd sent as argument must be initialized. */
1597 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1601 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1602 unsigned char *string;
1604 SILC_LOG_DEBUG(("Creating random number"));
1606 /* Get the random number as string */
1607 string = silc_rng_get_rn_data(ske->rng, ((len - 1) / 8));
1609 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1611 /* Decode the string into a MP integer */
1612 silc_mp_bin2mp(string, ((len - 1) / 8), rnd);
1613 silc_mp_mod_2exp(rnd, rnd, len);
1616 if (silc_mp_cmp_ui(rnd, 1) < 0)
1617 status = SILC_SKE_STATUS_ERROR;
1618 if (silc_mp_cmp(rnd, n) >= 0)
1619 status = SILC_SKE_STATUS_ERROR;
1621 memset(string, 'F', (len / 8));
1627 /* Creates a hash value HASH as defined in the SKE protocol. If the
1628 `initiator' is TRUE then this function is used to create the HASH_i
1629 hash value defined in the protocol. If it is FALSE then this is used
1630 to create the HASH value defined by the protocol. */
1632 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1633 unsigned char *return_hash,
1634 SilcUInt32 *return_hash_len,
1637 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1639 unsigned char *e, *f, *KEY;
1640 SilcUInt32 e_len, f_len, KEY_len;
1643 SILC_LOG_DEBUG(("Start"));
1645 if (initiator == FALSE) {
1646 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1647 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1648 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1650 /* Format the buffer used to compute the hash value */
1651 buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
1652 ske->ke2_payload->pk_len +
1653 ske->ke1_payload->pk_len +
1654 e_len + f_len + KEY_len);
1656 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1658 /* Initiator is not required to send its public key */
1659 if (!ske->ke1_payload->pk_data) {
1661 silc_buffer_format(buf,
1662 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1664 ske->start_payload_copy->
1666 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1667 ske->ke2_payload->pk_len),
1668 SILC_STR_UI_XNSTRING(e, e_len),
1669 SILC_STR_UI_XNSTRING(f, f_len),
1670 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1674 silc_buffer_format(buf,
1675 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1677 ske->start_payload_copy->
1679 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1680 ske->ke2_payload->pk_len),
1681 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1682 ske->ke1_payload->pk_len),
1683 SILC_STR_UI_XNSTRING(e, e_len),
1684 SILC_STR_UI_XNSTRING(f, f_len),
1685 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1689 silc_buffer_free(buf);
1690 memset(e, 0, e_len);
1691 memset(f, 0, f_len);
1692 memset(KEY, 0, KEY_len);
1696 return SILC_SKE_STATUS_ERROR;
1699 memset(e, 0, e_len);
1700 memset(f, 0, f_len);
1701 memset(KEY, 0, KEY_len);
1706 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1708 buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
1709 ske->ke1_payload->pk_len + e_len);
1711 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1713 /* Format the buffer used to compute the hash value */
1715 silc_buffer_format(buf,
1716 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1717 ske->start_payload_copy->len),
1718 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1719 ske->ke1_payload->pk_len),
1720 SILC_STR_UI_XNSTRING(e, e_len),
1723 silc_buffer_free(buf);
1724 memset(e, 0, e_len);
1726 return SILC_SKE_STATUS_ERROR;
1729 memset(e, 0, e_len);
1734 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1735 *return_hash_len = silc_hash_len(ske->prop->hash);
1737 if (initiator == FALSE) {
1738 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1740 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1743 silc_buffer_free(buf);
1748 /* Processes the provided key material `data' as the SILC protocol
1749 specification defines. */
1752 silc_ske_process_key_material_data(unsigned char *data,
1753 SilcUInt32 data_len,
1754 SilcUInt32 req_iv_len,
1755 SilcUInt32 req_enc_key_len,
1756 SilcUInt32 req_hmac_key_len,
1758 SilcSKEKeyMaterial *key)
1761 unsigned char hashd[32];
1762 SilcUInt32 hash_len = req_hmac_key_len;
1763 SilcUInt32 enc_key_len = req_enc_key_len / 8;
1765 SILC_LOG_DEBUG(("Start"));
1767 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1768 return SILC_SKE_STATUS_ERROR;
1770 buf = silc_buffer_alloc_size(1 + data_len);
1772 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1773 silc_buffer_format(buf,
1774 SILC_STR_UI_CHAR(0),
1775 SILC_STR_UI_XNSTRING(data, data_len),
1779 memset(hashd, 0, sizeof(hashd));
1781 silc_hash_make(hash, buf->data, buf->len, hashd);
1782 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1783 memcpy(key->send_iv, hashd, req_iv_len);
1784 memset(hashd, 0, sizeof(hashd));
1786 silc_hash_make(hash, buf->data, buf->len, hashd);
1787 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1788 memcpy(key->receive_iv, hashd, req_iv_len);
1789 key->iv_len = req_iv_len;
1791 /* Take the encryption keys. If requested key size is more than
1792 the size of hash length we will distribute more key material
1793 as protocol defines. */
1795 if (enc_key_len > hash_len) {
1797 unsigned char k1[32], k2[32], k3[32];
1798 unsigned char *dtmp;
1801 if (enc_key_len > (3 * hash_len))
1802 return SILC_SKE_STATUS_ERROR;
1804 /* Take first round */
1805 memset(k1, 0, sizeof(k1));
1806 silc_hash_make(hash, buf->data, buf->len, k1);
1808 /* Take second round */
1809 dist = silc_buffer_alloc_size(data_len + hash_len);
1811 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1812 silc_buffer_format(dist,
1813 SILC_STR_UI_XNSTRING(data, data_len),
1814 SILC_STR_UI_XNSTRING(k1, hash_len),
1816 memset(k2, 0, sizeof(k2));
1817 silc_hash_make(hash, dist->data, dist->len, k2);
1819 /* Take third round */
1820 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1821 silc_buffer_pull_tail(dist, hash_len);
1822 silc_buffer_pull(dist, data_len + hash_len);
1823 silc_buffer_format(dist,
1824 SILC_STR_UI_XNSTRING(k2, hash_len),
1826 silc_buffer_push(dist, data_len + hash_len);
1827 memset(k3, 0, sizeof(k3));
1828 silc_hash_make(hash, dist->data, dist->len, k3);
1830 /* Then, save the keys */
1831 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1832 memcpy(dtmp, k1, hash_len);
1833 memcpy(dtmp + hash_len, k2, hash_len);
1834 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1836 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1837 memcpy(key->send_enc_key, dtmp, enc_key_len);
1838 key->enc_key_len = req_enc_key_len;
1840 memset(dtmp, 0, (3 * hash_len));
1841 memset(k1, 0, sizeof(k1));
1842 memset(k2, 0, sizeof(k2));
1843 memset(k3, 0, sizeof(k3));
1845 silc_buffer_clear(dist);
1846 silc_buffer_free(dist);
1848 /* Take normal hash as key */
1849 memset(hashd, 0, sizeof(hashd));
1850 silc_hash_make(hash, buf->data, buf->len, hashd);
1851 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1852 memcpy(key->send_enc_key, hashd, enc_key_len);
1853 key->enc_key_len = req_enc_key_len;
1857 if (enc_key_len > hash_len) {
1859 unsigned char k1[32], k2[32], k3[32];
1860 unsigned char *dtmp;
1863 if (enc_key_len > (3 * hash_len))
1864 return SILC_SKE_STATUS_ERROR;
1866 /* Take first round */
1867 memset(k1, 0, sizeof(k1));
1868 silc_hash_make(hash, buf->data, buf->len, k1);
1870 /* Take second round */
1871 dist = silc_buffer_alloc_size(data_len + hash_len);
1873 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1874 silc_buffer_format(dist,
1875 SILC_STR_UI_XNSTRING(data, data_len),
1876 SILC_STR_UI_XNSTRING(k1, hash_len),
1878 memset(k2, 0, sizeof(k2));
1879 silc_hash_make(hash, dist->data, dist->len, k2);
1881 /* Take third round */
1882 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1883 silc_buffer_pull_tail(dist, hash_len);
1884 silc_buffer_pull(dist, data_len + hash_len);
1885 silc_buffer_format(dist,
1886 SILC_STR_UI_XNSTRING(k2, hash_len),
1888 silc_buffer_push(dist, data_len + hash_len);
1889 memset(k3, 0, sizeof(k3));
1890 silc_hash_make(hash, dist->data, dist->len, k3);
1892 /* Then, save the keys */
1893 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1894 memcpy(dtmp, k1, hash_len);
1895 memcpy(dtmp + hash_len, k2, hash_len);
1896 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1898 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1899 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1900 key->enc_key_len = req_enc_key_len;
1902 memset(dtmp, 0, (3 * hash_len));
1903 memset(k1, 0, sizeof(k1));
1904 memset(k2, 0, sizeof(k2));
1905 memset(k3, 0, sizeof(k3));
1907 silc_buffer_clear(dist);
1908 silc_buffer_free(dist);
1910 /* Take normal hash as key */
1911 memset(hashd, 0, sizeof(hashd));
1912 silc_hash_make(hash, buf->data, buf->len, hashd);
1913 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1914 memcpy(key->receive_enc_key, hashd, enc_key_len);
1915 key->enc_key_len = req_enc_key_len;
1918 /* Take HMAC keys */
1919 memset(hashd, 0, sizeof(hashd));
1921 silc_hash_make(hash, buf->data, buf->len, hashd);
1922 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1923 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1924 memset(hashd, 0, sizeof(hashd));
1926 silc_hash_make(hash, buf->data, buf->len, hashd);
1927 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1928 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1929 key->hmac_key_len = req_hmac_key_len;
1930 memset(hashd, 0, sizeof(hashd));
1932 silc_buffer_clear(buf);
1933 silc_buffer_free(buf);
1935 return SILC_SKE_STATUS_OK;
1938 /* Processes negotiated key material as protocol specifies. This returns
1939 the actual keys to be used in the SILC. */
1941 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1942 SilcUInt32 req_iv_len,
1943 SilcUInt32 req_enc_key_len,
1944 SilcUInt32 req_hmac_key_len,
1945 SilcSKEKeyMaterial *key)
1947 SilcSKEStatus status;
1949 unsigned char *tmpbuf;
1952 /* Encode KEY to binary data */
1953 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1955 buf = silc_buffer_alloc_size(klen + ske->hash_len);
1957 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1958 silc_buffer_format(buf,
1959 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1960 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1963 /* Process the key material */
1964 status = silc_ske_process_key_material_data(buf->data, buf->len,
1965 req_iv_len, req_enc_key_len,
1967 ske->prop->hash, key);
1969 memset(tmpbuf, 0, klen);
1971 silc_buffer_clear(buf);
1972 silc_buffer_free(buf);
1977 /* Free key material structure */
1979 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1985 silc_free(key->send_iv);
1986 if (key->receive_iv)
1987 silc_free(key->receive_iv);
1988 if (key->send_enc_key) {
1989 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1990 silc_free(key->send_enc_key);
1992 if (key->receive_enc_key) {
1993 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1994 silc_free(key->receive_enc_key);
1996 if (key->send_hmac_key) {
1997 memset(key->send_hmac_key, 0, key->hmac_key_len);
1998 silc_free(key->send_hmac_key);
2000 if (key->receive_hmac_key) {
2001 memset(key->receive_hmac_key, 0, key->hmac_key_len);
2002 silc_free(key->receive_hmac_key);
2007 const char *silc_ske_status_string[] =
2011 "Unkown error occurred",
2012 "Bad payload in packet",
2013 "Unsupported group",
2014 "Unsupported cipher",
2016 "Unsupported hash function",
2018 "Unsupported public key (or certificate)",
2019 "Incorrect signature",
2020 "Bad or unsupported version",
2025 "Remote did not provide public key",
2026 "Key exchange protocol is not active",
2027 "Bad reserved field in packet",
2028 "Bad payload length in packet",
2029 "Error computing signature",
2030 "System out of memory",
2035 /* Maps status to readable string and returns the string. If string is not
2036 found and empty character string ("") is returned. */
2038 const char *silc_ske_map_status(SilcSKEStatus status)
2042 for (i = 0; silc_ske_status_string[i]; i++)
2044 return silc_ske_status_string[i];
2049 /* Parses remote host's version string. */
2051 bool silc_ske_parse_version(SilcSKE ske,
2052 SilcUInt32 *protocol_version,
2053 char **protocol_version_string,
2054 SilcUInt32 *software_version,
2055 char **software_version_string,
2056 char **vendor_version)
2058 return silc_parse_version_string(ske->remote_version,
2060 protocol_version_string,
2062 software_version_string,