From 9bccc0b6c7413815b70b4c8554a886a021f0dd83 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Mon, 23 Oct 2006 16:34:02 +0000 Subject: [PATCH] Added SilcSKEParams and simplified the SKE interface even more. Added support for UDP/IP and IV included and session port in SKE cookie. --- lib/silcske/silcske.c | 173 +++++++++++++++++++++++----------------- lib/silcske/silcske.h | 95 +++++++++++----------- lib/silcske/silcske_i.h | 1 + 3 files changed, 149 insertions(+), 120 deletions(-) diff --git a/lib/silcske/silcske.c b/lib/silcske/silcske.c index 72a983ff..7a864c26 100644 --- a/lib/silcske/silcske.c +++ b/lib/silcske/silcske.c @@ -176,6 +176,11 @@ silc_ske_select_security_properties(SilcSKE ske, payload->cookie_len = SILC_SKE_COOKIE_LEN; memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN); + /* In case IV included flag and session port is set the first 16-bits of + cookie will include our session port. */ + if (rp->flags & SILC_SKE_SP_FLAG_IV_INCLUDED && ske->session_port) + SILC_PUT16_MSB(ske->session_port, payload->cookie); + /* Put our version to our reply */ payload->version = strdup(ske->version); if (!payload->version) { @@ -687,6 +692,72 @@ static SilcSKEStatus silc_ske_make_hash(SilcSKE ske, return status; } +/* Assembles security properties */ + +static SilcSKEStartPayload +silc_ske_assemble_security_properties(SilcSKE ske, + SilcSKESecurityPropertyFlag flags, + const char *version) +{ + SilcSKEStartPayload rp; + int i; + + SILC_LOG_DEBUG(("Assembling KE Start Payload")); + + rp = silc_calloc(1, sizeof(*rp)); + + /* Set flags */ + rp->flags = (unsigned char)flags; + + /* Set random cookie */ + rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie)); + for (i = 0; i < SILC_SKE_COOKIE_LEN; i++) + rp->cookie[i] = silc_rng_get_byte_fast(ske->rng); + rp->cookie_len = SILC_SKE_COOKIE_LEN; + + /* In case IV included flag and session port is set the first 16-bits of + cookie will include our session port. */ + if (flags & SILC_SKE_SP_FLAG_IV_INCLUDED && ske->session_port) + SILC_PUT16_MSB(ske->session_port, rp->cookie); + + /* Put version */ + rp->version = strdup(version); + rp->version_len = strlen(version); + + /* Get supported Key Exhange groups */ + rp->ke_grp_list = silc_ske_get_supported_groups(); + rp->ke_grp_len = strlen(rp->ke_grp_list); + + /* Get supported PKCS algorithms */ + rp->pkcs_alg_list = silc_pkcs_get_supported(); + rp->pkcs_alg_len = strlen(rp->pkcs_alg_list); + + /* Get supported encryption algorithms */ + rp->enc_alg_list = silc_cipher_get_supported(); + rp->enc_alg_len = strlen(rp->enc_alg_list); + + /* Get supported hash algorithms */ + rp->hash_alg_list = silc_hash_get_supported(); + rp->hash_alg_len = strlen(rp->hash_alg_list); + + /* Get supported HMACs */ + rp->hmac_alg_list = silc_hmac_get_supported(); + rp->hmac_alg_len = strlen(rp->hmac_alg_list); + + /* XXX */ + /* Get supported compression algorithms */ + rp->comp_alg_list = strdup("none"); + rp->comp_alg_len = strlen("none"); + + rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN + + 2 + rp->version_len + + 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len + + 2 + rp->enc_alg_len + 2 + rp->hash_alg_len + + 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len; + + return rp; +} + /******************************* Protocol API *******************************/ @@ -851,6 +922,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1) SilcSKESecurityProperties prop; SilcSKEDiffieHellmanGroup group; SilcBuffer packet_buf = &ske->packet->buffer; + int coff = 0; SILC_LOG_DEBUG(("Start")); @@ -869,11 +941,15 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase1) return SILC_FSM_CONTINUE; } - /* Check that the cookie is returned unmodified */ - if (memcmp(ske->start_payload->cookie, payload->cookie, - ske->start_payload->cookie_len)) { + /* Check that the cookie is returned unmodified. In case IV included + flag and session port has been set, the first two bytes of cookie + are the session port and we ignore them in this check. */ + if (payload->flags & SILC_SKE_SP_FLAG_IV_INCLUDED && ske->session_port) + coff = 2; + if (memcmp(ske->start_payload->cookie + coff, payload->cookie + coff, + SILC_SKE_COOKIE_LEN - coff)) { /** Invalid cookie */ - SILC_LOG_ERROR(("Responder modified our cookie and it must not do it")); + SILC_LOG_ERROR(("Invalid cookie, modified or unsupported feature")); ske->status = SILC_SKE_STATUS_INVALID_COOKIE; silc_fsm_next(fsm, silc_ske_st_initiator_error); return SILC_FSM_CONTINUE; @@ -1339,11 +1415,12 @@ static void silc_ske_initiator_finished(SilcFSM fsm, void *fsm_context, SilcAsyncOperation silc_ske_initiator(SilcSKE ske, SilcPacketStream stream, + SilcSKEParams params, SilcSKEStartPayload start_payload) { SILC_LOG_DEBUG(("Start SKE as initiator")); - if (!ske || !stream || !start_payload) + if (!ske || !stream || !params || !params->version) return NULL; if (!silc_async_init(&ske->op, silc_ske_abort, NULL, ske)) @@ -1353,6 +1430,18 @@ silc_ske_initiator(SilcSKE ske, ske->schedule)) return NULL; + if (params->flags & SILC_SKE_SP_FLAG_IV_INCLUDED) + ske->session_port = params->session_port; + + /* Generate security properties if not provided */ + if (!start_payload) { + start_payload = silc_ske_assemble_security_properties(ske, + params->flags, + params->version); + if (!start_payload) + return NULL; + } + ske->start_payload = start_payload; /* Link to packet stream to get key exchange packets */ @@ -1987,12 +2076,11 @@ static void silc_ske_responder_finished(SilcFSM fsm, void *fsm_context, SilcAsyncOperation silc_ske_responder(SilcSKE ske, SilcPacketStream stream, - const char *version, - SilcSKESecurityPropertyFlag flags) + SilcSKEParams params) { SILC_LOG_DEBUG(("Start SKE as responder")); - if (!ske || !stream || !version) { + if (!ske || !stream || !params || !params->version) { return NULL; } @@ -2003,11 +2091,13 @@ silc_ske_responder(SilcSKE ske, ske->schedule)) return NULL; - ske->flags = flags; - ske->version = strdup(version); + ske->responder = TRUE; + ske->flags = params->flags; + if (ske->flags & SILC_SKE_SP_FLAG_IV_INCLUDED) + ske->session_port = params->session_port; + ske->version = strdup(params->version); if (!ske->version) return NULL; - ske->responder = TRUE; /* Link to packet stream to get key exchange packets */ ske->stream = stream; @@ -2099,67 +2189,6 @@ silc_ske_rekey_responder(SilcSKE ske, return &ske->op; } -/* Assembles security properties */ - -SilcSKEStartPayload -silc_ske_assemble_security_properties(SilcSKE ske, - SilcSKESecurityPropertyFlag flags, - const char *version) -{ - SilcSKEStartPayload rp; - int i; - - SILC_LOG_DEBUG(("Assembling KE Start Payload")); - - rp = silc_calloc(1, sizeof(*rp)); - - /* Set flags */ - rp->flags = (unsigned char)flags; - - /* Set random cookie */ - rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie)); - for (i = 0; i < SILC_SKE_COOKIE_LEN; i++) - rp->cookie[i] = silc_rng_get_byte_fast(ske->rng); - rp->cookie_len = SILC_SKE_COOKIE_LEN; - - /* Put version */ - rp->version = strdup(version); - rp->version_len = strlen(version); - - /* Get supported Key Exhange groups */ - rp->ke_grp_list = silc_ske_get_supported_groups(); - rp->ke_grp_len = strlen(rp->ke_grp_list); - - /* Get supported PKCS algorithms */ - rp->pkcs_alg_list = silc_pkcs_get_supported(); - rp->pkcs_alg_len = strlen(rp->pkcs_alg_list); - - /* Get supported encryption algorithms */ - rp->enc_alg_list = silc_cipher_get_supported(); - rp->enc_alg_len = strlen(rp->enc_alg_list); - - /* Get supported hash algorithms */ - rp->hash_alg_list = silc_hash_get_supported(); - rp->hash_alg_len = strlen(rp->hash_alg_list); - - /* Get supported HMACs */ - rp->hmac_alg_list = silc_hmac_get_supported(); - rp->hmac_alg_len = strlen(rp->hmac_alg_list); - - /* XXX */ - /* Get supported compression algorithms */ - rp->comp_alg_list = strdup("none"); - rp->comp_alg_len = strlen("none"); - - rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN + - 2 + rp->version_len + - 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len + - 2 + rp->enc_alg_len + 2 + rp->hash_alg_len + - 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len; - - return rp; -} - /* Processes the provided key material `data' as the SILC protocol specification defines. */ diff --git a/lib/silcske/silcske.h b/lib/silcske/silcske.h index 04c69986..42d9bc63 100644 --- a/lib/silcske/silcske.h +++ b/lib/silcske/silcske.h @@ -179,6 +179,37 @@ typedef struct { } *SilcSKERekeyMaterial; /***/ +/****s* silcske/SilcSKEAPI/SilcSKEParams + * + * NAME + * + * typedef struct { ... } *SilcSKEParams, SilcSKEParamsStruct; + * + * DESCRIPTION + * + * SKE parameters structure. This structure is given as argument to + * silc_ske_initiator and silc_ske_responder functions. + * + * SOURCE + */ +typedef struct { + /* The SKE version string that is sent to the remote end. This field + must be set. Caller must free the pointer. */ + char *version; + + /* Security property flags. When initiator sets these it requests them + from the responder. Responder may set here the flags it supports + and wants to enforce for the initiator. */ + SilcSKESecurityPropertyFlag flags; + + /* SILC Session port when using UDP/IP and SILC_SKE_SP_FLAG_IV_INCLUDED + flag. It is the port the remote will use as SILC session port after + the key exchange protocol. Ignored without SILC_SKE_SP_FLAG_IV_INCLUDED + flag. */ + SilcUInt16 session_port; +} *SilcSKEParams, SilcSKEParamsStruct; +/***/ + /****d* silcske/SilcSKEAPI/SilcSKEPKType * * NAME @@ -315,13 +346,11 @@ typedef void (*SilcSKECompletionCb)(SilcSKE ske, * EXMPALE * * // Initiator example + * params.version = version; + * params.flags = SILC_SKE_SP_FLAG_PFS | SILC_SKE_SP_FLAG_MUTUAL; * ske = silc_ske_alloc(rng, scheduler, NULL, pk, prv, app); * silc_ske_set_callbacks(ske, verify_public_key, completion, app); - * start_payload = - * silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_PFS | - * SILC_SKE_SP_FLAG_MUTUAL, - * version); - * silc_ske_initiator_start(ske, stream, start_payload); + * silc_ske_initiator_start(ske, stream, ¶ms, NULL); * ***/ SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule, @@ -395,6 +424,7 @@ void silc_ske_set_callbacks(SilcSKE ske, * SilcAsyncOperation * silc_ske_initiator_start(SilcSKE ske, * SilcPacketStream stream, + * SilcSKEParams params, * SilcSKEStartPayload start_payload); * * DESCRIPTION @@ -403,13 +433,14 @@ void silc_ske_set_callbacks(SilcSKE ske, * callback that was set in silc_ske_set_callbacks will be called once * the protocol has completed. The `stream' is the network connection * to the remote host. The SKE library will handle all key exchange - * packets sent and received in the `stream' connection. + * packets sent and received in the `stream' connection. The `params' + * include SKE parameters, and it must be provided. * - * The `start_payload' includes all configured security properties that - * will be sent to the responder. The `start_payload' must be provided. - * It can be created by calling silc_ske_assemble_security_properties - * function. The caller must not free the payload once it has been - * given as argument to this function. + * If the `start_payload' is NULL the library will generate it + * automatically. Caller may provide it if it wants to send its own + * security properties instead of using the default ones library + * generates. If caller provides it, it must not free it once it has + * been given as argument to this function. * * This function returns SilcAsyncOperation operation context which can * be used to control the protocol from the application. Application may @@ -420,6 +451,7 @@ void silc_ske_set_callbacks(SilcSKE ske, SilcAsyncOperation silc_ske_initiator(SilcSKE ske, SilcPacketStream stream, + SilcSKEParams params, SilcSKEStartPayload start_payload); /****f* silcske/SilcSKEAPI/silc_ske_responder_start @@ -429,9 +461,7 @@ silc_ske_initiator(SilcSKE ske, * SilcAsyncOperation * silc_ske_responder_start(SilcSKE ske, * SilcPacketStream stream, - * const char *version, - * SilcBuffer start_payload, - * SilcSKESecurityPropertyFlag flags); + * SilcSKEParams params); * * DESCRIPTION * @@ -439,13 +469,8 @@ silc_ske_initiator(SilcSKE ske, * callback that was set in silc_ske_set_callbacks will be called once * the protocol has completed. The `stream' is the network connection * to the remote host. The SKE library will handle all key exchange - * packets sent and received in the `stream' connection. - * - * The `version' is the responder's SILC protocol version that will be - * sent in reply to the initiator. The `flags' indicates the - * SilcSKESecurityPropertyFlag flags that responder supports and enforces - * for the initiator. Responder may, for example, enforce that the PFS - * will be performed in rekey. + * packets sent and received in the `stream' connection. The `params' + * include SKE parameters, and must be provided. * * This function returns SilcAsyncOperation operation context which can * be used to control the protocol from the application. Application may @@ -456,8 +481,7 @@ silc_ske_initiator(SilcSKE ske, SilcAsyncOperation silc_ske_responder(SilcSKE ske, SilcPacketStream stream, - const char *version, - SilcSKESecurityPropertyFlag flags); + SilcSKEParams params); SilcAsyncOperation silc_ske_rekey_initiator(SilcSKE ske, @@ -470,31 +494,6 @@ silc_ske_rekey_responder(SilcSKE ske, SilcBuffer ke_payload, SilcSKERekeyMaterial rekey); -/****f* silcske/SilcSKEAPI/silc_ske_assemble_security_properties - * - * SYNOPSIS - * - * SilcSKEStartPayload - * silc_ske_assemble_security_properties(SilcSKE ske, - * SilcSKESecurityPropertyFlag flags, - * const char *version); - * - * DESCRIPTION - * - * Assembles security properties to Key Exchange Start Payload to be - * sent to the remote end. This checks system wide (SILC system, that is) - * settings and chooses from those. However, if other properties - * should be used this function is easy to replace by another function. - * Returns NULL on error. This is an utility function. This is used - * by the initiator of the protocol. The `version' is the local SILC - * protocol version string. - * - ***/ -SilcSKEStartPayload -silc_ske_assemble_security_properties(SilcSKE ske, - SilcSKESecurityPropertyFlag flags, - const char *version); - /****f* silcske/SilcSKEAPI/silc_ske_assemble_security_properties * * SYNOPSIS diff --git a/lib/silcske/silcske_i.h b/lib/silcske/silcske_i.h index e36fbdc9..ae61adf7 100644 --- a/lib/silcske/silcske_i.h +++ b/lib/silcske/silcske_i.h @@ -69,6 +69,7 @@ struct SilcSKEStruct { SilcSchedule schedule; SilcFSMStruct fsm; SilcAsyncOperationStruct op; + SilcUInt16 session_port; unsigned int aborted : 1; unsigned int responder : 1; -- 2.24.0