From 364323cd28181ba3e5e66f8b8b1c495be9af339e Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 7 Dec 2006 16:59:22 +0000 Subject: [PATCH] Added silc_ske_get_key_material. Error handling fixes. --- lib/silcske/groups.c | 12 ++-- lib/silcske/silcske.c | 130 ++++++++++++++++++++++++---------------- lib/silcske/silcske.h | 20 ++++++- lib/silcske/silcske_i.h | 2 + 4 files changed, 105 insertions(+), 59 deletions(-) diff --git a/lib/silcske/groups.c b/lib/silcske/groups.c index 99277912..7f55aced 100644 --- a/lib/silcske/groups.c +++ b/lib/silcske/groups.c @@ -4,12 +4,12 @@ Author: Pekka Riikonen - Copyright (C) 2000 - 2001 Pekka Riikonen + Copyright (C) 2000 - 2006 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -24,7 +24,7 @@ /* Fixed and public Diffie Hellman Groups defined by the SKE protocol. These are equivalent to the OAKLEY Key Determination protocol groups (taken from RFC 2412). */ -const struct SilcSKEDiffieHellmanGroupDefStruct silc_ske_groups[] = +const struct SilcSKEDiffieHellmanGroupDefStruct silc_ske_groups[] = { /* 1024 bits modulus (Mandatory group) */ { 1, "diffie-hellman-group1", @@ -98,7 +98,7 @@ SilcSKEStatus silc_ske_group_get_by_number(int number, silc_mp_set_str(&group->group, silc_ske_groups[i].group, 16); silc_mp_set_str(&group->group_order, silc_ske_groups[i].group_order, 16); silc_mp_set_str(&group->generator, silc_ske_groups[i].generator, 16); - + *ret = group; } @@ -134,7 +134,7 @@ SilcSKEStatus silc_ske_group_get_by_name(const char *name, silc_mp_set_str(&group->group, silc_ske_groups[i].group, 16); silc_mp_set_str(&group->group_order, silc_ske_groups[i].group_order, 16); silc_mp_set_str(&group->generator, silc_ske_groups[i].generator, 16); - + *ret = group; } @@ -163,7 +163,7 @@ char *silc_ske_get_supported_groups() len += strlen(silc_ske_groups[i].name); list = silc_realloc(list, len + 1); - memcpy(list + (len - strlen(silc_ske_groups[i].name)), + memcpy(list + (len - strlen(silc_ske_groups[i].name)), silc_ske_groups[i].name, strlen(silc_ske_groups[i].name)); memcpy(list + len, ",", 1); len++; diff --git a/lib/silcske/silcske.c b/lib/silcske/silcske.c index d4ad07ab..dcd8aad4 100644 --- a/lib/silcske/silcske.c +++ b/lib/silcske/silcske.c @@ -387,8 +387,7 @@ silc_ske_select_security_properties(SilcSKE ske, } /* Save selected cipher to security properties */ - if (silc_cipher_alloc(payload->enc_alg_list, - &(*prop)->cipher) == FALSE) { + if (silc_cipher_alloc(payload->enc_alg_list, &(*prop)->cipher) == FALSE) { silc_free(payload->ke_grp_list); silc_free(payload->pkcs_alg_list); silc_free(payload); @@ -446,8 +445,7 @@ silc_ske_select_security_properties(SilcSKE ske, } /* Save selected hash algorithm to security properties */ - if (silc_hash_alloc(ske->start_payload->hash_alg_list, - &(*prop)->hash) == FALSE) { + if (silc_hash_alloc(payload->hash_alg_list, &(*prop)->hash) == FALSE) { silc_free(payload->ke_grp_list); silc_free(payload->pkcs_alg_list); silc_free(payload->enc_alg_list); @@ -507,8 +505,7 @@ silc_ske_select_security_properties(SilcSKE ske, } /* Save selected HMACc to security properties */ - if (silc_hmac_alloc(ske->start_payload->hmac_alg_list, NULL, - &(*prop)->hmac) == FALSE) { + if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &(*prop)->hmac) == FALSE) { silc_free(payload->ke_grp_list); silc_free(payload->pkcs_alg_list); silc_free(payload->enc_alg_list); @@ -812,9 +809,14 @@ SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule, SILC_LOG_DEBUG(("Allocating new Key Exchange object")); - if (!rng || !schedule || !public_key) + if (!rng || !schedule) return NULL; + if (!public_key) { + SILC_LOG_ERROR(("Public key must be given to silc_ske_alloc")); + return NULL; + } + ske = silc_calloc(1, sizeof(*ske)); if (!ske) return NULL; @@ -835,46 +837,52 @@ void silc_ske_free(SilcSKE ske) { SILC_LOG_DEBUG(("Freeing Key Exchange object")); - if (ske) { - /* Free start payload */ - if (ske->start_payload) - silc_ske_payload_start_free(ske->start_payload); - - /* Free KE payload */ - if (ske->ke1_payload) - silc_ske_payload_ke_free(ske->ke1_payload); - if (ske->ke2_payload) - silc_ske_payload_ke_free(ske->ke2_payload); - silc_free(ske->remote_version); - - /* Free rest */ - if (ske->prop) { - if (ske->prop->group) - silc_ske_group_free(ske->prop->group); - if (ske->prop->cipher) - silc_cipher_free(ske->prop->cipher); - if (ske->prop->hash) - silc_hash_free(ske->prop->hash); - if (ske->prop->hmac) - silc_hmac_free(ske->prop->hmac); - silc_free(ske->prop); - } - if (ske->start_payload_copy) - silc_buffer_free(ske->start_payload_copy); - if (ske->x) { - silc_mp_uninit(ske->x); - silc_free(ske->x); - } - if (ske->KEY) { - silc_mp_uninit(ske->KEY); - silc_free(ske->KEY); - } - silc_free(ske->hash); - silc_free(ske->callbacks); + if (!ske) + return; + + if (ske->running) { + ske->freed = TRUE; + return; + } - memset(ske, 'F', sizeof(*ske)); - silc_free(ske); + /* Free start payload */ + if (ske->start_payload) + silc_ske_payload_start_free(ske->start_payload); + + /* Free KE payload */ + if (ske->ke1_payload) + silc_ske_payload_ke_free(ske->ke1_payload); + if (ske->ke2_payload) + silc_ske_payload_ke_free(ske->ke2_payload); + silc_free(ske->remote_version); + + /* Free rest */ + if (ske->prop) { + if (ske->prop->group) + silc_ske_group_free(ske->prop->group); + if (ske->prop->cipher) + silc_cipher_free(ske->prop->cipher); + if (ske->prop->hash) + silc_hash_free(ske->prop->hash); + if (ske->prop->hmac) + silc_hmac_free(ske->prop->hmac); + silc_free(ske->prop); + } + if (ske->start_payload_copy) + silc_buffer_free(ske->start_payload_copy); + if (ske->x) { + silc_mp_uninit(ske->x); + silc_free(ske->x); + } + if (ske->KEY) { + silc_mp_uninit(ske->KEY); + silc_free(ske->KEY); } + silc_free(ske->hash); + silc_free(ske->callbacks); + + memset(ske, 'F', sizeof(*ske)); + silc_free(ske); } /* Return user context */ @@ -972,7 +980,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1) SilcSKEStatus status; SilcSKEStartPayload payload; SilcSKESecurityProperties prop; - SilcSKEDiffieHellmanGroup group; + SilcSKEDiffieHellmanGroup group = NULL; SilcBuffer packet_buf = &ske->packet->buffer; SilcUInt16 remote_port = 0; SilcID id; @@ -1084,9 +1092,8 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1) err: if (payload) silc_ske_payload_start_free(payload); - - silc_ske_group_free(group); - + if (group) + silc_ske_group_free(group); if (prop->cipher) silc_cipher_free(prop->cipher); if (prop->hash) @@ -1491,6 +1498,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_end) ske->rekey, ske->callbacks->context); silc_packet_free(ske->packet); + silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); return SILC_FSM_FINISH; } @@ -1507,6 +1515,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_aborted) /* Send FAILURE packet */ SILC_PUT32_MSB(SILC_SKE_STATUS_ERROR, data); silc_packet_send(ske->stream, SILC_PACKET_FAILURE, 0, data, 4); + silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); return SILC_FSM_FINISH; } @@ -1535,6 +1544,8 @@ SILC_FSM_STATE(silc_ske_st_initiator_error) ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL, ske->callbacks->context); + silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); + return SILC_FSM_FINISH; } @@ -1552,6 +1563,8 @@ SILC_FSM_STATE(silc_ske_st_initiator_failure) ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL, ske->callbacks->context); + silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); + return SILC_FSM_FINISH; } @@ -1561,7 +1574,10 @@ static void silc_ske_initiator_finished(SilcFSM fsm, void *fsm_context, void *destructor_context) { SilcSKE ske = fsm_context; - silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); + + ske->running = FALSE; + if (ske->freed) + silc_ske_free(ske); } /* Starts the protocol as initiator */ @@ -1598,6 +1614,7 @@ silc_ske_initiator(SilcSKE ske, ske->start_payload = start_payload; ske->version = params->version; + ske->running = TRUE; /* Link to packet stream to get key exchange packets */ ske->stream = stream; @@ -2158,7 +2175,6 @@ SILC_FSM_STATE(silc_ske_st_responder_error) ske->status = SILC_SKE_STATUS_BAD_PAYLOAD; SILC_PUT32_MSB(ske->status, tmp); silc_packet_send(ske->stream, SILC_PACKET_FAILURE, 0, tmp, 4); - silc_packet_stream_unlink(ske->stream, &silc_ske_stream_cbs, ske); return SILC_FSM_FINISH; @@ -2168,7 +2184,11 @@ SILC_FSM_STATE(silc_ske_st_responder_error) static void silc_ske_responder_finished(SilcFSM fsm, void *fsm_context, void *destructor_context) { + SilcSKE ske = fsm_context; + ske->running = FALSE; + if (ske->freed) + silc_ske_free(ske); } /* Starts the protocol as responder. */ @@ -2198,6 +2218,7 @@ silc_ske_responder(SilcSKE ske, ske->version = strdup(params->version); if (!ske->version) return NULL; + ske->running = TRUE; /* Link to packet stream to get key exchange packets */ ske->stream = stream; @@ -2686,3 +2707,10 @@ SilcSKESecurityProperties silc_ske_get_security_properties(SilcSKE ske) { return ske->prop; } + +/* Get key material */ + +SilcSKEKeyMaterial silc_ske_get_key_material(SilcSKE ske) +{ + return ske->keymat; +} diff --git a/lib/silcske/silcske.h b/lib/silcske/silcske.h index 98d3f63a..c0febeaf 100644 --- a/lib/silcske/silcske.h +++ b/lib/silcske/silcske.h @@ -74,6 +74,7 @@ typedef enum { SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH, /* Payload includes garbage */ SILC_SKE_STATUS_SIGNATURE_ERROR, /* Error computing signature */ SILC_SKE_STATUS_OUT_OF_MEMORY, /* System out of memory */ + SILC_SKE_STATUS_TIMEOUT, /* Timeout */ } SilcSKEStatus; /***/ @@ -165,7 +166,7 @@ typedef struct { * This context is returned after key exchange protocol to application * in the completion callback. Application may save it and use it later * to perform the rekey with silc_ske_rekey_initiator_start and/or - * silc_ske_rekey_responder_start functions. If application does not + * silc_ske_rekey_responder functions. If application does not * need the context, it may free it with silc_free function. * * Application may save application specific data to `user_context'. @@ -455,7 +456,7 @@ silc_ske_initiator(SilcSKE ske, SilcSKEParams params, SilcSKEStartPayload start_payload); -/****f* silcske/SilcSKEAPI/silc_ske_responder_start +/****f* silcske/SilcSKEAPI/silc_ske_responder * * SYNOPSIS * @@ -565,6 +566,21 @@ SilcBool silc_ske_parse_version(SilcSKE ske, ***/ SilcSKESecurityProperties silc_ske_get_security_properties(SilcSKE ske); +/****f* silcske/SilcSKEAPI/silc_ske_get_key_material + * + * SYNOPSIS + * + * SilcSKEKeyMaterial silc_ske_get_key_material(SilcSKE ske); + * + * DESCRIPTION + * + * Returns the negotiated key material from the `ske' or NULL if the + * key material does not exist. The caller must not free the returned + * pointer. + * + ***/ +SilcSKEKeyMaterial silc_ske_get_key_material(SilcSKE ske); + /****f* silcske/SilcSKEAPI/silc_ske_process_key_material_data * * SYNOPSIS diff --git a/lib/silcske/silcske_i.h b/lib/silcske/silcske_i.h index ae61adf7..8904b05d 100644 --- a/lib/silcske/silcske_i.h +++ b/lib/silcske/silcske_i.h @@ -72,7 +72,9 @@ struct SilcSKEStruct { SilcUInt16 session_port; unsigned int aborted : 1; + unsigned int freed : 1; unsigned int responder : 1; + unsigned int running : 1; }; #endif /* SILCSKE_I_H */ -- 2.24.0