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));
53 ske->status = SILC_SKE_STATUS_OK;
55 ske->user_data = context;
61 /* Free's SKE object. */
63 void silc_ske_free(SilcSKE ske)
67 SILC_LOG_DEBUG(("Key Exchange set to FREED status"));
68 ske->status = SILC_SKE_STATUS_FREED;
72 SILC_LOG_DEBUG(("Freeing Key Exchange object"));
75 /* Free start payload */
76 if (ske->start_payload)
77 silc_ske_payload_start_free(ske->start_payload);
81 silc_ske_payload_ke_free(ske->ke1_payload);
83 silc_ske_payload_ke_free(ske->ke2_payload);
84 silc_free(ske->remote_version);
89 silc_ske_group_free(ske->prop->group);
91 silc_pkcs_free(ske->prop->pkcs);
92 if (ske->prop->cipher)
93 silc_cipher_free(ske->prop->cipher);
95 silc_hash_free(ske->prop->hash);
97 silc_hmac_free(ske->prop->hmac);
100 if (ske->start_payload_copy)
101 silc_buffer_free(ske->start_payload_copy);
103 silc_mp_uninit(ske->x);
107 silc_mp_uninit(ske->KEY);
110 silc_free(ske->hash);
111 silc_free(ske->callbacks);
116 /* Sets the callback functions for the SKE session.
118 The `send_packet' callback is a function that sends the packet to
119 network. The SKE library will call it at any time packet needs to
120 be sent to the remote host.
122 The `payload_receive' callback is called when the remote host's Key
123 Exchange Start Payload has been processed. The payload is saved
124 to ske->start_payload if the application would need it. The application
125 must also provide the payload to the next state of the SKE.
127 The `verify_key' callback is called to verify the received public key
128 or certificate. The verification process is most likely asynchronous.
129 That is why the application must call the completion callback when the
130 verification process has been completed. The library then calls the user
131 callback (`proto_continue'), if it is provided to indicate that the SKE
132 protocol may continue.
134 The `proto_continue' callback is called to indicate that it is
135 safe to continue the execution of the SKE protocol after executing
136 an asynchronous operation, such as calling the `verify_key' callback
137 function, which is asynchronous. The application should check the
138 ske->status in this function to check whether it is Ok to continue
139 the execution of the protocol.
141 The `check_version' callback is called to verify the remote host's
142 version. The application may check its own version against the remote
143 host's version and determine whether supporting the remote host
146 The `context' is passed as argument to all of the above callback
149 void silc_ske_set_callbacks(SilcSKE ske,
150 SilcSKESendPacketCb send_packet,
151 SilcSKECb payload_receive,
152 SilcSKEVerifyCb verify_key,
153 SilcSKECb proto_continue,
154 SilcSKECheckVersion check_version,
158 silc_free(ske->callbacks);
159 ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
160 ske->callbacks->send_packet = send_packet;
161 ske->callbacks->payload_receive = payload_receive;
162 ske->callbacks->verify_key = verify_key;
163 ske->callbacks->proto_continue = proto_continue;
164 ske->callbacks->check_version = check_version;
165 ske->callbacks->context = context;
168 /* Starts the SILC Key Exchange protocol for initiator. The connection
169 to the remote end must be established before calling this function
170 and the connecting socket must be sent as argument. This function
171 creates the Key Exchange Start Payload which includes all our
172 configured security properties. This payload is then sent to the
173 remote end for further processing. This payload must be sent as
174 argument to the function, however, it must not be encoded
175 already, it is done by this function. The caller must not free
176 the `start_payload' since the SKE library will save it.
178 The packet sending is done by calling a callback function. Caller
179 must provide a routine to send the packet. */
181 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
182 SilcSocketConnection sock,
183 SilcSKEStartPayload *start_payload)
185 SilcSKEStatus status = SILC_SKE_STATUS_OK;
186 SilcBuffer payload_buf;
188 SILC_LOG_DEBUG(("Start"));
193 /* Encode the payload */
194 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
195 if (status != SILC_SKE_STATUS_OK)
198 /* Take a copy of the payload buffer for future use. It is used to
199 compute the HASH value. */
200 ske->start_payload_copy = silc_buffer_copy(payload_buf);
201 ske->start_payload = start_payload;
203 /* Send the packet. */
204 if (ske->callbacks->send_packet)
205 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
206 ske->callbacks->context);
208 silc_buffer_free(payload_buf);
213 /* Function called after ske_initiator_start fuction. This receives
214 the remote ends Key Exchange Start payload which includes the
215 security properties selected by the responder from our payload
216 sent in the silc_ske_initiator_start function. */
218 SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
219 SilcBuffer start_payload)
221 SilcSKEStatus status = SILC_SKE_STATUS_OK;
222 SilcSKEStartPayload *payload;
223 SilcSKESecurityProperties prop;
224 SilcSKEDiffieHellmanGroup group;
226 SILC_LOG_DEBUG(("Start"));
228 /* Decode the payload */
229 status = silc_ske_payload_start_decode(ske, start_payload, &payload);
230 if (status != SILC_SKE_STATUS_OK) {
231 ske->status = status;
232 silc_ske_payload_start_free(ske->start_payload);
236 /* Check that the cookie is returned unmodified */
237 if (memcmp(ske->start_payload->cookie, payload->cookie,
238 ske->start_payload->cookie_len)) {
239 SILC_LOG_DEBUG(("Responder modified our cookie and it must not do it"));
240 ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
241 silc_ske_payload_start_free(ske->start_payload);
245 /* Check version string */
246 if (ske->callbacks->check_version) {
247 status = ske->callbacks->check_version(ske, payload->version,
248 payload->version_len,
249 ske->callbacks->context);
250 if (status != SILC_SKE_STATUS_OK) {
251 ske->status = status;
252 silc_ske_payload_start_free(ske->start_payload);
257 /* Free our KE Start Payload context, we don't need it anymore. */
258 silc_ske_payload_start_free(ske->start_payload);
260 /* Take the selected security properties into use while doing
261 the key exchange. This is used only while doing the key
262 exchange. The same data is returned to upper levels by calling
263 the callback function. */
264 ske->prop = prop = silc_calloc(1, sizeof(*prop));
265 prop->flags = payload->flags;
266 status = silc_ske_group_get_by_name(payload->ke_grp_list, &group);
267 if (status != SILC_SKE_STATUS_OK)
272 if (silc_pkcs_alloc(payload->pkcs_alg_list, &prop->pkcs) == FALSE) {
273 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
277 if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
278 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
282 if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
283 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
287 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
288 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
292 /* Save remote's KE Start Payload */
293 ske->start_payload = payload;
295 /* Return the received payload by calling the callback function. */
296 if (ske->callbacks->payload_receive)
297 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
303 silc_ske_payload_start_free(payload);
305 silc_ske_group_free(group);
308 silc_pkcs_free(prop->pkcs);
310 silc_cipher_free(prop->cipher);
312 silc_hash_free(prop->hash);
314 silc_hmac_free(prop->hmac);
318 if (status == SILC_SKE_STATUS_OK)
319 return SILC_SKE_STATUS_ERROR;
321 ske->status = status;
325 /* This function creates random number x, such that 1 < x < q and
326 computes e = g ^ x mod p and sends the result to the remote end in
327 Key Exchange Payload. */
329 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
330 SilcPublicKey public_key,
331 SilcPrivateKey private_key,
332 SilcSKEPKType pk_type)
334 SilcSKEStatus status = SILC_SKE_STATUS_OK;
335 SilcBuffer payload_buf;
337 SilcSKEKEPayload *payload;
340 SILC_LOG_DEBUG(("Start"));
342 /* Create the random number x, 1 < x < q. */
343 x = silc_calloc(1, sizeof(*x));
346 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
347 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
349 if (status != SILC_SKE_STATUS_OK) {
352 ske->status = status;
356 /* Encode the result to Key Exchange Payload. */
358 payload = silc_calloc(1, sizeof(*payload));
359 ske->ke1_payload = payload;
361 SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
363 /* Do the Diffie Hellman computation, e = g ^ x mod p */
364 silc_mp_init(&payload->x);
365 silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
366 &ske->prop->group->group);
370 payload->pk_data = silc_pkcs_public_key_encode(public_key, &pk_len);
371 if (!payload->pk_data) {
374 silc_mp_uninit(&payload->x);
376 ske->status = SILC_SKE_STATUS_OK;
379 payload->pk_len = pk_len;
381 payload->pk_type = pk_type;
383 /* Compute signature data if we are doing mutual authentication */
384 if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
385 unsigned char hash[32], sign[2048];
386 SilcUInt32 hash_len, sign_len;
388 SILC_LOG_DEBUG(("We are doing mutual authentication"));
389 SILC_LOG_DEBUG(("Computing HASH_i value"));
391 /* Compute the hash value */
392 memset(hash, 0, sizeof(hash));
393 silc_ske_make_hash(ske, hash, &hash_len, TRUE);
395 SILC_LOG_DEBUG(("Signing HASH_i value"));
397 /* Sign the hash value */
398 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
399 private_key->prv_len);
400 if (silc_pkcs_get_key_len(ske->prop->pkcs) > sizeof(sign) - 1 ||
401 !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
404 silc_mp_uninit(&payload->x);
405 silc_free(payload->pk_data);
407 ske->status = status;
410 payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
411 memcpy(payload->sign_data, sign, sign_len);
412 memset(sign, 0, sizeof(sign));
413 payload->sign_len = sign_len;
416 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
417 if (status != SILC_SKE_STATUS_OK) {
420 silc_mp_uninit(&payload->x);
421 silc_free(payload->pk_data);
423 ske->status = status;
429 /* Send the packet. */
430 if (ske->callbacks->send_packet)
431 (*ske->callbacks->send_packet)(ske, payload_buf,
432 SILC_PACKET_KEY_EXCHANGE_1,
433 ske->callbacks->context);
435 silc_buffer_free(payload_buf);
440 /* An initiator finish final callback that is called to indicate that
441 the SKE protocol may continue. */
443 static void silc_ske_initiator_finish_final(SilcSKE ske,
444 SilcSKEStatus status,
447 SilcSKEKEPayload *payload;
448 unsigned char hash[32];
450 SilcPublicKey public_key = NULL;
452 /* If the SKE was freed during the async call then free it really now,
453 otherwise just decrement the reference counter. */
454 if (ske->status == SILC_SKE_STATUS_FREED) {
459 /* If the caller returns PENDING status SKE library will assume that
460 the caller will re-call this callback when it is not anymore in
462 if (status == SILC_SKE_STATUS_PENDING)
466 payload = ske->ke2_payload;
468 /* If the status is an error then the public key that was verified
469 by the caller is not authentic. */
470 if (status != SILC_SKE_STATUS_OK) {
471 ske->status = status;
472 if (ske->callbacks->proto_continue)
473 ske->callbacks->proto_continue(ske, ske->callbacks->context);
477 if (payload->pk_data) {
478 /* Decode the public key */
479 if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
481 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
482 if (ske->callbacks->proto_continue)
483 ske->callbacks->proto_continue(ske, ske->callbacks->context);
487 SILC_LOG_DEBUG(("Public key is authentic"));
489 /* Compute the hash value */
490 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
491 if (status != SILC_SKE_STATUS_OK)
494 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
495 memcpy(ske->hash, hash, hash_len);
496 ske->hash_len = hash_len;
498 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
500 /* Verify signature */
501 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
502 if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
503 payload->sign_len, hash, hash_len) == FALSE) {
505 SILC_LOG_DEBUG(("Signature don't match"));
507 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
511 SILC_LOG_DEBUG(("Signature is Ok"));
513 silc_pkcs_public_key_free(public_key);
514 memset(hash, 'F', hash_len);
517 ske->status = SILC_SKE_STATUS_OK;
519 /* Call the callback. The caller may now continue the SKE protocol. */
520 if (ske->callbacks->proto_continue)
521 ske->callbacks->proto_continue(ske, ske->callbacks->context);
526 memset(hash, 'F', sizeof(hash));
527 silc_ske_payload_ke_free(payload);
528 ske->ke2_payload = NULL;
530 silc_mp_uninit(ske->KEY);
535 silc_pkcs_public_key_free(public_key);
538 memset(ske->hash, 'F', hash_len);
539 silc_free(ske->hash);
543 if (status == SILC_SKE_STATUS_OK)
544 ske->status = SILC_SKE_STATUS_ERROR;
546 ske->status = status;
548 /* Call the callback. */
549 if (ske->callbacks->proto_continue)
550 ske->callbacks->proto_continue(ske, ske->callbacks->context);
553 /* Receives Key Exchange Payload from responder consisting responders
554 public key, f, and signature. This function verifies the public key,
555 computes the secret shared key and verifies the signature.
557 The `proto_continue' will be called to indicate that the caller may
558 continue with the SKE protocol. The caller must not continue
559 before the SKE libary has called that callback. If this function
560 returns an error the callback will not be called. It is called
561 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
562 However, note that when the library calls the callback the ske->status
565 This calls the `verify_key' callback to verify the received public
566 key or certificate. If the `verify_key' is provided then the remote
567 must send public key and it is considered to be an error if remote
568 does not send its public key. If caller is performing a re-key with
569 SKE then the `verify_key' is usually not provided when it is not also
570 required for the remote to send its public key. */
572 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
573 SilcBuffer ke_payload)
575 SilcSKEStatus status = SILC_SKE_STATUS_OK;
576 SilcSKEKEPayload *payload;
579 SILC_LOG_DEBUG(("Start"));
581 /* Decode the payload */
582 status = silc_ske_payload_ke_decode(ske, ke_payload, &payload);
583 if (status != SILC_SKE_STATUS_OK) {
584 ske->status = status;
587 ske->ke2_payload = payload;
589 if (!payload->pk_data && ske->callbacks->verify_key) {
590 SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
591 "even though we require it"));
592 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
596 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
598 /* Compute the shared secret key */
599 KEY = silc_calloc(1, sizeof(*KEY));
601 silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
604 if (payload->pk_data && ske->callbacks->verify_key) {
605 SILC_LOG_DEBUG(("Verifying public key"));
608 (*ske->callbacks->verify_key)(ske, payload->pk_data, payload->pk_len,
609 payload->pk_type, ske->callbacks->context,
610 silc_ske_initiator_finish_final, NULL);
612 /* We will continue to the final state after the public key has
613 been verified by the caller. */
614 return SILC_SKE_STATUS_PENDING;
617 /* Continue to final state */
619 silc_ske_initiator_finish_final(ske, SILC_SKE_STATUS_OK, NULL);
621 return SILC_SKE_STATUS_OK;
624 silc_ske_payload_ke_free(payload);
625 ske->ke2_payload = NULL;
627 silc_mp_uninit(ske->KEY);
631 if (status == SILC_SKE_STATUS_OK)
632 return SILC_SKE_STATUS_ERROR;
634 ske->status = status;
638 /* Starts Key Exchange protocol for responder. Responder receives
639 Key Exchange Start Payload from initiator consisting of all the
640 security properties the initiator supports. This function decodes
641 the payload and parses the payload further and selects the right
642 security properties. */
644 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
645 SilcSocketConnection sock,
647 SilcBuffer start_payload,
648 SilcSKESecurityPropertyFlag flags)
650 SilcSKEStatus status = SILC_SKE_STATUS_OK;
651 SilcSKEStartPayload *remote_payload = NULL, *payload = NULL;
653 SILC_LOG_DEBUG(("Start"));
658 /* Decode the payload */
659 status = silc_ske_payload_start_decode(ske, start_payload, &remote_payload);
660 if (status != SILC_SKE_STATUS_OK) {
661 ske->status = status;
665 /* Take a copy of the payload buffer for future use. It is used to
666 compute the HASH value. */
667 ske->start_payload_copy = silc_buffer_copy(start_payload);
669 /* Force the mutual authentication flag if we want to do it. */
670 if (flags & SILC_SKE_SP_FLAG_MUTUAL) {
671 SILC_LOG_DEBUG(("Force mutual authentication"));
672 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
675 /* Force PFS flag if we require it */
676 if (flags & SILC_SKE_SP_FLAG_PFS) {
677 SILC_LOG_DEBUG(("Force PFS"));
678 remote_payload->flags |= SILC_SKE_SP_FLAG_PFS;
681 /* Parse and select the security properties from the payload */
682 payload = silc_calloc(1, sizeof(*payload));
683 status = silc_ske_select_security_properties(ske, version,
684 payload, remote_payload);
685 if (status != SILC_SKE_STATUS_OK)
688 ske->start_payload = payload;
690 /* Call the callback function. */
691 if (ske->callbacks->payload_receive)
692 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
694 silc_ske_payload_start_free(remote_payload);
700 silc_ske_payload_start_free(remote_payload);
704 if (status == SILC_SKE_STATUS_OK)
705 return SILC_SKE_STATUS_ERROR;
707 ske->status = status;
711 /* The selected security properties from the initiator payload is now
712 encoded into Key Exchange Start Payload and sent to the initiator. */
714 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske)
716 SilcSKEStatus status = SILC_SKE_STATUS_OK;
717 SilcBuffer payload_buf;
718 SilcSKESecurityProperties prop;
719 SilcSKEDiffieHellmanGroup group = NULL;
721 SILC_LOG_DEBUG(("Start"));
723 /* Allocate security properties from the payload. These are allocated
724 only for this negotiation and will be free'd after KE is over. */
725 ske->prop = prop = silc_calloc(1, sizeof(*prop));
726 prop->flags = ske->start_payload->flags;
727 status = silc_ske_group_get_by_name(ske->start_payload->ke_grp_list, &group);
728 if (status != SILC_SKE_STATUS_OK)
733 if (silc_pkcs_alloc(ske->start_payload->pkcs_alg_list,
734 &prop->pkcs) == FALSE) {
735 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
739 if (silc_cipher_alloc(ske->start_payload->enc_alg_list,
740 &prop->cipher) == FALSE) {
741 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
745 if (silc_hash_alloc(ske->start_payload->hash_alg_list,
746 &prop->hash) == FALSE) {
747 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
751 if (silc_hmac_alloc(ske->start_payload->hmac_alg_list, NULL,
752 &prop->hmac) == FALSE) {
753 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
757 /* Encode the payload */
758 status = silc_ske_payload_start_encode(ske, ske->start_payload,
760 if (status != SILC_SKE_STATUS_OK)
763 /* Send the packet. */
764 if (ske->callbacks->send_packet)
765 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
766 ske->callbacks->context);
768 silc_buffer_free(payload_buf);
774 silc_ske_group_free(group);
777 silc_pkcs_free(prop->pkcs);
779 silc_cipher_free(prop->cipher);
781 silc_hash_free(prop->hash);
783 silc_hmac_free(prop->hmac);
787 if (status == SILC_SKE_STATUS_OK)
788 return SILC_SKE_STATUS_ERROR;
790 ske->status = status;
794 /* An responder phase 2 final callback that is called to indicate that
795 the SKE protocol may continue. */
797 static void silc_ske_responder_phase2_final(SilcSKE ske,
798 SilcSKEStatus status,
801 SilcSKEKEPayload *recv_payload, *send_payload;
804 /* If the SKE was freed during the async call then free it really now,
805 otherwise just decrement the reference counter. */
806 if (ske->status == SILC_SKE_STATUS_FREED) {
811 /* If the caller returns PENDING status SKE library will assume that
812 the caller will re-call this callback when it is not anymore in
814 if (status == SILC_SKE_STATUS_PENDING)
818 recv_payload = ske->ke1_payload;
820 /* If the status is an error then the public key that was verified
821 by the caller is not authentic. */
822 if (status != SILC_SKE_STATUS_OK) {
823 ske->status = status;
824 if (ske->callbacks->proto_continue)
825 ske->callbacks->proto_continue(ske, ske->callbacks->context);
829 /* The public key verification was performed only if the Mutual
830 Authentication flag is set. */
831 if (ske->start_payload &&
832 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
833 SilcPublicKey public_key = NULL;
834 unsigned char hash[32];
837 /* Decode the public key */
838 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
839 recv_payload->pk_len,
841 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
842 if (ske->callbacks->proto_continue)
843 ske->callbacks->proto_continue(ske, ske->callbacks->context);
847 SILC_LOG_DEBUG(("Public key is authentic"));
849 /* Compute the hash value */
850 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
851 if (status != SILC_SKE_STATUS_OK) {
852 ske->status = status;
853 if (ske->callbacks->proto_continue)
854 ske->callbacks->proto_continue(ske, ske->callbacks->context);
858 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
860 /* Verify signature */
861 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
862 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
863 recv_payload->sign_len, hash, hash_len) == FALSE) {
865 SILC_LOG_DEBUG(("Signature don't match"));
867 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
868 if (ske->callbacks->proto_continue)
869 ske->callbacks->proto_continue(ske, ske->callbacks->context);
873 SILC_LOG_DEBUG(("Signature is Ok"));
875 silc_pkcs_public_key_free(public_key);
876 memset(hash, 'F', hash_len);
879 /* Create the random number x, 1 < x < q. */
880 x = silc_calloc(1, sizeof(*x));
883 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
884 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
886 if (status != SILC_SKE_STATUS_OK) {
889 ske->status = status;
890 if (ske->callbacks->proto_continue)
891 ske->callbacks->proto_continue(ske, ske->callbacks->context);
895 /* Save the results for later processing */
896 send_payload = silc_calloc(1, sizeof(*send_payload));
898 ske->ke2_payload = send_payload;
900 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
902 /* Do the Diffie Hellman computation, f = g ^ x mod p */
903 silc_mp_init(&send_payload->x);
904 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
905 &ske->prop->group->group);
907 /* Call the callback. The caller may now continue with the SKE protocol. */
908 ske->status = SILC_SKE_STATUS_OK;
909 if (ske->callbacks->proto_continue)
910 ske->callbacks->proto_continue(ske, ske->callbacks->context);
913 /* This function receives the Key Exchange Payload from the initiator.
914 This also performs the mutual authentication if required. Then, this
915 function first generated a random number x, such that 1 < x < q
916 and computes f = g ^ x mod p. This then puts the result f to a Key
919 The `proto_continue' will be called to indicate that the caller may
920 continue with the SKE protocol. The caller must not continue
921 before the SKE libary has called that callback. If this function
922 returns an error the callback will not be called. It is called
923 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
924 However, note that when the library calls the callback the ske->status
927 This calls the `verify_key' callback to verify the received public
928 key or certificate if the Mutual Authentication flag is set. If the
929 `verify_key' is provided then the remote must send public key and it
930 is considered to be an error if remote does not send its public key. */
932 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
933 SilcBuffer ke_payload)
935 SilcSKEStatus status = SILC_SKE_STATUS_OK;
936 SilcSKEKEPayload *recv_payload;
938 SILC_LOG_DEBUG(("Start"));
940 /* Decode Key Exchange Payload */
941 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
942 if (status != SILC_SKE_STATUS_OK) {
943 ske->status = status;
947 ske->ke1_payload = recv_payload;
949 /* Verify the received public key and verify the signature if we are
950 doing mutual authentication. */
951 if (ske->start_payload &&
952 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
954 SILC_LOG_DEBUG(("We are doing mutual authentication"));
956 if (!recv_payload->pk_data && ske->callbacks->verify_key) {
957 SILC_LOG_DEBUG(("Remote end did not send its public key (or "
958 "certificate), even though we require it"));
959 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
963 if (recv_payload->pk_data && ske->callbacks->verify_key) {
964 SILC_LOG_DEBUG(("Verifying public key"));
967 (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
968 recv_payload->pk_len,
969 recv_payload->pk_type,
970 ske->callbacks->context,
971 silc_ske_responder_phase2_final, NULL);
973 /* We will continue to the final state after the public key has
974 been verified by the caller. */
975 return SILC_SKE_STATUS_PENDING;
979 /* Continue to final state */
981 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
983 return SILC_SKE_STATUS_OK;
986 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
987 value to be signed and sent to the other end. This then encodes Key
988 Exchange Payload and sends it to the other end. */
990 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
991 SilcPublicKey public_key,
992 SilcPrivateKey private_key,
993 SilcSKEPKType pk_type)
995 SilcSKEStatus status = SILC_SKE_STATUS_OK;
996 SilcBuffer payload_buf;
998 unsigned char hash[32], sign[2048], *pk;
999 SilcUInt32 hash_len, sign_len, pk_len;
1001 SILC_LOG_DEBUG(("Start"));
1003 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
1005 /* Compute the shared secret key */
1006 KEY = silc_calloc(1, sizeof(*KEY));
1008 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
1009 &ske->prop->group->group);
1012 if (public_key && private_key) {
1013 SILC_LOG_DEBUG(("Getting public key"));
1015 /* Get the public key */
1016 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
1018 status = SILC_SKE_STATUS_ERROR;
1021 ske->ke2_payload->pk_data = pk;
1022 ske->ke2_payload->pk_len = pk_len;
1024 SILC_LOG_DEBUG(("Computing HASH value"));
1026 /* Compute the hash value */
1027 memset(hash, 0, sizeof(hash));
1028 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1029 if (status != SILC_SKE_STATUS_OK)
1032 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
1033 memcpy(ske->hash, hash, hash_len);
1034 ske->hash_len = hash_len;
1036 SILC_LOG_DEBUG(("Signing HASH value"));
1038 /* Sign the hash value */
1039 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
1040 private_key->prv_len);
1041 if (silc_pkcs_get_key_len(ske->prop->pkcs) > sizeof(sign) - 1 ||
1042 !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len))
1044 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
1045 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
1046 memset(sign, 0, sizeof(sign));
1047 ske->ke2_payload->sign_len = sign_len;
1049 ske->ke2_payload->pk_type = pk_type;
1051 /* Encode the Key Exchange Payload */
1052 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
1054 if (status != SILC_SKE_STATUS_OK)
1057 /* Send the packet. */
1058 if (ske->callbacks->send_packet)
1059 (*ske->callbacks->send_packet)(ske, payload_buf,
1060 SILC_PACKET_KEY_EXCHANGE_2,
1061 ske->callbacks->context);
1063 silc_buffer_free(payload_buf);
1068 silc_mp_uninit(ske->KEY);
1069 silc_free(ske->KEY);
1071 silc_ske_payload_ke_free(ske->ke2_payload);
1073 if (status == SILC_SKE_STATUS_OK)
1074 return SILC_SKE_STATUS_ERROR;
1076 ske->status = status;
1080 /* The Key Exchange protocol is ended by calling this function. This
1081 must not be called until the keys are processed like the protocol
1082 defines. This function is for both initiator and responder. */
1084 SilcSKEStatus silc_ske_end(SilcSKE ske)
1088 SILC_LOG_DEBUG(("Start"));
1090 packet = silc_buffer_alloc(4);
1091 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1092 silc_buffer_format(packet,
1093 SILC_STR_UI_INT((SilcUInt32)SILC_SKE_STATUS_OK),
1096 if (ske->callbacks->send_packet)
1097 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS,
1098 ske->callbacks->context);
1100 silc_buffer_free(packet);
1102 return SILC_SKE_STATUS_OK;
1105 /* Aborts the Key Exchange protocol. This is called if error occurs
1106 while performing the protocol. The status argument is the error
1107 status and it is sent to the remote end. */
1109 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
1113 SILC_LOG_DEBUG(("Start"));
1115 if (status > SILC_SKE_STATUS_INVALID_COOKIE)
1116 status = SILC_SKE_STATUS_BAD_PAYLOAD;
1118 packet = silc_buffer_alloc(4);
1119 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1120 silc_buffer_format(packet,
1121 SILC_STR_UI_INT((SilcUInt32)status),
1124 if (ske->callbacks->send_packet)
1125 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
1126 ske->callbacks->context);
1128 silc_buffer_free(packet);
1130 return SILC_SKE_STATUS_OK;
1133 /* Assembles security properties to Key Exchange Start Payload to be
1134 sent to the remote end. This checks system wide (SILC system, that is)
1135 settings and chooses from those. However, if other properties
1136 should be used this function is easy to replace by another function,
1137 as, this function is called by the caller of the protocol and not
1138 by the protocol itself. */
1141 silc_ske_assemble_security_properties(SilcSKE ske,
1142 SilcSKESecurityPropertyFlag flags,
1143 const char *version,
1144 SilcSKEStartPayload **return_payload)
1146 SilcSKEStartPayload *rp;
1149 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1151 rp = silc_calloc(1, sizeof(*rp));
1154 rp->flags = (unsigned char)flags;
1156 /* Set random cookie */
1157 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1158 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1159 rp->cookie[i] = silc_rng_get_byte(ske->rng);
1160 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1163 rp->version = strdup(version);
1164 rp->version_len = strlen(version);
1166 /* Get supported Key Exhange groups */
1167 rp->ke_grp_list = silc_ske_get_supported_groups();
1168 rp->ke_grp_len = strlen(rp->ke_grp_list);
1170 /* Get supported PKCS algorithms */
1171 rp->pkcs_alg_list = silc_pkcs_get_supported();
1172 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1174 /* Get supported encryption algorithms */
1175 rp->enc_alg_list = silc_cipher_get_supported();
1176 rp->enc_alg_len = strlen(rp->enc_alg_list);
1178 /* Get supported hash algorithms */
1179 rp->hash_alg_list = silc_hash_get_supported();
1180 rp->hash_alg_len = strlen(rp->hash_alg_list);
1182 /* Get supported HMACs */
1183 rp->hmac_alg_list = silc_hmac_get_supported();
1184 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1187 /* Get supported compression algorithms */
1188 rp->comp_alg_list = strdup("");
1189 rp->comp_alg_len = 0;
1191 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1192 2 + rp->version_len +
1193 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1194 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1195 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1197 *return_payload = rp;
1199 return SILC_SKE_STATUS_OK;
1202 /* Selects the supported security properties from the remote end's Key
1203 Exchange Start Payload. */
1206 silc_ske_select_security_properties(SilcSKE ske,
1207 const char *version,
1208 SilcSKEStartPayload *payload,
1209 SilcSKEStartPayload *remote_payload)
1211 SilcSKEStatus status;
1212 SilcSKEStartPayload *rp;
1216 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1218 rp = remote_payload;
1220 /* Check version string */
1221 if (ske->callbacks->check_version) {
1222 status = ske->callbacks->check_version(ske, rp->version,
1224 ske->callbacks->context);
1225 if (status != SILC_SKE_STATUS_OK) {
1226 ske->status = status;
1231 ske->remote_version = silc_memdup(rp->version, rp->version_len);
1233 /* Flags are returned unchanged. */
1234 payload->flags = rp->flags;
1236 /* Take cookie, we must return it to sender unmodified. */
1237 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1238 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1239 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1241 /* Put our version to our reply */
1242 payload->version = strdup(version);
1243 payload->version_len = strlen(version);
1245 /* Get supported Key Exchange groups */
1246 cp = rp->ke_grp_list;
1247 if (cp && strchr(cp, ',')) {
1251 len = strcspn(cp, ",");
1252 item = silc_calloc(len + 1, sizeof(char));
1253 memcpy(item, cp, len);
1255 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1257 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1258 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1260 payload->ke_grp_len = len;
1261 payload->ke_grp_list = item;
1266 if (strlen(cp) == 0)
1275 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1276 SILC_LOG_DEBUG(("Could not find supported KE group"));
1278 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1282 if (!rp->ke_grp_len) {
1283 SILC_LOG_DEBUG(("KE group not defined in payload"));
1285 return SILC_SKE_STATUS_BAD_PAYLOAD;
1288 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1289 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1291 payload->ke_grp_len = rp->ke_grp_len;
1292 payload->ke_grp_list = strdup(rp->ke_grp_list);
1295 /* Get supported PKCS algorithms */
1296 cp = rp->pkcs_alg_list;
1297 if (cp && strchr(cp, ',')) {
1301 len = strcspn(cp, ",");
1302 item = silc_calloc(len + 1, sizeof(char));
1303 memcpy(item, cp, len);
1305 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1307 if (silc_pkcs_is_supported(item) == TRUE) {
1308 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1310 payload->pkcs_alg_len = len;
1311 payload->pkcs_alg_list = item;
1316 if (strlen(cp) == 0)
1325 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1326 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1327 silc_free(payload->ke_grp_list);
1329 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1333 if (!rp->pkcs_alg_len) {
1334 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1335 silc_free(payload->ke_grp_list);
1337 return SILC_SKE_STATUS_BAD_PAYLOAD;
1340 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1341 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1343 payload->pkcs_alg_len = rp->pkcs_alg_len;
1344 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1347 /* Get supported encryption algorithms */
1348 cp = rp->enc_alg_list;
1349 if (cp && strchr(cp, ',')) {
1353 len = strcspn(cp, ",");
1354 item = silc_calloc(len + 1, sizeof(char));
1355 memcpy(item, cp, len);
1357 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1359 if (silc_cipher_is_supported(item) == TRUE) {
1360 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1362 payload->enc_alg_len = len;
1363 payload->enc_alg_list = item;
1368 if (strlen(cp) == 0)
1377 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1378 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1379 silc_free(payload->ke_grp_list);
1380 silc_free(payload->pkcs_alg_list);
1382 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1386 if (!rp->enc_alg_len) {
1387 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1388 silc_free(payload->ke_grp_list);
1389 silc_free(payload->pkcs_alg_list);
1391 return SILC_SKE_STATUS_BAD_PAYLOAD;
1394 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1397 payload->enc_alg_len = rp->enc_alg_len;
1398 payload->enc_alg_list = strdup(rp->enc_alg_list);
1401 /* Get supported hash algorithms */
1402 cp = rp->hash_alg_list;
1403 if (cp && strchr(cp, ',')) {
1407 len = strcspn(cp, ",");
1408 item = silc_calloc(len + 1, sizeof(char));
1409 memcpy(item, cp, len);
1411 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1413 if (silc_hash_is_supported(item) == TRUE) {
1414 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1416 payload->hash_alg_len = len;
1417 payload->hash_alg_list = item;
1422 if (strlen(cp) == 0)
1431 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1432 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1433 silc_free(payload->ke_grp_list);
1434 silc_free(payload->pkcs_alg_list);
1435 silc_free(payload->enc_alg_list);
1437 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1441 if (!rp->hash_alg_len) {
1442 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1443 silc_free(payload->ke_grp_list);
1444 silc_free(payload->pkcs_alg_list);
1445 silc_free(payload->enc_alg_list);
1447 return SILC_SKE_STATUS_BAD_PAYLOAD;
1450 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1451 rp->hash_alg_list));
1453 payload->hash_alg_len = rp->hash_alg_len;
1454 payload->hash_alg_list = strdup(rp->hash_alg_list);
1457 /* Get supported HMACs */
1458 cp = rp->hmac_alg_list;
1459 if (cp && strchr(cp, ',')) {
1463 len = strcspn(cp, ",");
1464 item = silc_calloc(len + 1, sizeof(char));
1465 memcpy(item, cp, len);
1467 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1469 if (silc_hmac_is_supported(item) == TRUE) {
1470 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1472 payload->hmac_alg_len = len;
1473 payload->hmac_alg_list = item;
1478 if (strlen(cp) == 0)
1487 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1488 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1489 silc_free(payload->ke_grp_list);
1490 silc_free(payload->pkcs_alg_list);
1491 silc_free(payload->enc_alg_list);
1492 silc_free(payload->hash_alg_list);
1494 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1498 if (!rp->hmac_alg_len) {
1499 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1500 silc_free(payload->ke_grp_list);
1501 silc_free(payload->pkcs_alg_list);
1502 silc_free(payload->enc_alg_list);
1503 silc_free(payload->hash_alg_list);
1505 return SILC_SKE_STATUS_BAD_PAYLOAD;
1508 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1509 rp->hmac_alg_list));
1511 payload->hmac_alg_len = rp->hmac_alg_len;
1512 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1516 /* Get supported compression algorithms */
1517 cp = rp->hash_alg_list;
1518 if (cp && strchr(cp, ',')) {
1522 len = strcspn(cp, ",");
1523 item = silc_calloc(len + 1, sizeof(char));
1524 memcpy(item, cp, len);
1526 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1528 if (silc_hash_is_supported(item) == TRUE) {
1529 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1531 payload->hash_alg_len = len;
1532 payload->hash_alg_list = item;
1537 if (strlen(cp) == 0)
1546 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1547 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1548 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1549 silc_free(payload->ke_grp_list);
1550 silc_free(payload->pkcs_alg_list);
1551 silc_free(payload->enc_alg_list);
1560 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1561 2 + payload->version_len +
1562 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1563 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1564 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1566 return SILC_SKE_STATUS_OK;
1569 /* Creates random number such that 1 < rnd < n and at most length
1570 of len bits. The rnd sent as argument must be initialized. */
1572 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1576 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1577 unsigned char *string;
1579 SILC_LOG_DEBUG(("Creating random number"));
1581 /* Get the random number as string */
1582 string = silc_rng_get_rn_data(ske->rng, (len / 8));
1584 return SILC_SKE_STATUS_ERROR;
1586 /* Decode the string into a MP integer */
1587 silc_mp_bin2mp(string, (len / 8), rnd);
1588 silc_mp_mod_2exp(rnd, rnd, len);
1591 if (silc_mp_cmp_ui(rnd, 1) < 0)
1592 status = SILC_SKE_STATUS_ERROR;
1594 if (silc_mp_cmp(rnd, n) >= 0)
1595 status = SILC_SKE_STATUS_ERROR;
1597 memset(string, 'F', (len / 8));
1603 /* Creates a hash value HASH as defined in the SKE protocol. If the
1604 `initiator' is TRUE then this function is used to create the HASH_i
1605 hash value defined in the protocol. If it is FALSE then this is used
1606 to create the HASH value defined by the protocol. */
1608 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1609 unsigned char *return_hash,
1610 SilcUInt32 *return_hash_len,
1613 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1615 unsigned char *e, *f, *KEY;
1616 SilcUInt32 e_len, f_len, KEY_len;
1619 SILC_LOG_DEBUG(("Start"));
1621 if (initiator == FALSE) {
1622 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1623 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1624 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1626 /* Format the buffer used to compute the hash value */
1627 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1628 ske->ke2_payload->pk_len +
1629 ske->ke1_payload->pk_len +
1630 e_len + f_len + KEY_len);
1631 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1633 /* Initiator is not required to send its public key */
1634 if (!ske->ke1_payload->pk_data) {
1636 silc_buffer_format(buf,
1637 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1639 ske->start_payload_copy->
1641 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1642 ske->ke2_payload->pk_len),
1643 SILC_STR_UI_XNSTRING(e, e_len),
1644 SILC_STR_UI_XNSTRING(f, f_len),
1645 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1649 silc_buffer_format(buf,
1650 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1652 ske->start_payload_copy->
1654 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1655 ske->ke2_payload->pk_len),
1656 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1657 ske->ke1_payload->pk_len),
1658 SILC_STR_UI_XNSTRING(e, e_len),
1659 SILC_STR_UI_XNSTRING(f, f_len),
1660 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1664 silc_buffer_free(buf);
1665 memset(e, 0, e_len);
1666 memset(f, 0, f_len);
1667 memset(KEY, 0, KEY_len);
1671 return SILC_SKE_STATUS_ERROR;
1674 memset(e, 0, e_len);
1675 memset(f, 0, f_len);
1676 memset(KEY, 0, KEY_len);
1681 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1683 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1684 ske->ke1_payload->pk_len + e_len);
1685 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1687 /* Format the buffer used to compute the hash value */
1689 silc_buffer_format(buf,
1690 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1691 ske->start_payload_copy->len),
1692 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1693 ske->ke1_payload->pk_len),
1694 SILC_STR_UI_XNSTRING(e, e_len),
1697 silc_buffer_free(buf);
1698 memset(e, 0, e_len);
1700 return SILC_SKE_STATUS_ERROR;
1703 memset(e, 0, e_len);
1708 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1709 *return_hash_len = silc_hash_len(ske->prop->hash);
1711 if (initiator == FALSE) {
1712 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1714 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1717 silc_buffer_free(buf);
1722 /* Processes the provided key material `data' as the SILC protocol
1723 specification defines. */
1726 silc_ske_process_key_material_data(unsigned char *data,
1727 SilcUInt32 data_len,
1728 SilcUInt32 req_iv_len,
1729 SilcUInt32 req_enc_key_len,
1730 SilcUInt32 req_hmac_key_len,
1732 SilcSKEKeyMaterial *key)
1735 unsigned char hashd[32];
1736 SilcUInt32 hash_len = req_hmac_key_len;
1737 SilcUInt32 enc_key_len = req_enc_key_len / 8;
1739 SILC_LOG_DEBUG(("Start"));
1741 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1742 return SILC_SKE_STATUS_ERROR;
1744 buf = silc_buffer_alloc(1 + data_len);
1745 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1746 silc_buffer_format(buf,
1747 SILC_STR_UI_CHAR(0),
1748 SILC_STR_UI_XNSTRING(data, data_len),
1752 memset(hashd, 0, sizeof(hashd));
1754 silc_hash_make(hash, buf->data, buf->len, hashd);
1755 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1756 memcpy(key->send_iv, hashd, req_iv_len);
1757 memset(hashd, 0, sizeof(hashd));
1759 silc_hash_make(hash, buf->data, buf->len, hashd);
1760 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1761 memcpy(key->receive_iv, hashd, req_iv_len);
1762 key->iv_len = req_iv_len;
1764 /* Take the encryption keys. If requested key size is more than
1765 the size of hash length we will distribute more key material
1766 as protocol defines. */
1768 if (enc_key_len > hash_len) {
1770 unsigned char k1[32], k2[32], k3[32];
1771 unsigned char *dtmp;
1774 if (enc_key_len > (3 * hash_len))
1775 return SILC_SKE_STATUS_ERROR;
1777 /* Take first round */
1778 memset(k1, 0, sizeof(k1));
1779 silc_hash_make(hash, buf->data, buf->len, k1);
1781 /* Take second round */
1782 dist = silc_buffer_alloc(data_len + hash_len);
1783 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1784 silc_buffer_format(dist,
1785 SILC_STR_UI_XNSTRING(data, data_len),
1786 SILC_STR_UI_XNSTRING(k1, hash_len),
1788 memset(k2, 0, sizeof(k2));
1789 silc_hash_make(hash, dist->data, dist->len, k2);
1791 /* Take third round */
1792 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1793 silc_buffer_pull_tail(dist, hash_len);
1794 silc_buffer_pull(dist, data_len + hash_len);
1795 silc_buffer_format(dist,
1796 SILC_STR_UI_XNSTRING(k2, hash_len),
1798 silc_buffer_push(dist, data_len + hash_len);
1799 memset(k3, 0, sizeof(k3));
1800 silc_hash_make(hash, dist->data, dist->len, k3);
1802 /* Then, save the keys */
1803 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1804 memcpy(dtmp, k1, hash_len);
1805 memcpy(dtmp + hash_len, k2, hash_len);
1806 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1808 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1809 memcpy(key->send_enc_key, dtmp, enc_key_len);
1810 key->enc_key_len = req_enc_key_len;
1812 memset(dtmp, 0, (3 * hash_len));
1813 memset(k1, 0, sizeof(k1));
1814 memset(k2, 0, sizeof(k2));
1815 memset(k3, 0, sizeof(k3));
1817 silc_buffer_free(dist);
1819 /* Take normal hash as key */
1820 memset(hashd, 0, sizeof(hashd));
1821 silc_hash_make(hash, buf->data, buf->len, hashd);
1822 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1823 memcpy(key->send_enc_key, hashd, enc_key_len);
1824 key->enc_key_len = req_enc_key_len;
1828 if (enc_key_len > hash_len) {
1830 unsigned char k1[32], k2[32], k3[32];
1831 unsigned char *dtmp;
1834 if (enc_key_len > (3 * hash_len))
1835 return SILC_SKE_STATUS_ERROR;
1837 /* Take first round */
1838 memset(k1, 0, sizeof(k1));
1839 silc_hash_make(hash, buf->data, buf->len, k1);
1841 /* Take second round */
1842 dist = silc_buffer_alloc(data_len + hash_len);
1843 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1844 silc_buffer_format(dist,
1845 SILC_STR_UI_XNSTRING(data, data_len),
1846 SILC_STR_UI_XNSTRING(k1, hash_len),
1848 memset(k2, 0, sizeof(k2));
1849 silc_hash_make(hash, dist->data, dist->len, k2);
1851 /* Take third round */
1852 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1853 silc_buffer_pull_tail(dist, hash_len);
1854 silc_buffer_pull(dist, data_len + hash_len);
1855 silc_buffer_format(dist,
1856 SILC_STR_UI_XNSTRING(k2, hash_len),
1858 silc_buffer_push(dist, data_len + hash_len);
1859 memset(k3, 0, sizeof(k3));
1860 silc_hash_make(hash, dist->data, dist->len, k3);
1862 /* Then, save the keys */
1863 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1864 memcpy(dtmp, k1, hash_len);
1865 memcpy(dtmp + hash_len, k2, hash_len);
1866 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1868 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1869 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1870 key->enc_key_len = req_enc_key_len;
1872 memset(dtmp, 0, (3 * hash_len));
1873 memset(k1, 0, sizeof(k1));
1874 memset(k2, 0, sizeof(k2));
1875 memset(k3, 0, sizeof(k3));
1877 silc_buffer_free(dist);
1879 /* Take normal hash as key */
1880 memset(hashd, 0, sizeof(hashd));
1881 silc_hash_make(hash, buf->data, buf->len, hashd);
1882 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1883 memcpy(key->receive_enc_key, hashd, enc_key_len);
1884 key->enc_key_len = req_enc_key_len;
1887 /* Take HMAC keys */
1888 memset(hashd, 0, sizeof(hashd));
1890 silc_hash_make(hash, buf->data, buf->len, hashd);
1891 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1892 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1893 memset(hashd, 0, sizeof(hashd));
1895 silc_hash_make(hash, buf->data, buf->len, hashd);
1896 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1897 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1898 key->hmac_key_len = req_hmac_key_len;
1899 memset(hashd, 0, sizeof(hashd));
1901 silc_buffer_free(buf);
1903 return SILC_SKE_STATUS_OK;
1906 /* Processes negotiated key material as protocol specifies. This returns
1907 the actual keys to be used in the SILC. */
1909 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1910 SilcUInt32 req_iv_len,
1911 SilcUInt32 req_enc_key_len,
1912 SilcUInt32 req_hmac_key_len,
1913 SilcSKEKeyMaterial *key)
1915 SilcSKEStatus status;
1917 unsigned char *tmpbuf;
1920 /* Encode KEY to binary data */
1921 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1923 buf = silc_buffer_alloc(klen + ske->hash_len);
1924 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1925 silc_buffer_format(buf,
1926 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1927 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1930 /* Process the key material */
1931 status = silc_ske_process_key_material_data(buf->data, buf->len,
1932 req_iv_len, req_enc_key_len,
1934 ske->prop->hash, key);
1936 memset(tmpbuf, 0, klen);
1938 silc_buffer_free(buf);
1943 /* Free key material structure */
1945 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1951 silc_free(key->send_iv);
1952 if (key->receive_iv)
1953 silc_free(key->receive_iv);
1954 if (key->send_enc_key) {
1955 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1956 silc_free(key->send_enc_key);
1958 if (key->receive_enc_key) {
1959 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1960 silc_free(key->receive_enc_key);
1962 if (key->send_hmac_key) {
1963 memset(key->send_hmac_key, 0, key->hmac_key_len);
1964 silc_free(key->send_hmac_key);
1966 if (key->receive_hmac_key) {
1967 memset(key->receive_hmac_key, 0, key->hmac_key_len);
1968 silc_free(key->receive_hmac_key);
1973 const char *silc_ske_status_string[] =
1977 "Unkown error occurred",
1978 "Bad payload in packet",
1979 "Unsupported group",
1980 "Unsupported cipher",
1982 "Unsupported hash function",
1984 "Unsupported public key (or certificate)",
1985 "Incorrect signature",
1986 "Bad or unsupported version",
1991 "Remote did not provide public key",
1992 "Key exchange protocol is not active",
1993 "Bad reserved field in packet",
1994 "Bad payload length in packet",
2000 /* Maps status to readable string and returns the string. If string is not
2001 found and empty character string ("") is returned. */
2003 const char *silc_ske_map_status(SilcSKEStatus status)
2007 for (i = 0; silc_ske_status_string[i]; i++)
2009 return silc_ske_status_string[i];
2014 /* Parses remote host's version string. */
2016 bool silc_ske_parse_version(SilcSKE ske,
2017 SilcUInt32 *protocol_version,
2018 char **protocol_version_string,
2019 SilcUInt32 *software_version,
2020 char **software_version_string,
2021 char **vendor_version)
2023 return silc_parse_version_string(ske->remote_version,
2025 protocol_version_string,
2027 software_version_string,