5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2000 - 2006 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);
60 silc_ske_process_key_material(SilcSKE ske,
61 SilcUInt32 req_iv_len,
62 SilcUInt32 req_enc_key_len,
63 SilcUInt32 req_hmac_key_len,
64 SilcSKERekeyMaterial *rekey);
65 static SilcBool silc_ske_packet_send(SilcSKE ske,
67 SilcPacketFlags flags,
68 const unsigned char *data,
73 static SilcBool silc_ske_packet_receive(SilcPacketEngine engine,
74 SilcPacketStream stream,
76 void *callback_context,
79 SilcSKE ske = callback_context;
81 /* Clear retransmission */
82 ske->retry_timer = SILC_SKE_RETRY_MIN;
84 silc_schedule_task_del_by_context(ske->schedule, ske);
86 /* Signal for new packet */
89 /* Check if we were aborted */
91 silc_packet_free(packet);
95 silc_fsm_next(&ske->fsm, silc_ske_st_responder_aborted);
97 silc_fsm_next(&ske->fsm, silc_ske_st_initiator_aborted);
99 silc_fsm_continue_sync(&ske->fsm);
103 /* See if received failure from remote */
104 if (packet->type == SILC_PACKET_FAILURE) {
106 silc_fsm_next(&ske->fsm, silc_ske_st_responder_failure);
108 silc_fsm_next(&ske->fsm, silc_ske_st_initiator_failure);
111 /* Handle rekey synchronously */
113 silc_fsm_continue_sync(&ske->fsm);
115 silc_fsm_continue(&ske->fsm);
120 /* Packet stream callbacks */
121 static SilcPacketCallbacks silc_ske_stream_cbs =
123 silc_ske_packet_receive, NULL, NULL
126 /* Aborts SKE protocol */
128 static void silc_ske_abort(SilcAsyncOperation op, void *context)
130 SilcSKE ske = context;
134 /* Public key verification completion callback */
136 static void silc_ske_pk_verified(SilcSKE ske, SilcSKEStatus status,
137 void *completion_context)
139 ske->status = status;
140 SILC_FSM_CALL_CONTINUE(&ske->fsm);
143 /* SKR find callback */
145 static void silc_ske_skr_callback(SilcSKR repository,
147 SilcSKRStatus status,
148 SilcDList keys, void *context)
150 SilcSKE ske = context;
152 silc_skr_find_free(find);
154 if (status != SILC_SKR_OK) {
155 if (ske->callbacks->verify_key) {
156 /* Verify from application */
157 ske->callbacks->verify_key(ske, ske->prop->public_key,
158 ske->callbacks->context,
159 silc_ske_pk_verified, NULL);
165 silc_dlist_uninit(keys);
168 ske->status = (status == SILC_SKR_OK ? SILC_SKE_STATUS_OK :
169 SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY);
170 SILC_FSM_CALL_CONTINUE(&ske->fsm);
173 /* Checks remote and local versions */
175 static SilcSKEStatus silc_ske_check_version(SilcSKE ske)
177 SilcUInt32 l_protocol_version = 0, r_protocol_version = 0;
178 SilcUInt32 r_software_version = 0;
180 if (!ske->remote_version || !ske->version)
181 return SILC_SKE_STATUS_BAD_VERSION;
183 if (!silc_parse_version_string(ske->remote_version, &r_protocol_version,
184 NULL, &r_software_version, NULL, NULL))
185 return SILC_SKE_STATUS_BAD_VERSION;
187 if (!silc_parse_version_string(ske->version, &l_protocol_version,
188 NULL, NULL, NULL, NULL))
189 return SILC_SKE_STATUS_BAD_VERSION;
191 /* If remote is too new, don't connect */
192 if (l_protocol_version < r_protocol_version)
193 return SILC_SKE_STATUS_BAD_VERSION;
195 /* Backwards compatibility checks */
197 /* Old server versions requires "valid" looking Source ID in the SILC
198 packets during initial key exchange. All version before 1.1.0. */
199 if (r_software_version < 110) {
201 memset(&id, 0, sizeof(id));
203 SILC_LOG_DEBUG(("Remote is old version, add dummy Source ID to packets"));
204 silc_packet_set_ids(ske->stream, SILC_ID_CLIENT, &id, 0, NULL);
207 return SILC_SKE_STATUS_OK;
210 /* Selects the supported security properties from the initiator's Key
211 Exchange Start Payload. A responder function. Saves our reply
212 start payload to ske->start_payload. */
215 silc_ske_select_security_properties(SilcSKE ske,
216 SilcSKEStartPayload remote_payload,
217 SilcSKESecurityProperties *prop)
219 SilcSKEStatus status;
220 SilcSKEStartPayload rp, payload;
224 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
228 /* Check for mandatory fields */
229 if (!rp->ke_grp_len) {
230 SILC_LOG_DEBUG(("KE group not defined in payload"));
231 return SILC_SKE_STATUS_BAD_PAYLOAD;
233 if (!rp->pkcs_alg_len) {
234 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
235 return SILC_SKE_STATUS_BAD_PAYLOAD;
237 if (!rp->enc_alg_len) {
238 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
239 return SILC_SKE_STATUS_BAD_PAYLOAD;
241 if (!rp->hash_alg_len) {
242 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
243 return SILC_SKE_STATUS_BAD_PAYLOAD;
245 if (!rp->hmac_alg_len) {
246 SILC_LOG_DEBUG(("HMAC not defined in payload"));
247 return SILC_SKE_STATUS_BAD_PAYLOAD;
250 /* Allocate security properties */
251 *prop = silc_calloc(1, sizeof(**prop));
253 return SILC_SKE_STATUS_OUT_OF_MEMORY;
255 /* Allocate our reply start payload */
256 payload = silc_calloc(1, sizeof(*payload));
259 return SILC_SKE_STATUS_OUT_OF_MEMORY;
262 /* Check version string */
263 ske->remote_version = silc_memdup(rp->version, rp->version_len);
264 status = silc_ske_check_version(ske);
265 if (status != SILC_SKE_STATUS_OK) {
266 ske->status = status;
270 /* Flags are returned unchanged. */
271 (*prop)->flags = payload->flags = rp->flags;
273 /* Take cookie, we must return it to sender unmodified. */
274 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
275 if (!payload->cookie) {
276 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
279 payload->cookie_len = SILC_SKE_COOKIE_LEN;
280 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
282 /* In case IV included flag and session port is set the first 16-bits of
283 cookie will include our session port. */
284 if (rp->flags & SILC_SKE_SP_FLAG_IV_INCLUDED && ske->session_port) {
285 /* Take remote port */
286 SILC_GET16_MSB((*prop)->remote_port, payload->cookie);
289 SILC_PUT16_MSB(ske->session_port, payload->cookie);
292 /* Put our version to our reply */
293 payload->version = strdup(ske->version);
294 if (!payload->version) {
295 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
298 payload->version_len = strlen(ske->version);
300 /* Get supported Key Exchange groups */
301 cp = rp->ke_grp_list;
302 if (cp && strchr(cp, ',')) {
306 len = strcspn(cp, ",");
307 item = silc_calloc(len + 1, sizeof(char));
309 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
312 memcpy(item, cp, len);
314 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
316 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
317 SILC_LOG_DEBUG(("Found KE group `%s'", item));
319 payload->ke_grp_len = len;
320 payload->ke_grp_list = item;
334 if (!payload->ke_grp_len && !payload->ke_grp_list) {
335 SILC_LOG_DEBUG(("Could not find supported KE group"));
337 return SILC_SKE_STATUS_UNKNOWN_GROUP;
340 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
341 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
343 payload->ke_grp_len = rp->ke_grp_len;
344 payload->ke_grp_list = strdup(rp->ke_grp_list);
347 /* Save group to security properties */
348 status = silc_ske_group_get_by_name(payload->ke_grp_list, &(*prop)->group);
349 if (status != SILC_SKE_STATUS_OK) {
351 return SILC_SKE_STATUS_UNKNOWN_GROUP;
354 /* Get supported PKCS algorithms */
355 cp = rp->pkcs_alg_list;
356 if (cp && strchr(cp, ',')) {
360 len = strcspn(cp, ",");
361 item = silc_calloc(len + 1, sizeof(char));
363 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
366 memcpy(item, cp, len);
368 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
370 if (silc_pkcs_find_algorithm(item, NULL)) {
371 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
373 payload->pkcs_alg_len = len;
374 payload->pkcs_alg_list = item;
388 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
389 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
390 silc_free(payload->ke_grp_list);
392 return SILC_SKE_STATUS_UNKNOWN_PKCS;
395 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
396 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
398 payload->pkcs_alg_len = rp->pkcs_alg_len;
399 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
402 /* Get supported encryption algorithms */
403 cp = rp->enc_alg_list;
404 if (cp && strchr(cp, ',')) {
408 len = strcspn(cp, ",");
409 item = silc_calloc(len + 1, sizeof(char));
411 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
414 memcpy(item, cp, len);
416 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
418 if (silc_cipher_is_supported(item) == TRUE) {
419 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
421 payload->enc_alg_len = len;
422 payload->enc_alg_list = item;
436 if (!payload->enc_alg_len && !payload->enc_alg_list) {
437 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
438 silc_free(payload->ke_grp_list);
439 silc_free(payload->pkcs_alg_list);
441 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
444 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
447 payload->enc_alg_len = rp->enc_alg_len;
448 payload->enc_alg_list = strdup(rp->enc_alg_list);
451 /* Save selected cipher to security properties */
452 if (silc_cipher_alloc(payload->enc_alg_list, &(*prop)->cipher) == FALSE) {
453 silc_free(payload->ke_grp_list);
454 silc_free(payload->pkcs_alg_list);
456 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
459 /* Get supported hash algorithms */
460 cp = rp->hash_alg_list;
461 if (cp && strchr(cp, ',')) {
465 len = strcspn(cp, ",");
466 item = silc_calloc(len + 1, sizeof(char));
468 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
471 memcpy(item, cp, len);
473 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
475 if (silc_hash_is_supported(item) == TRUE) {
476 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
478 payload->hash_alg_len = len;
479 payload->hash_alg_list = item;
493 if (!payload->hash_alg_len && !payload->hash_alg_list) {
494 SILC_LOG_DEBUG(("Could not find supported hash alg"));
495 silc_free(payload->ke_grp_list);
496 silc_free(payload->pkcs_alg_list);
497 silc_free(payload->enc_alg_list);
499 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
502 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
505 payload->hash_alg_len = rp->hash_alg_len;
506 payload->hash_alg_list = strdup(rp->hash_alg_list);
509 /* Save selected hash algorithm to security properties */
510 if (silc_hash_alloc(payload->hash_alg_list, &(*prop)->hash) == FALSE) {
511 silc_free(payload->ke_grp_list);
512 silc_free(payload->pkcs_alg_list);
513 silc_free(payload->enc_alg_list);
515 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
518 /* Get supported HMACs */
519 cp = rp->hmac_alg_list;
520 if (cp && strchr(cp, ',')) {
524 len = strcspn(cp, ",");
525 item = silc_calloc(len + 1, sizeof(char));
527 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
530 memcpy(item, cp, len);
532 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
534 if (silc_hmac_is_supported(item) == TRUE) {
535 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
537 payload->hmac_alg_len = len;
538 payload->hmac_alg_list = item;
552 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
553 SILC_LOG_DEBUG(("Could not find supported HMAC"));
554 silc_free(payload->ke_grp_list);
555 silc_free(payload->pkcs_alg_list);
556 silc_free(payload->enc_alg_list);
557 silc_free(payload->hash_alg_list);
559 return SILC_SKE_STATUS_UNKNOWN_HMAC;
562 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
565 payload->hmac_alg_len = rp->hmac_alg_len;
566 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
569 /* Save selected HMACc to security properties */
570 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &(*prop)->hmac) == FALSE) {
571 silc_free(payload->ke_grp_list);
572 silc_free(payload->pkcs_alg_list);
573 silc_free(payload->enc_alg_list);
574 silc_free(payload->hash_alg_list);
576 return SILC_SKE_STATUS_UNKNOWN_HMAC;
579 /* Get supported compression algorithms */
580 cp = rp->comp_alg_list;
581 if (cp && strchr(cp, ',')) {
585 len = strcspn(cp, ",");
586 item = silc_calloc(len + 1, sizeof(char));
588 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
591 memcpy(item, cp, len);
593 SILC_LOG_DEBUG(("Proposed Compression `%s'", item));
596 if (!strcmp(item, "none")) {
597 SILC_LOG_DEBUG(("Found Compression `%s'", item));
598 payload->comp_alg_len = len;
599 payload->comp_alg_list = item;
603 if (silc_hmac_is_supported(item) == TRUE) {
604 SILC_LOG_DEBUG(("Found Compression `%s'", item));
605 payload->comp_alg_len = len;
606 payload->comp_alg_list = item;
622 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
623 2 + payload->version_len +
624 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
625 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
626 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
628 /* Save our reply payload */
629 ske->start_payload = payload;
631 return SILC_SKE_STATUS_OK;
634 /* Creates random number such that 1 < rnd < n and at most length
635 of len bits. The rnd sent as argument must be initialized. */
637 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
641 SilcSKEStatus status = SILC_SKE_STATUS_OK;
642 unsigned char *string;
646 return SILC_SKE_STATUS_ERROR;
648 SILC_LOG_DEBUG(("Creating random number"));
652 /* Get the random number as string */
653 string = silc_rng_get_rn_data(ske->rng, l);
655 return SILC_SKE_STATUS_OUT_OF_MEMORY;
657 /* Decode the string into a MP integer */
658 silc_mp_bin2mp(string, l, rnd);
659 silc_mp_mod_2exp(rnd, rnd, len);
662 if (silc_mp_cmp_ui(rnd, 1) < 0)
663 status = SILC_SKE_STATUS_ERROR;
664 if (silc_mp_cmp(rnd, n) >= 0)
665 status = SILC_SKE_STATUS_ERROR;
667 memset(string, 'F', l);
673 /* Creates a hash value HASH as defined in the SKE protocol. If the
674 `initiator' is TRUE then this function is used to create the HASH_i
675 hash value defined in the protocol. If it is FALSE then this is used
676 to create the HASH value defined by the protocol. */
678 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
679 unsigned char *return_hash,
680 SilcUInt32 *return_hash_len,
683 SilcSKEStatus status = SILC_SKE_STATUS_OK;
685 unsigned char *e, *f, *KEY;
686 SilcUInt32 e_len, f_len, KEY_len;
689 SILC_LOG_DEBUG(("Start"));
691 if (initiator == FALSE) {
692 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
693 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
694 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
696 /* Format the buffer used to compute the hash value */
697 buf = silc_buffer_alloc_size(silc_buffer_len(ske->start_payload_copy) +
698 ske->ke2_payload->pk_len +
699 ske->ke1_payload->pk_len +
700 e_len + f_len + KEY_len);
702 return SILC_SKE_STATUS_OUT_OF_MEMORY;
704 /* Initiator is not required to send its public key */
705 if (!ske->ke1_payload->pk_data) {
707 silc_buffer_format(buf,
708 SILC_STR_UI_XNSTRING(
709 ske->start_payload_copy->data,
710 silc_buffer_len(ske->start_payload_copy)),
711 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
712 ske->ke2_payload->pk_len),
713 SILC_STR_UI_XNSTRING(e, e_len),
714 SILC_STR_UI_XNSTRING(f, f_len),
715 SILC_STR_UI_XNSTRING(KEY, KEY_len),
719 silc_buffer_format(buf,
720 SILC_STR_UI_XNSTRING(
721 ske->start_payload_copy->data,
722 silc_buffer_len(ske->start_payload_copy)),
723 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
724 ske->ke2_payload->pk_len),
725 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
726 ske->ke1_payload->pk_len),
727 SILC_STR_UI_XNSTRING(e, e_len),
728 SILC_STR_UI_XNSTRING(f, f_len),
729 SILC_STR_UI_XNSTRING(KEY, KEY_len),
733 silc_buffer_free(buf);
736 memset(KEY, 0, KEY_len);
740 return SILC_SKE_STATUS_ERROR;
745 memset(KEY, 0, KEY_len);
750 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
752 buf = silc_buffer_alloc_size(silc_buffer_len(ske->start_payload_copy) +
753 ske->ke1_payload->pk_len + e_len);
755 return SILC_SKE_STATUS_OUT_OF_MEMORY;
757 /* Format the buffer used to compute the hash value */
759 silc_buffer_format(buf,
760 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
761 silc_buffer_len(ske->start_payload_copy)),
762 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
763 ske->ke1_payload->pk_len),
764 SILC_STR_UI_XNSTRING(e, e_len),
767 silc_buffer_free(buf);
770 return SILC_SKE_STATUS_ERROR;
773 SILC_LOG_HEXDUMP(("hash buf"), buf->data, silc_buffer_len(buf));
780 silc_hash_make(ske->prop->hash, buf->data, silc_buffer_len(buf),
782 *return_hash_len = silc_hash_len(ske->prop->hash);
784 if (initiator == FALSE) {
785 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
787 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
790 silc_buffer_free(buf);
795 /* Generate rekey material */
797 static SilcSKERekeyMaterial
798 silc_ske_make_rekey_material(SilcSKE ske, SilcSKEKeyMaterial keymat)
800 SilcSKERekeyMaterial rekey;
803 /* Create rekey material */
804 rekey = silc_calloc(1, sizeof(*rekey));
809 if (ske->prop->group)
810 rekey->ske_group = silc_ske_group_get_number(ske->prop->group);
811 rekey->pfs = (ske->prop->flags & SILC_SKE_SP_FLAG_PFS ? TRUE : FALSE);
812 hash = silc_hash_get_name(ske->prop->hash);
813 rekey->hash = silc_memdup(hash, strlen(hash));
818 if (rekey->pfs == FALSE) {
819 rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
820 keymat->enc_key_len / 8);
821 if (!rekey->send_enc_key) {
825 rekey->enc_key_len = keymat->enc_key_len;
831 /* Assembles security properties */
833 static SilcSKEStartPayload
834 silc_ske_assemble_security_properties(SilcSKE ske,
835 SilcSKESecurityPropertyFlag flags,
838 SilcSKEStartPayload rp;
841 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
843 rp = silc_calloc(1, sizeof(*rp));
846 rp->flags = (unsigned char)flags;
848 /* Set random cookie */
849 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
850 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
851 rp->cookie[i] = silc_rng_get_byte_fast(ske->rng);
852 rp->cookie_len = SILC_SKE_COOKIE_LEN;
854 /* In case IV included flag and session port is set the first 16-bits of
855 cookie will include our session port. */
856 if (flags & SILC_SKE_SP_FLAG_IV_INCLUDED && ske->session_port)
857 SILC_PUT16_MSB(ske->session_port, rp->cookie);
860 rp->version = strdup(version);
861 rp->version_len = strlen(version);
863 /* Get supported Key Exhange groups */
864 rp->ke_grp_list = silc_ske_get_supported_groups();
865 rp->ke_grp_len = strlen(rp->ke_grp_list);
867 /* Get supported PKCS algorithms */
868 rp->pkcs_alg_list = silc_pkcs_get_supported();
869 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
871 /* Get supported encryption algorithms */
872 rp->enc_alg_list = silc_cipher_get_supported();
873 rp->enc_alg_len = strlen(rp->enc_alg_list);
875 /* Get supported hash algorithms */
876 rp->hash_alg_list = silc_hash_get_supported();
877 rp->hash_alg_len = strlen(rp->hash_alg_list);
879 /* Get supported HMACs */
880 rp->hmac_alg_list = silc_hmac_get_supported();
881 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
884 /* Get supported compression algorithms */
885 rp->comp_alg_list = strdup("none");
886 rp->comp_alg_len = strlen("none");
888 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
889 2 + rp->version_len +
890 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
891 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
892 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
897 /* Packet retransmission callback. */
899 SILC_TASK_CALLBACK(silc_ske_packet_send_retry)
901 SilcSKE ske = context;
903 if (ske->retry_count++ >= SILC_SKE_RETRY_COUNT ||
905 SILC_LOG_DEBUG(("Retransmission limit reached, packet was lost"));
906 ske->retry_count = 0;
907 ske->retry_timer = SILC_SKE_RETRY_MIN;
908 silc_free(ske->retrans.data);
909 ske->retrans.data = NULL;
910 ske->status = SILC_SKE_STATUS_TIMEOUT;
912 silc_fsm_next(&ske->fsm, silc_ske_st_responder_failure);
914 silc_fsm_next(&ske->fsm, silc_ske_st_initiator_failure);
915 silc_fsm_continue_sync(&ske->fsm);
919 SILC_LOG_DEBUG(("Retransmitting packet"));
920 silc_ske_packet_send(ske, ske->retrans.type, ske->retrans.flags,
921 ske->retrans.data, ske->retrans.data_len);
924 /* Install retransmission timer */
926 static void silc_ske_install_retransmission(SilcSKE ske)
928 if (!silc_packet_stream_is_udp(ske->stream))
931 if (ske->retrans.data) {
932 SILC_LOG_DEBUG(("Installing retransmission timer %d secs",
934 silc_schedule_task_add_timeout(ske->schedule, silc_ske_packet_send_retry,
935 ske, ske->retry_timer, 0);
937 ske->retry_timer = ((ske->retry_timer * SILC_SKE_RETRY_MUL) +
938 (silc_rng_get_rn16(ske->rng) % SILC_SKE_RETRY_RAND));
941 /* Sends SILC packet. Handles retransmissions with UDP streams. */
943 static SilcBool silc_ske_packet_send(SilcSKE ske,
945 SilcPacketFlags flags,
946 const unsigned char *data,
951 /* Send the packet */
952 ret = silc_packet_send(ske->stream, type, flags, data, data_len);
954 if (silc_packet_stream_is_udp(ske->stream) &&
955 type != SILC_PACKET_FAILURE && type != SILC_PACKET_REKEY) {
956 silc_free(ske->retrans.data);
957 ske->retrans.type = type;
958 ske->retrans.flags = flags;
959 ske->retrans.data = silc_memdup(data, data_len);
960 ske->retrans.data_len = data_len;
961 silc_ske_install_retransmission(ske);
967 /* SKE FSM destructor. We call completion callback here. All SKE
968 machines go here and call the completion. Completion must not be called
969 from any other place. */
971 static void silc_ske_finished(SilcFSM fsm, void *fsm_context,
972 void *destructor_context)
974 SilcSKE ske = fsm_context;
976 /* Call the completion callback */
977 if (!ske->freed && !ske->aborted && ske->callbacks->completed) {
978 if (ske->status != SILC_SKE_STATUS_OK)
979 ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL,
980 ske->callbacks->context);
982 ske->callbacks->completed(ske, ske->status, ske->prop, ske->keymat,
983 ske->rekey, ske->callbacks->context);
986 ske->running = FALSE;
991 /******************************* Protocol API *******************************/
993 /* Allocates new SKE object. */
995 SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule,
996 SilcSKR repository, SilcPublicKey public_key,
997 SilcPrivateKey private_key, void *context)
1001 SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
1003 if (!rng || !schedule)
1007 SILC_LOG_ERROR(("Public key must be given to silc_ske_alloc"));
1011 ske = silc_calloc(1, sizeof(*ske));
1014 ske->status = SILC_SKE_STATUS_OK;
1016 ske->repository = repository;
1017 ske->user_data = context;
1018 ske->schedule = schedule;
1019 ske->public_key = public_key;
1020 ske->private_key = private_key;
1021 ske->retry_timer = SILC_SKE_RETRY_MIN;
1026 /* Free's SKE object. */
1028 void silc_ske_free(SilcSKE ske)
1030 SILC_LOG_DEBUG(("Freeing Key Exchange object"));
1040 /* Free start payload */
1041 if (ske->start_payload)
1042 silc_ske_payload_start_free(ske->start_payload);
1044 /* Free KE payload */
1045 if (ske->ke1_payload)
1046 silc_ske_payload_ke_free(ske->ke1_payload);
1047 if (ske->ke2_payload)
1048 silc_ske_payload_ke_free(ske->ke2_payload);
1049 silc_free(ske->remote_version);
1053 if (ske->prop->group)
1054 silc_ske_group_free(ske->prop->group);
1055 if (ske->prop->cipher)
1056 silc_cipher_free(ske->prop->cipher);
1057 if (ske->prop->hash)
1058 silc_hash_free(ske->prop->hash);
1059 if (ske->prop->hmac)
1060 silc_hmac_free(ske->prop->hmac);
1061 silc_free(ske->prop);
1064 silc_ske_free_key_material(ske->keymat);
1065 if (ske->start_payload_copy)
1066 silc_buffer_free(ske->start_payload_copy);
1068 silc_mp_uninit(ske->x);
1072 silc_mp_uninit(ske->KEY);
1073 silc_free(ske->KEY);
1075 silc_free(ske->retrans.data);
1076 silc_free(ske->hash);
1077 silc_free(ske->callbacks);
1079 memset(ske, 'F', sizeof(*ske));
1083 /* Return user context */
1085 void *silc_ske_get_context(SilcSKE ske)
1087 return ske->user_data;
1090 /* Sets protocol callbacks */
1092 void silc_ske_set_callbacks(SilcSKE ske,
1093 SilcSKEVerifyCb verify_key,
1094 SilcSKECompletionCb completed,
1098 silc_free(ske->callbacks);
1099 ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
1100 if (!ske->callbacks)
1102 ske->callbacks->verify_key = verify_key;
1103 ske->callbacks->completed = completed;
1104 ske->callbacks->context = context;
1108 /******************************** Initiator *********************************/
1110 /* Start protocol. Send our proposal */
1112 SILC_FSM_STATE(silc_ske_st_initiator_start)
1114 SilcSKE ske = fsm_context;
1115 SilcBuffer payload_buf;
1118 SILC_LOG_DEBUG(("Start"));
1122 silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
1126 /* Encode the payload */
1127 status = silc_ske_payload_start_encode(ske, ske->start_payload,
1129 if (status != SILC_SKE_STATUS_OK) {
1130 /** Error encoding Start Payload */
1131 ske->status = status;
1132 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1136 /* Save the the payload buffer for future use. It is later used to
1137 compute the HASH value. */
1138 ske->start_payload_copy = payload_buf;
1140 /* Send the packet. */
1141 if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE, 0,
1142 silc_buffer_data(payload_buf),
1143 silc_buffer_len(payload_buf))) {
1144 /** Error sending packet */
1145 SILC_LOG_DEBUG(("Error sending packet"));
1146 ske->status = SILC_SKE_STATUS_ERROR;
1147 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1153 /** Wait for responder proposal */
1154 SILC_LOG_DEBUG(("Waiting for reponder proposal"));
1155 silc_fsm_next(fsm, silc_ske_st_initiator_phase1);
1159 /* Phase-1. Receives responder's proposal */
1161 SILC_FSM_STATE(silc_ske_st_initiator_phase1)
1163 SilcSKE ske = fsm_context;
1164 SilcSKEStatus status;
1165 SilcSKEStartPayload payload;
1166 SilcSKESecurityProperties prop;
1167 SilcSKEDiffieHellmanGroup group = NULL;
1168 SilcBuffer packet_buf = &ske->packet->buffer;
1169 SilcUInt16 remote_port = 0;
1173 SILC_LOG_DEBUG(("Start"));
1175 if (ske->packet->type != SILC_PACKET_KEY_EXCHANGE) {
1176 SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
1177 silc_ske_install_retransmission(ske);
1178 silc_packet_free(ske->packet);
1183 /* Decode the payload */
1184 status = silc_ske_payload_start_decode(ske, packet_buf, &payload);
1185 if (status != SILC_SKE_STATUS_OK) {
1186 /** Error decoding Start Payload */
1187 silc_packet_free(ske->packet);
1189 ske->status = status;
1190 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1194 /* Get remote ID and set it to stream */
1195 if (ske->packet->src_id_len) {
1196 silc_id_str2id(ske->packet->src_id, ske->packet->src_id_len,
1197 ske->packet->src_id_type,
1198 (ske->packet->src_id_type == SILC_ID_SERVER ?
1199 (void *)&id.u.server_id : (void *)&id.u.client_id),
1200 (ske->packet->src_id_type == SILC_ID_SERVER ?
1201 sizeof(id.u.server_id) : sizeof(id.u.client_id)));
1202 silc_packet_set_ids(ske->stream, 0, NULL, ske->packet->src_id_type,
1203 (ske->packet->src_id_type == SILC_ID_SERVER ?
1204 (void *)&id.u.server_id : (void *)&id.u.client_id));
1207 silc_packet_free(ske->packet);
1210 /* Check that the cookie is returned unmodified. In case IV included
1211 flag and session port has been set, the first two bytes of cookie
1212 are the session port and we ignore them in this check. */
1213 if (payload->flags & SILC_SKE_SP_FLAG_IV_INCLUDED && ske->session_port) {
1214 /* Take remote port */
1215 SILC_GET16_MSB(remote_port, ske->start_payload->cookie);
1218 if (memcmp(ske->start_payload->cookie + coff, payload->cookie + coff,
1219 SILC_SKE_COOKIE_LEN - coff)) {
1220 /** Invalid cookie */
1221 SILC_LOG_ERROR(("Invalid cookie, modified or unsupported feature"));
1222 ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
1223 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1227 /* Check version string */
1228 ske->remote_version = silc_memdup(payload->version, payload->version_len);
1229 status = silc_ske_check_version(ske);
1230 if (status != SILC_SKE_STATUS_OK) {
1231 /** Version mismatch */
1232 ske->status = status;
1233 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1237 /* Free our KE Start Payload context, we don't need it anymore. */
1238 silc_ske_payload_start_free(ske->start_payload);
1239 ske->start_payload = NULL;
1241 /* Take the selected security properties into use while doing
1242 the key exchange. This is used only while doing the key
1244 ske->prop = prop = silc_calloc(1, sizeof(*prop));
1247 prop->flags = payload->flags;
1248 status = silc_ske_group_get_by_name(payload->ke_grp_list, &group);
1249 if (status != SILC_SKE_STATUS_OK)
1252 prop->group = group;
1253 prop->remote_port = remote_port;
1255 if (silc_pkcs_find_algorithm(payload->pkcs_alg_list, NULL) == NULL) {
1256 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
1259 if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
1260 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
1263 if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
1264 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1267 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
1268 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
1272 /* Save remote's KE Start Payload */
1273 ske->start_payload = payload;
1275 /** Send KE Payload */
1276 silc_fsm_next(fsm, silc_ske_st_initiator_phase2);
1281 silc_ske_payload_start_free(payload);
1283 silc_ske_group_free(group);
1285 silc_cipher_free(prop->cipher);
1287 silc_hash_free(prop->hash);
1289 silc_hmac_free(prop->hmac);
1293 if (status == SILC_SKE_STATUS_OK)
1294 status = SILC_SKE_STATUS_ERROR;
1297 ske->status = status;
1298 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1302 /* Phase-2. Send KE payload */
1304 SILC_FSM_STATE(silc_ske_st_initiator_phase2)
1306 SilcSKE ske = fsm_context;
1307 SilcSKEStatus status;
1308 SilcBuffer payload_buf;
1310 SilcSKEKEPayload payload;
1313 SILC_LOG_DEBUG(("Start"));
1315 /* Create the random number x, 1 < x < q. */
1316 x = silc_calloc(1, sizeof(*x));
1318 /** Out of memory */
1319 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1320 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1325 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
1326 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
1328 if (status != SILC_SKE_STATUS_OK) {
1329 /** Error generating random number */
1332 ske->status = status;
1333 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1337 /* Encode the result to Key Exchange Payload. */
1339 payload = silc_calloc(1, sizeof(*payload));
1341 /** Out of memory */
1344 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1345 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1348 ske->ke1_payload = payload;
1350 SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
1352 /* Do the Diffie Hellman computation, e = g ^ x mod p */
1353 silc_mp_init(&payload->x);
1354 silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
1355 &ske->prop->group->group);
1357 /* Get public key */
1358 payload->pk_data = silc_pkcs_public_key_encode(ske->public_key, &pk_len);
1359 if (!payload->pk_data) {
1360 /** Error encoding public key */
1363 silc_mp_uninit(&payload->x);
1365 ske->ke1_payload = NULL;
1366 ske->status = SILC_SKE_STATUS_ERROR;
1367 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1370 payload->pk_len = pk_len;
1371 payload->pk_type = silc_pkcs_get_type(ske->public_key);
1373 /* Compute signature data if we are doing mutual authentication */
1374 if (ske->private_key && ske->prop->flags & SILC_SKE_SP_FLAG_MUTUAL) {
1375 unsigned char hash[SILC_HASH_MAXLEN], sign[2048 + 1];
1376 SilcUInt32 hash_len, sign_len;
1378 SILC_LOG_DEBUG(("We are doing mutual authentication"));
1379 SILC_LOG_DEBUG(("Computing HASH_i value"));
1381 /* Compute the hash value */
1382 memset(hash, 0, sizeof(hash));
1383 silc_ske_make_hash(ske, hash, &hash_len, TRUE);
1385 SILC_LOG_DEBUG(("Signing HASH_i value"));
1387 /* Sign the hash value */
1388 if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
1389 sizeof(sign) - 1, &sign_len, NULL)) {
1390 /** Error computing signature */
1393 silc_mp_uninit(&payload->x);
1394 silc_free(payload->pk_data);
1396 ske->ke1_payload = NULL;
1397 ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
1398 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1401 payload->sign_data = silc_memdup(sign, sign_len);
1402 if (payload->sign_data)
1403 payload->sign_len = sign_len;
1404 memset(sign, 0, sizeof(sign));
1407 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
1408 if (status != SILC_SKE_STATUS_OK) {
1409 /** Error encoding KE payload */
1412 silc_mp_uninit(&payload->x);
1413 silc_free(payload->pk_data);
1414 silc_free(payload->sign_data);
1416 ske->ke1_payload = NULL;
1417 ske->status = status;
1418 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1424 /* Check for backwards compatibility */
1426 /* Send the packet. */
1427 if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE_1, 0,
1428 silc_buffer_data(payload_buf),
1429 silc_buffer_len(payload_buf))) {
1430 /** Error sending packet */
1431 SILC_LOG_DEBUG(("Error sending packet"));
1432 ske->status = SILC_SKE_STATUS_ERROR;
1433 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1437 silc_buffer_free(payload_buf);
1439 /** Waiting responder's KE payload */
1440 silc_fsm_next(fsm, silc_ske_st_initiator_phase3);
1444 /* Phase-3. Process responder's KE payload */
1446 SILC_FSM_STATE(silc_ske_st_initiator_phase3)
1448 SilcSKE ske = fsm_context;
1449 SilcSKEStatus status;
1450 SilcSKEKEPayload payload;
1452 SilcBuffer packet_buf = &ske->packet->buffer;
1454 SILC_LOG_DEBUG(("Start"));
1456 if (ske->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
1457 SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
1458 silc_ske_install_retransmission(ske);
1459 silc_packet_free(ske->packet);
1464 /* Decode the payload */
1465 status = silc_ske_payload_ke_decode(ske, packet_buf, &payload);
1466 if (status != SILC_SKE_STATUS_OK) {
1467 /** Error decoding KE payload */
1468 silc_packet_free(ske->packet);
1470 ske->status = status;
1471 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1474 silc_packet_free(ske->packet);
1476 ske->ke2_payload = payload;
1478 if (!payload->pk_data && (ske->callbacks->verify_key || ske->repository)) {
1479 SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
1480 "even though we require it"));
1481 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
1485 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
1487 /* Compute the shared secret key */
1488 KEY = silc_calloc(1, sizeof(*KEY));
1490 silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
1493 /* Decode the remote's public key */
1494 if (payload->pk_data &&
1495 !silc_pkcs_public_key_alloc(payload->pk_type,
1496 payload->pk_data, payload->pk_len,
1497 &ske->prop->public_key)) {
1498 SILC_LOG_ERROR(("Unsupported/malformed public key received"));
1499 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
1503 if (ske->prop->public_key && (ske->callbacks->verify_key ||
1505 SILC_LOG_DEBUG(("Verifying public key"));
1507 /** Waiting public key verification */
1508 silc_fsm_next(fsm, silc_ske_st_initiator_phase4);
1510 /* If repository is provided, verify the key from there. */
1511 if (ske->repository) {
1514 find = silc_skr_find_alloc();
1516 status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1519 silc_skr_find_set_pkcs_type(find,
1520 silc_pkcs_get_type(ske->prop->public_key));
1521 silc_skr_find_set_public_key(find, ske->prop->public_key);
1522 silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT);
1524 /* Find key from repository */
1525 SILC_FSM_CALL(silc_skr_find(ske->repository, find,
1526 silc_ske_skr_callback, ske));
1528 /* Verify from application */
1529 SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key,
1530 ske->callbacks->context,
1531 silc_ske_pk_verified, NULL));
1536 /** Process key material */
1537 silc_fsm_next(fsm, silc_ske_st_initiator_phase4);
1541 silc_ske_payload_ke_free(payload);
1542 ske->ke2_payload = NULL;
1544 silc_mp_uninit(ske->KEY);
1545 silc_free(ske->KEY);
1548 if (status == SILC_SKE_STATUS_OK)
1549 return SILC_SKE_STATUS_ERROR;
1552 ske->status = status;
1553 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1557 /* Process key material */
1559 SILC_FSM_STATE(silc_ske_st_initiator_phase4)
1561 SilcSKE ske = fsm_context;
1562 SilcSKEStatus status;
1563 SilcSKEKEPayload payload;
1564 unsigned char hash[SILC_HASH_MAXLEN];
1565 SilcUInt32 hash_len;
1566 int key_len, block_len;
1570 silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
1574 /* Check result of public key verification */
1575 if (ske->status != SILC_SKE_STATUS_OK) {
1576 /** Public key not verified */
1577 SILC_LOG_DEBUG(("Public key verification failed"));
1578 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1582 payload = ske->ke2_payload;
1584 if (ske->prop->public_key) {
1585 SILC_LOG_DEBUG(("Public key is authentic"));
1587 /* Compute the hash value */
1588 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1589 if (status != SILC_SKE_STATUS_OK)
1592 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
1594 /* Verify signature */
1595 if (!silc_pkcs_verify(ske->prop->public_key, payload->sign_data,
1596 payload->sign_len, hash, hash_len, NULL)) {
1597 SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
1598 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
1602 SILC_LOG_DEBUG(("Signature is Ok"));
1604 ske->hash = silc_memdup(hash, hash_len);
1605 ske->hash_len = hash_len;
1606 memset(hash, 'F', hash_len);
1609 ske->status = SILC_SKE_STATUS_OK;
1611 /* In case we are doing rekey move to finish it. */
1614 silc_fsm_next(fsm, silc_ske_st_rekey_initiator_done);
1618 /* Process key material */
1619 key_len = silc_cipher_get_key_len(ske->prop->cipher);
1620 block_len = silc_cipher_get_block_len(ske->prop->cipher);
1621 hash_len = silc_hash_len(ske->prop->hash);
1622 ske->keymat = silc_ske_process_key_material(ske, block_len,
1626 SILC_LOG_ERROR(("Error processing key material"));
1627 status = SILC_SKE_STATUS_ERROR;
1631 /* Send SUCCESS packet */
1632 SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, hash);
1633 if (!silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, hash, 4)) {
1634 /** Error sending packet */
1635 SILC_LOG_DEBUG(("Error sending packet"));
1636 ske->status = SILC_SKE_STATUS_ERROR;
1637 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1641 /** Waiting completion */
1642 silc_fsm_next(fsm, silc_ske_st_initiator_end);
1646 memset(hash, 'F', sizeof(hash));
1647 silc_ske_payload_ke_free(payload);
1648 ske->ke2_payload = NULL;
1650 silc_mp_uninit(ske->KEY);
1651 silc_free(ske->KEY);
1655 memset(ske->hash, 'F', hash_len);
1656 silc_free(ske->hash);
1660 if (status == SILC_SKE_STATUS_OK)
1661 status = SILC_SKE_STATUS_ERROR;
1664 ske->status = status;
1665 silc_fsm_next(fsm, silc_ske_st_initiator_error);
1669 /* Protocol completed */
1671 SILC_FSM_STATE(silc_ske_st_initiator_end)
1673 SilcSKE ske = fsm_context;
1675 SILC_LOG_DEBUG(("Start"));
1677 if (ske->packet->type != SILC_PACKET_SUCCESS) {
1678 SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
1679 silc_ske_install_retransmission(ske);
1680 silc_packet_free(ske->packet);
1685 SILC_LOG_DEBUG(("Key exchange completed successfully"));
1687 silc_packet_free(ske->packet);
1689 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1690 silc_schedule_task_del_by_context(ske->schedule, ske);
1695 /* Aborted by application */
1697 SILC_FSM_STATE(silc_ske_st_initiator_aborted)
1699 SilcSKE ske = fsm_context;
1700 unsigned char data[4];
1702 SILC_LOG_DEBUG(("Aborted by caller"));
1704 /* Send FAILURE packet */
1705 SILC_PUT32_MSB(SILC_SKE_STATUS_ERROR, data);
1706 silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, data, 4);
1708 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1709 silc_schedule_task_del_by_context(ske->schedule, ske);
1714 /* Error occurred. Send error to remote host */
1716 SILC_FSM_STATE(silc_ske_st_initiator_error)
1718 SilcSKE ske = fsm_context;
1719 SilcSKEStatus status;
1720 unsigned char data[4];
1722 SILC_LOG_DEBUG(("Error %s (%d) occurred during key exchange",
1723 silc_ske_map_status(ske->status), ske->status));
1725 status = ske->status;
1726 if (status > SILC_SKE_STATUS_INVALID_COOKIE)
1727 status = SILC_SKE_STATUS_ERROR;
1729 /* Send FAILURE packet */
1730 SILC_PUT32_MSB((SilcUInt32)status, data);
1731 silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, data, 4);
1733 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1734 silc_schedule_task_del_by_context(ske->schedule, ske);
1739 /* Failure received from remote */
1741 SILC_FSM_STATE(silc_ske_st_initiator_failure)
1743 SilcSKE ske = fsm_context;
1744 SilcUInt32 error = SILC_SKE_STATUS_ERROR;
1746 SILC_LOG_DEBUG(("Error %s (%d) received during key exchange",
1747 silc_ske_map_status(ske->status), ske->status));
1749 if (ske->packet && silc_buffer_len(&ske->packet->buffer) == 4) {
1750 SILC_GET32_MSB(error, ske->packet->buffer.data);
1751 ske->status = error;
1752 silc_packet_free(ske->packet);
1756 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
1757 silc_schedule_task_del_by_context(ske->schedule, ske);
1762 /* Starts the protocol as initiator */
1765 silc_ske_initiator(SilcSKE ske,
1766 SilcPacketStream stream,
1767 SilcSKEParams params,
1768 SilcSKEStartPayload start_payload)
1770 SILC_LOG_DEBUG(("Start SKE as initiator"));
1772 if (!ske || !stream || !params || !params->version)
1775 if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
1778 if (!silc_fsm_init(&ske->fsm, ske, silc_ske_finished, ske, ske->schedule))
1781 if (params->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)
1782 ske->session_port = params->session_port;
1784 /* Generate security properties if not provided */
1785 if (!start_payload) {
1786 start_payload = silc_ske_assemble_security_properties(ske,
1793 ske->start_payload = start_payload;
1794 ske->version = params->version;
1795 ske->running = TRUE;
1797 /* Link to packet stream to get key exchange packets */
1798 ske->stream = stream;
1799 silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
1800 SILC_PACKET_KEY_EXCHANGE,
1801 SILC_PACKET_KEY_EXCHANGE_2,
1802 SILC_PACKET_SUCCESS,
1803 SILC_PACKET_FAILURE, -1);
1805 /* Start SKE as initiator */
1806 silc_fsm_start(&ske->fsm, silc_ske_st_initiator_start);
1811 /******************************** Responder *********************************/
1813 /* Start protocol as responder. Wait initiator's start payload */
1815 SILC_FSM_STATE(silc_ske_st_responder_start)
1817 SilcSKE ske = fsm_context;
1819 SILC_LOG_DEBUG(("Start"));
1823 silc_fsm_next(fsm, silc_ske_st_responder_aborted);
1830 /** Wait for initiator */
1831 silc_fsm_next(fsm, silc_ske_st_responder_phase1);
1835 /* Decode initiator's start payload. Select the security properties from
1836 the initiator's start payload and send our reply start payload back. */
1838 SILC_FSM_STATE(silc_ske_st_responder_phase1)
1840 SilcSKE ske = fsm_context;
1841 SilcSKEStatus status;
1842 SilcSKEStartPayload remote_payload = NULL;
1843 SilcBuffer packet_buf = &ske->packet->buffer;
1845 SILC_LOG_DEBUG(("Start"));
1847 /* Decode the payload */
1848 status = silc_ske_payload_start_decode(ske, packet_buf, &remote_payload);
1849 if (status != SILC_SKE_STATUS_OK) {
1850 /** Error decoding Start Payload */
1851 silc_packet_free(ske->packet);
1853 ske->status = status;
1854 silc_fsm_next(fsm, silc_ske_st_responder_error);
1858 /* Take a copy of the payload buffer for future use. It is used to
1859 compute the HASH value. */
1860 ske->start_payload_copy = silc_buffer_copy(packet_buf);
1862 silc_packet_free(ske->packet);
1865 /* Force the mutual authentication flag if we want to do it. */
1866 if (ske->flags & SILC_SKE_SP_FLAG_MUTUAL) {
1867 SILC_LOG_DEBUG(("Force mutual authentication"));
1868 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
1871 /* Force PFS flag if we require it */
1872 if (ske->flags & SILC_SKE_SP_FLAG_PFS) {
1873 SILC_LOG_DEBUG(("Force PFS"));
1874 remote_payload->flags |= SILC_SKE_SP_FLAG_PFS;
1877 /* Disable IV Included flag if requested */
1878 if (remote_payload->flags & SILC_SKE_SP_FLAG_IV_INCLUDED &&
1879 !(ske->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)) {
1880 SILC_LOG_DEBUG(("We do not support IV Included flag"));
1881 remote_payload->flags &= ~SILC_SKE_SP_FLAG_IV_INCLUDED;
1884 /* Check and select security properties */
1885 status = silc_ske_select_security_properties(ske, remote_payload,
1887 if (status != SILC_SKE_STATUS_OK) {
1888 /** Error selecting proposal */
1889 silc_ske_payload_start_free(remote_payload);
1890 ske->status = status;
1891 silc_fsm_next(fsm, silc_ske_st_responder_error);
1895 silc_ske_payload_start_free(remote_payload);
1897 /* Encode our reply payload to send the selected security properties */
1898 status = silc_ske_payload_start_encode(ske, ske->start_payload,
1900 if (status != SILC_SKE_STATUS_OK)
1903 /* Send the packet. */
1904 if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE, 0,
1905 silc_buffer_data(packet_buf),
1906 silc_buffer_len(packet_buf)))
1909 silc_buffer_free(packet_buf);
1911 /** Waiting initiator's KE payload */
1912 silc_fsm_next(fsm, silc_ske_st_responder_phase2);
1916 if (ske->prop->group)
1917 silc_ske_group_free(ske->prop->group);
1918 if (ske->prop->cipher)
1919 silc_cipher_free(ske->prop->cipher);
1920 if (ske->prop->hash)
1921 silc_hash_free(ske->prop->hash);
1922 if (ske->prop->hmac)
1923 silc_hmac_free(ske->prop->hmac);
1924 silc_free(ske->prop);
1927 if (status == SILC_SKE_STATUS_OK)
1928 status = SILC_SKE_STATUS_ERROR;
1931 ske->status = status;
1932 silc_fsm_next(fsm, silc_ske_st_responder_error);
1936 /* Phase-2. Decode initiator's KE payload */
1938 SILC_FSM_STATE(silc_ske_st_responder_phase2)
1940 SilcSKE ske = fsm_context;
1941 SilcSKEStatus status;
1942 SilcSKEKEPayload recv_payload;
1943 SilcBuffer packet_buf = &ske->packet->buffer;
1945 SILC_LOG_DEBUG(("Start"));
1947 if (ske->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
1948 SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
1949 silc_ske_install_retransmission(ske);
1950 silc_packet_free(ske->packet);
1955 /* Decode Key Exchange Payload */
1956 status = silc_ske_payload_ke_decode(ske, packet_buf, &recv_payload);
1957 if (status != SILC_SKE_STATUS_OK) {
1958 /** Error decoding KE payload */
1959 silc_packet_free(ske->packet);
1961 ske->status = status;
1962 silc_fsm_next(fsm, silc_ske_st_responder_error);
1966 ske->ke1_payload = recv_payload;
1968 silc_packet_free(ske->packet);
1971 /* Verify the received public key and verify the signature if we are
1972 doing mutual authentication. */
1973 if (ske->start_payload &&
1974 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
1976 SILC_LOG_DEBUG(("We are doing mutual authentication"));
1978 if (!recv_payload->pk_data && (ske->callbacks->verify_key ||
1980 /** Public key not provided */
1981 SILC_LOG_ERROR(("Remote end did not send its public key (or "
1982 "certificate), even though we require it"));
1983 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
1984 silc_fsm_next(fsm, silc_ske_st_responder_error);
1988 /* Decode the remote's public key */
1989 if (recv_payload->pk_data &&
1990 !silc_pkcs_public_key_alloc(recv_payload->pk_type,
1991 recv_payload->pk_data,
1992 recv_payload->pk_len,
1993 &ske->prop->public_key)) {
1994 /** Error decoding public key */
1995 SILC_LOG_ERROR(("Unsupported/malformed public key received"));
1996 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
1997 silc_fsm_next(fsm, silc_ske_st_responder_error);
2001 if (ske->prop->public_key && (ske->callbacks->verify_key ||
2003 SILC_LOG_DEBUG(("Verifying public key"));
2005 /** Waiting public key verification */
2006 silc_fsm_next(fsm, silc_ske_st_responder_phase4);
2008 /* If repository is provided, verify the key from there. */
2009 if (ske->repository) {
2012 find = silc_skr_find_alloc();
2014 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2015 silc_fsm_next(fsm, silc_ske_st_responder_error);
2018 silc_skr_find_set_pkcs_type(find,
2019 silc_pkcs_get_type(ske->prop->public_key));
2020 silc_skr_find_set_public_key(find, ske->prop->public_key);
2021 silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT);
2023 /* Find key from repository */
2024 SILC_FSM_CALL(silc_skr_find(ske->repository, find,
2025 silc_ske_skr_callback, ske));
2027 /* Verify from application */
2028 SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key,
2029 ske->callbacks->context,
2030 silc_ske_pk_verified, NULL));
2036 /** Generate KE2 payload */
2037 silc_fsm_next(fsm, silc_ske_st_responder_phase4);
2041 /* Phase-4. Generate KE2 payload */
2043 SILC_FSM_STATE(silc_ske_st_responder_phase4)
2045 SilcSKE ske = fsm_context;
2046 SilcSKEStatus status;
2047 SilcSKEKEPayload recv_payload, send_payload;
2052 silc_fsm_next(fsm, silc_ske_st_responder_aborted);
2056 /* Check result of public key verification */
2057 if (ske->status != SILC_SKE_STATUS_OK) {
2058 /** Public key not verified */
2059 SILC_LOG_DEBUG(("Public key verification failed"));
2060 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2064 recv_payload = ske->ke1_payload;
2066 /* The public key verification was performed only if the Mutual
2067 Authentication flag is set. */
2068 if (ske->start_payload &&
2069 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
2070 unsigned char hash[SILC_HASH_MAXLEN];
2071 SilcUInt32 hash_len;
2073 SILC_LOG_DEBUG(("Public key is authentic"));
2075 /* Compute the hash value */
2076 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
2077 if (status != SILC_SKE_STATUS_OK) {
2078 /** Error computing hash */
2079 ske->status = status;
2080 silc_fsm_next(fsm, silc_ske_st_responder_error);
2084 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
2086 /* Verify signature */
2087 if (!silc_pkcs_verify(ske->prop->public_key, recv_payload->sign_data,
2088 recv_payload->sign_len, hash, hash_len, NULL)) {
2089 /** Incorrect signature */
2090 SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
2091 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
2092 silc_fsm_next(fsm, silc_ske_st_responder_error);
2096 SILC_LOG_DEBUG(("Signature is Ok"));
2098 memset(hash, 'F', hash_len);
2101 /* Create the random number x, 1 < x < q. */
2102 x = silc_calloc(1, sizeof(*x));
2105 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
2106 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
2108 if (status != SILC_SKE_STATUS_OK) {
2109 /** Error generating random number */
2112 ske->status = status;
2113 silc_fsm_next(fsm, silc_ske_st_responder_error);
2117 /* Save the results for later processing */
2118 send_payload = silc_calloc(1, sizeof(*send_payload));
2120 ske->ke2_payload = send_payload;
2122 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
2124 /* Do the Diffie Hellman computation, f = g ^ x mod p */
2125 silc_mp_init(&send_payload->x);
2126 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
2127 &ske->prop->group->group);
2129 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
2131 /* Compute the shared secret key */
2132 KEY = silc_calloc(1, sizeof(*KEY));
2134 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
2135 &ske->prop->group->group);
2138 /** Send KE2 payload */
2139 silc_fsm_next(fsm, silc_ske_st_responder_phase5);
2143 /* Phase-5. Send KE2 payload */
2145 SILC_FSM_STATE(silc_ske_st_responder_phase5)
2147 SilcSKE ske = fsm_context;
2148 SilcSKEStatus status;
2149 SilcBuffer payload_buf;
2150 unsigned char hash[SILC_HASH_MAXLEN], sign[2048 + 1], *pk;
2151 SilcUInt32 hash_len, sign_len, pk_len;
2153 SILC_LOG_DEBUG(("Start"));
2155 if (ske->public_key && ske->private_key) {
2156 SILC_LOG_DEBUG(("Getting public key"));
2158 /* Get the public key */
2159 pk = silc_pkcs_public_key_encode(ske->public_key, &pk_len);
2161 /** Error encoding public key */
2162 status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2163 silc_fsm_next(fsm, silc_ske_st_responder_error);
2166 ske->ke2_payload->pk_data = pk;
2167 ske->ke2_payload->pk_len = pk_len;
2169 SILC_LOG_DEBUG(("Computing HASH value"));
2171 /* Compute the hash value */
2172 memset(hash, 0, sizeof(hash));
2173 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
2174 if (status != SILC_SKE_STATUS_OK) {
2175 /** Error computing hash */
2176 ske->status = status;
2177 silc_fsm_next(fsm, silc_ske_st_responder_error);
2181 ske->hash = silc_memdup(hash, hash_len);
2182 ske->hash_len = hash_len;
2184 SILC_LOG_DEBUG(("Signing HASH value"));
2186 /* Sign the hash value */
2187 if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
2188 sizeof(sign) - 1, &sign_len, NULL)) {
2189 /** Error computing signature */
2190 status = SILC_SKE_STATUS_SIGNATURE_ERROR;
2191 silc_fsm_next(fsm, silc_ske_st_responder_error);
2194 ske->ke2_payload->sign_data = silc_memdup(sign, sign_len);
2195 ske->ke2_payload->sign_len = sign_len;
2196 memset(sign, 0, sizeof(sign));
2198 ske->ke2_payload->pk_type = silc_pkcs_get_type(ske->public_key);
2200 /* Encode the Key Exchange Payload */
2201 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
2203 if (status != SILC_SKE_STATUS_OK) {
2204 /** Error encoding KE payload */
2205 ske->status = status;
2206 silc_fsm_next(fsm, silc_ske_st_responder_error);
2210 /* Send the packet. */
2211 if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE_2, 0,
2212 payload_buf->data, silc_buffer_len(payload_buf))) {
2213 SILC_LOG_DEBUG(("Error sending packet"));
2214 ske->status = SILC_SKE_STATUS_ERROR;
2215 silc_fsm_next(fsm, silc_ske_st_responder_error);
2219 silc_buffer_free(payload_buf);
2221 /** Waiting completion */
2222 silc_fsm_next(fsm, silc_ske_st_responder_end);
2226 /* Protocol completed */
2228 SILC_FSM_STATE(silc_ske_st_responder_end)
2230 SilcSKE ske = fsm_context;
2231 unsigned char tmp[4];
2232 SilcUInt32 hash_len, key_len, block_len;
2234 if (ske->packet->type != SILC_PACKET_SUCCESS) {
2235 SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
2236 silc_ske_install_retransmission(ske);
2237 silc_packet_free(ske->packet);
2241 silc_packet_free(ske->packet);
2244 /* Process key material */
2245 key_len = silc_cipher_get_key_len(ske->prop->cipher);
2246 block_len = silc_cipher_get_block_len(ske->prop->cipher);
2247 hash_len = silc_hash_len(ske->prop->hash);
2248 ske->keymat = silc_ske_process_key_material(ske, block_len,
2252 /** Error processing key material */
2253 ske->status = SILC_SKE_STATUS_ERROR;
2254 silc_fsm_next(fsm, silc_ske_st_responder_error);
2258 /* Send SUCCESS packet */
2259 SILC_PUT32_MSB(SILC_SKE_STATUS_OK, tmp);
2260 silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, tmp, 4);
2262 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2263 silc_schedule_task_del_by_context(ske->schedule, ske);
2268 /* Aborted by application */
2270 SILC_FSM_STATE(silc_ske_st_responder_aborted)
2272 SilcSKE ske = fsm_context;
2273 unsigned char tmp[4];
2275 SILC_LOG_DEBUG(("Key exchange protocol aborted"));
2277 /* Send FAILURE packet */
2278 SILC_PUT32_MSB(SILC_SKE_STATUS_ERROR, tmp);
2279 silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, tmp, 4);
2281 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2282 silc_schedule_task_del_by_context(ske->schedule, ske);
2287 /* Failure received from remote */
2289 SILC_FSM_STATE(silc_ske_st_responder_failure)
2291 SilcSKE ske = fsm_context;
2292 SilcUInt32 error = SILC_SKE_STATUS_ERROR;
2294 SILC_LOG_DEBUG(("Key exchange protocol failed"));
2296 if (ske->packet && silc_buffer_len(&ske->packet->buffer) == 4) {
2297 SILC_GET32_MSB(error, ske->packet->buffer.data);
2298 ske->status = error;
2299 silc_packet_free(ske->packet);
2303 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2304 silc_schedule_task_del_by_context(ske->schedule, ske);
2309 /* Error occurred */
2311 SILC_FSM_STATE(silc_ske_st_responder_error)
2313 SilcSKE ske = fsm_context;
2314 unsigned char tmp[4];
2316 SILC_LOG_DEBUG(("Error %d (%s) during key exchange protocol",
2317 ske->status, silc_ske_map_status(ske->status)));
2319 /* Send FAILURE packet */
2320 if (ske->status > SILC_SKE_STATUS_INVALID_COOKIE)
2321 ske->status = SILC_SKE_STATUS_BAD_PAYLOAD;
2322 SILC_PUT32_MSB(ske->status, tmp);
2323 silc_ske_packet_send(ske, SILC_PACKET_FAILURE, 0, tmp, 4);
2325 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2326 silc_schedule_task_del_by_context(ske->schedule, ske);
2331 /* Starts the protocol as responder. */
2334 silc_ske_responder(SilcSKE ske,
2335 SilcPacketStream stream,
2336 SilcSKEParams params)
2338 SILC_LOG_DEBUG(("Start SKE as responder"));
2340 if (!ske || !stream || !params || !params->version)
2343 if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
2346 if (!silc_fsm_init(&ske->fsm, ske, silc_ske_finished, ske, ske->schedule))
2349 ske->responder = TRUE;
2350 ske->flags = params->flags;
2351 if (ske->flags & SILC_SKE_SP_FLAG_IV_INCLUDED)
2352 ske->session_port = params->session_port;
2353 ske->version = strdup(params->version);
2356 ske->running = TRUE;
2358 /* Link to packet stream to get key exchange packets */
2359 ske->stream = stream;
2360 silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
2361 SILC_PACKET_KEY_EXCHANGE,
2362 SILC_PACKET_KEY_EXCHANGE_1,
2363 SILC_PACKET_SUCCESS,
2364 SILC_PACKET_FAILURE, -1);
2366 /* Start SKE as responder */
2367 silc_fsm_start(&ske->fsm, silc_ske_st_responder_start);
2372 /***************************** Initiator Rekey ******************************/
2376 SILC_FSM_STATE(silc_ske_st_rekey_initiator_start)
2378 SilcSKE ske = fsm_context;
2381 SILC_LOG_DEBUG(("Start rekey (%s)", ske->rekey->pfs ? "PFS" : "No PFS"));
2385 silc_fsm_next(fsm, silc_ske_st_initiator_aborted);
2391 ske->prop = silc_calloc(1, sizeof(*ske->prop));
2394 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2395 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2399 /* Send REKEY packet to start rekey protocol */
2400 if (!silc_ske_packet_send(ske, SILC_PACKET_REKEY, 0, NULL, 0)) {
2401 /** Error sending packet */
2402 SILC_LOG_DEBUG(("Error sending packet"));
2403 ske->status = SILC_SKE_STATUS_ERROR;
2404 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2408 /* If doing rekey without PFS, move directly to the end of the protocol. */
2409 if (!ske->rekey->pfs) {
2410 /** Rekey without PFS */
2411 silc_fsm_next(fsm, silc_ske_st_rekey_initiator_done);
2415 status = silc_ske_group_get_by_number(ske->rekey->ske_group,
2417 if (status != SILC_SKE_STATUS_OK) {
2418 /** Unknown group */
2419 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2423 /** Rekey with PFS */
2424 silc_fsm_next(fsm, silc_ske_st_initiator_phase2);
2428 /* Sends REKEY_DONE packet to finish the protocol. */
2430 SILC_FSM_STATE(silc_ske_st_rekey_initiator_done)
2432 SilcSKE ske = fsm_context;
2433 SilcCipher send_key;
2436 SilcUInt32 key_len, block_len, hash_len, x_len;
2437 unsigned char *pfsbuf;
2439 SILC_LOG_DEBUG(("Start"));
2441 silc_packet_get_keys(ske->stream, &send_key, NULL, &hmac_send, NULL);
2442 key_len = silc_cipher_get_key_len(send_key);
2443 block_len = silc_cipher_get_block_len(send_key);
2445 if (!silc_hash_alloc(ske->rekey->hash, &hash)) {
2446 /** Cannot allocate hash */
2447 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2448 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2451 hash_len = silc_hash_len(hash);
2453 /* Process key material */
2454 if (ske->rekey->pfs) {
2456 pfsbuf = silc_mp_mp2bin(ske->KEY, 0, &x_len);
2458 ske->keymat = silc_ske_process_key_material_data(pfsbuf, x_len,
2461 memset(pfsbuf, 0, x_len);
2467 silc_ske_process_key_material_data(ske->rekey->send_enc_key,
2468 ske->rekey->enc_key_len / 8,
2474 SILC_LOG_ERROR(("Error processing key material"));
2475 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2479 ske->prop->cipher = send_key;
2480 ske->prop->hmac = hmac_send;
2481 ske->prop->hash = hash;
2483 /* Get sending keys */
2484 if (!silc_ske_set_keys(ske, ske->keymat, ske->prop, &send_key, NULL,
2485 &hmac_send, NULL, NULL)) {
2486 /** Cannot get keys */
2487 ske->status = SILC_SKE_STATUS_ERROR;
2488 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2492 /* Set the new keys into use. This will also send REKEY_DONE packet. Any
2493 packet sent after this call will be protected with the new keys. */
2494 if (!silc_packet_set_keys(ske->stream, send_key, NULL, hmac_send, NULL,
2496 /** Cannot set keys */
2497 SILC_LOG_DEBUG(("Cannot set new keys, error sending REKEY_DONE"));
2498 ske->status = SILC_SKE_STATUS_ERROR;
2499 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2503 /** Wait for REKEY_DONE */
2504 silc_fsm_next(fsm, silc_ske_st_rekey_initiator_end);
2508 /* Rekey protocol end */
2510 SILC_FSM_STATE(silc_ske_st_rekey_initiator_end)
2512 SilcSKE ske = fsm_context;
2513 SilcCipher receive_key;
2514 SilcHmac hmac_receive;
2515 SilcSKERekeyMaterial rekey;
2517 SILC_LOG_DEBUG(("Start"));
2519 if (ske->packet->type != SILC_PACKET_REKEY_DONE) {
2520 SILC_LOG_DEBUG(("Remote retransmitted an old packet"));
2521 silc_packet_free(ske->packet);
2526 silc_packet_get_keys(ske->stream, NULL, &receive_key, NULL, &hmac_receive);
2527 ske->prop->cipher = receive_key;
2528 ske->prop->hmac = hmac_receive;
2530 /* Get receiving keys */
2531 if (!silc_ske_set_keys(ske, ske->keymat, ske->prop, NULL, &receive_key,
2532 NULL, &hmac_receive, NULL)) {
2533 /** Cannot get keys */
2534 ske->status = SILC_SKE_STATUS_ERROR;
2535 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2539 /* Set new receiving keys into use. All packets received after this will
2540 be decrypted with the new keys. */
2541 if (!silc_packet_set_keys(ske->stream, NULL, receive_key, NULL,
2542 hmac_receive, FALSE)) {
2543 /** Cannot set keys */
2544 SILC_LOG_DEBUG(("Cannot set new keys"));
2545 ske->status = SILC_SKE_STATUS_ERROR;
2546 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2550 SILC_LOG_DEBUG(("Rekey completed successfully"));
2552 /* Generate new rekey material */
2553 rekey = silc_ske_make_rekey_material(ske, ske->keymat);
2556 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
2557 silc_fsm_next(fsm, silc_ske_st_initiator_error);
2560 rekey->pfs = ske->rekey->pfs;
2563 ske->prop->cipher = NULL;
2564 ske->prop->hmac = NULL;
2565 silc_packet_free(ske->packet);
2567 silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske);
2568 silc_schedule_task_del_by_context(ske->schedule, ske);
2573 /* Starts rekey protocol as initiator */
2576 silc_ske_rekey_initiator(SilcSKE ske,
2577 SilcPacketStream stream,
2578 SilcSKERekeyMaterial rekey)
2580 SILC_LOG_DEBUG(("Start SKE rekey as initator"));
2582 if (!ske || !stream || !rekey)
2585 if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
2588 if (!silc_fsm_init(&ske->fsm, ske, silc_ske_finished, ske, ske->schedule))
2592 ske->responder = FALSE;
2593 ske->running = TRUE;
2594 ske->rekeying = TRUE;
2596 /* Link to packet stream to get key exchange packets */
2597 ske->stream = stream;
2598 silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
2600 SILC_PACKET_REKEY_DONE,
2601 SILC_PACKET_KEY_EXCHANGE_2,
2602 SILC_PACKET_SUCCESS,
2603 SILC_PACKET_FAILURE, -1);
2605 /* Start SKE rekey as initiator */
2606 silc_fsm_start(&ske->fsm, silc_ske_st_rekey_initiator_start);
2611 /***************************** Responder Rekey ******************************/
2613 SILC_FSM_STATE(silc_ske_st_rekey_responder_start);
2615 SILC_FSM_STATE(silc_ske_st_rekey_responder_start)
2620 /* Starts rekey protocol as responder */
2623 silc_ske_rekey_responder(SilcSKE ske,
2624 SilcPacketStream stream,
2625 SilcSKERekeyMaterial rekey)
2627 SILC_LOG_DEBUG(("Start SKE rekey as responder"));
2629 if (!ske || !stream || !rekey)
2632 if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske))
2635 if (!silc_fsm_init(&ske->fsm, ske, silc_ske_finished, ske, ske->schedule))
2639 ske->responder = TRUE;
2640 ske->running = TRUE;
2641 ske->rekeying = TRUE;
2643 /* Link to packet stream to get key exchange packets */
2644 ske->stream = stream;
2645 silc_packet_stream_link(ske->stream, &silc_ske_stream_cbs, ske, 1000000,
2647 SILC_PACKET_REKEY_DONE,
2648 SILC_PACKET_KEY_EXCHANGE_1,
2649 SILC_PACKET_SUCCESS,
2650 SILC_PACKET_FAILURE, -1);
2652 /* Start SKE rekey as responder */
2653 silc_fsm_start(&ske->fsm, silc_ske_st_rekey_responder_start);
2658 /* Processes the provided key material `data' as the SILC protocol
2659 specification defines. */
2662 silc_ske_process_key_material_data(unsigned char *data,
2663 SilcUInt32 data_len,
2664 SilcUInt32 req_iv_len,
2665 SilcUInt32 req_enc_key_len,
2666 SilcUInt32 req_hmac_key_len,
2670 unsigned char hashd[SILC_HASH_MAXLEN];
2671 SilcUInt32 hash_len = req_hmac_key_len;
2672 SilcUInt32 enc_key_len = req_enc_key_len / 8;
2673 SilcSKEKeyMaterial key;
2675 SILC_LOG_DEBUG(("Start"));
2677 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
2680 key = silc_calloc(1, sizeof(*key));
2684 buf = silc_buffer_alloc_size(1 + data_len);
2687 silc_buffer_format(buf,
2688 SILC_STR_UI_CHAR(0),
2689 SILC_STR_UI_XNSTRING(data, data_len),
2693 memset(hashd, 0, sizeof(hashd));
2695 silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2696 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
2697 memcpy(key->send_iv, hashd, req_iv_len);
2698 memset(hashd, 0, sizeof(hashd));
2700 silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2701 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
2702 memcpy(key->receive_iv, hashd, req_iv_len);
2703 key->iv_len = req_iv_len;
2705 /* Take the encryption keys. If requested key size is more than
2706 the size of hash length we will distribute more key material
2707 as protocol defines. */
2709 if (enc_key_len > hash_len) {
2711 unsigned char k1[SILC_HASH_MAXLEN], k2[SILC_HASH_MAXLEN],
2712 k3[SILC_HASH_MAXLEN];
2713 unsigned char *dtmp;
2716 if (enc_key_len > (3 * hash_len))
2719 /* Take first round */
2720 memset(k1, 0, sizeof(k1));
2721 silc_hash_make(hash, buf->data, silc_buffer_len(buf), k1);
2723 /* Take second round */
2724 dist = silc_buffer_alloc_size(data_len + hash_len);
2727 silc_buffer_format(dist,
2728 SILC_STR_UI_XNSTRING(data, data_len),
2729 SILC_STR_UI_XNSTRING(k1, hash_len),
2731 memset(k2, 0, sizeof(k2));
2732 silc_hash_make(hash, dist->data, silc_buffer_len(dist), k2);
2734 /* Take third round */
2735 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
2736 silc_buffer_pull_tail(dist, hash_len);
2737 silc_buffer_pull(dist, data_len + hash_len);
2738 silc_buffer_format(dist,
2739 SILC_STR_UI_XNSTRING(k2, hash_len),
2741 silc_buffer_push(dist, data_len + hash_len);
2742 memset(k3, 0, sizeof(k3));
2743 silc_hash_make(hash, dist->data, silc_buffer_len(dist), k3);
2745 /* Then, save the keys */
2746 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
2747 memcpy(dtmp, k1, hash_len);
2748 memcpy(dtmp + hash_len, k2, hash_len);
2749 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
2751 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
2752 memcpy(key->send_enc_key, dtmp, enc_key_len);
2753 key->enc_key_len = req_enc_key_len;
2755 memset(dtmp, 0, (3 * hash_len));
2756 memset(k1, 0, sizeof(k1));
2757 memset(k2, 0, sizeof(k2));
2758 memset(k3, 0, sizeof(k3));
2760 silc_buffer_clear(dist);
2761 silc_buffer_free(dist);
2763 /* Take normal hash as key */
2764 memset(hashd, 0, sizeof(hashd));
2765 silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2766 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
2767 memcpy(key->send_enc_key, hashd, enc_key_len);
2768 key->enc_key_len = req_enc_key_len;
2772 if (enc_key_len > hash_len) {
2774 unsigned char k1[SILC_HASH_MAXLEN], k2[SILC_HASH_MAXLEN],
2775 k3[SILC_HASH_MAXLEN];
2776 unsigned char *dtmp;
2779 if (enc_key_len > (3 * hash_len))
2782 /* Take first round */
2783 memset(k1, 0, sizeof(k1));
2784 silc_hash_make(hash, buf->data, silc_buffer_len(buf), k1);
2786 /* Take second round */
2787 dist = silc_buffer_alloc_size(data_len + hash_len);
2790 silc_buffer_format(dist,
2791 SILC_STR_UI_XNSTRING(data, data_len),
2792 SILC_STR_UI_XNSTRING(k1, hash_len),
2794 memset(k2, 0, sizeof(k2));
2795 silc_hash_make(hash, dist->data, silc_buffer_len(dist), k2);
2797 /* Take third round */
2798 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
2799 silc_buffer_pull_tail(dist, hash_len);
2800 silc_buffer_pull(dist, data_len + hash_len);
2801 silc_buffer_format(dist,
2802 SILC_STR_UI_XNSTRING(k2, hash_len),
2804 silc_buffer_push(dist, data_len + hash_len);
2805 memset(k3, 0, sizeof(k3));
2806 silc_hash_make(hash, dist->data, silc_buffer_len(dist), k3);
2808 /* Then, save the keys */
2809 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
2810 memcpy(dtmp, k1, hash_len);
2811 memcpy(dtmp + hash_len, k2, hash_len);
2812 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
2814 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
2815 memcpy(key->receive_enc_key, dtmp, enc_key_len);
2816 key->enc_key_len = req_enc_key_len;
2818 memset(dtmp, 0, (3 * hash_len));
2819 memset(k1, 0, sizeof(k1));
2820 memset(k2, 0, sizeof(k2));
2821 memset(k3, 0, sizeof(k3));
2823 silc_buffer_clear(dist);
2824 silc_buffer_free(dist);
2826 /* Take normal hash as key */
2827 memset(hashd, 0, sizeof(hashd));
2828 silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2829 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
2830 memcpy(key->receive_enc_key, hashd, enc_key_len);
2831 key->enc_key_len = req_enc_key_len;
2834 /* Take HMAC keys */
2835 memset(hashd, 0, sizeof(hashd));
2837 silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2838 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
2839 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
2840 memset(hashd, 0, sizeof(hashd));
2842 silc_hash_make(hash, buf->data, silc_buffer_len(buf), hashd);
2843 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
2844 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
2845 key->hmac_key_len = req_hmac_key_len;
2846 memset(hashd, 0, sizeof(hashd));
2848 silc_buffer_clear(buf);
2849 silc_buffer_free(buf);
2851 SILC_LOG_HEXDUMP(("enc"), key->send_enc_key, key->enc_key_len / 8);
2856 /* Processes negotiated key material as protocol specifies. This returns
2857 the actual keys to be used in the SILC. */
2860 silc_ske_process_key_material(SilcSKE ske,
2861 SilcUInt32 req_iv_len,
2862 SilcUInt32 req_enc_key_len,
2863 SilcUInt32 req_hmac_key_len,
2864 SilcSKERekeyMaterial *rekey)
2867 unsigned char *tmpbuf;
2869 SilcSKEKeyMaterial key;
2871 /* Encode KEY to binary data */
2872 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
2874 buf = silc_buffer_alloc_size(klen + ske->hash_len);
2877 silc_buffer_format(buf,
2878 SILC_STR_UI_XNSTRING(tmpbuf, klen),
2879 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
2882 /* Process the key material */
2883 key = silc_ske_process_key_material_data(buf->data, silc_buffer_len(buf),
2884 req_iv_len, req_enc_key_len,
2888 memset(tmpbuf, 0, klen);
2890 silc_buffer_clear(buf);
2891 silc_buffer_free(buf);
2894 *rekey = silc_ske_make_rekey_material(ske, key);
2902 /* Free key material structure */
2904 void silc_ske_free_key_material(SilcSKEKeyMaterial key)
2910 silc_free(key->send_iv);
2911 if (key->receive_iv)
2912 silc_free(key->receive_iv);
2913 if (key->send_enc_key) {
2914 memset(key->send_enc_key, 0, key->enc_key_len / 8);
2915 silc_free(key->send_enc_key);
2917 if (key->receive_enc_key) {
2918 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
2919 silc_free(key->receive_enc_key);
2921 if (key->send_hmac_key) {
2922 memset(key->send_hmac_key, 0, key->hmac_key_len);
2923 silc_free(key->send_hmac_key);
2925 if (key->receive_hmac_key) {
2926 memset(key->receive_hmac_key, 0, key->hmac_key_len);
2927 silc_free(key->receive_hmac_key);
2932 /* Free rekey material */
2934 void silc_ske_free_rekey_material(SilcSKERekeyMaterial rekey)
2938 if (rekey->send_enc_key) {
2939 memset(rekey->send_enc_key, 0, rekey->enc_key_len / 8);
2940 silc_free(rekey->send_enc_key);
2942 silc_free(rekey->hash);
2946 /* Set keys into use */
2948 SilcBool silc_ske_set_keys(SilcSKE ske,
2949 SilcSKEKeyMaterial keymat,
2950 SilcSKESecurityProperties prop,
2951 SilcCipher *ret_send_key,
2952 SilcCipher *ret_receive_key,
2953 SilcHmac *ret_hmac_send,
2954 SilcHmac *ret_hmac_receive,
2957 unsigned char iv[32];
2959 /* Allocate ciphers to be used in the communication */
2961 if (!silc_cipher_alloc((char *)silc_cipher_get_name(prop->cipher),
2965 if (ret_receive_key) {
2966 if (!silc_cipher_alloc((char *)silc_cipher_get_name(prop->cipher),
2971 /* Allocate HMACs */
2972 if (ret_hmac_send) {
2973 if (!silc_hmac_alloc((char *)silc_hmac_get_name(prop->hmac), NULL,
2977 if (ret_hmac_receive) {
2978 if (!silc_hmac_alloc((char *)silc_hmac_get_name(prop->hmac), NULL,
2983 /* Set key material */
2984 memset(iv, 0, sizeof(iv));
2985 if (ske->responder) {
2987 silc_cipher_set_key(*ret_send_key, keymat->receive_enc_key,
2988 keymat->enc_key_len, TRUE);
2990 if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) {
2991 memcpy(iv, ske->hash, 4);
2992 memcpy(iv + 4, keymat->receive_iv, 4);
2993 silc_cipher_set_iv(*ret_send_key, iv);
2995 silc_cipher_set_iv(*ret_send_key, keymat->receive_iv);
2998 if (ret_receive_key) {
2999 silc_cipher_set_key(*ret_receive_key, keymat->send_enc_key,
3000 keymat->enc_key_len, FALSE);
3002 if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) {
3003 memcpy(iv, ske->hash, 4);
3004 memcpy(iv + 4, keymat->send_iv, 4);
3005 silc_cipher_set_iv(*ret_receive_key, iv);
3007 silc_cipher_set_iv(*ret_receive_key, keymat->send_iv);
3011 silc_hmac_set_key(*ret_hmac_send, keymat->receive_hmac_key,
3012 keymat->hmac_key_len);
3013 if (ret_hmac_receive)
3014 silc_hmac_set_key(*ret_hmac_receive, keymat->send_hmac_key,
3015 keymat->hmac_key_len);
3018 silc_cipher_set_key(*ret_send_key, keymat->send_enc_key,
3019 keymat->enc_key_len, TRUE);
3021 if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) {
3022 memcpy(iv, ske->hash, 4);
3023 memcpy(iv + 4, keymat->send_iv, 4);
3024 silc_cipher_set_iv(*ret_send_key, iv);
3026 silc_cipher_set_iv(*ret_send_key, keymat->send_iv);
3029 if (ret_receive_key) {
3030 silc_cipher_set_key(*ret_receive_key, keymat->receive_enc_key,
3031 keymat->enc_key_len, FALSE);
3033 if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) {
3034 memcpy(iv, ske->hash, 4);
3035 memcpy(iv + 4, keymat->receive_iv, 4);
3036 silc_cipher_set_iv(*ret_receive_key, iv);
3038 silc_cipher_set_iv(*ret_receive_key, keymat->receive_iv);
3042 silc_hmac_set_key(*ret_hmac_send, keymat->send_hmac_key,
3043 keymat->hmac_key_len);
3044 if (ret_hmac_receive)
3045 silc_hmac_set_key(*ret_hmac_receive, keymat->receive_hmac_key,
3046 keymat->hmac_key_len);
3051 if (!silc_hash_alloc(silc_hash_get_name(prop->hash), ret_hash))
3058 const char *silc_ske_status_string[] =
3062 "Unkown error occurred",
3063 "Bad payload in packet",
3064 "Unsupported group",
3065 "Unsupported cipher",
3067 "Unsupported hash function",
3069 "Unsupported public key (or certificate)",
3070 "Incorrect signature",
3071 "Bad or unsupported version",
3075 "Remote did not provide public key",
3076 "Bad reserved field in packet",
3077 "Bad payload length in packet",
3078 "Error computing signature",
3079 "System out of memory",
3084 /* Maps status to readable string and returns the string. If string is not
3085 found and empty character string ("") is returned. */
3087 const char *silc_ske_map_status(SilcSKEStatus status)
3091 for (i = 0; silc_ske_status_string[i]; i++)
3093 return silc_ske_status_string[i];
3098 /* Parses remote host's version string. */
3100 SilcBool silc_ske_parse_version(SilcSKE ske,
3101 SilcUInt32 *protocol_version,
3102 char **protocol_version_string,
3103 SilcUInt32 *software_version,
3104 char **software_version_string,
3105 char **vendor_version)
3107 return silc_parse_version_string(ske->remote_version,
3109 protocol_version_string,
3111 software_version_string,
3115 /* Get security properties */
3117 SilcSKESecurityProperties silc_ske_get_security_properties(SilcSKE ske)
3122 /* Get key material */
3124 SilcSKEKeyMaterial silc_ske_get_key_material(SilcSKE ske)