5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2000 - 2014 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.
23 #include "groups_internal.h"
25 /************************** Types and definitions ***************************/
27 /* Structure to hold all SKE callbacks. */
28 struct SilcSKECallbacksStruct {
29 SilcSKEVerifyCb verify_key;
30 SilcSKECompletionCb completed;
34 /************************ Static utility functions **************************/
37 SILC_FSM_STATE(silc_ske_st_initiator_start);
38 SILC_FSM_STATE(silc_ske_st_initiator_phase1);
39 SILC_FSM_STATE(silc_ske_st_initiator_phase2);
40 SILC_FSM_STATE(silc_ske_st_initiator_phase3);
41 SILC_FSM_STATE(silc_ske_st_initiator_phase4);
42 SILC_FSM_STATE(silc_ske_st_initiator_end);
43 SILC_FSM_STATE(silc_ske_st_initiator_aborted);
44 SILC_FSM_STATE(silc_ske_st_initiator_error);
45 SILC_FSM_STATE(silc_ske_st_initiator_failure);
46 SILC_FSM_STATE(silc_ske_st_responder_start);
47 SILC_FSM_STATE(silc_ske_st_responder_phase1);
48 SILC_FSM_STATE(silc_ske_st_responder_phase2);
49 SILC_FSM_STATE(silc_ske_st_responder_phase4);
50 SILC_FSM_STATE(silc_ske_st_responder_phase5);
51 SILC_FSM_STATE(silc_ske_st_responder_end);
52 SILC_FSM_STATE(silc_ske_st_responder_aborted);
53 SILC_FSM_STATE(silc_ske_st_responder_failure);
54 SILC_FSM_STATE(silc_ske_st_responder_error);
55 SILC_FSM_STATE(silc_ske_st_rekey_initiator_start);
56 SILC_FSM_STATE(silc_ske_st_rekey_initiator_done);
57 SILC_FSM_STATE(silc_ske_st_rekey_initiator_end);
58 SILC_FSM_STATE(silc_ske_st_rekey_responder_wait);
59 SILC_FSM_STATE(silc_ske_st_rekey_responder_start);
60 SILC_FSM_STATE(silc_ske_st_rekey_responder_done);
61 SILC_FSM_STATE(silc_ske_st_rekey_responder_end);
62 SILC_TASK_CALLBACK(silc_ske_packet_send_retry);
65 silc_ske_process_key_material(SilcSKE ske,
66 SilcUInt32 req_iv_len,
67 SilcUInt32 req_enc_key_len,
68 SilcUInt32 req_hmac_key_len,
69 SilcSKERekeyMaterial *rekey);
70 static SilcBool silc_ske_packet_send(SilcSKE ske,
72 SilcPacketFlags flags,
73 const unsigned char *data,
77 * Notify the owner of the ske that we failed. Ensures that we don't make the
78 * same callout twice, as the notification callback routines are not designed
79 * to handle that case.
81 static void silc_ske_notify_failure(SilcSKE ske)
83 SILC_LOG_DEBUG(("Notifying SKE %p owner of failure (failure_notified = %d)",
84 ske, ske->failure_notified));
87 * First, check if we have already made a failure callout. If so, then we
90 if (ske->failure_notified)
94 * Mark ourselves as having already sent the failure notification here and
97 ske->failure_notified = TRUE;
99 SILC_LOG_DEBUG(("Deliver failure notification for SKE %p (%s)",
100 ske, ske->responder ? "responder" : "initiator"));
103 * Finally, make the call to the owner's registered failure callback.
106 silc_fsm_next(&ske->fsm, silc_ske_st_responder_failure);
108 silc_fsm_next(&ske->fsm, silc_ske_st_initiator_failure);
111 /* Packet callback */
113 static SilcBool silc_ske_packet_receive(SilcPacketEngine engine,
114 SilcPacketStream stream,
116 void *callback_context,
119 SilcSKE ske = callback_context;
121 /* Clear retransmission */
122 ske->retry_timer = SILC_SKE_RETRY_MIN;
123 ske->retry_count = 0;
124 silc_schedule_task_del_by_callback(ske->schedule,
125 silc_ske_packet_send_retry);
127 /* Signal for new packet */
128 ske->packet = packet;
130 /* Check if we were aborted */
132 silc_packet_free(packet);
136 silc_fsm_next(&ske->fsm, silc_ske_st_responder_aborted);
138 silc_fsm_next(&ske->fsm, silc_ske_st_initiator_aborted);
140 silc_fsm_continue_sync(&ske->fsm);
144 /* See if received failure from remote */
145 if (packet->type == SILC_PACKET_FAILURE)
146 silc_ske_notify_failure(ske);
148 /* Handle rekey and SUCCESS packets synchronously. After SUCCESS packets
149 they keys are taken into use immediately, hence the synchronous
150 processing to get the keys in use as soon as possible. */
151 if (ske->rekeying || packet->type == SILC_PACKET_SUCCESS)
152 silc_fsm_continue_sync(&ske->fsm);
154 silc_fsm_continue(&ske->fsm);
159 /* Packet stream callbacks */
160 static SilcPacketCallbacks silc_ske_stream_cbs =
162 silc_ske_packet_receive, NULL, NULL
165 /* Aborts SKE protocol */
167 static void silc_ske_abort(SilcAsyncOperation op, void *context)
169 SilcSKE ske = context;
173 /* Public key verification completion callback */
175 static void silc_ske_pk_verified(SilcSKE ske, SilcSKEStatus status,
176 void *completion_context)
178 ske->status = status;
179 SILC_FSM_CALL_CONTINUE(&ske->fsm);
182 /* SKR find callback */
184 static void silc_ske_skr_callback(SilcSKR repository,
186 SilcSKRStatus status,
187 SilcDList keys, void *context)
189 SilcSKE ske = context;
191 silc_skr_find_free(find);
193 if (status != SILC_SKR_OK) {
194 if (ske->callbacks->verify_key) {
195 /* Verify from application */
196 ske->callbacks->verify_key(ske, ske->prop->public_key,
197 ske->callbacks->context,
198 silc_ske_pk_verified, NULL);
204 silc_dlist_uninit(keys);
207 ske->status = (status == SILC_SKR_OK ? SILC_SKE_STATUS_OK :
208 SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY);
209 SILC_FSM_CALL_CONTINUE(&ske->fsm);
212 /* Checks remote and local versions */
214 static SilcSKEStatus silc_ske_check_version(SilcSKE ske)
216 if (!ske->remote_version || !ske->version)
217 return SILC_SKE_STATUS_BAD_VERSION;
219 if (!silc_parse_version_string(ske->remote_version, NULL, NULL,
221 return SILC_SKE_STATUS_BAD_VERSION;
223 return SILC_SKE_STATUS_OK;
226 /* Selects the supported security properties from the initiator's Key
227 Exchange Start Payload. A responder function. Saves our reply
228 start payload to ske->start_payload. */
231 silc_ske_select_security_properties(SilcSKE ske,
232 SilcSKEStartPayload remote_payload,
233 SilcSKESecurityProperties *prop)
235 SilcSKEStatus status;
236 SilcSKEStartPayload rp, payload;
240 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
244 return SILC_SKE_STATUS_BAD_VERSION;
246 /* Check for mandatory fields */
247 if (!rp->ke_grp_len) {
248 SILC_LOG_DEBUG(("KE group not defined in payload"));
249 return SILC_SKE_STATUS_BAD_PAYLOAD;
251 if (!rp->pkcs_alg_len) {
252 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
253 return SILC_SKE_STATUS_BAD_PAYLOAD;
255 if (!rp->enc_alg_len) {
256 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
257 return SILC_SKE_STATUS_BAD_PAYLOAD;
259 if (!rp->hash_alg_len) {
260 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
261 return SILC_SKE_STATUS_BAD_PAYLOAD;
263 if (!rp->hmac_alg_len) {
264 SILC_LOG_DEBUG(("HMAC not defined in payload"));
265 return SILC_SKE_STATUS_BAD_PAYLOAD;
268 /* Allocate security properties */
269 *prop = silc_calloc(1, sizeof(**prop));
271 return SILC_SKE_STATUS_OUT_OF_MEMORY;
273 /* Allocate our reply start payload */
274 payload = silc_calloc(1, sizeof(*payload));
277 return SILC_SKE_STATUS_OUT_OF_MEMORY;
280 /* Check version string */
281 ske->remote_version = silc_memdup(rp->version, rp->version_len);
282 status = silc_ske_check_version(ske);
283 if (status != SILC_SKE_STATUS_OK) {
284 ske->status = status;
288 /* Flags are returned unchanged. */
289 (*prop)->flags = payload->flags = rp->flags;
291 /* Take cookie, we must return it to sender unmodified. */
292 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
293 if (!payload->cookie) {
294 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
297 payload->cookie_len = SILC_SKE_COOKIE_LEN;
298 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
300 /* In case IV included flag and session port is set the first 16-bits of
301 cookie will include our session port. */
302 if (rp->flags & SILC_SKE_SP_FLAG_IV_INCLUDED && ske->session_port) {
303 /* Take remote port */
304 SILC_GET16_MSB((*prop)->remote_port, payload->cookie);
307 SILC_PUT16_MSB(ske->session_port, payload->cookie);
310 /* Put our version to our reply */
311 payload->version = strdup(ske->version);
312 if (!payload->version) {
313 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
316 payload->version_len = strlen(ske->version);
318 /* Get supported Key Exchange groups */
319 cp = rp->ke_grp_list;
320 if (cp && strchr(cp, ',')) {
324 len = strcspn(cp, ",");
325 item = silc_calloc(len + 1, sizeof(char));
327 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
330 memcpy(item, cp, len);
332 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
334 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
335 SILC_LOG_DEBUG(("Found KE group `%s'", item));
337 payload->ke_grp_len = len;
338 payload->ke_grp_list = item;
352 if (!payload->ke_grp_len && !payload->ke_grp_list) {
353 SILC_LOG_DEBUG(("Could not find supported KE group"));
355 return SILC_SKE_STATUS_UNKNOWN_GROUP;
358 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
359 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
361 payload->ke_grp_len = rp->ke_grp_len;
362 payload->ke_grp_list = strdup(rp->ke_grp_list);
365 /* Save group to security properties */
366 status = silc_ske_group_get_by_name(payload->ke_grp_list, &(*prop)->group);
367 if (status != SILC_SKE_STATUS_OK) {
369 return SILC_SKE_STATUS_UNKNOWN_GROUP;
372 /* Get supported PKCS algorithms */
373 cp = rp->pkcs_alg_list;
374 if (cp && strchr(cp, ',')) {
378 len = strcspn(cp, ",");
379 item = silc_calloc(len + 1, sizeof(char));
381 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
384 memcpy(item, cp, len);
386 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
388 if (silc_pkcs_find_algorithm(item, NULL)) {
389 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
391 payload->pkcs_alg_len = len;
392 payload->pkcs_alg_list = item;
406 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
407 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
408 silc_free(payload->ke_grp_list);
410 return SILC_SKE_STATUS_UNKNOWN_PKCS;
413 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
414 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
416 payload->pkcs_alg_len = rp->pkcs_alg_len;
417 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
420 /* Get supported encryption algorithms */
421 cp = rp->enc_alg_list;
422 if (cp && strchr(cp, ',')) {
426 len = strcspn(cp, ",");
427 item = silc_calloc(len + 1, sizeof(char));
429 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
432 memcpy(item, cp, len);
434 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
436 if (silc_cipher_is_supported(item) == TRUE) {
437 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
439 payload->enc_alg_len = len;
440 payload->enc_alg_list = item;
454 if (!payload->enc_alg_len && !payload->enc_alg_list) {
455 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
456 silc_free(payload->ke_grp_list);
457 silc_free(payload->pkcs_alg_list);
459 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
462 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
465 payload->enc_alg_len = rp->enc_alg_len;
466 payload->enc_alg_list = strdup(rp->enc_alg_list);
469 /* Save selected cipher to security properties */
470 if (silc_cipher_alloc(payload->enc_alg_list, &(*prop)->cipher) == FALSE) {
471 silc_free(payload->ke_grp_list);
472 silc_free(payload->pkcs_alg_list);
474 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
477 /* Get supported hash algorithms */
478 cp = rp->hash_alg_list;
479 if (cp && strchr(cp, ',')) {
483 len = strcspn(cp, ",");
484 item = silc_calloc(len + 1, sizeof(char));
486 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
489 memcpy(item, cp, len);
491 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
493 if (silc_hash_is_supported(item) == TRUE) {
494 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
496 payload->hash_alg_len = len;
497 payload->hash_alg_list = item;
511 if (!payload->hash_alg_len && !payload->hash_alg_list) {
512 SILC_LOG_DEBUG(("Could not find supported hash alg"));
513 silc_free(payload->ke_grp_list);
514 silc_free(payload->pkcs_alg_list);
515 silc_free(payload->enc_alg_list);
517 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
520 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
523 payload->hash_alg_len = rp->hash_alg_len;
524 payload->hash_alg_list = strdup(rp->hash_alg_list);
527 /* Save selected hash algorithm to security properties */
528 if (silc_hash_alloc(payload->hash_alg_list, &(*prop)->hash) == FALSE) {
529 silc_free(payload->ke_grp_list);
530 silc_free(payload->pkcs_alg_list);
531 silc_free(payload->enc_alg_list);
533 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
536 /* Get supported HMACs */
537 cp = rp->hmac_alg_list;
538 if (cp && strchr(cp, ',')) {
542 len = strcspn(cp, ",");
543 item = silc_calloc(len + 1, sizeof(char));
545 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
548 memcpy(item, cp, len);
550 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
552 if (silc_hmac_is_supported(item) == TRUE) {
553 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
555 payload->hmac_alg_len = len;
556 payload->hmac_alg_list = item;
570 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
571 SILC_LOG_DEBUG(("Could not find supported HMAC"));
572 silc_free(payload->ke_grp_list);
573 silc_free(payload->pkcs_alg_list);
574 silc_free(payload->enc_alg_list);
575 silc_free(payload->hash_alg_list);
577 return SILC_SKE_STATUS_UNKNOWN_HMAC;
580 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
583 payload->hmac_alg_len = rp->hmac_alg_len;
584 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
587 /* Save selected HMACc to security properties */
588 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &(*prop)->hmac) == FALSE) {
589 silc_free(payload->ke_grp_list);
590 silc_free(payload->pkcs_alg_list);
591 silc_free(payload->enc_alg_list);
592 silc_free(payload->hash_alg_list);
594 return SILC_SKE_STATUS_UNKNOWN_HMAC;
597 /* Get supported compression algorithms */
598 cp = rp->comp_alg_list;
599 if (cp && strchr(cp, ',')) {
603 len = strcspn(cp, ",");
604 item = silc_calloc(len + 1, sizeof(char));
606 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
609 memcpy(item, cp, len);
611 SILC_LOG_DEBUG(("Proposed Compression `%s'", item));
614 if (!strcmp(item, "none")) {
615 SILC_LOG_DEBUG(("Found Compression `%s'", item));
616 payload->comp_alg_len = len;
617 payload->comp_alg_list = item;
621 if (silc_hmac_is_supported(item) == TRUE) {
622 SILC_LOG_DEBUG(("Found Compression `%s'", item));
623 payload->comp_alg_len = len;
624 payload->comp_alg_list = item;
640 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
641 2 + payload->version_len +
642 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
643 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
644 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
646 /* Save our reply payload */
647 ske->start_payload = payload;
649 return SILC_SKE_STATUS_OK;
652 /* Creates random number such that 1 < rnd < n and at most length
653 of len bits. The rnd sent as argument must be initialized. */
655 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
659 SilcSKEStatus status = SILC_SKE_STATUS_OK;
660 unsigned char *string;
664 return SILC_SKE_STATUS_ERROR;
666 SILC_LOG_DEBUG(("Creating random number"));
670 /* Get the random number as string */
671 string = silc_rng_get_rn_data(ske->rng, l);
673 return SILC_SKE_STATUS_OUT_OF_MEMORY;
675 /* Decode the string into a MP integer */
676 silc_mp_bin2mp(string, l, rnd);
677 silc_mp_mod_2exp(rnd, rnd, len);
680 if (silc_mp_cmp_ui(rnd, 1) < 0)
681 status = SILC_SKE_STATUS_ERROR;
682 if (silc_mp_cmp(rnd, n) >= 0)
683 status = SILC_SKE_STATUS_ERROR;
685 memset(string, 'F', l);
691 /* Creates a hash value HASH as defined in the SKE protocol. If the
692 `initiator' is TRUE then this function is used to create the HASH_i
693 hash value defined in the protocol. If it is FALSE then this is used
694 to create the HASH value defined by the protocol. */
696 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
697 unsigned char *return_hash,
698 SilcUInt32 *return_hash_len,
701 SilcSKEStatus status = SILC_SKE_STATUS_OK;
703 unsigned char *e, *f, *KEY, *s_data;
704 SilcUInt32 e_len, f_len, KEY_len, s_len;
707 SILC_LOG_DEBUG(("Start"));
709 if (initiator == FALSE) {
710 s_data = (ske->start_payload_copy ?
711 silc_buffer_data(ske->start_payload_copy) : NULL);
712 s_len = (ske->start_payload_copy ?
713 silc_buffer_len(ske->start_payload_copy) : 0);
714 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
716 return SILC_SKE_STATUS_OUT_OF_MEMORY;
717 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
719 return SILC_SKE_STATUS_OUT_OF_MEMORY;
720 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
722 return SILC_SKE_STATUS_OUT_OF_MEMORY;
724 /* Format the buffer used to compute the hash value */
725 buf = silc_buffer_alloc_size(s_len +
726 ske->ke2_payload->pk_len +
727 ske->ke1_payload->pk_len +
728 e_len + f_len + KEY_len);
730 return SILC_SKE_STATUS_OUT_OF_MEMORY;
732 /* Initiator is not required to send its public key */
733 if (!ske->ke1_payload->pk_data) {
735 silc_buffer_format(buf,
736 SILC_STR_DATA(s_data, s_len),
737 SILC_STR_DATA(ske->ke2_payload->pk_data,
738 ske->ke2_payload->pk_len),
739 SILC_STR_DATA(e, e_len),
740 SILC_STR_DATA(f, f_len),
741 SILC_STR_DATA(KEY, KEY_len),
745 silc_buffer_format(buf,
746 SILC_STR_DATA(s_data, s_len),
747 SILC_STR_DATA(ske->ke2_payload->pk_data,
748 ske->ke2_payload->pk_len),
749 SILC_STR_DATA(ske->ke1_payload->pk_data,
750 ske->ke1_payload->pk_len),
751 SILC_STR_DATA(e, e_len),
752 SILC_STR_DATA(f, f_len),
753 SILC_STR_DATA(KEY, KEY_len),
757 silc_buffer_free(buf);
760 memset(KEY, 0, KEY_len);
764 return SILC_SKE_STATUS_ERROR;
769 memset(KEY, 0, KEY_len);
774 s_data = (ske->start_payload_copy ?
775 silc_buffer_data(ske->start_payload_copy) : NULL);
776 s_len = (ske->start_payload_copy ?
777 silc_buffer_len(ske->start_payload_copy) : 0);
778 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
780 return SILC_SKE_STATUS_OUT_OF_MEMORY;
782 buf = silc_buffer_alloc_size(s_len + ske->ke1_payload->pk_len + e_len);
784 return SILC_SKE_STATUS_OUT_OF_MEMORY;
786 /* Format the buffer used to compute the hash value */
788 silc_buffer_format(buf,
789 SILC_STR_DATA(s_data, s_len),
790 SILC_STR_DATA(ske->ke1_payload->pk_data,
791 ske->ke1_payload->pk_len),
792 SILC_STR_DATA(e, e_len),
795 silc_buffer_free(buf);
798 return SILC_SKE_STATUS_ERROR;
801 SILC_LOG_HEXDUMP(("hash buf"), buf->data, silc_buffer_len(buf));
808 silc_hash_make(ske->prop->hash, buf->data, silc_buffer_len(buf),
810 *return_hash_len = silc_hash_len(ske->prop->hash);
812 if (initiator == FALSE) {
813 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
815 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
818 silc_buffer_free(buf);
823 /* Generate rekey material */
825 static SilcSKERekeyMaterial
826 silc_ske_make_rekey_material(SilcSKE ske, SilcSKEKeyMaterial keymat)
828 SilcSKERekeyMaterial rekey;
834 /* Create rekey material */
835 rekey = silc_calloc(1, sizeof(*rekey));
840 if (ske->prop->group)
841 rekey->ske_group = silc_ske_group_get_number(ske->prop->group);
842 rekey->pfs = (ske->prop->flags & SILC_SKE_SP_FLAG_PFS ? TRUE : FALSE);
843 hash = silc_hash_get_name(ske->prop->hash);
844 rekey->hash = silc_memdup(hash, strlen(hash));
849 if (rekey->pfs == FALSE) {
850 rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
851 keymat->enc_key_len / 8);
852 if (!rekey->send_enc_key) {
856 rekey->enc_key_len = keymat->enc_key_len;
862 /* Assembles security properties */
864 static SilcSKEStartPayload
865 silc_ske_assemble_security_properties(SilcSKE ske,
866 SilcSKESecurityPropertyFlag flags,
868 SilcBool small_proposal)
870 SilcSKEStartPayload rp;
873 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
875 rp = silc_calloc(1, sizeof(*rp));
880 rp->flags = (unsigned char)flags;
882 /* Set random cookie */
883 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
888 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
889 rp->cookie[i] = silc_rng_get_byte_fast(ske->rng);
890 rp->cookie_len = SILC_SKE_COOKIE_LEN;
892 /* In case IV included flag and session port is set the first 16-bits of
893 cookie will include our session port. */
894 if (flags & SILC_SKE_SP_FLAG_IV_INCLUDED && ske->session_port)
895 SILC_PUT16_MSB(ske->session_port, rp->cookie);
898 rp->version = strdup(version);
900 rp->version_len = strlen(version);
902 /* Get supported Key Exhange groups */
903 rp->ke_grp_list = silc_ske_get_supported_groups(small_proposal);
905 rp->ke_grp_len = strlen(rp->ke_grp_list);
907 /* Get supported PKCS algorithms */
909 rp->pkcs_alg_list = strdup(silc_default_pkcs_alg[0].name);
911 rp->pkcs_alg_list = silc_pkcs_get_supported();
912 if (rp->pkcs_alg_list)
913 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
915 /* Get supported encryption algorithms */
917 rp->enc_alg_list = strdup(silc_default_ciphers[0].name);
919 rp->enc_alg_list = silc_cipher_get_supported();
920 if (rp->enc_alg_list)
921 rp->enc_alg_len = strlen(rp->enc_alg_list);
923 /* Get supported hash algorithms */
925 rp->hash_alg_list = strdup(silc_default_hash[0].name);
927 rp->hash_alg_list = silc_hash_get_supported();
928 if (rp->hash_alg_list)
929 rp->hash_alg_len = strlen(rp->hash_alg_list);
931 /* Get supported HMACs */
933 rp->hmac_alg_list = strdup(silc_default_hmacs[0].name);
935 rp->hmac_alg_list = silc_hmac_get_supported();
936 if (rp->hmac_alg_list)
937 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
939 if (!small_proposal) {
941 /* Get supported compression algorithms */
942 rp->comp_alg_list = strdup("none");
943 rp->comp_alg_len = strlen("none");
946 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
947 2 + rp->version_len +
948 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
949 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
950 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
955 /* Packet retransmission callback. */
957 SILC_TASK_CALLBACK(silc_ske_packet_send_retry)
959 SilcSKE ske = context;
961 if (ske->retry_count++ >= SILC_SKE_RETRY_COUNT ||
963 SILC_LOG_DEBUG(("Retransmission limit reached, packet was lost"));
964 ske->retry_count = 0;
965 ske->retry_timer = SILC_SKE_RETRY_MIN;
966 silc_free(ske->retrans.data);
967 ske->retrans.data = NULL;
968 ske->status = SILC_SKE_STATUS_TIMEOUT;
969 silc_ske_notify_failure(ske);
970 silc_fsm_continue_sync(&ske->fsm);
974 SILC_LOG_DEBUG(("Retransmitting packet"));
975 silc_ske_packet_send(ske, ske->retrans.type, ske->retrans.flags,
976 ske->retrans.data, ske->retrans.data_len);
979 /* Install retransmission timer */
981 static void silc_ske_install_retransmission(SilcSKE ske)
983 if (!silc_packet_stream_is_udp(ske->stream))
986 if (ske->retrans.data) {
987 SILC_LOG_DEBUG(("Installing retransmission timer %d secs",
989 silc_schedule_task_add_timeout(ske->schedule, silc_ske_packet_send_retry,
990 ske, ske->retry_timer, 0);
992 ske->retry_timer = ((ske->retry_timer * SILC_SKE_RETRY_MUL) +
993 (silc_rng_get_rn16(ske->rng) % SILC_SKE_RETRY_RAND));
996 /* Sends SILC packet. Handles retransmissions with UDP streams. */
998 static SilcBool silc_ske_packet_send(SilcSKE ske,
1000 SilcPacketFlags flags,
1001 const unsigned char *data,
1002 SilcUInt32 data_len)
1006 /* Send the packet */
1007 ret = silc_packet_send(ske->stream, type, flags, data, data_len);
1009 if (silc_packet_stream_is_udp(ske->stream) &&
1010 type != SILC_PACKET_FAILURE && type != SILC_PACKET_REKEY) {
1011 silc_free(ske->retrans.data);
1012 ske->retrans.type = type;
1013 ske->retrans.flags = flags;
1014 ske->retrans.data = silc_memdup(data, data_len);
1015 if (ske->retrans.data) {
1016 ske->retrans.data_len = data_len;
1017 silc_ske_install_retransmission(ske);
1024 /* Calls completion callback. Completion is called always in this function
1025 and must not be called anywhere else. */
1027 static void silc_ske_completion(SilcSKE ske)
1029 /* Call the completion callback */
1030 if (!ske->aborted && ske->callbacks->completed) {
1031 if (ske->status != SILC_SKE_STATUS_OK)
1032 ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL,
1033 ske->callbacks->context);
1035 ske->callbacks->completed(ske, ske->status, ske->prop, ske->keymat,
1036 ske->rekey, ske->callbacks->context);
1040 /* SKE FSM destructor. */
1042 static void silc_ske_finished(SilcFSM fsm, void *fsm_context,
1043 void *destructor_context)
1045 SilcSKE ske = fsm_context;
1049 /* Key exchange timeout task callback */
1051 SILC_TASK_CALLBACK(silc_ske_timeout)
1053 SilcSKE ske = context;
1055 SILC_LOG_DEBUG(("Timeout"));
1058 ske->status = SILC_SKE_STATUS_TIMEOUT;
1059 silc_ske_notify_failure(ske);
1061 silc_fsm_continue_sync(&ske->fsm);
1064 /* Key exchange timeout task callback */
1066 SILC_TASK_CALLBACK(silc_ske_probe_timeout)
1068 SilcSKE ske = context;
1070 SILC_LOG_DEBUG(("Probe timeout"));
1073 ske->status = SILC_SKE_STATUS_PROBE_TIMEOUT;
1074 silc_ske_notify_failure(ske);
1076 silc_fsm_continue_sync(&ske->fsm);
1079 /******************************* Protocol API *******************************/
1081 /* Allocates new SKE object. */
1083 SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule,
1084 SilcSKR repository, SilcPublicKey public_key,
1085 SilcPrivateKey private_key, void *context)
1089 SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
1091 if (!rng || !schedule)
1095 SILC_LOG_ERROR(("Public key must be given to silc_ske_alloc"));
1099 ske = silc_calloc(1, sizeof(*ske));
1102 ske->status = SILC_SKE_STATUS_OK;
1104 ske->repository = repository;
1105 ske->user_data = context;
1106 ske->schedule = schedule;
1107 ske->public_key = public_key;
1108 ske->private_key = private_key;
1109 ske->retry_timer = SILC_SKE_RETRY_MIN;
1115 /* Free's SKE object. */
1117 void silc_ske_free(SilcSKE ske)
1122 SILC_LOG_DEBUG(("Freeing Key Exchange object %p: aborted=%u refcount=%hu",
1123 ske, ske->aborted, ske->refcnt));
1127 * If already aborted, destroy the session immediately. Only do the
1128 * notification work if we have not already though, as doing so twice
1129 * results in memory corruption. We may have silc_ske_free called
1130 * twice, once when the abort is requested, and then again when the
1131 * FSM finish routine is called. We have to be prepared to handle
1135 ske->status = SILC_SKE_STATUS_ERROR;
1137 silc_ske_notify_failure(ske);
1139 if (silc_fsm_is_started(&ske->fsm))
1140 silc_fsm_continue_sync(&ske->fsm);
1142 SILC_LOG_DEBUG(("Not continuing FSM as it's finished for SKE %p", ske));
1146 if (ske->refcnt > 0)
1149 /* Free start payload */
1150 if (ske->start_payload)
1151 silc_ske_payload_start_free(ske->start_payload);
1153 /* Free KE payload */
1154 if (ske->ke1_payload)
1155 silc_ske_payload_ke_free(ske->ke1_payload);
1156 if (ske->ke2_payload)
1157 silc_ske_payload_ke_free(ske->ke2_payload);
1158 silc_free(ske->remote_version);
1162 if (ske->prop->group)
1163 silc_ske_group_free(ske->prop->group);
1164 if (ske->prop->cipher)
1165 silc_cipher_free(ske->prop->cipher);
1166 if (ske->prop->hash)
1167 silc_hash_free(ske->prop->hash);
1168 if (ske->prop->hmac)
1169 silc_hmac_free(ske->prop->hmac);
1170 if (ske->prop->public_key)
1171 silc_pkcs_public_key_free(ske->prop->public_key);
1172 silc_free(ske->prop);
1175 silc_ske_free_key_material(ske->keymat);
1176 if (ske->start_payload_copy)
1177 silc_buffer_free(ske->start_payload_copy);
1179 silc_mp_uninit(ske->x);
1183 silc_mp_uninit(ske->KEY);
1184 silc_free(ske->KEY);
1186 silc_free(ske->retrans.data);
1187 silc_free(ske->hash);
1188 silc_free(ske->callbacks);
1190 memset(ske, 0xdd, sizeof(*ske));
1194 /* Return user context */
1196 void *silc_ske_get_context(SilcSKE ske)
1198 return ske->user_data;
1201 /* Sets protocol callbacks */
1203 void silc_ske_set_callbacks(SilcSKE ske,
1204 SilcSKEVerifyCb verify_key,
1205 SilcSKECompletionCb completed,
1209 silc_free(ske->callbacks);
1210 ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
1211 if (!ske->callbacks)
1213 ske->callbacks->verify_key = verify_key;
1214 ske->callbacks->completed = completed;
1215 ske->callbacks->context = context;
1219 /******************************** Initiator *********************************/
1221 /* Start protocol. Send our proposal */
1223 SILC_FSM_STATE(silc_ske_st_initiator_start)
1225 SilcSKE ske = fsm_context;
1226 SilcBuffer payload_buf;
1229 SILC_LOG_DEBUG(("Start"));
1233 silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
1234 return SILC_FSM_CONTINUE;
1237 /* Encode the payload */
1238 status = silc_ske_payload_start_encode(ske, ske->start_payload,
1240 if (status != SILC_SKE_STATUS_OK) {
1241 /** Error encoding Start Payload */
1242 ske->status = status;
1243 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1244 return SILC_FSM_CONTINUE;
1247 /* Save the the payload buffer for future use. It is later used to
1248 compute the HASH value. */
1249 ske->start_payload_copy = payload_buf;
1251 /* Send the packet. */
1252 if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE, 0,
1253 silc_buffer_data(payload_buf),
1254 silc_buffer_len(payload_buf))) {
1255 /** Error sending packet */
1256 SILC_LOG_DEBUG(("Error sending packet"));
1257 ske->status = SILC_SKE_STATUS_ERROR;
1258 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1259 return SILC_FSM_CONTINUE;
1262 /** Wait for responder proposal */
1263 SILC_LOG_DEBUG(("Waiting for responder proposal"));
1264 silc_fsm_next(fsm, silc_ske_st_initiator_phase1);
1265 return SILC_FSM_WAIT;
1268 /* Phase-1. Receives responder's proposal */
1270 SILC_FSM_STATE(silc_ske_st_initiator_phase1)
1272 SilcSKE ske = fsm_context;
1273 SilcSKEStatus status;
1274 SilcSKEStartPayload payload;
1275 SilcSKESecurityProperties prop;
1276 SilcSKEDiffieHellmanGroup group = NULL;
1277 SilcBuffer packet_buf = &ske->packet->buffer;
1278 SilcUInt16 remote_port = 0;
1282 SILC_LOG_DEBUG(("Start"));
1284 if (ske->packet->type != SILC_PACKET_KEY_EXCHANGE) {
1285 SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
1286 silc_ske_install_retransmission(ske);
1287 silc_packet_free(ske->packet);
1289 return SILC_FSM_WAIT;
1292 silc_schedule_task_del_by_all(ske->schedule, 0, silc_ske_probe_timeout, ske);
1294 /* Decode the payload */
1295 status = silc_ske_payload_start_decode(ske, packet_buf, &payload);
1296 if (status != SILC_SKE_STATUS_OK) {
1297 /** Error decoding Start Payload */
1298 silc_packet_free(ske->packet);
1300 ske->status = status;
1301 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1302 return SILC_FSM_CONTINUE;
1305 /* Get remote ID and set it to stream */
1306 if (ske->packet->src_id_len &&
1307 (ske->packet->src_id_type == SILC_ID_SERVER ||
1308 ske->packet->src_id_type == SILC_ID_CLIENT)) {
1309 silc_id_str2id(ske->packet->src_id, ske->packet->src_id_len,
1310 ske->packet->src_id_type,
1311 (ske->packet->src_id_type == SILC_ID_SERVER ?
1312 (void *)&id.u.server_id : (void *)&id.u.client_id),
1313 (ske->packet->src_id_type == SILC_ID_SERVER ?
1314 sizeof(id.u.server_id) : sizeof(id.u.client_id)));
1315 silc_packet_set_ids(ske->stream, 0, NULL, ske->packet->src_id_type,
1316 (ske->packet->src_id_type == SILC_ID_SERVER ?
1317 (void *)&id.u.server_id : (void *)&id.u.client_id));
1320 silc_packet_free(ske->packet);
1323 /* Check that the cookie is returned unmodified. In case IV included
1324 flag and session port has been set, the first two bytes of cookie
1325 are the session port and we ignore them in this check. */
1326 if (payload->flags & SILC_SKE_SP_FLAG_IV_INCLUDED && ske->session_port) {
1327 /* Take remote port */
1328 SILC_GET16_MSB(remote_port, ske->start_payload->cookie);
1331 if (memcmp(ske->start_payload->cookie + coff, payload->cookie + coff,
1332 SILC_SKE_COOKIE_LEN - coff)) {
1333 /** Invalid cookie */
1334 SILC_LOG_ERROR(("Invalid cookie, modified or unsupported feature"));
1335 ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
1336 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1337 return SILC_FSM_CONTINUE;
1340 /* Check version string */
1341 ske->remote_version = silc_memdup(payload->version, payload->version_len);
1342 status = silc_ske_check_version(ske);
1343 if (status != SILC_SKE_STATUS_OK) {
1344 /** Version mismatch */
1345 ske->status = status;
1346 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1347 return SILC_FSM_CONTINUE;
1350 /* Free our KE Start Payload context, we don't need it anymore. */
1351 silc_ske_payload_start_free(ske->start_payload);
1352 ske->start_payload = NULL;
1354 /* Take the selected security properties into use while doing
1355 the key exchange. This is used only while doing the key
1357 ske->prop = prop = silc_calloc(1, sizeof(*prop));
1360 prop->flags = payload->flags;
1361 status = silc_ske_group_get_by_name(payload->ke_grp_list, &group);
1362 if (status != SILC_SKE_STATUS_OK)
1365 prop->group = group;
1366 prop->remote_port = remote_port;
1368 if (silc_pkcs_find_algorithm(payload->pkcs_alg_list, NULL) == NULL) {
1369 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
1372 if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
1373 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
1376 if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
1377 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1380 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
1381 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
1385 /* Save remote's KE Start Payload */
1386 ske->start_payload = payload;
1388 /** Send KE Payload */
1389 silc_fsm_next(fsm, silc_ske_st_initiator_phase2);
1390 return SILC_FSM_CONTINUE;
1394 silc_ske_payload_start_free(payload);
1396 silc_ske_group_free(group);
1399 silc_cipher_free(prop->cipher);
1401 silc_hash_free(prop->hash);
1403 silc_hmac_free(prop->hmac);
1408 if (status == SILC_SKE_STATUS_OK)
1409 status = SILC_SKE_STATUS_ERROR;
1412 ske->status = status;
1413 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1414 return SILC_FSM_CONTINUE;
1417 /* Phase-2. Send KE payload */
1419 SILC_FSM_STATE(silc_ske_st_initiator_phase2)
1421 SilcSKE ske = fsm_context;
1422 SilcSKEStatus status;
1423 SilcBuffer payload_buf;
1425 SilcSKEKEPayload payload;
1428 SILC_LOG_DEBUG(("Start"));
1430 /* Create the random number x, 1 < x < q. */
1431 x = silc_calloc(1, sizeof(*x));
1433 /** Out of memory */
1434 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1435 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1436 return SILC_FSM_CONTINUE;
1440 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
1441 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
1443 if (status != SILC_SKE_STATUS_OK) {
1444 /** Error generating random number */
1447 ske->status = status;
1448 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1449 return SILC_FSM_CONTINUE;
1452 /* Encode the result to Key Exchange Payload. */
1454 payload = silc_calloc(1, sizeof(*payload));
1456 /** Out of memory */
1459 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1460 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1461 return SILC_FSM_CONTINUE;
1463 ske->ke1_payload = payload;
1465 SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
1467 /* Do the Diffie Hellman computation, e = g ^ x mod p */
1468 silc_mp_init(&payload->x);
1469 silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
1470 &ske->prop->group->group);
1472 /* Get public key */
1473 payload->pk_data = silc_pkcs_public_key_encode(ske->public_key, &pk_len);
1474 if (!payload->pk_data) {
1475 /** Error encoding public key */
1478 silc_mp_uninit(&payload->x);
1480 ske->ke1_payload = NULL;
1481 ske->status = SILC_SKE_STATUS_ERROR;
1482 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1483 return SILC_FSM_CONTINUE;
1485 payload->pk_len = pk_len;
1486 payload->pk_type = silc_pkcs_get_type(ske->public_key);
1488 /* Compute signature data if we are doing mutual authentication */
1489 if (ske->private_key && ske->prop->flags & SILC_SKE_SP_FLAG_MUTUAL) {
1490 unsigned char hash[SILC_HASH_MAXLEN], sign[65536 + 1];
1491 SilcUInt32 hash_len, sign_len;
1493 SILC_LOG_DEBUG(("We are doing mutual authentication"));
1494 SILC_LOG_DEBUG(("Computing HASH_i value"));
1496 /* Compute the hash value */
1497 memset(hash, 0, sizeof(hash));
1498 if (silc_ske_make_hash(ske, hash, &hash_len, TRUE) != SILC_SKE_STATUS_OK)
1500 /** Error computing hash */
1503 silc_mp_uninit(&payload->x);
1504 silc_free(payload->pk_data);
1506 ske->ke1_payload = NULL;
1507 ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
1508 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1509 return SILC_FSM_CONTINUE;
1512 SILC_LOG_DEBUG(("Signing HASH_i value"));
1514 /* Sign the hash value */
1515 if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
1516 sizeof(sign) - 1, &sign_len, FALSE, ske->prop->hash)) {
1517 /** Error computing signature */
1520 silc_mp_uninit(&payload->x);
1521 silc_free(payload->pk_data);
1523 ske->ke1_payload = NULL;
1524 ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
1525 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1526 return SILC_FSM_CONTINUE;
1528 payload->sign_data = silc_memdup(sign, sign_len);
1529 if (payload->sign_data)
1530 payload->sign_len = sign_len;
1531 memset(sign, 0, sizeof(sign));
1534 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
1535 if (status != SILC_SKE_STATUS_OK) {
1536 /** Error encoding KE payload */
1539 silc_mp_uninit(&payload->x);
1540 silc_free(payload->pk_data);
1541 silc_free(payload->sign_data);
1543 ske->ke1_payload = NULL;
1544 ske->status = status;
1545 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1546 return SILC_FSM_CONTINUE;
1551 /* Check for backwards compatibility */
1553 /* Send the packet. */
1554 if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE_1, 0,
1555 silc_buffer_data(payload_buf),
1556 silc_buffer_len(payload_buf))) {
1557 /** Error sending packet */
1558 SILC_LOG_DEBUG(("Error sending packet"));
1559 ske->status = SILC_SKE_STATUS_ERROR;
1560 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1561 return SILC_FSM_CONTINUE;
1564 silc_buffer_free(payload_buf);
1566 /** Waiting responder's KE payload */
1567 silc_fsm_next(fsm, silc_ske_st_initiator_phase3);
1568 return SILC_FSM_WAIT;
1571 /* Phase-3. Process responder's KE payload */
1573 SILC_FSM_STATE(silc_ske_st_initiator_phase3)
1575 SilcSKE ske = fsm_context;
1576 SilcSKEStatus status;
1577 SilcSKEKEPayload payload;
1579 SilcBuffer packet_buf = &ske->packet->buffer;
1581 SILC_LOG_DEBUG(("Start"));
1583 if (ske->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
1584 SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
1585 silc_ske_install_retransmission(ske);
1586 silc_packet_free(ske->packet);
1588 return SILC_FSM_WAIT;
1591 /* Decode the payload */
1592 status = silc_ske_payload_ke_decode(ske, packet_buf, &payload);
1593 if (status != SILC_SKE_STATUS_OK) {
1594 /** Error decoding KE payload */
1595 silc_packet_free(ske->packet);
1597 ske->status = status;
1598 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1599 return SILC_FSM_CONTINUE;
1601 silc_packet_free(ske->packet);
1603 ske->ke2_payload = payload;
1605 if (!payload->pk_data && (ske->callbacks->verify_key || ske->repository)) {
1606 SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
1607 "even though we require it"));
1608 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
1612 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
1614 /* Compute the shared secret key */
1615 KEY = silc_calloc(1, sizeof(*KEY));
1617 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1621 silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
1624 /* Decode the remote's public key */
1625 if (payload->pk_data &&
1626 !silc_pkcs_public_key_alloc(payload->pk_type,
1627 payload->pk_data, payload->pk_len,
1628 &ske->prop->public_key)) {
1629 SILC_LOG_ERROR(("Unsupported/malformed public key received"));
1630 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
1634 if (ske->prop->public_key && (ske->callbacks->verify_key ||
1636 SILC_LOG_DEBUG(("Verifying public key"));
1638 /** Waiting public key verification */
1639 silc_fsm_next(fsm, silc_ske_st_initiator_phase4);
1641 /* If repository is provided, verify the key from there. */
1642 if (ske->repository) {
1645 find = silc_skr_find_alloc();
1647 status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1650 silc_skr_find_set_pkcs_type(find,
1651 silc_pkcs_get_type(ske->prop->public_key));
1652 silc_skr_find_set_public_key(find, ske->prop->public_key);
1653 silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT);
1655 /* Find key from repository */
1656 SILC_FSM_CALL(silc_skr_find(ske->repository, silc_fsm_get_schedule(fsm),
1657 find, silc_ske_skr_callback, ske));
1659 /* Verify from application */
1660 SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key,
1661 ske->callbacks->context,
1662 silc_ske_pk_verified, NULL));
1667 /** Process key material */
1668 silc_fsm_next(fsm, silc_ske_st_initiator_phase4);
1669 return SILC_FSM_CONTINUE;
1672 silc_ske_payload_ke_free(payload);
1673 ske->ke2_payload = NULL;
1675 silc_mp_uninit(ske->KEY);
1676 silc_free(ske->KEY);
1679 if (status == SILC_SKE_STATUS_OK)
1680 return SILC_SKE_STATUS_ERROR;
1683 ske->status = status;
1684 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1685 return SILC_FSM_CONTINUE;
1688 /* Process key material */
1690 SILC_FSM_STATE(silc_ske_st_initiator_phase4)
1692 SilcSKE ske = fsm_context;
1693 SilcSKEStatus status;
1694 SilcSKEKEPayload payload;
1695 unsigned char hash[SILC_HASH_MAXLEN];
1696 SilcUInt32 hash_len;
1697 int key_len, block_len;
1701 silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
1702 return SILC_FSM_CONTINUE;
1705 /* Check result of public key verification */
1706 if (ske->status != SILC_SKE_STATUS_OK) {
1707 /** Public key not verified */
1708 SILC_LOG_DEBUG(("Public key verification failed"));
1709 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1710 return SILC_FSM_CONTINUE;
1713 payload = ske->ke2_payload;
1715 /* Compute the HASH value */
1716 SILC_LOG_DEBUG(("Computing HASH value"));
1717 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1718 if (status != SILC_SKE_STATUS_OK)
1720 ske->hash = silc_memdup(hash, hash_len);
1722 status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1725 ske->hash_len = hash_len;
1727 if (ske->prop->public_key) {
1728 SILC_LOG_DEBUG(("Public key is authentic"));
1729 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
1731 /* Verify signature */
1732 if (!silc_pkcs_verify(ske->prop->public_key, payload->sign_data,
1733 payload->sign_len, hash, hash_len, NULL)) {
1734 SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
1735 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
1739 SILC_LOG_DEBUG(("Signature is Ok"));
1740 memset(hash, 'F', hash_len);
1743 ske->status = SILC_SKE_STATUS_OK;
1745 /* In case we are doing rekey move to finish it. */
1748 silc_fsm_next(fsm, silc_ske_st_rekey_initiator_done);
1749 return SILC_FSM_CONTINUE;
1752 /* Process key material */
1753 key_len = silc_cipher_get_key_len(ske->prop->cipher);
1754 block_len = silc_cipher_get_block_len(ske->prop->cipher);
1755 hash_len = silc_hash_len(ske->prop->hash);
1756 ske->keymat = silc_ske_process_key_material(ske, block_len,
1760 SILC_LOG_ERROR(("Error processing key material"));
1761 status = SILC_SKE_STATUS_ERROR;
1765 if (!ske->no_acks) {
1766 /* Send SUCCESS packet */
1767 SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, hash);
1768 if (!silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, hash, 4)) {
1769 /** Error sending packet */
1770 SILC_LOG_DEBUG(("Error sending packet"));
1771 ske->status = SILC_SKE_STATUS_ERROR;
1772 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1773 return SILC_FSM_CONTINUE;
1776 /** Waiting completion */
1777 silc_fsm_next(fsm, silc_ske_st_initiator_end);
1778 return SILC_FSM_WAIT;
1780 /** Complete protocol */
1781 silc_fsm_next(fsm, silc_ske_st_initiator_end);
1782 return SILC_FSM_CONTINUE;
1786 memset(hash, 'F', sizeof(hash));
1787 silc_ske_payload_ke_free(payload);
1788 ske->ke2_payload = NULL;
1790 silc_mp_uninit(ske->KEY);
1791 silc_free(ske->KEY);
1795 memset(ske->hash, 'F', hash_len);
1796 silc_free(ske->hash);
1800 if (status == SILC_SKE_STATUS_OK)
1801 status = SILC_SKE_STATUS_ERROR;
1804 ske->status = status;
1805 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1806 return SILC_FSM_CONTINUE;
1809 /* Protocol completed */
1811 SILC_FSM_STATE(silc_ske_st_initiator_end)
1813 SilcSKE ske = fsm_context;
1815 SILC_LOG_DEBUG(("Start"));
1817 if (!ske->no_acks && ske->packet->type != SILC_PACKET_SUCCESS) {
1818 SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
1819 silc_ske_install_retransmission(ske);
1820 silc_packet_free(ske->packet);
1822 return SILC_FSM_WAIT;
1825 SILC_LOG_DEBUG(("Key exchange completed successfully"));
1828 silc_packet_free(ske->packet);
1830 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1831 silc_schedule_task_del_by_context(ske->schedule, ske);
1833 /* Call completion */
1834 silc_ske_completion(ske);
1836 return SILC_FSM_FINISH;
1839 /* Aborted by application */
1841 SILC_FSM_STATE(silc_ske_st_initiator_aborted)
1843 SilcSKE ske = fsm_context;
1844 unsigned char data[4];
1846 SILC_LOG_DEBUG(("Aborted by caller"));
1848 /* Send FAILURE packet */
1849 SILC_PUT32_MSB(SILC_SKE_STATUS_ERROR, data);
1850 silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, data, 4);
1852 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1853 silc_schedule_task_del_by_context(ske->schedule, ske);
1855 /* Call completion */
1856 silc_ske_completion(ske);
1858 return SILC_FSM_FINISH;
1861 /* Error occurred. Send error to remote host */
1863 SILC_FSM_STATE(silc_ske_st_initiator_error)
1865 SilcSKE ske = fsm_context;
1867 unsigned char data[4];
1869 SILC_LOG_DEBUG(("Error %s (%d) occurred during key exchange",
1870 silc_ske_map_status(ske->status), ske->status));
1872 status = ske->status;
1873 if (status > SILC_SKE_STATUS_INVALID_COOKIE)
1874 status = SILC_SKE_STATUS_ERROR;
1876 /* Send FAILURE packet */
1877 SILC_PUT32_MSB(status, data);
1878 silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, data, 4);
1880 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1881 silc_schedule_task_del_by_context(ske->schedule, ske);
1883 /* Call completion */
1884 silc_ske_completion(ske);
1886 return SILC_FSM_FINISH;
1889 /* Failure received from remote */
1891 SILC_FSM_STATE(silc_ske_st_initiator_failure)
1893 SilcSKE ske = fsm_context;
1894 SilcUInt32 error = ske->status;
1896 if (ske->packet && silc_buffer_len(&ske->packet->buffer) == 4) {
1897 SILC_GET32_MSB(error, ske->packet->buffer.data);
1898 silc_packet_free(ske->packet);
1901 if (error == SILC_SKE_STATUS_OK)
1902 error = SILC_SKE_STATUS_ERROR;
1903 ske->status = error;
1905 SILC_LOG_DEBUG(("Error %s (%d) received during key exchange",
1906 silc_ske_map_status(ske->status), ske->status));
1908 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1909 silc_schedule_task_del_by_context(ske->schedule, ske);
1911 /* Call completion */
1912 silc_ske_completion(ske);
1914 return SILC_FSM_FINISH;
1917 /* Starts the protocol as initiator */
1919 SilcAsyncOperation silc_ske_initiator(SilcSKE ske,
1920 SilcPacketStream stream,
1921 SilcSKEParams params,
1922 SilcSKEStartPayload start_payload)
1924 SILC_LOG_DEBUG(("Start SKE %p as initiator; stream=%p; params=%p; "
1925 "start_payload=%p", ske, stream, params, start_payload));
1927 if (!ske || !stream || !params || !params->version)
1930 if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
1933 if (!silc_fsm_init(&ske->fsm, ske, silc_ske_finished, ske, ske->schedule))
1936 if (params->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)
1937 ske->session_port = params->session_port;
1939 /* Generate security properties if not provided */
1940 if (!start_payload && !params->prop) {
1942 silc_ske_assemble_security_properties(ske, params->flags,
1944 params->small_proposal);
1949 ske->timeout = params->timeout_secs ? params->timeout_secs : 30;
1950 ske->probe_timeout = (params->probe_timeout_secs ?
1951 params->probe_timeout_secs : 30);
1952 ske->start_payload = start_payload;
1953 ske->prop = params->prop;
1954 ske->version = params->version;
1955 ske->no_acks = params->no_acks;
1958 /* Link to packet stream to get key exchange packets */
1959 ske->stream = stream;
1960 silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
1961 SILC_PACKET_KEY_EXCHANGE,
1962 SILC_PACKET_KEY_EXCHANGE_2,
1963 SILC_PACKET_SUCCESS,
1964 SILC_PACKET_FAILURE, -1);
1966 /* Add key exchange timeout */
1967 silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout,
1968 ske, ske->timeout, 0);
1969 if (ske->timeout != ske->probe_timeout)
1970 silc_schedule_task_add_timeout(ske->schedule, silc_ske_probe_timeout,
1971 ske, ske->probe_timeout, 0);
1973 /* Start SKE as initiator */
1975 silc_fsm_start(&ske->fsm, silc_ske_st_initiator_start);
1977 silc_fsm_start(&ske->fsm, silc_ske_st_initiator_phase2);
1982 /******************************** Responder *********************************/
1984 /* Start protocol as responder. Wait initiator's start payload */
1986 SILC_FSM_STATE(silc_ske_st_responder_start)
1988 SilcSKE ske = fsm_context;
1990 SILC_LOG_DEBUG(("Start"));
1994 silc_fsm_next(fsm, silc_ske_st_responder_aborted);
1995 return SILC_FSM_CONTINUE;
1998 /** Wait for initiator */
2000 silc_fsm_next(fsm, silc_ske_st_responder_phase1);
2002 silc_fsm_next(fsm, silc_ske_st_responder_phase2);
2003 return SILC_FSM_WAIT;
2006 /* Decode initiator's start payload. Select the security properties from
2007 the initiator's start payload and send our reply start payload back. */
2009 SILC_FSM_STATE(silc_ske_st_responder_phase1)
2011 SilcSKE ske = fsm_context;
2012 SilcSKEStatus status;
2013 SilcSKEStartPayload remote_payload = NULL;
2014 SilcBuffer packet_buf = &ske->packet->buffer;
2017 SILC_LOG_DEBUG(("Start"));
2019 /* Decode the payload */
2020 status = silc_ske_payload_start_decode(ske, packet_buf, &remote_payload);
2021 if (status != SILC_SKE_STATUS_OK) {
2022 /** Error decoding Start Payload */
2023 silc_packet_free(ske->packet);
2025 ske->status = status;
2026 silc_fsm_next(fsm, silc_ske_st_responder_error);
2027 return SILC_FSM_CONTINUE;
2030 /* Get remote ID and set it to stream */
2031 if (ske->packet->src_id_len &&
2032 (ske->packet->src_id_type == SILC_ID_SERVER ||
2033 ske->packet->src_id_type == SILC_ID_CLIENT)) {
2034 silc_id_str2id(ske->packet->src_id, ske->packet->src_id_len,
2035 ske->packet->src_id_type,
2036 (ske->packet->src_id_type == SILC_ID_SERVER ?
2037 (void *)&id.u.server_id : (void *)&id.u.client_id),
2038 (ske->packet->src_id_type == SILC_ID_SERVER ?
2039 sizeof(id.u.server_id) : sizeof(id.u.client_id)));
2040 silc_packet_set_ids(ske->stream, 0, NULL, ske->packet->src_id_type,
2041 (ske->packet->src_id_type == SILC_ID_SERVER ?
2042 (void *)&id.u.server_id : (void *)&id.u.client_id));
2045 /* Take a copy of the payload buffer for future use. It is used to
2046 compute the HASH value. */
2047 ske->start_payload_copy = silc_buffer_copy(packet_buf);
2048 if (!ske->start_payload_copy) {
2049 silc_packet_free(ske->packet);
2051 ske->status = status;
2052 silc_fsm_next(fsm, silc_ske_st_responder_error);
2053 return SILC_FSM_CONTINUE;
2056 silc_packet_free(ske->packet);
2059 /* Force the mutual authentication flag if we want to do it. */
2060 if (ske->flags & SILC_SKE_SP_FLAG_MUTUAL) {
2061 SILC_LOG_DEBUG(("Force mutual authentication"));
2062 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
2065 /* Force PFS flag if we require it */
2066 if (ske->flags & SILC_SKE_SP_FLAG_PFS) {
2067 SILC_LOG_DEBUG(("Force PFS"));
2068 remote_payload->flags |= SILC_SKE_SP_FLAG_PFS;
2071 /* Disable IV Included flag if requested */
2072 if (remote_payload->flags & SILC_SKE_SP_FLAG_IV_INCLUDED &&
2073 !(ske->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)) {
2074 SILC_LOG_DEBUG(("We do not support IV Included flag"));
2075 remote_payload->flags &= ~SILC_SKE_SP_FLAG_IV_INCLUDED;
2078 /* Check and select security properties */
2079 status = silc_ske_select_security_properties(ske, remote_payload,
2081 if (status != SILC_SKE_STATUS_OK) {
2082 /** Error selecting proposal */
2083 silc_ske_payload_start_free(remote_payload);
2084 ske->status = status;
2085 silc_fsm_next(fsm, silc_ske_st_responder_error);
2086 return SILC_FSM_CONTINUE;
2089 silc_ske_payload_start_free(remote_payload);
2091 /* Encode our reply payload to send the selected security properties */
2092 status = silc_ske_payload_start_encode(ske, ske->start_payload,
2094 if (status != SILC_SKE_STATUS_OK)
2097 /* Send the packet. */
2098 if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE, 0,
2099 silc_buffer_data(packet_buf),
2100 silc_buffer_len(packet_buf)))
2103 silc_buffer_free(packet_buf);
2105 /** Waiting initiator's KE payload */
2106 silc_fsm_next(fsm, silc_ske_st_responder_phase2);
2107 return SILC_FSM_WAIT;
2110 if (ske->prop->group)
2111 silc_ske_group_free(ske->prop->group);
2112 if (ske->prop->cipher)
2113 silc_cipher_free(ske->prop->cipher);
2114 if (ske->prop->hash)
2115 silc_hash_free(ske->prop->hash);
2116 if (ske->prop->hmac)
2117 silc_hmac_free(ske->prop->hmac);
2118 silc_free(ske->prop);
2121 if (status == SILC_SKE_STATUS_OK)
2122 status = SILC_SKE_STATUS_ERROR;
2125 ske->status = status;
2126 silc_fsm_next(fsm, silc_ske_st_responder_error);
2127 return SILC_FSM_CONTINUE;
2130 /* Phase-2. Decode initiator's KE payload */
2132 SILC_FSM_STATE(silc_ske_st_responder_phase2)
2134 SilcSKE ske = fsm_context;
2135 SilcSKEStatus status;
2136 SilcSKEKEPayload recv_payload;
2137 SilcBuffer packet_buf = &ske->packet->buffer;
2139 SILC_LOG_DEBUG(("Start"));
2141 if (ske->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
2142 SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
2143 silc_ske_install_retransmission(ske);
2144 silc_packet_free(ske->packet);
2146 return SILC_FSM_WAIT;
2149 /* Decode Key Exchange Payload */
2150 status = silc_ske_payload_ke_decode(ske, packet_buf, &recv_payload);
2151 if (status != SILC_SKE_STATUS_OK) {
2152 /** Error decoding KE payload */
2153 silc_packet_free(ske->packet);
2155 ske->status = status;
2156 silc_fsm_next(fsm, silc_ske_st_responder_error);
2157 return SILC_FSM_CONTINUE;
2160 ske->ke1_payload = recv_payload;
2162 silc_packet_free(ske->packet);
2165 /* Verify public key, except in rekey, when it is not sent */
2167 if (!recv_payload->pk_data) {
2168 /** Public key not provided */
2169 SILC_LOG_ERROR(("Remote end did not send its public key (or "
2170 "certificate), even though we require it"));
2171 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
2172 silc_fsm_next(fsm, silc_ske_st_responder_error);
2173 return SILC_FSM_CONTINUE;
2176 /* Decode the remote's public key */
2177 if (!silc_pkcs_public_key_alloc(recv_payload->pk_type,
2178 recv_payload->pk_data,
2179 recv_payload->pk_len,
2180 &ske->prop->public_key)) {
2181 /** Error decoding public key */
2182 SILC_LOG_ERROR(("Unsupported/malformed public key received"));
2183 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
2184 silc_fsm_next(fsm, silc_ske_st_responder_error);
2185 return SILC_FSM_CONTINUE;
2188 SILC_LOG_DEBUG(("Verifying public key"));
2190 /** Waiting public key verification */
2191 silc_fsm_next(fsm, silc_ske_st_responder_phase4);
2193 /* If repository is provided, verify the key from there. */
2194 if (ske->repository) {
2197 find = silc_skr_find_alloc();
2199 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2200 silc_fsm_next(fsm, silc_ske_st_responder_error);
2201 return SILC_FSM_CONTINUE;
2203 silc_skr_find_set_pkcs_type(find,
2204 silc_pkcs_get_type(ske->prop->public_key));
2205 silc_skr_find_set_public_key(find, ske->prop->public_key);
2206 silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT);
2208 /* Find key from repository */
2209 SILC_FSM_CALL(silc_skr_find(ske->repository,
2210 silc_fsm_get_schedule(fsm), find,
2211 silc_ske_skr_callback, ske));
2213 /* Verify from application */
2214 if (ske->callbacks->verify_key)
2215 SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key,
2216 ske->callbacks->context,
2217 silc_ske_pk_verified, NULL));
2221 /** Generate KE2 payload */
2222 silc_fsm_next(fsm, silc_ske_st_responder_phase4);
2223 return SILC_FSM_CONTINUE;
2226 /* Phase-4. Generate KE2 payload */
2228 SILC_FSM_STATE(silc_ske_st_responder_phase4)
2230 SilcSKE ske = fsm_context;
2231 SilcSKEStatus status;
2232 SilcSKEKEPayload recv_payload, send_payload = NULL;
2233 SilcMPInt *x = NULL, *KEY;
2237 silc_fsm_next(fsm, silc_ske_st_responder_aborted);
2238 return SILC_FSM_CONTINUE;
2241 /* Check result of public key verification */
2242 if (ske->status != SILC_SKE_STATUS_OK) {
2243 /** Public key not verified */
2244 SILC_LOG_DEBUG(("Public key verification failed"));
2248 recv_payload = ske->ke1_payload;
2250 /* The public key verification was performed only if the Mutual
2251 Authentication flag is set. */
2252 if ((ske->start_payload &&
2253 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) ||
2254 ske->prop->flags & SILC_SKE_SP_FLAG_MUTUAL) {
2255 unsigned char hash[SILC_HASH_MAXLEN];
2256 SilcUInt32 hash_len;
2258 SILC_LOG_DEBUG(("We are doing mutual authentication"));
2260 /* Compute the hash value */
2261 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
2262 if (status != SILC_SKE_STATUS_OK) {
2263 /** Error computing hash */
2264 SILC_LOG_DEBUG(("Error computing hash"));
2265 ske->status = status;
2269 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
2271 /* Verify signature */
2272 if (!silc_pkcs_verify(ske->prop->public_key, recv_payload->sign_data,
2273 recv_payload->sign_len, hash, hash_len, NULL)) {
2274 /** Incorrect signature */
2275 SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
2276 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
2280 SILC_LOG_DEBUG(("Signature is Ok"));
2282 memset(hash, 'F', hash_len);
2285 /* Create the random number x, 1 < x < q. */
2286 x = silc_calloc(1, sizeof(*x));
2288 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2293 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
2294 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
2296 if (status != SILC_SKE_STATUS_OK) {
2297 /** Error generating random number */
2298 ske->status = status;
2302 /* Save the results for later processing */
2303 send_payload = silc_calloc(1, sizeof(*send_payload));
2304 if (!send_payload) {
2305 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2309 ske->ke2_payload = send_payload;
2311 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
2313 /* Do the Diffie Hellman computation, f = g ^ x mod p */
2314 silc_mp_init(&send_payload->x);
2315 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
2316 &ske->prop->group->group);
2318 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
2320 /* Compute the shared secret key */
2321 KEY = silc_calloc(1, sizeof(*KEY));
2323 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2327 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
2328 &ske->prop->group->group);
2331 /** Send KE2 payload */
2332 silc_fsm_next(fsm, silc_ske_st_responder_phase5);
2333 return SILC_FSM_CONTINUE;
2339 silc_free(send_payload);
2340 ske->ke2_payload = NULL;
2342 silc_fsm_next(fsm, silc_ske_st_responder_error);
2343 return SILC_FSM_CONTINUE;
2346 /* Phase-5. Send KE2 payload */
2348 SILC_FSM_STATE(silc_ske_st_responder_phase5)
2350 SilcSKE ske = fsm_context;
2351 SilcSKEStatus status;
2352 SilcBuffer payload_buf;
2353 unsigned char hash[SILC_HASH_MAXLEN], sign[65536 + 1], *pk;
2354 SilcUInt32 hash_len, sign_len, pk_len;
2356 SILC_LOG_DEBUG(("Start"));
2358 if (ske->public_key && ske->private_key) {
2359 SILC_LOG_DEBUG(("Getting public key"));
2361 /* Get the public key */
2362 pk = silc_pkcs_public_key_encode(ske->public_key, &pk_len);
2364 /** Error encoding public key */
2365 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2366 silc_fsm_next(fsm, silc_ske_st_responder_error);
2367 return SILC_FSM_CONTINUE;
2369 ske->ke2_payload->pk_data = pk;
2370 ske->ke2_payload->pk_len = pk_len;
2373 SILC_LOG_DEBUG(("Computing HASH value"));
2375 /* Compute the hash value */
2376 memset(hash, 0, sizeof(hash));
2377 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
2378 if (status != SILC_SKE_STATUS_OK) {
2379 /** Error computing hash */
2380 ske->status = status;
2381 silc_fsm_next(fsm, silc_ske_st_responder_error);
2382 return SILC_FSM_CONTINUE;
2384 ske->hash = silc_memdup(hash, hash_len);
2386 /** Error computing hash */
2387 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2388 silc_fsm_next(fsm, silc_ske_st_responder_error);
2389 return SILC_FSM_CONTINUE;
2391 ske->hash_len = hash_len;
2393 if (ske->public_key && ske->private_key) {
2394 SILC_LOG_DEBUG(("Signing HASH value"));
2396 /* Sign the hash value */
2397 if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
2398 sizeof(sign) - 1, &sign_len, FALSE, ske->prop->hash)) {
2399 /** Error computing signature */
2400 ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
2401 silc_fsm_next(fsm, silc_ske_st_responder_error);
2402 return SILC_FSM_CONTINUE;
2404 ske->ke2_payload->sign_data = silc_memdup(sign, sign_len);
2405 if (!ske->ke2_payload->sign_data) {
2406 /** Error computing hash */
2407 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2408 silc_fsm_next(fsm, silc_ske_st_responder_error);
2409 return SILC_FSM_CONTINUE;
2411 ske->ke2_payload->sign_len = sign_len;
2412 memset(sign, 0, sizeof(sign));
2414 ske->ke2_payload->pk_type = silc_pkcs_get_type(ske->public_key);
2416 /* Encode the Key Exchange Payload */
2417 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
2419 if (status != SILC_SKE_STATUS_OK) {
2420 /** Error encoding KE payload */
2421 ske->status = status;
2422 silc_fsm_next(fsm, silc_ske_st_responder_error);
2423 return SILC_FSM_CONTINUE;
2426 /* Send the packet. */
2427 if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE_2, 0,
2428 payload_buf->data, silc_buffer_len(payload_buf))) {
2429 SILC_LOG_DEBUG(("Error sending packet"));
2430 ske->status = SILC_SKE_STATUS_ERROR;
2431 silc_fsm_next(fsm, silc_ske_st_responder_error);
2432 return SILC_FSM_CONTINUE;
2435 silc_buffer_free(payload_buf);
2437 /* In case we are doing rekey move to finish it. */
2440 silc_fsm_next(fsm, silc_ske_st_rekey_responder_done);
2441 return SILC_FSM_CONTINUE;
2444 if (!ske->no_acks) {
2445 /** Waiting completion */
2446 silc_fsm_next(fsm, silc_ske_st_responder_end);
2447 return SILC_FSM_WAIT;
2449 /** Complete protocol */
2450 silc_fsm_next(fsm, silc_ske_st_responder_end);
2451 return SILC_FSM_CONTINUE;
2455 /* Protocol completed */
2457 SILC_FSM_STATE(silc_ske_st_responder_end)
2459 SilcSKE ske = fsm_context;
2460 unsigned char tmp[4];
2461 SilcUInt32 hash_len, key_len, block_len;
2463 if (!ske->no_acks && ske->packet->type != SILC_PACKET_SUCCESS) {
2464 SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
2465 silc_ske_install_retransmission(ske);
2466 silc_packet_free(ske->packet);
2468 return SILC_FSM_WAIT;
2471 silc_packet_free(ske->packet);
2474 /* Process key material */
2475 key_len = silc_cipher_get_key_len(ske->prop->cipher);
2476 block_len = silc_cipher_get_block_len(ske->prop->cipher);
2477 hash_len = silc_hash_len(ske->prop->hash);
2478 ske->keymat = silc_ske_process_key_material(ske, block_len,
2482 /** Error processing key material */
2483 ske->status = SILC_SKE_STATUS_ERROR;
2484 silc_fsm_next(fsm, silc_ske_st_responder_error);
2485 return SILC_FSM_CONTINUE;
2488 if (!ske->no_acks) {
2489 /* Send SUCCESS packet */
2490 SILC_PUT32_MSB(SILC_SKE_STATUS_OK, tmp);
2491 silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, tmp, 4);
2494 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2495 silc_schedule_task_del_by_context(ske->schedule, ske);
2497 /* Call completion */
2498 silc_ske_completion(ske);
2500 return SILC_FSM_FINISH;
2503 /* Aborted by application */
2505 SILC_FSM_STATE(silc_ske_st_responder_aborted)
2507 SilcSKE ske = fsm_context;
2508 unsigned char tmp[4];
2510 SILC_LOG_DEBUG(("Key exchange protocol aborted"));
2512 /* Send FAILURE packet */
2513 SILC_PUT32_MSB(SILC_SKE_STATUS_ERROR, tmp);
2514 silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, tmp, 4);
2516 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2517 silc_schedule_task_del_by_context(ske->schedule, ske);
2519 /* Call completion */
2520 silc_ske_completion(ske);
2522 return SILC_FSM_FINISH;
2525 /* Failure received from remote */
2527 SILC_FSM_STATE(silc_ske_st_responder_failure)
2529 SilcSKE ske = fsm_context;
2530 SilcUInt32 error = ske->status;
2532 SILC_LOG_DEBUG(("Key exchange protocol failed"));
2534 if (ske->packet && silc_buffer_len(&ske->packet->buffer) == 4) {
2535 SILC_GET32_MSB(error, ske->packet->buffer.data);
2536 silc_packet_free(ske->packet);
2539 if (error == SILC_SKE_STATUS_OK)
2540 error = SILC_SKE_STATUS_ERROR;
2541 ske->status = error;
2543 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2544 silc_schedule_task_del_by_context(ske->schedule, ske);
2546 /* Call completion */
2547 silc_ske_completion(ske);
2549 return SILC_FSM_FINISH;
2552 /* Error occurred */
2554 SILC_FSM_STATE(silc_ske_st_responder_error)
2556 SilcSKE ske = fsm_context;
2557 unsigned char tmp[4];
2560 SILC_LOG_DEBUG(("Error %d (%s) during key exchange protocol",
2561 ske->status, silc_ske_map_status(ske->status)));
2563 /* Send FAILURE packet */
2564 status = ske->status;
2565 if (status > SILC_SKE_STATUS_INVALID_COOKIE)
2566 status = SILC_SKE_STATUS_ERROR;
2567 SILC_PUT32_MSB(status, tmp);
2568 silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, tmp, 4);
2570 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2571 silc_schedule_task_del_by_context(ske->schedule, ske);
2573 /* Call completion */
2574 silc_ske_completion(ske);
2576 return SILC_FSM_FINISH;
2579 /* Starts the protocol as responder. */
2581 SilcAsyncOperation silc_ske_responder(SilcSKE ske,
2582 SilcPacketStream stream,
2583 SilcSKEParams params)
2585 SILC_LOG_DEBUG(("Start SKE as responder"));
2587 if (!ske || !stream || !params || !params->version)
2590 if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
2593 if (!silc_fsm_init(&ske->fsm, ske, silc_ske_finished, ske, ske->schedule))
2596 ske->responder = TRUE;
2597 ske->flags = params->flags;
2598 ske->timeout = params->timeout_secs ? params->timeout_secs : 30;
2599 if (ske->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)
2600 ske->session_port = params->session_port;
2601 ske->version = params->version;
2602 ske->no_acks = params->no_acks;
2603 ske->prop = params->prop;
2608 /* Link to packet stream to get key exchange packets */
2609 ske->stream = stream;
2610 silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
2611 SILC_PACKET_KEY_EXCHANGE,
2612 SILC_PACKET_KEY_EXCHANGE_1,
2613 SILC_PACKET_SUCCESS,
2614 SILC_PACKET_FAILURE, -1);
2616 /* Add key exchange timeout */
2617 silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout,
2618 ske, ske->timeout, 0);
2620 /* Start SKE as responder */
2621 silc_fsm_start(&ske->fsm, silc_ske_st_responder_start);
2626 /***************************** Initiator Rekey ******************************/
2630 SILC_FSM_STATE(silc_ske_st_rekey_initiator_start)
2632 SilcSKE ske = fsm_context;
2635 SILC_LOG_DEBUG(("Start rekey (%s)", ske->rekey->pfs ? "PFS" : "No PFS"));
2639 silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
2640 return SILC_FSM_CONTINUE;
2643 /* Add rekey exchange timeout */
2644 silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout,
2647 ske->prop = silc_calloc(1, sizeof(*ske->prop));
2650 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2651 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2652 return SILC_FSM_CONTINUE;
2655 if (!silc_hash_alloc(ske->rekey->hash, &ske->prop->hash)) {
2656 /** Cannot allocate hash */
2657 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2658 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2659 return SILC_FSM_CONTINUE;
2662 /* Send REKEY packet to start rekey protocol */
2663 if (!silc_ske_packet_send(ske, SILC_PACKET_REKEY, 0, NULL, 0)) {
2664 /** Error sending packet */
2665 SILC_LOG_DEBUG(("Error sending packet"));
2666 ske->status = SILC_SKE_STATUS_ERROR;
2667 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2668 return SILC_FSM_CONTINUE;
2671 /* If doing rekey without PFS, move directly to the end of the protocol. */
2672 if (!ske->rekey->pfs) {
2673 /** Rekey without PFS */
2674 silc_fsm_next(fsm, silc_ske_st_rekey_initiator_done);
2675 return SILC_FSM_CONTINUE;
2678 status = silc_ske_group_get_by_number(ske->rekey->ske_group,
2680 if (status != SILC_SKE_STATUS_OK) {
2681 /** Unknown group */
2682 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2683 return SILC_FSM_CONTINUE;
2686 /** Rekey with PFS */
2687 silc_fsm_next(fsm, silc_ske_st_initiator_phase2);
2688 return SILC_FSM_CONTINUE;
2691 /* Sends REKEY_DONE packet to finish the protocol. */
2693 SILC_FSM_STATE(silc_ske_st_rekey_initiator_done)
2695 SilcSKE ske = fsm_context;
2696 SilcCipher send_key;
2699 SilcUInt32 key_len, block_len, hash_len, x_len;
2700 unsigned char *pfsbuf;
2702 SILC_LOG_DEBUG(("Start"));
2704 silc_packet_get_keys(ske->stream, &send_key, NULL, &hmac_send, NULL);
2705 key_len = silc_cipher_get_key_len(send_key);
2706 block_len = silc_cipher_get_block_len(send_key);
2707 hash = ske->prop->hash;
2708 hash_len = silc_hash_len(hash);
2710 /* Process key material */
2711 if (ske->rekey->pfs) {
2713 pfsbuf = silc_mp_mp2bin(ske->KEY, 0, &x_len);
2715 SILC_LOG_ERROR(("Error processing key material"));
2716 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2717 return SILC_FSM_CONTINUE;
2719 ske->keymat = silc_ske_process_key_material_data(pfsbuf, x_len,
2722 memset(pfsbuf, 0, x_len);
2727 silc_ske_process_key_material_data(ske->rekey->send_enc_key,
2728 ske->rekey->enc_key_len / 8,
2734 SILC_LOG_ERROR(("Error processing key material"));
2735 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2736 return SILC_FSM_CONTINUE;
2739 ske->prop->cipher = send_key;
2740 ske->prop->hmac = hmac_send;
2742 /* Get sending keys */
2743 if (!silc_ske_set_keys(ske, ske->keymat, ske->prop, &send_key, NULL,
2744 &hmac_send, NULL, NULL)) {
2745 /** Cannot get keys */
2746 ske->status = SILC_SKE_STATUS_ERROR;
2747 ske->prop->cipher = NULL;
2748 ske->prop->hmac = NULL;
2749 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2750 return SILC_FSM_CONTINUE;
2753 ske->prop->cipher = NULL;
2754 ske->prop->hmac = NULL;
2756 /* Set the new keys into use. This will also send REKEY_DONE packet. Any
2757 packet sent after this call will be protected with the new keys. */
2758 if (!silc_packet_set_keys(ske->stream, send_key, NULL, hmac_send, NULL,
2760 /** Cannot set keys */
2761 SILC_LOG_DEBUG(("Cannot set new keys, error sending REKEY_DONE"));
2762 ske->status = SILC_SKE_STATUS_ERROR;
2763 silc_cipher_free(send_key);
2764 silc_hmac_free(hmac_send);
2765 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2766 return SILC_FSM_CONTINUE;
2769 /** Wait for REKEY_DONE */
2770 silc_fsm_next(fsm, silc_ske_st_rekey_initiator_end);
2771 return SILC_FSM_WAIT;
2774 /* Rekey protocol end */
2776 SILC_FSM_STATE(silc_ske_st_rekey_initiator_end)
2778 SilcSKE ske = fsm_context;
2779 SilcCipher receive_key;
2780 SilcHmac hmac_receive;
2781 SilcSKERekeyMaterial rekey;
2783 SILC_LOG_DEBUG(("Start"));
2785 if (ske->packet->type != SILC_PACKET_REKEY_DONE) {
2786 SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
2787 silc_packet_free(ske->packet);
2789 return SILC_FSM_WAIT;
2792 silc_packet_get_keys(ske->stream, NULL, &receive_key, NULL, &hmac_receive);
2793 ske->prop->cipher = receive_key;
2794 ske->prop->hmac = hmac_receive;
2796 /* Get receiving keys */
2797 if (!silc_ske_set_keys(ske, ske->keymat, ske->prop, NULL, &receive_key,
2798 NULL, &hmac_receive, NULL)) {
2799 /** Cannot get keys */
2800 ske->status = SILC_SKE_STATUS_ERROR;
2801 ske->prop->cipher = NULL;
2802 ske->prop->hmac = NULL;
2803 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2804 return SILC_FSM_CONTINUE;
2807 /* Set new receiving keys into use. All packets received after this will
2808 be decrypted with the new keys. */
2809 if (!silc_packet_set_keys(ske->stream, NULL, receive_key, NULL,
2810 hmac_receive, FALSE)) {
2811 /** Cannot set keys */
2812 SILC_LOG_DEBUG(("Cannot set new keys"));
2813 ske->status = SILC_SKE_STATUS_ERROR;
2814 silc_cipher_free(receive_key);
2815 silc_hmac_free(hmac_receive);
2816 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2817 return SILC_FSM_CONTINUE;
2820 SILC_LOG_DEBUG(("Rekey completed successfully"));
2822 /* Generate new rekey material */
2823 rekey = silc_ske_make_rekey_material(ske, ske->keymat);
2826 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2827 ske->prop->cipher = NULL;
2828 ske->prop->hmac = NULL;
2829 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2830 return SILC_FSM_CONTINUE;
2832 rekey->pfs = ske->rekey->pfs;
2835 ske->prop->cipher = NULL;
2836 ske->prop->hmac = NULL;
2837 silc_packet_free(ske->packet);
2839 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2840 silc_schedule_task_del_by_context(ske->schedule, ske);
2842 /* Call completion */
2843 silc_ske_completion(ske);
2845 return SILC_FSM_FINISH;
2848 /* Starts rekey protocol as initiator */
2851 silc_ske_rekey_initiator(SilcSKE ske,
2852 SilcPacketStream stream,
2853 SilcSKERekeyMaterial rekey)
2855 SILC_LOG_DEBUG(("Start SKE rekey as initator"));
2857 if (!ske || !stream || !rekey) {
2858 SILC_LOG_ERROR(("Missing arguments to silc_ske_rekey_initiator"));
2863 if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
2866 if (!silc_fsm_init(&ske->fsm, ske, silc_ske_finished, ske, ske->schedule))
2870 ske->responder = FALSE;
2871 ske->rekeying = TRUE;
2874 /* Link to packet stream to get key exchange packets */
2875 ske->stream = stream;
2876 silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
2878 SILC_PACKET_REKEY_DONE,
2879 SILC_PACKET_KEY_EXCHANGE_2,
2880 SILC_PACKET_SUCCESS,
2881 SILC_PACKET_FAILURE, -1);
2883 /* Start SKE rekey as initiator */
2884 silc_fsm_start(&ske->fsm, silc_ske_st_rekey_initiator_start);
2889 /***************************** Responder Rekey ******************************/
2891 /* Wait for initiator's packet */
2893 SILC_FSM_STATE(silc_ske_st_rekey_responder_wait)
2895 SilcSKE ske = fsm_context;
2897 SILC_LOG_DEBUG(("Start rekey (%s)", ske->rekey->pfs ? "PFS" : "No PFS"));
2901 silc_fsm_next(fsm, silc_ske_st_responder_aborted);
2902 return SILC_FSM_CONTINUE;
2905 /* Add rekey exchange timeout */
2906 silc_schedule_task_add_timeout(ske->schedule, silc_ske_timeout,
2909 silc_fsm_next(fsm, silc_ske_st_rekey_responder_start);
2911 /* If REKEY packet already received process it directly */
2912 if (ske->packet && ske->packet->type == SILC_PACKET_REKEY)
2913 return SILC_FSM_CONTINUE;
2915 /* Wait for REKEY */
2916 return SILC_FSM_WAIT;
2919 /* Process initiator's REKEY packet */
2921 SILC_FSM_STATE(silc_ske_st_rekey_responder_start)
2923 SilcSKE ske = fsm_context;
2924 SilcSKEStatus status;
2926 SILC_LOG_DEBUG(("Start"));
2928 if (ske->packet->type != SILC_PACKET_REKEY) {
2929 ske->status = SILC_SKE_STATUS_ERROR;
2930 silc_packet_free(ske->packet);
2932 silc_fsm_next(fsm, silc_ske_st_responder_error);
2933 return SILC_FSM_CONTINUE;
2936 ske->prop = silc_calloc(1, sizeof(*ske->prop));
2939 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2940 silc_fsm_next(fsm, silc_ske_st_responder_error);
2941 return SILC_FSM_CONTINUE;
2944 if (!silc_hash_alloc(ske->rekey->hash, &ske->prop->hash)) {
2945 /** Cannot allocate hash */
2946 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2947 silc_fsm_next(fsm, silc_ske_st_responder_error);
2948 return SILC_FSM_CONTINUE;
2951 /* If doing rekey without PFS, move directly to the end of the protocol. */
2952 if (!ske->rekey->pfs) {
2953 /** Rekey without PFS */
2954 silc_fsm_next(fsm, silc_ske_st_rekey_responder_done);
2955 return SILC_FSM_CONTINUE;
2958 status = silc_ske_group_get_by_number(ske->rekey->ske_group,
2960 if (status != SILC_SKE_STATUS_OK) {
2961 /** Unknown group */
2962 silc_fsm_next(fsm, silc_ske_st_responder_error);
2963 return SILC_FSM_CONTINUE;
2966 /** Rekey with PFS */
2967 silc_fsm_next(fsm, silc_ske_st_responder_phase2);
2968 return SILC_FSM_WAIT;
2971 /* Sends REKEY_DONE packet to finish the protocol. */
2973 SILC_FSM_STATE(silc_ske_st_rekey_responder_done)
2975 SilcSKE ske = fsm_context;
2976 SilcCipher send_key;
2979 SilcUInt32 key_len, block_len, hash_len, x_len;
2980 unsigned char *pfsbuf;
2982 SILC_LOG_DEBUG(("Start"));
2984 silc_packet_get_keys(ske->stream, &send_key, NULL, &hmac_send, NULL);
2985 key_len = silc_cipher_get_key_len(send_key);
2986 block_len = silc_cipher_get_block_len(send_key);
2987 hash = ske->prop->hash;
2988 hash_len = silc_hash_len(hash);
2990 /* Process key material */
2991 if (ske->rekey->pfs) {
2993 pfsbuf = silc_mp_mp2bin(ske->KEY, 0, &x_len);
2995 SILC_LOG_ERROR(("Error processing key material"));
2996 silc_fsm_next(fsm, silc_ske_st_responder_error);
2997 return SILC_FSM_CONTINUE;
2999 ske->keymat = silc_ske_process_key_material_data(pfsbuf, x_len,
3002 memset(pfsbuf, 0, x_len);
3007 silc_ske_process_key_material_data(ske->rekey->send_enc_key,
3008 ske->rekey->enc_key_len / 8,
3014 SILC_LOG_ERROR(("Error processing key material"));
3015 silc_fsm_next(fsm, silc_ske_st_responder_error);
3016 return SILC_FSM_CONTINUE;
3019 ske->prop->cipher = send_key;
3020 ske->prop->hmac = hmac_send;
3022 /* Get sending keys */
3023 if (!silc_ske_set_keys(ske, ske->keymat, ske->prop, &send_key, NULL,
3024 &hmac_send, NULL, NULL)) {
3025 /** Cannot get keys */
3026 ske->status = SILC_SKE_STATUS_ERROR;
3027 ske->prop->cipher = NULL;
3028 ske->prop->hmac = NULL;
3029 silc_fsm_next(fsm, silc_ske_st_responder_error);
3030 return SILC_FSM_CONTINUE;
3033 ske->prop->cipher = NULL;
3034 ske->prop->hmac = NULL;
3036 /* Set the new keys into use. This will also send REKEY_DONE packet. Any
3037 packet sent after this call will be protected with the new keys. */
3038 if (!silc_packet_set_keys(ske->stream, send_key, NULL, hmac_send, NULL,
3040 /** Cannot set keys */
3041 SILC_LOG_DEBUG(("Cannot set new keys, error sending REKEY_DONE"));
3042 ske->status = SILC_SKE_STATUS_ERROR;
3043 silc_cipher_free(send_key);
3044 silc_hmac_free(hmac_send);
3045 silc_fsm_next(fsm, silc_ske_st_responder_error);
3046 return SILC_FSM_CONTINUE;
3049 /** Wait for REKEY_DONE */
3050 silc_fsm_next(fsm, silc_ske_st_rekey_responder_end);
3051 return SILC_FSM_WAIT;
3054 /* Rekey protocol end */
3056 SILC_FSM_STATE(silc_ske_st_rekey_responder_end)
3058 SilcSKE ske = fsm_context;
3059 SilcCipher receive_key;
3060 SilcHmac hmac_receive;
3061 SilcSKERekeyMaterial rekey;
3063 SILC_LOG_DEBUG(("Start"));
3065 if (ske->packet->type != SILC_PACKET_REKEY_DONE) {
3066 SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
3067 silc_packet_free(ske->packet);
3069 return SILC_FSM_WAIT;
3072 silc_packet_get_keys(ske->stream, NULL, &receive_key, NULL, &hmac_receive);
3073 ske->prop->cipher = receive_key;
3074 ske->prop->hmac = hmac_receive;
3076 /* Get receiving keys */
3077 if (!silc_ske_set_keys(ske, ske->keymat, ske->prop, NULL, &receive_key,
3078 NULL, &hmac_receive, NULL)) {
3079 /** Cannot get keys */
3080 ske->status = SILC_SKE_STATUS_ERROR;
3081 ske->prop->cipher = NULL;
3082 ske->prop->hmac = NULL;
3083 silc_fsm_next(fsm, silc_ske_st_responder_error);
3084 return SILC_FSM_CONTINUE;
3087 /* Set new receiving keys into use. All packets received after this will
3088 be decrypted with the new keys. */
3089 if (!silc_packet_set_keys(ske->stream, NULL, receive_key, NULL,
3090 hmac_receive, FALSE)) {
3091 /** Cannot set keys */
3092 SILC_LOG_DEBUG(("Cannot set new keys"));
3093 ske->status = SILC_SKE_STATUS_ERROR;
3094 ske->prop->cipher = NULL;
3095 ske->prop->hmac = NULL;
3096 silc_cipher_free(receive_key);
3097 silc_hmac_free(hmac_receive);
3098 silc_fsm_next(fsm, silc_ske_st_responder_error);
3099 return SILC_FSM_CONTINUE;
3102 SILC_LOG_DEBUG(("Rekey completed successfully"));
3104 /* Generate new rekey material */
3105 rekey = silc_ske_make_rekey_material(ske, ske->keymat);
3108 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
3109 ske->prop->cipher = NULL;
3110 ske->prop->hmac = NULL;
3111 silc_fsm_next(fsm, silc_ske_st_responder_error);
3112 return SILC_FSM_CONTINUE;
3114 rekey->pfs = ske->rekey->pfs;
3117 ske->prop->cipher = NULL;
3118 ske->prop->hmac = NULL;
3119 silc_packet_free(ske->packet);
3121 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
3122 silc_schedule_task_del_by_context(ske->schedule, ske);
3124 /* Call completion */
3125 silc_ske_completion(ske);
3127 return SILC_FSM_FINISH;
3130 /* Starts rekey protocol as responder */
3133 silc_ske_rekey_responder(SilcSKE ske,
3134 SilcPacketStream stream,
3135 SilcSKERekeyMaterial rekey,
3138 SILC_LOG_DEBUG(("Start SKE rekey as responder"));
3140 if (!ske || !stream || !rekey)
3143 if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
3146 if (!silc_fsm_init(&ske->fsm, ske, silc_ske_finished, ske, ske->schedule))
3150 ske->responder = TRUE;
3151 ske->rekeying = TRUE;
3152 ske->packet = packet;
3155 /* Link to packet stream to get key exchange packets */
3156 ske->stream = stream;
3157 silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
3159 SILC_PACKET_REKEY_DONE,
3160 SILC_PACKET_KEY_EXCHANGE_1,
3161 SILC_PACKET_SUCCESS,
3162 SILC_PACKET_FAILURE, -1);
3164 /* Start SKE rekey as responder */
3165 silc_fsm_start_sync(&ske->fsm, silc_ske_st_rekey_responder_wait);
3170 /* Processes the provided key material `data' as the SILC protocol
3171 specification defines. */
3174 silc_ske_process_key_material_data(unsigned char *data,
3175 SilcUInt32 data_len,
3176 SilcUInt32 req_iv_len,
3177 SilcUInt32 req_enc_key_len,
3178 SilcUInt32 req_hmac_key_len,
3182 unsigned char hashd[SILC_HASH_MAXLEN];
3183 SilcUInt32 hash_len = req_hmac_key_len;
3184 SilcUInt32 enc_key_len = req_enc_key_len / 8;
3185 SilcSKEKeyMaterial key;
3187 SILC_LOG_DEBUG(("Start"));
3189 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
3192 key = silc_calloc(1, sizeof(*key));
3196 buf = silc_buffer_alloc_size(1 + data_len);
3199 silc_buffer_format(buf,
3200 SILC_STR_UI_CHAR(0),
3201 SILC_STR_DATA(data, data_len),
3205 memset(hashd, 0, sizeof(hashd));
3207 silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
3208 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
3209 if (!key->send_iv) {
3210 silc_buffer_clear(buf);
3211 silc_buffer_free(buf);
3215 memcpy(key->send_iv, hashd, req_iv_len);
3216 memset(hashd, 0, sizeof(hashd));
3218 silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
3219 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
3220 if (!key->receive_iv) {
3221 silc_buffer_clear(buf);
3222 silc_buffer_free(buf);
3226 memcpy(key->receive_iv, hashd, req_iv_len);
3227 key->iv_len = req_iv_len;
3229 /* Take the encryption keys. If requested key size is more than
3230 the size of hash length we will distribute more key material
3231 as protocol defines. */
3233 if (enc_key_len > hash_len) {
3235 unsigned char k1[SILC_HASH_MAXLEN], k2[SILC_HASH_MAXLEN],
3236 k3[SILC_HASH_MAXLEN];
3237 unsigned char *dtmp;
3240 if (enc_key_len > (3 * hash_len))
3243 /* Take first round */
3244 memset(k1, 0, sizeof(k1));
3245 silc_hash_make(hash, buf->data, silc_buffer_len(buf), k1);
3247 /* Take second round */
3248 dist = silc_buffer_alloc_size(data_len + hash_len);
3251 silc_buffer_format(dist,
3252 SILC_STR_DATA(data, data_len),
3253 SILC_STR_DATA(k1, hash_len),
3255 memset(k2, 0, sizeof(k2));
3256 silc_hash_make(hash, dist->data, silc_buffer_len(dist), k2);
3258 /* Take third round */
3259 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
3260 silc_buffer_pull_tail(dist, hash_len);
3261 silc_buffer_pull(dist, data_len + hash_len);
3262 silc_buffer_format(dist,
3263 SILC_STR_DATA(k2, hash_len),
3265 silc_buffer_push(dist, data_len + hash_len);
3266 memset(k3, 0, sizeof(k3));
3267 silc_hash_make(hash, dist->data, silc_buffer_len(dist), k3);
3269 /* Then, save the keys */
3270 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
3272 silc_buffer_clear(buf);
3273 silc_buffer_free(buf);
3277 memcpy(dtmp, k1, hash_len);
3278 memcpy(dtmp + hash_len, k2, hash_len);
3279 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
3281 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
3282 if (!key->send_enc_key) {
3283 silc_buffer_clear(buf);
3284 silc_buffer_free(buf);
3289 memcpy(key->send_enc_key, dtmp, enc_key_len);
3290 key->enc_key_len = req_enc_key_len;
3292 memset(dtmp, 0, (3 * hash_len));
3293 memset(k1, 0, sizeof(k1));
3294 memset(k2, 0, sizeof(k2));
3295 memset(k3, 0, sizeof(k3));
3297 silc_buffer_clear(dist);
3298 silc_buffer_free(dist);
3300 /* Take normal hash as key */
3301 memset(hashd, 0, sizeof(hashd));
3302 silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
3303 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
3304 if (!key->send_enc_key) {
3305 silc_buffer_clear(buf);
3306 silc_buffer_free(buf);
3310 memcpy(key->send_enc_key, hashd, enc_key_len);
3311 key->enc_key_len = req_enc_key_len;
3315 if (enc_key_len > hash_len) {
3317 unsigned char k1[SILC_HASH_MAXLEN], k2[SILC_HASH_MAXLEN],
3318 k3[SILC_HASH_MAXLEN];
3319 unsigned char *dtmp;
3322 if (enc_key_len > (3 * hash_len))
3325 /* Take first round */
3326 memset(k1, 0, sizeof(k1));
3327 silc_hash_make(hash, buf->data, silc_buffer_len(buf), k1);
3329 /* Take second round */
3330 dist = silc_buffer_alloc_size(data_len + hash_len);
3333 silc_buffer_format(dist,
3334 SILC_STR_DATA(data, data_len),
3335 SILC_STR_DATA(k1, hash_len),
3337 memset(k2, 0, sizeof(k2));
3338 silc_hash_make(hash, dist->data, silc_buffer_len(dist), k2);
3340 /* Take third round */
3341 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
3342 silc_buffer_pull_tail(dist, hash_len);
3343 silc_buffer_pull(dist, data_len + hash_len);
3344 silc_buffer_format(dist,
3345 SILC_STR_DATA(k2, hash_len),
3347 silc_buffer_push(dist, data_len + hash_len);
3348 memset(k3, 0, sizeof(k3));
3349 silc_hash_make(hash, dist->data, silc_buffer_len(dist), k3);
3351 /* Then, save the keys */
3352 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
3354 silc_buffer_clear(buf);
3355 silc_buffer_free(buf);
3359 memcpy(dtmp, k1, hash_len);
3360 memcpy(dtmp + hash_len, k2, hash_len);
3361 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
3363 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
3364 if (!key->receive_enc_key) {
3365 silc_buffer_clear(buf);
3366 silc_buffer_free(buf);
3371 memcpy(key->receive_enc_key, dtmp, enc_key_len);
3372 key->enc_key_len = req_enc_key_len;
3374 memset(dtmp, 0, (3 * hash_len));
3375 memset(k1, 0, sizeof(k1));
3376 memset(k2, 0, sizeof(k2));
3377 memset(k3, 0, sizeof(k3));
3379 silc_buffer_clear(dist);
3380 silc_buffer_free(dist);
3382 /* Take normal hash as key */
3383 memset(hashd, 0, sizeof(hashd));
3384 silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
3385 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
3386 if (!key->receive_enc_key) {
3387 silc_buffer_clear(buf);
3388 silc_buffer_free(buf);
3392 memcpy(key->receive_enc_key, hashd, enc_key_len);
3393 key->enc_key_len = req_enc_key_len;
3396 /* Take HMAC keys */
3397 memset(hashd, 0, sizeof(hashd));
3399 silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
3400 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
3401 if (!key->send_hmac_key) {
3402 silc_buffer_clear(buf);
3403 silc_buffer_free(buf);
3407 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
3408 memset(hashd, 0, sizeof(hashd));
3410 silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
3411 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
3412 if (!key->receive_hmac_key) {
3413 silc_buffer_clear(buf);
3414 silc_buffer_free(buf);
3418 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
3419 key->hmac_key_len = req_hmac_key_len;
3420 memset(hashd, 0, sizeof(hashd));
3422 silc_buffer_clear(buf);
3423 silc_buffer_free(buf);
3425 SILC_LOG_HEXDUMP(("enc"), key->send_enc_key, key->enc_key_len / 8);
3430 /* Processes negotiated key material as protocol specifies. This returns
3431 the actual keys to be used in the SILC. */
3434 silc_ske_process_key_material(SilcSKE ske,
3435 SilcUInt32 req_iv_len,
3436 SilcUInt32 req_enc_key_len,
3437 SilcUInt32 req_hmac_key_len,
3438 SilcSKERekeyMaterial *rekey)
3441 unsigned char *tmpbuf;
3443 SilcSKEKeyMaterial key;
3445 /* Encode KEY to binary data */
3446 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
3448 buf = silc_buffer_alloc_size(klen + ske->hash_len);
3451 silc_buffer_format(buf,
3452 SILC_STR_DATA(tmpbuf, klen),
3453 SILC_STR_DATA(ske->hash, ske->hash_len),
3456 /* Process the key material */
3457 key = silc_ske_process_key_material_data(buf->data, silc_buffer_len(buf),
3458 req_iv_len, req_enc_key_len,
3462 memset(tmpbuf, 0, klen);
3464 silc_buffer_clear(buf);
3465 silc_buffer_free(buf);
3468 *rekey = silc_ske_make_rekey_material(ske, key);
3476 /* Free key material structure */
3478 void silc_ske_free_key_material(SilcSKEKeyMaterial key)
3484 silc_free(key->send_iv);
3485 if (key->receive_iv)
3486 silc_free(key->receive_iv);
3487 if (key->send_enc_key) {
3488 memset(key->send_enc_key, 0, key->enc_key_len / 8);
3489 silc_free(key->send_enc_key);
3491 if (key->receive_enc_key) {
3492 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
3493 silc_free(key->receive_enc_key);
3495 if (key->send_hmac_key) {
3496 memset(key->send_hmac_key, 0, key->hmac_key_len);
3497 silc_free(key->send_hmac_key);
3499 if (key->receive_hmac_key) {
3500 memset(key->receive_hmac_key, 0, key->hmac_key_len);
3501 silc_free(key->receive_hmac_key);
3506 /* Free rekey material */
3508 void silc_ske_free_rekey_material(SilcSKERekeyMaterial rekey)
3512 if (rekey->send_enc_key) {
3513 memset(rekey->send_enc_key, 0, rekey->enc_key_len / 8);
3514 silc_free(rekey->send_enc_key);
3516 silc_free(rekey->hash);
3520 /* Set keys into use */
3522 SilcBool silc_ske_set_keys(SilcSKE ske,
3523 SilcSKEKeyMaterial keymat,
3524 SilcSKESecurityProperties prop,
3525 SilcCipher *ret_send_key,
3526 SilcCipher *ret_receive_key,
3527 SilcHmac *ret_hmac_send,
3528 SilcHmac *ret_hmac_receive,
3531 unsigned char iv[SILC_HASH_MAXLEN];
3532 SilcBool iv_included = (prop->flags & SILC_SKE_SP_FLAG_IV_INCLUDED);
3534 /* Allocate ciphers to be used in the communication */
3536 if (!silc_cipher_alloc((char *)silc_cipher_get_name(prop->cipher),
3540 if (ret_receive_key) {
3541 if (!silc_cipher_alloc((char *)silc_cipher_get_name(prop->cipher),
3546 /* Allocate HMACs */
3547 if (ret_hmac_send) {
3548 if (!silc_hmac_alloc((char *)silc_hmac_get_name(prop->hmac), NULL,
3552 if (ret_hmac_receive) {
3553 if (!silc_hmac_alloc((char *)silc_hmac_get_name(prop->hmac), NULL,
3560 if (!silc_hash_alloc(silc_hash_get_name(prop->hash), ret_hash))
3564 /* Set key material */
3565 memset(iv, 0, sizeof(iv));
3566 if (ske->responder) {
3568 silc_cipher_set_key(*ret_send_key, keymat->receive_enc_key,
3569 keymat->enc_key_len, TRUE);
3571 if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) {
3573 if (!ske->rekeying) {
3575 memcpy(iv, ske->hash, 4);
3577 memcpy(iv + 4, keymat->receive_iv, 8);
3579 /* Rekey, recompute the truncated hash value. */
3580 silc_hash_make(prop->hash, keymat->receive_iv, 8, iv);
3582 memcpy(iv + 4, keymat->receive_iv, 8);
3584 memset(iv + 4, 0, 12);
3587 silc_cipher_set_iv(*ret_send_key, iv);
3590 silc_cipher_set_iv(*ret_send_key, keymat->receive_iv);
3593 if (ret_receive_key) {
3594 silc_cipher_set_key(*ret_receive_key, keymat->send_enc_key,
3595 keymat->enc_key_len, FALSE);
3597 if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) {
3599 if (!ske->rekeying) {
3601 memcpy(iv, ske->hash, 4);
3603 memcpy(iv + 4, keymat->send_iv, 8);
3605 /* Rekey, recompute the truncated hash value. */
3606 silc_hash_make(prop->hash, keymat->send_iv, 8, iv);
3608 memcpy(iv + 4, keymat->send_iv, 8);
3610 memset(iv + 4, 0, 12);
3613 silc_cipher_set_iv(*ret_receive_key, iv);
3616 silc_cipher_set_iv(*ret_receive_key, keymat->send_iv);
3620 silc_hmac_set_key(*ret_hmac_send, keymat->receive_hmac_key,
3621 keymat->hmac_key_len);
3622 if (ret_hmac_receive)
3623 silc_hmac_set_key(*ret_hmac_receive, keymat->send_hmac_key,
3624 keymat->hmac_key_len);
3627 silc_cipher_set_key(*ret_send_key, keymat->send_enc_key,
3628 keymat->enc_key_len, TRUE);
3630 if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) {
3632 if (!ske->rekeying) {
3634 memcpy(iv, ske->hash, 4);
3636 memcpy(iv + 4, keymat->send_iv, 8);
3638 /* Rekey, recompute the truncated hash value. */
3639 silc_hash_make(prop->hash, keymat->send_iv, 8, iv);
3641 memcpy(iv + 4, keymat->send_iv, 8);
3643 memset(iv + 4, 0, 12);
3646 silc_cipher_set_iv(*ret_send_key, iv);
3649 silc_cipher_set_iv(*ret_send_key, keymat->send_iv);
3652 if (ret_receive_key) {
3653 silc_cipher_set_key(*ret_receive_key, keymat->receive_enc_key,
3654 keymat->enc_key_len, FALSE);
3656 if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) {
3658 if (!ske->rekeying) {
3659 /* Set IV. If IV Included flag was negotiated we only set the
3660 truncated hash value. */
3661 memcpy(iv, ske->hash, 4);
3663 memcpy(iv + 4, keymat->receive_iv, 8);
3665 /* Rekey, recompute the truncated hash value. */
3666 silc_hash_make(prop->hash, keymat->receive_iv, 8, iv);
3668 memcpy(iv + 4, keymat->receive_iv, 8);
3670 memset(iv + 4, 0, 12);
3673 silc_cipher_set_iv(*ret_receive_key, iv);
3676 silc_cipher_set_iv(*ret_receive_key, keymat->receive_iv);
3680 silc_hmac_set_key(*ret_hmac_send, keymat->send_hmac_key,
3681 keymat->hmac_key_len);
3682 if (ret_hmac_receive)
3683 silc_hmac_set_key(*ret_hmac_receive, keymat->receive_hmac_key,
3684 keymat->hmac_key_len);
3690 const char *silc_ske_status_string[] =
3694 "Unexpected error occurred",
3695 "Bad payload in packet",
3696 "Unsupported group",
3697 "Unsupported cipher",
3699 "Unsupported hash function",
3701 "Public key not accepted",
3702 "Incorrect signature",
3703 "Bad or unsupported version",
3707 "Remote did not provide public key",
3708 "Bad reserved field in packet",
3709 "Bad payload length in packet",
3710 "Error computing signature",
3711 "System out of memory",
3712 "Key exchange timeout",
3713 "Key exchange timeout",
3718 /* Maps status to readable string and returns the string. If string is not
3719 found and empty character string ("") is returned. */
3721 const char *silc_ske_map_status(SilcSKEStatus status)
3725 for (i = 0; silc_ske_status_string[i]; i++)
3727 return silc_ske_status_string[i];
3732 /* Parses remote host's version string. */
3734 SilcBool silc_ske_parse_version(SilcSKE ske,
3735 SilcUInt32 *protocol_version,
3736 char **protocol_version_string,
3737 SilcUInt32 *software_version,
3738 char **software_version_string,
3739 char **vendor_version)
3741 return silc_parse_version_string(ske->remote_version,
3743 protocol_version_string,
3745 software_version_string,
3749 /* Get security properties */
3751 SilcSKESecurityProperties silc_ske_get_security_properties(SilcSKE ske)
3756 /* Get key material */
3758 SilcSKEKeyMaterial silc_ske_get_key_material(SilcSKE ske)