5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2000 - 2005 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);
115 memset(ske, 'F', sizeof(*ske));
120 /* Sets the callback functions for the SKE session.
122 The `send_packet' callback is a function that sends the packet to
123 network. The SKE library will call it at any time packet needs to
124 be sent to the remote host.
126 The `payload_receive' callback is called when the remote host's Key
127 Exchange Start Payload has been processed. The payload is saved
128 to ske->start_payload if the application would need it. The application
129 must also provide the payload to the next state of the SKE.
131 The `verify_key' callback is called to verify the received public key
132 or certificate. The verification process is most likely asynchronous.
133 That is why the application must call the completion callback when the
134 verification process has been completed. The library then calls the user
135 callback (`proto_continue'), if it is provided to indicate that the SKE
136 protocol may continue.
138 The `proto_continue' callback is called to indicate that it is
139 safe to continue the execution of the SKE protocol after executing
140 an asynchronous operation, such as calling the `verify_key' callback
141 function, which is asynchronous. The application should check the
142 ske->status in this function to check whether it is Ok to continue
143 the execution of the protocol.
145 The `check_version' callback is called to verify the remote host's
146 version. The application may check its own version against the remote
147 host's version and determine whether supporting the remote host
150 The `context' is passed as argument to all of the above callback
153 void silc_ske_set_callbacks(SilcSKE ske,
154 SilcSKESendPacketCb send_packet,
155 SilcSKECb payload_receive,
156 SilcSKEVerifyCb verify_key,
157 SilcSKECb proto_continue,
158 SilcSKECheckVersion check_version,
162 silc_free(ske->callbacks);
163 ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
166 ske->callbacks->send_packet = send_packet;
167 ske->callbacks->payload_receive = payload_receive;
168 ske->callbacks->verify_key = verify_key;
169 ske->callbacks->proto_continue = proto_continue;
170 ske->callbacks->check_version = check_version;
171 ske->callbacks->context = context;
174 /* Starts the SILC Key Exchange protocol for initiator. The connection
175 to the remote end must be established before calling this function
176 and the connecting socket must be sent as argument. This function
177 creates the Key Exchange Start Payload which includes all our
178 configured security properties. This payload is then sent to the
179 remote end for further processing. This payload must be sent as
180 argument to the function, however, it must not be encoded
181 already, it is done by this function. The caller must not free
182 the `start_payload' since the SKE library will save it.
184 The packet sending is done by calling a callback function. Caller
185 must provide a routine to send the packet. */
187 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
188 SilcSocketConnection sock,
189 SilcSKEStartPayload *start_payload)
191 SilcSKEStatus status = SILC_SKE_STATUS_OK;
192 SilcBuffer payload_buf;
194 SILC_LOG_DEBUG(("Start"));
199 /* Encode the payload */
200 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
201 if (status != SILC_SKE_STATUS_OK)
204 /* Send the packet. */
205 if (ske->callbacks->send_packet)
206 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
207 ske->callbacks->context);
209 /* Save the the payload buffer for future use. It is later used to
210 compute the HASH value. */
211 ske->start_payload_copy = payload_buf;
212 ske->start_payload = start_payload;
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->ke1_payload = NULL;
393 ske->status = SILC_SKE_STATUS_OK;
396 payload->pk_len = pk_len;
398 payload->pk_type = pk_type;
400 /* Compute signature data if we are doing mutual authentication */
401 if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
402 unsigned char hash[SILC_HASH_MAXLEN], sign[2048 + 1];
403 SilcUInt32 hash_len, sign_len;
405 SILC_LOG_DEBUG(("We are doing mutual authentication"));
406 SILC_LOG_DEBUG(("Computing HASH_i value"));
408 /* Compute the hash value */
409 memset(hash, 0, sizeof(hash));
410 silc_ske_make_hash(ske, hash, &hash_len, TRUE);
412 SILC_LOG_DEBUG(("Signing HASH_i value"));
414 /* Sign the hash value */
415 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
416 private_key->prv_len);
417 if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
418 !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
421 silc_mp_uninit(&payload->x);
422 silc_free(payload->pk_data);
424 ske->ke1_payload = NULL;
425 ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
428 payload->sign_data = silc_memdup(sign, sign_len);
429 payload->sign_len = sign_len;
430 memset(sign, 0, sizeof(sign));
433 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
434 if (status != SILC_SKE_STATUS_OK) {
437 silc_mp_uninit(&payload->x);
438 silc_free(payload->pk_data);
439 silc_free(payload->sign_data);
441 ske->ke1_payload = NULL;
442 ske->status = status;
448 /* Send the packet. */
449 if (ske->callbacks->send_packet)
450 (*ske->callbacks->send_packet)(ske, payload_buf,
451 SILC_PACKET_KEY_EXCHANGE_1,
452 ske->callbacks->context);
454 silc_buffer_free(payload_buf);
459 /* An initiator finish final callback that is called to indicate that
460 the SKE protocol may continue. */
462 static void silc_ske_initiator_finish_final(SilcSKE ske,
463 SilcSKEStatus status,
466 SilcSKEKEPayload *payload;
467 unsigned char hash[SILC_HASH_MAXLEN];
469 SilcPublicKey public_key = NULL;
471 /* If the SKE was freed during the async call then free it really now,
472 otherwise just decrement the reference counter. */
473 if (ske->status == SILC_SKE_STATUS_FREED) {
478 /* If the caller returns PENDING status SKE library will assume that
479 the caller will re-call this callback when it is not anymore in
481 if (status == SILC_SKE_STATUS_PENDING)
485 payload = ske->ke2_payload;
487 /* If the status is an error then the public key that was verified
488 by the caller is not authentic. */
489 if (status != SILC_SKE_STATUS_OK) {
490 ske->status = status;
491 if (ske->callbacks->proto_continue)
492 ske->callbacks->proto_continue(ske, ske->callbacks->context);
496 if (payload->pk_data) {
497 /* Decode the public key */
498 if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
500 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
501 SILC_LOG_ERROR(("Unsupported/malformed public key received"));
502 if (ske->callbacks->proto_continue)
503 ske->callbacks->proto_continue(ske, ske->callbacks->context);
507 SILC_LOG_DEBUG(("Public key is authentic"));
509 /* Compute the hash value */
510 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
511 if (status != SILC_SKE_STATUS_OK)
514 ske->hash = silc_memdup(hash, hash_len);
515 ske->hash_len = hash_len;
517 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
519 /* Verify signature */
520 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
521 if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
522 payload->sign_len, hash, hash_len) == FALSE) {
523 SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
524 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
528 SILC_LOG_DEBUG(("Signature is Ok"));
530 silc_pkcs_public_key_free(public_key);
531 memset(hash, 'F', hash_len);
534 ske->status = SILC_SKE_STATUS_OK;
536 /* Call the callback. The caller may now continue the SKE protocol. */
537 if (ske->callbacks->proto_continue)
538 ske->callbacks->proto_continue(ske, ske->callbacks->context);
543 memset(hash, 'F', sizeof(hash));
544 silc_ske_payload_ke_free(payload);
545 ske->ke2_payload = NULL;
547 silc_mp_uninit(ske->KEY);
552 silc_pkcs_public_key_free(public_key);
555 memset(ske->hash, 'F', hash_len);
556 silc_free(ske->hash);
560 if (status == SILC_SKE_STATUS_OK)
561 ske->status = SILC_SKE_STATUS_ERROR;
563 ske->status = status;
565 /* Call the callback. */
566 if (ske->callbacks->proto_continue)
567 ske->callbacks->proto_continue(ske, ske->callbacks->context);
570 /* Receives Key Exchange Payload from responder consisting responders
571 public key, f, and signature. This function verifies the public key,
572 computes the secret shared key and verifies the signature.
574 The `proto_continue' will be called to indicate that the caller may
575 continue with the SKE protocol. The caller must not continue
576 before the SKE libary has called that callback. If this function
577 returns an error the callback will not be called. It is called
578 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
579 However, note that when the library calls the callback the ske->status
582 This calls the `verify_key' callback to verify the received public
583 key or certificate. If the `verify_key' is provided then the remote
584 must send public key and it is considered to be an error if remote
585 does not send its public key. If caller is performing a re-key with
586 SKE then the `verify_key' is usually not provided when it is not also
587 required for the remote to send its public key. */
589 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
590 SilcBuffer ke_payload)
592 SilcSKEStatus status = SILC_SKE_STATUS_OK;
593 SilcSKEKEPayload *payload;
596 SILC_LOG_DEBUG(("Start"));
598 /* Decode the payload */
599 status = silc_ske_payload_ke_decode(ske, ke_payload, &payload);
600 if (status != SILC_SKE_STATUS_OK) {
601 ske->status = status;
604 ske->ke2_payload = payload;
606 if (!payload->pk_data && ske->callbacks->verify_key) {
607 SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
608 "even though we require it"));
609 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
613 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
615 /* Compute the shared secret key */
616 KEY = silc_calloc(1, sizeof(*KEY));
618 silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
621 if (payload->pk_data && ske->callbacks->verify_key) {
622 SILC_LOG_DEBUG(("Verifying public key"));
625 (*ske->callbacks->verify_key)(ske, payload->pk_data, payload->pk_len,
626 payload->pk_type, ske->callbacks->context,
627 silc_ske_initiator_finish_final, NULL);
629 /* We will continue to the final state after the public key has
630 been verified by the caller. */
631 return SILC_SKE_STATUS_PENDING;
634 /* Continue to final state */
636 silc_ske_initiator_finish_final(ske, SILC_SKE_STATUS_OK, NULL);
638 return SILC_SKE_STATUS_OK;
641 silc_ske_payload_ke_free(payload);
642 ske->ke2_payload = NULL;
644 silc_mp_uninit(ske->KEY);
648 if (status == SILC_SKE_STATUS_OK)
649 return SILC_SKE_STATUS_ERROR;
651 ske->status = status;
655 /* Starts Key Exchange protocol for responder. Responder receives
656 Key Exchange Start Payload from initiator consisting of all the
657 security properties the initiator supports. This function decodes
658 the payload and parses the payload further and selects the right
659 security properties. */
661 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
662 SilcSocketConnection sock,
664 SilcBuffer start_payload,
665 SilcSKESecurityPropertyFlag flags)
667 SilcSKEStatus status = SILC_SKE_STATUS_OK;
668 SilcSKEStartPayload *remote_payload = NULL, *payload = NULL;
670 SILC_LOG_DEBUG(("Start"));
675 /* Decode the payload */
676 status = silc_ske_payload_start_decode(ske, start_payload, &remote_payload);
677 if (status != SILC_SKE_STATUS_OK) {
678 ske->status = status;
682 /* Take a copy of the payload buffer for future use. It is used to
683 compute the HASH value. */
684 ske->start_payload_copy = silc_buffer_copy(start_payload);
686 /* Force the mutual authentication flag if we want to do it. */
687 if (flags & SILC_SKE_SP_FLAG_MUTUAL) {
688 SILC_LOG_DEBUG(("Force mutual authentication"));
689 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
692 /* Force PFS flag if we require it */
693 if (flags & SILC_SKE_SP_FLAG_PFS) {
694 SILC_LOG_DEBUG(("Force PFS"));
695 remote_payload->flags |= SILC_SKE_SP_FLAG_PFS;
698 /* Disable IV Included flag if requested */
699 if (remote_payload->flags & SILC_SKE_SP_FLAG_IV_INCLUDED &&
700 !(flags & SILC_SKE_SP_FLAG_IV_INCLUDED)) {
701 SILC_LOG_DEBUG(("We do not support IV Included flag"));
702 remote_payload->flags &= ~SILC_SKE_SP_FLAG_IV_INCLUDED;
705 /* Parse and select the security properties from the payload */
706 payload = silc_calloc(1, sizeof(*payload));
707 status = silc_ske_select_security_properties(ske, version,
708 payload, remote_payload);
709 if (status != SILC_SKE_STATUS_OK)
712 ske->start_payload = payload;
714 /* Call the callback function. */
715 if (ske->callbacks->payload_receive)
716 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
718 silc_ske_payload_start_free(remote_payload);
724 silc_ske_payload_start_free(remote_payload);
727 if (status == SILC_SKE_STATUS_OK)
728 return SILC_SKE_STATUS_ERROR;
730 ske->status = status;
734 /* The selected security properties from the initiator payload is now
735 encoded into Key Exchange Start Payload and sent to the initiator. */
737 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske)
739 SilcSKEStatus status = SILC_SKE_STATUS_OK;
740 SilcBuffer payload_buf;
741 SilcSKESecurityProperties prop;
742 SilcSKEDiffieHellmanGroup group = NULL;
744 SILC_LOG_DEBUG(("Start"));
746 /* Allocate security properties from the payload. These are allocated
747 only for this negotiation and will be free'd after KE is over. */
748 ske->prop = prop = silc_calloc(1, sizeof(*prop));
749 prop->flags = ske->start_payload->flags;
750 status = silc_ske_group_get_by_name(ske->start_payload->ke_grp_list, &group);
751 if (status != SILC_SKE_STATUS_OK)
756 if (silc_pkcs_alloc(ske->start_payload->pkcs_alg_list,
757 &prop->pkcs) == FALSE) {
758 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
762 if (silc_cipher_alloc(ske->start_payload->enc_alg_list,
763 &prop->cipher) == FALSE) {
764 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
768 if (silc_hash_alloc(ske->start_payload->hash_alg_list,
769 &prop->hash) == FALSE) {
770 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
774 if (silc_hmac_alloc(ske->start_payload->hmac_alg_list, NULL,
775 &prop->hmac) == FALSE) {
776 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
780 /* Encode the payload */
781 status = silc_ske_payload_start_encode(ske, ske->start_payload,
783 if (status != SILC_SKE_STATUS_OK)
786 /* Send the packet. */
787 if (ske->callbacks->send_packet)
788 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
789 ske->callbacks->context);
791 silc_buffer_free(payload_buf);
797 silc_ske_group_free(group);
800 silc_pkcs_free(prop->pkcs);
802 silc_cipher_free(prop->cipher);
804 silc_hash_free(prop->hash);
806 silc_hmac_free(prop->hmac);
810 if (status == SILC_SKE_STATUS_OK)
811 return SILC_SKE_STATUS_ERROR;
813 ske->status = status;
817 /* An responder phase 2 final callback that is called to indicate that
818 the SKE protocol may continue. */
820 static void silc_ske_responder_phase2_final(SilcSKE ske,
821 SilcSKEStatus status,
824 SilcSKEKEPayload *recv_payload, *send_payload;
827 /* If the SKE was freed during the async call then free it really now,
828 otherwise just decrement the reference counter. */
829 if (ske->status == SILC_SKE_STATUS_FREED) {
834 /* If the caller returns PENDING status SKE library will assume that
835 the caller will re-call this callback when it is not anymore in
837 if (status == SILC_SKE_STATUS_PENDING)
841 recv_payload = ske->ke1_payload;
843 /* If the status is an error then the public key that was verified
844 by the caller is not authentic. */
845 if (status != SILC_SKE_STATUS_OK) {
846 ske->status = status;
847 if (ske->callbacks->proto_continue)
848 ske->callbacks->proto_continue(ske, ske->callbacks->context);
852 /* The public key verification was performed only if the Mutual
853 Authentication flag is set. */
854 if (ske->start_payload &&
855 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
856 SilcPublicKey public_key = NULL;
857 unsigned char hash[SILC_HASH_MAXLEN];
860 /* Decode the public key */
861 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
862 recv_payload->pk_len,
864 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
865 SILC_LOG_ERROR(("Unsupported/malformed public key received"));
866 if (ske->callbacks->proto_continue)
867 ske->callbacks->proto_continue(ske, ske->callbacks->context);
871 SILC_LOG_DEBUG(("Public key is authentic"));
873 /* Compute the hash value */
874 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
875 if (status != SILC_SKE_STATUS_OK) {
876 ske->status = status;
877 if (ske->callbacks->proto_continue)
878 ske->callbacks->proto_continue(ske, ske->callbacks->context);
882 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
884 /* Verify signature */
885 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
886 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
887 recv_payload->sign_len, hash, hash_len) == FALSE) {
888 SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
889 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
890 if (ske->callbacks->proto_continue)
891 ske->callbacks->proto_continue(ske, ske->callbacks->context);
895 SILC_LOG_DEBUG(("Signature is Ok"));
897 silc_pkcs_public_key_free(public_key);
898 memset(hash, 'F', hash_len);
901 /* Create the random number x, 1 < x < q. */
902 x = silc_calloc(1, sizeof(*x));
905 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
906 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
908 if (status != SILC_SKE_STATUS_OK) {
911 ske->status = status;
912 if (ske->callbacks->proto_continue)
913 ske->callbacks->proto_continue(ske, ske->callbacks->context);
917 /* Save the results for later processing */
918 send_payload = silc_calloc(1, sizeof(*send_payload));
920 ske->ke2_payload = send_payload;
922 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
924 /* Do the Diffie Hellman computation, f = g ^ x mod p */
925 silc_mp_init(&send_payload->x);
926 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
927 &ske->prop->group->group);
929 /* Call the callback. The caller may now continue with the SKE protocol. */
930 ske->status = SILC_SKE_STATUS_OK;
931 if (ske->callbacks->proto_continue)
932 ske->callbacks->proto_continue(ske, ske->callbacks->context);
935 /* This function receives the Key Exchange Payload from the initiator.
936 This also performs the mutual authentication if required. Then, this
937 function first generated a random number x, such that 1 < x < q
938 and computes f = g ^ x mod p. This then puts the result f to a Key
941 The `proto_continue' will be called to indicate that the caller may
942 continue with the SKE protocol. The caller must not continue
943 before the SKE libary has called that callback. If this function
944 returns an error the callback will not be called. It is called
945 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
946 However, note that when the library calls the callback the ske->status
949 This calls the `verify_key' callback to verify the received public
950 key or certificate if the Mutual Authentication flag is set. If the
951 `verify_key' is provided then the remote must send public key and it
952 is considered to be an error if remote does not send its public key. */
954 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
955 SilcBuffer ke_payload)
957 SilcSKEStatus status = SILC_SKE_STATUS_OK;
958 SilcSKEKEPayload *recv_payload;
960 SILC_LOG_DEBUG(("Start"));
962 /* Decode Key Exchange Payload */
963 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
964 if (status != SILC_SKE_STATUS_OK) {
965 ske->status = status;
969 ske->ke1_payload = recv_payload;
971 /* Verify the received public key and verify the signature if we are
972 doing mutual authentication. */
973 if (ske->start_payload &&
974 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
976 SILC_LOG_DEBUG(("We are doing mutual authentication"));
978 if (!recv_payload->pk_data && ske->callbacks->verify_key) {
979 SILC_LOG_ERROR(("Remote end did not send its public key (or "
980 "certificate), even though we require it"));
981 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
985 if (recv_payload->pk_data && ske->callbacks->verify_key) {
986 SILC_LOG_DEBUG(("Verifying public key"));
989 (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
990 recv_payload->pk_len,
991 recv_payload->pk_type,
992 ske->callbacks->context,
993 silc_ske_responder_phase2_final, NULL);
995 /* We will continue to the final state after the public key has
996 been verified by the caller. */
997 return SILC_SKE_STATUS_PENDING;
1001 /* Continue to final state */
1003 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
1005 return SILC_SKE_STATUS_OK;
1008 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
1009 value to be signed and sent to the other end. This then encodes Key
1010 Exchange Payload and sends it to the other end. */
1012 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
1013 SilcPublicKey public_key,
1014 SilcPrivateKey private_key,
1015 SilcSKEPKType pk_type)
1017 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1018 SilcBuffer payload_buf;
1020 unsigned char hash[SILC_HASH_MAXLEN], sign[2048 + 1], *pk;
1021 SilcUInt32 hash_len, sign_len, pk_len;
1023 SILC_LOG_DEBUG(("Start"));
1025 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
1027 /* Compute the shared secret key */
1028 KEY = silc_calloc(1, sizeof(*KEY));
1030 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
1031 &ske->prop->group->group);
1034 if (public_key && private_key) {
1035 SILC_LOG_DEBUG(("Getting public key"));
1037 /* Get the public key */
1038 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
1040 status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1043 ske->ke2_payload->pk_data = pk;
1044 ske->ke2_payload->pk_len = pk_len;
1046 SILC_LOG_DEBUG(("Computing HASH value"));
1048 /* Compute the hash value */
1049 memset(hash, 0, sizeof(hash));
1050 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1051 if (status != SILC_SKE_STATUS_OK)
1054 ske->hash = silc_memdup(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_memdup(sign, sign_len);
1068 ske->ke2_payload->sign_len = sign_len;
1069 memset(sign, 0, sizeof(sign));
1071 ske->ke2_payload->pk_type = pk_type;
1073 /* Encode the Key Exchange Payload */
1074 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
1076 if (status != SILC_SKE_STATUS_OK)
1079 /* Send the packet. */
1080 if (ske->callbacks->send_packet)
1081 (*ske->callbacks->send_packet)(ske, payload_buf,
1082 SILC_PACKET_KEY_EXCHANGE_2,
1083 ske->callbacks->context);
1085 silc_buffer_free(payload_buf);
1090 silc_mp_uninit(ske->KEY);
1091 silc_free(ske->KEY);
1093 silc_ske_payload_ke_free(ske->ke2_payload);
1095 if (status == SILC_SKE_STATUS_OK)
1096 return SILC_SKE_STATUS_ERROR;
1098 ske->status = status;
1102 /* The Key Exchange protocol is ended by calling this function. This
1103 must not be called until the keys are processed like the protocol
1104 defines. This function is for both initiator and responder. */
1106 SilcSKEStatus silc_ske_end(SilcSKE ske)
1108 SilcBufferStruct packet;
1109 unsigned char data[4];
1111 SILC_LOG_DEBUG(("Start"));
1113 SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, data);
1114 silc_buffer_set(&packet, data, 4);
1116 if (ske->callbacks->send_packet)
1117 (*ske->callbacks->send_packet)(ske, &packet, SILC_PACKET_SUCCESS,
1118 ske->callbacks->context);
1120 return SILC_SKE_STATUS_OK;
1123 /* Aborts the Key Exchange protocol. This is called if error occurs
1124 while performing the protocol. The status argument is the error
1125 status and it is sent to the remote end. */
1127 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
1129 SilcBufferStruct packet;
1130 unsigned char data[4];
1132 SILC_LOG_DEBUG(("Start"));
1134 if (status > SILC_SKE_STATUS_INVALID_COOKIE)
1135 status = SILC_SKE_STATUS_BAD_PAYLOAD;
1137 SILC_PUT32_MSB((SilcUInt32)status, data);
1138 silc_buffer_set(&packet, data, 4);
1140 if (ske->callbacks->send_packet)
1141 (*ske->callbacks->send_packet)(ske, &packet, SILC_PACKET_FAILURE,
1142 ske->callbacks->context);
1144 return SILC_SKE_STATUS_OK;
1147 /* Assembles security properties to Key Exchange Start Payload to be
1148 sent to the remote end. This checks system wide (SILC system, that is)
1149 settings and chooses from those. However, if other properties
1150 should be used this function is easy to replace by another function,
1151 as, this function is called by the caller of the protocol and not
1152 by the protocol itself. */
1155 silc_ske_assemble_security_properties(SilcSKE ske,
1156 SilcSKESecurityPropertyFlag flags,
1157 const char *version,
1158 SilcSKEStartPayload **return_payload)
1160 SilcSKEStartPayload *rp;
1163 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1165 rp = silc_calloc(1, sizeof(*rp));
1168 rp->flags = (unsigned char)flags;
1170 /* Set random cookie */
1171 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1172 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1173 rp->cookie[i] = silc_rng_get_byte_fast(ske->rng);
1174 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1177 rp->version = strdup(version);
1178 rp->version_len = strlen(version);
1180 /* Get supported Key Exhange groups */
1181 rp->ke_grp_list = silc_ske_get_supported_groups();
1182 rp->ke_grp_len = strlen(rp->ke_grp_list);
1184 /* Get supported PKCS algorithms */
1185 rp->pkcs_alg_list = silc_pkcs_get_supported();
1186 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1188 /* Get supported encryption algorithms */
1189 rp->enc_alg_list = silc_cipher_get_supported();
1190 rp->enc_alg_len = strlen(rp->enc_alg_list);
1192 /* Get supported hash algorithms */
1193 rp->hash_alg_list = silc_hash_get_supported();
1194 rp->hash_alg_len = strlen(rp->hash_alg_list);
1196 /* Get supported HMACs */
1197 rp->hmac_alg_list = silc_hmac_get_supported();
1198 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1201 /* Get supported compression algorithms */
1202 rp->comp_alg_list = strdup("none");
1203 rp->comp_alg_len = strlen("none");
1205 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1206 2 + rp->version_len +
1207 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1208 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1209 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1211 *return_payload = rp;
1213 return SILC_SKE_STATUS_OK;
1216 /* Selects the supported security properties from the remote end's Key
1217 Exchange Start Payload. */
1220 silc_ske_select_security_properties(SilcSKE ske,
1221 const char *version,
1222 SilcSKEStartPayload *payload,
1223 SilcSKEStartPayload *remote_payload)
1225 SilcSKEStatus status;
1226 SilcSKEStartPayload *rp;
1230 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1232 rp = remote_payload;
1234 /* Check version string */
1235 if (ske->callbacks->check_version) {
1236 status = ske->callbacks->check_version(ske, rp->version,
1238 ske->callbacks->context);
1239 if (status != SILC_SKE_STATUS_OK) {
1240 ske->status = status;
1245 ske->remote_version = silc_memdup(rp->version, rp->version_len);
1247 /* Flags are returned unchanged. */
1248 payload->flags = rp->flags;
1250 /* Take cookie, we must return it to sender unmodified. */
1251 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1252 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1253 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1255 /* Put our version to our reply */
1256 payload->version = strdup(version);
1257 payload->version_len = strlen(version);
1259 /* Get supported Key Exchange groups */
1260 cp = rp->ke_grp_list;
1261 if (cp && strchr(cp, ',')) {
1265 len = strcspn(cp, ",");
1266 item = silc_calloc(len + 1, sizeof(char));
1267 memcpy(item, cp, len);
1269 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1271 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1272 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1274 payload->ke_grp_len = len;
1275 payload->ke_grp_list = item;
1280 if (strlen(cp) == 0)
1289 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1290 SILC_LOG_DEBUG(("Could not find supported KE group"));
1292 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1296 if (!rp->ke_grp_len) {
1297 SILC_LOG_DEBUG(("KE group not defined in payload"));
1299 return SILC_SKE_STATUS_BAD_PAYLOAD;
1302 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1303 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1305 payload->ke_grp_len = rp->ke_grp_len;
1306 payload->ke_grp_list = strdup(rp->ke_grp_list);
1309 /* Get supported PKCS algorithms */
1310 cp = rp->pkcs_alg_list;
1311 if (cp && strchr(cp, ',')) {
1315 len = strcspn(cp, ",");
1316 item = silc_calloc(len + 1, sizeof(char));
1317 memcpy(item, cp, len);
1319 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1321 if (silc_pkcs_is_supported(item) == TRUE) {
1322 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1324 payload->pkcs_alg_len = len;
1325 payload->pkcs_alg_list = item;
1330 if (strlen(cp) == 0)
1339 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1340 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1341 silc_free(payload->ke_grp_list);
1343 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1347 if (!rp->pkcs_alg_len) {
1348 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1349 silc_free(payload->ke_grp_list);
1351 return SILC_SKE_STATUS_BAD_PAYLOAD;
1354 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1355 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1357 payload->pkcs_alg_len = rp->pkcs_alg_len;
1358 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1361 /* Get supported encryption algorithms */
1362 cp = rp->enc_alg_list;
1363 if (cp && strchr(cp, ',')) {
1367 len = strcspn(cp, ",");
1368 item = silc_calloc(len + 1, sizeof(char));
1369 memcpy(item, cp, len);
1371 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1373 if (silc_cipher_is_supported(item) == TRUE) {
1374 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1376 payload->enc_alg_len = len;
1377 payload->enc_alg_list = item;
1382 if (strlen(cp) == 0)
1391 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1392 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1393 silc_free(payload->ke_grp_list);
1394 silc_free(payload->pkcs_alg_list);
1396 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1400 if (!rp->enc_alg_len) {
1401 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1402 silc_free(payload->ke_grp_list);
1403 silc_free(payload->pkcs_alg_list);
1405 return SILC_SKE_STATUS_BAD_PAYLOAD;
1408 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1411 payload->enc_alg_len = rp->enc_alg_len;
1412 payload->enc_alg_list = strdup(rp->enc_alg_list);
1415 /* Get supported hash algorithms */
1416 cp = rp->hash_alg_list;
1417 if (cp && strchr(cp, ',')) {
1421 len = strcspn(cp, ",");
1422 item = silc_calloc(len + 1, sizeof(char));
1423 memcpy(item, cp, len);
1425 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1427 if (silc_hash_is_supported(item) == TRUE) {
1428 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1430 payload->hash_alg_len = len;
1431 payload->hash_alg_list = item;
1436 if (strlen(cp) == 0)
1445 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1446 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1447 silc_free(payload->ke_grp_list);
1448 silc_free(payload->pkcs_alg_list);
1449 silc_free(payload->enc_alg_list);
1451 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1455 if (!rp->hash_alg_len) {
1456 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1457 silc_free(payload->ke_grp_list);
1458 silc_free(payload->pkcs_alg_list);
1459 silc_free(payload->enc_alg_list);
1461 return SILC_SKE_STATUS_BAD_PAYLOAD;
1464 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1465 rp->hash_alg_list));
1467 payload->hash_alg_len = rp->hash_alg_len;
1468 payload->hash_alg_list = strdup(rp->hash_alg_list);
1471 /* Get supported HMACs */
1472 cp = rp->hmac_alg_list;
1473 if (cp && strchr(cp, ',')) {
1477 len = strcspn(cp, ",");
1478 item = silc_calloc(len + 1, sizeof(char));
1479 memcpy(item, cp, len);
1481 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1483 if (silc_hmac_is_supported(item) == TRUE) {
1484 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1486 payload->hmac_alg_len = len;
1487 payload->hmac_alg_list = item;
1492 if (strlen(cp) == 0)
1501 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1502 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1503 silc_free(payload->ke_grp_list);
1504 silc_free(payload->pkcs_alg_list);
1505 silc_free(payload->enc_alg_list);
1506 silc_free(payload->hash_alg_list);
1508 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1512 if (!rp->hmac_alg_len) {
1513 SILC_LOG_DEBUG(("HMAC not defined in payload"));
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_BAD_PAYLOAD;
1522 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1523 rp->hmac_alg_list));
1525 payload->hmac_alg_len = rp->hmac_alg_len;
1526 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1529 /* Get supported compression algorithms */
1530 cp = rp->comp_alg_list;
1531 if (cp && strchr(cp, ',')) {
1535 len = strcspn(cp, ",");
1536 item = silc_calloc(len + 1, sizeof(char));
1537 memcpy(item, cp, len);
1539 SILC_LOG_DEBUG(("Proposed Compression `%s'", item));
1542 if (!strcmp(item, "none")) {
1543 SILC_LOG_DEBUG(("Found Compression `%s'", item));
1544 payload->comp_alg_len = len;
1545 payload->comp_alg_list = item;
1549 if (silc_hmac_is_supported(item) == TRUE) {
1550 SILC_LOG_DEBUG(("Found Compression `%s'", item));
1551 payload->comp_alg_len = len;
1552 payload->comp_alg_list = item;
1558 if (strlen(cp) == 0)
1568 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1569 2 + payload->version_len +
1570 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1571 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1572 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1574 return SILC_SKE_STATUS_OK;
1577 /* Creates random number such that 1 < rnd < n and at most length
1578 of len bits. The rnd sent as argument must be initialized. */
1580 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1584 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1585 unsigned char *string;
1589 return SILC_SKE_STATUS_ERROR;
1591 SILC_LOG_DEBUG(("Creating random number"));
1593 l = ((len - 1) / 8);
1595 /* Get the random number as string */
1596 string = silc_rng_get_rn_data(ske->rng, l);
1598 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1600 /* Decode the string into a MP integer */
1601 silc_mp_bin2mp(string, l, rnd);
1602 silc_mp_mod_2exp(rnd, rnd, len);
1605 if (silc_mp_cmp_ui(rnd, 1) < 0)
1606 status = SILC_SKE_STATUS_ERROR;
1607 if (silc_mp_cmp(rnd, n) >= 0)
1608 status = SILC_SKE_STATUS_ERROR;
1610 memset(string, 'F', l);
1616 /* Creates a hash value HASH as defined in the SKE protocol. If the
1617 `initiator' is TRUE then this function is used to create the HASH_i
1618 hash value defined in the protocol. If it is FALSE then this is used
1619 to create the HASH value defined by the protocol. */
1621 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1622 unsigned char *return_hash,
1623 SilcUInt32 *return_hash_len,
1626 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1628 unsigned char *e, *f, *KEY;
1629 SilcUInt32 e_len, f_len, KEY_len;
1632 SILC_LOG_DEBUG(("Start"));
1634 if (initiator == FALSE) {
1635 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1636 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1637 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1639 /* Format the buffer used to compute the hash value */
1640 buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
1641 ske->ke2_payload->pk_len +
1642 ske->ke1_payload->pk_len +
1643 e_len + f_len + KEY_len);
1645 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1647 /* Initiator is not required to send its public key */
1648 if (!ske->ke1_payload->pk_data) {
1650 silc_buffer_format(buf,
1651 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1653 ske->start_payload_copy->
1655 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1656 ske->ke2_payload->pk_len),
1657 SILC_STR_UI_XNSTRING(e, e_len),
1658 SILC_STR_UI_XNSTRING(f, f_len),
1659 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1663 silc_buffer_format(buf,
1664 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1666 ske->start_payload_copy->
1668 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1669 ske->ke2_payload->pk_len),
1670 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1671 ske->ke1_payload->pk_len),
1672 SILC_STR_UI_XNSTRING(e, e_len),
1673 SILC_STR_UI_XNSTRING(f, f_len),
1674 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1678 silc_buffer_free(buf);
1679 memset(e, 0, e_len);
1680 memset(f, 0, f_len);
1681 memset(KEY, 0, KEY_len);
1685 return SILC_SKE_STATUS_ERROR;
1688 memset(e, 0, e_len);
1689 memset(f, 0, f_len);
1690 memset(KEY, 0, KEY_len);
1695 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1697 buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
1698 ske->ke1_payload->pk_len + e_len);
1700 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1702 /* Format the buffer used to compute the hash value */
1704 silc_buffer_format(buf,
1705 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1706 ske->start_payload_copy->len),
1707 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1708 ske->ke1_payload->pk_len),
1709 SILC_STR_UI_XNSTRING(e, e_len),
1712 silc_buffer_free(buf);
1713 memset(e, 0, e_len);
1715 return SILC_SKE_STATUS_ERROR;
1718 memset(e, 0, e_len);
1723 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1724 *return_hash_len = silc_hash_len(ske->prop->hash);
1726 if (initiator == FALSE) {
1727 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1729 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1732 silc_buffer_free(buf);
1737 /* Processes the provided key material `data' as the SILC protocol
1738 specification defines. */
1741 silc_ske_process_key_material_data(unsigned char *data,
1742 SilcUInt32 data_len,
1743 SilcUInt32 req_iv_len,
1744 SilcUInt32 req_enc_key_len,
1745 SilcUInt32 req_hmac_key_len,
1747 SilcSKEKeyMaterial *key)
1750 unsigned char hashd[SILC_HASH_MAXLEN];
1751 SilcUInt32 hash_len = req_hmac_key_len;
1752 SilcUInt32 enc_key_len = req_enc_key_len / 8;
1754 SILC_LOG_DEBUG(("Start"));
1756 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1757 return SILC_SKE_STATUS_ERROR;
1759 buf = silc_buffer_alloc_size(1 + data_len);
1761 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1762 silc_buffer_format(buf,
1763 SILC_STR_UI_CHAR(0),
1764 SILC_STR_UI_XNSTRING(data, data_len),
1768 memset(hashd, 0, sizeof(hashd));
1770 silc_hash_make(hash, buf->data, buf->len, hashd);
1771 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1772 memcpy(key->send_iv, hashd, req_iv_len);
1773 memset(hashd, 0, sizeof(hashd));
1775 silc_hash_make(hash, buf->data, buf->len, hashd);
1776 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1777 memcpy(key->receive_iv, hashd, req_iv_len);
1778 key->iv_len = req_iv_len;
1780 /* Take the encryption keys. If requested key size is more than
1781 the size of hash length we will distribute more key material
1782 as protocol defines. */
1784 if (enc_key_len > hash_len) {
1786 unsigned char k1[SILC_HASH_MAXLEN], k2[SILC_HASH_MAXLEN],
1787 k3[SILC_HASH_MAXLEN];
1788 unsigned char *dtmp;
1791 if (enc_key_len > (3 * hash_len))
1792 return SILC_SKE_STATUS_ERROR;
1794 /* Take first round */
1795 memset(k1, 0, sizeof(k1));
1796 silc_hash_make(hash, buf->data, buf->len, k1);
1798 /* Take second round */
1799 dist = silc_buffer_alloc_size(data_len + hash_len);
1801 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1802 silc_buffer_format(dist,
1803 SILC_STR_UI_XNSTRING(data, data_len),
1804 SILC_STR_UI_XNSTRING(k1, hash_len),
1806 memset(k2, 0, sizeof(k2));
1807 silc_hash_make(hash, dist->data, dist->len, k2);
1809 /* Take third round */
1810 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1811 silc_buffer_pull_tail(dist, hash_len);
1812 silc_buffer_pull(dist, data_len + hash_len);
1813 silc_buffer_format(dist,
1814 SILC_STR_UI_XNSTRING(k2, hash_len),
1816 silc_buffer_push(dist, data_len + hash_len);
1817 memset(k3, 0, sizeof(k3));
1818 silc_hash_make(hash, dist->data, dist->len, k3);
1820 /* Then, save the keys */
1821 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1822 memcpy(dtmp, k1, hash_len);
1823 memcpy(dtmp + hash_len, k2, hash_len);
1824 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1826 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1827 memcpy(key->send_enc_key, dtmp, enc_key_len);
1828 key->enc_key_len = req_enc_key_len;
1830 memset(dtmp, 0, (3 * hash_len));
1831 memset(k1, 0, sizeof(k1));
1832 memset(k2, 0, sizeof(k2));
1833 memset(k3, 0, sizeof(k3));
1835 silc_buffer_clear(dist);
1836 silc_buffer_free(dist);
1838 /* Take normal hash as key */
1839 memset(hashd, 0, sizeof(hashd));
1840 silc_hash_make(hash, buf->data, buf->len, hashd);
1841 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1842 memcpy(key->send_enc_key, hashd, enc_key_len);
1843 key->enc_key_len = req_enc_key_len;
1847 if (enc_key_len > hash_len) {
1849 unsigned char k1[SILC_HASH_MAXLEN], k2[SILC_HASH_MAXLEN],
1850 k3[SILC_HASH_MAXLEN];
1851 unsigned char *dtmp;
1854 if (enc_key_len > (3 * hash_len))
1855 return SILC_SKE_STATUS_ERROR;
1857 /* Take first round */
1858 memset(k1, 0, sizeof(k1));
1859 silc_hash_make(hash, buf->data, buf->len, k1);
1861 /* Take second round */
1862 dist = silc_buffer_alloc_size(data_len + hash_len);
1864 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1865 silc_buffer_format(dist,
1866 SILC_STR_UI_XNSTRING(data, data_len),
1867 SILC_STR_UI_XNSTRING(k1, hash_len),
1869 memset(k2, 0, sizeof(k2));
1870 silc_hash_make(hash, dist->data, dist->len, k2);
1872 /* Take third round */
1873 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1874 silc_buffer_pull_tail(dist, hash_len);
1875 silc_buffer_pull(dist, data_len + hash_len);
1876 silc_buffer_format(dist,
1877 SILC_STR_UI_XNSTRING(k2, hash_len),
1879 silc_buffer_push(dist, data_len + hash_len);
1880 memset(k3, 0, sizeof(k3));
1881 silc_hash_make(hash, dist->data, dist->len, k3);
1883 /* Then, save the keys */
1884 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1885 memcpy(dtmp, k1, hash_len);
1886 memcpy(dtmp + hash_len, k2, hash_len);
1887 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1889 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1890 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1891 key->enc_key_len = req_enc_key_len;
1893 memset(dtmp, 0, (3 * hash_len));
1894 memset(k1, 0, sizeof(k1));
1895 memset(k2, 0, sizeof(k2));
1896 memset(k3, 0, sizeof(k3));
1898 silc_buffer_clear(dist);
1899 silc_buffer_free(dist);
1901 /* Take normal hash as key */
1902 memset(hashd, 0, sizeof(hashd));
1903 silc_hash_make(hash, buf->data, buf->len, hashd);
1904 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1905 memcpy(key->receive_enc_key, hashd, enc_key_len);
1906 key->enc_key_len = req_enc_key_len;
1909 /* Take HMAC keys */
1910 memset(hashd, 0, sizeof(hashd));
1912 silc_hash_make(hash, buf->data, buf->len, hashd);
1913 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1914 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1915 memset(hashd, 0, sizeof(hashd));
1917 silc_hash_make(hash, buf->data, buf->len, hashd);
1918 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1919 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1920 key->hmac_key_len = req_hmac_key_len;
1921 memset(hashd, 0, sizeof(hashd));
1923 silc_buffer_clear(buf);
1924 silc_buffer_free(buf);
1926 return SILC_SKE_STATUS_OK;
1929 /* Processes negotiated key material as protocol specifies. This returns
1930 the actual keys to be used in the SILC. */
1932 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1933 SilcUInt32 req_iv_len,
1934 SilcUInt32 req_enc_key_len,
1935 SilcUInt32 req_hmac_key_len,
1936 SilcSKEKeyMaterial *key)
1938 SilcSKEStatus status;
1940 unsigned char *tmpbuf;
1943 /* Encode KEY to binary data */
1944 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1946 buf = silc_buffer_alloc_size(klen + ske->hash_len);
1948 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1949 silc_buffer_format(buf,
1950 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1951 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1954 /* Process the key material */
1955 status = silc_ske_process_key_material_data(buf->data, buf->len,
1956 req_iv_len, req_enc_key_len,
1958 ske->prop->hash, key);
1960 memset(tmpbuf, 0, klen);
1962 silc_buffer_clear(buf);
1963 silc_buffer_free(buf);
1968 /* Free key material structure */
1970 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1976 silc_free(key->send_iv);
1977 if (key->receive_iv)
1978 silc_free(key->receive_iv);
1979 if (key->send_enc_key) {
1980 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1981 silc_free(key->send_enc_key);
1983 if (key->receive_enc_key) {
1984 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1985 silc_free(key->receive_enc_key);
1987 if (key->send_hmac_key) {
1988 memset(key->send_hmac_key, 0, key->hmac_key_len);
1989 silc_free(key->send_hmac_key);
1991 if (key->receive_hmac_key) {
1992 memset(key->receive_hmac_key, 0, key->hmac_key_len);
1993 silc_free(key->receive_hmac_key);
1998 const char *silc_ske_status_string[] =
2002 "Unkown error occurred",
2003 "Bad payload in packet",
2004 "Unsupported group",
2005 "Unsupported cipher",
2007 "Unsupported hash function",
2009 "Unsupported public key (or certificate)",
2010 "Incorrect signature",
2011 "Bad or unsupported version",
2016 "Remote did not provide public key",
2017 "Key exchange protocol is not active",
2018 "Bad reserved field in packet",
2019 "Bad payload length in packet",
2020 "Error computing signature",
2021 "System out of memory",
2026 /* Maps status to readable string and returns the string. If string is not
2027 found and empty character string ("") is returned. */
2029 const char *silc_ske_map_status(SilcSKEStatus status)
2033 for (i = 0; silc_ske_status_string[i]; i++)
2035 return silc_ske_status_string[i];
2040 /* Parses remote host's version string. */
2042 bool silc_ske_parse_version(SilcSKE ske,
2043 SilcUInt32 *protocol_version,
2044 char **protocol_version_string,
2045 SilcUInt32 *software_version,
2046 char **software_version_string,
2047 char **vendor_version)
2049 return silc_parse_version_string(ske->remote_version,
2051 protocol_version_string,
2053 software_version_string,