From 5cf2f961968f70aaa304b8b020ba2315d179f7eb Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Fri, 30 Jun 2006 17:41:08 +0000 Subject: [PATCH] Added support for SilcSKR in SKE for finding public keys. --- lib/silcske/silcske.c | 110 ++++++++++++++++++++++++++++++++-------- lib/silcske/silcske.h | 22 +++++--- lib/silcske/silcske_i.h | 3 +- 3 files changed, 108 insertions(+), 27 deletions(-) diff --git a/lib/silcske/silcske.c b/lib/silcske/silcske.c index c0e8d7f1..72a983ff 100644 --- a/lib/silcske/silcske.c +++ b/lib/silcske/silcske.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2000 - 2005 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 @@ -85,6 +85,36 @@ static void silc_ske_pk_verified(SilcSKE ske, SilcSKEStatus status, SILC_FSM_CALL_CONTINUE(&ske->fsm); } +/* SKR find callback */ + +static void silc_ske_skr_callback(SilcSKR repository, + SilcSKRFind find, + SilcSKRStatus status, + SilcDList keys, void *context) +{ + SilcSKE ske = context; + + silc_skr_find_free(find); + + if (status != SILC_SKR_OK) { + if (ske->callbacks->verify_key) { + /* Verify from application */ + ske->callbacks->verify_key(ske, ske->prop->public_key, + ske->callbacks->context, + silc_ske_pk_verified, NULL); + return; + } + } + + if (keys) + silc_dlist_uninit(keys); + + /* Continue */ + ske->status = (status == SILC_SKR_OK ? SILC_SKE_STATUS_OK : + SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY); + SILC_FSM_CALL_CONTINUE(&ske->fsm); +} + /* Checks remote and local versions */ static SilcSKEStatus silc_ske_check_version(SilcSKE ske) @@ -663,8 +693,8 @@ static SilcSKEStatus silc_ske_make_hash(SilcSKE ske, /* Allocates new SKE object. */ SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule, - SilcPublicKey public_key, SilcPrivateKey private_key, - void *context) + SilcSKR repository, SilcPublicKey public_key, + SilcPrivateKey private_key, void *context) { SilcSKE ske; @@ -678,11 +708,11 @@ SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule, return NULL; ske->status = SILC_SKE_STATUS_OK; ske->rng = rng; + ske->repository = repository; ske->user_data = context; ske->schedule = schedule; ske->public_key = public_key; ske->private_key = private_key; - ske->pk_type = SILC_SKE_PK_TYPE_SILC; return ske; } @@ -995,7 +1025,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) } payload->pk_len = pk_len; } - payload->pk_type = ske->pk_type; + payload->pk_type = silc_pkcs_get_type(ske->public_key); /* Compute signature data if we are doing mutual authentication */ if (ske->private_key && @@ -1086,7 +1116,7 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase3) } ske->ke2_payload = payload; - if (!payload->pk_data && ske->callbacks->verify_key) { + if (!payload->pk_data && (ske->callbacks->verify_key || ske->repository)) { SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), " "even though we require it")); ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED; @@ -1111,16 +1141,35 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase3) goto err; } - if (ske->prop->public_key && ske->callbacks->verify_key) { + if (ske->prop->public_key && (ske->callbacks->verify_key || + ske->repository)) { SILC_LOG_DEBUG(("Verifying public key")); /** Waiting public key verification */ silc_fsm_next(fsm, silc_ske_st_initiator_phase4); - SILC_FSM_CALL(ske->callbacks->verify_key(ske, - payload->pk_type, - ske->prop->public_key, - ske->callbacks->context, - silc_ske_pk_verified, NULL)); + + /* If repository is provided, verify the key from there. */ + if (ske->repository) { + SilcSKRFind find; + + find = silc_skr_find_alloc(); + if (!find) { + status = SILC_SKE_STATUS_OUT_OF_MEMORY; + goto err; + } + silc_skr_find_set_pkcs_type(find, + silc_pkcs_get_type(ske->prop->public_key)); + silc_skr_find_set_public_key(find, ske->prop->public_key); + + /* Find key from repository */ + SILC_FSM_CALL(silc_skr_find(ske->repository, find, + silc_ske_skr_callback, ske)); + } else { + /* Verify from application */ + SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key, + ske->callbacks->context, + silc_ske_pk_verified, NULL)); + } /* NOT REACHED */ } @@ -1569,7 +1618,8 @@ SILC_FSM_STATE(silc_ske_st_responder_phase3) SILC_LOG_DEBUG(("We are doing mutual authentication")); - if (!recv_payload->pk_data && ske->callbacks->verify_key) { + if (!recv_payload->pk_data && (ske->callbacks->verify_key || + ske->repository)) { /** Public key not provided */ SILC_LOG_ERROR(("Remote end did not send its public key (or " "certificate), even though we require it")); @@ -1591,16 +1641,36 @@ SILC_FSM_STATE(silc_ske_st_responder_phase3) return SILC_FSM_CONTINUE; } - if (ske->prop->public_key && ske->callbacks->verify_key) { + if (ske->prop->public_key && (ske->callbacks->verify_key || + ske->repository)) { SILC_LOG_DEBUG(("Verifying public key")); /** Waiting public key verification */ silc_fsm_next(fsm, silc_ske_st_responder_phase4); - SILC_FSM_CALL(ske->callbacks->verify_key(ske, - recv_payload->pk_type, - ske->prop->public_key, - ske->callbacks->context, - silc_ske_pk_verified, NULL)); + + /* If repository is provided, verify the key from there. */ + if (ske->repository) { + SilcSKRFind find; + + find = silc_skr_find_alloc(); + if (!find) { + ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY; + silc_fsm_next(fsm, silc_ske_st_responder_error); + return SILC_FSM_CONTINUE; + } + silc_skr_find_set_pkcs_type(find, + silc_pkcs_get_type(ske->prop->public_key)); + silc_skr_find_set_public_key(find, ske->prop->public_key); + + /* Find key from repository */ + SILC_FSM_CALL(silc_skr_find(ske->repository, find, + silc_ske_skr_callback, ske)); + } else { + /* Verify from application */ + SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key, + ske->callbacks->context, + silc_ske_pk_verified, NULL)); + } /* NOT REACHED */ } } @@ -1767,7 +1837,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase5) ske->ke2_payload->sign_len = sign_len; memset(sign, 0, sizeof(sign)); } - ske->ke2_payload->pk_type = ske->pk_type; + ske->ke2_payload->pk_type = silc_pkcs_get_type(ske->public_key); /* Encode the Key Exchange Payload */ status = silc_ske_payload_ke_encode(ske, ske->ke2_payload, diff --git a/lib/silcske/silcske.h b/lib/silcske/silcske.h index 65802b83..04c69986 100644 --- a/lib/silcske/silcske.h +++ b/lib/silcske/silcske.h @@ -228,7 +228,6 @@ typedef void (*SilcSKEVerifyCbCompletion)(SilcSKE ske, * SYNOPSIS * * typedef void (*SilcSKEVerifyCb)(SilcSKE ske, - * SilcSKEPKType pk_type, * SilcPublicKey public_key, * void *context, * SilcSKEVerifyCbCompletion completion, @@ -243,9 +242,11 @@ typedef void (*SilcSKEVerifyCbCompletion)(SilcSKE ske, * arugment to silc_ske_set_callbacks. See silc_ske_set_callbacks for * more information. * + * If the key repository was provided in silc_ske_alloc this callback + * is called only if the public key was not found from the repository. + * ***/ typedef void (*SilcSKEVerifyCb)(SilcSKE ske, - SilcSKEPKType pk_type, SilcPublicKey public_key, void *context, SilcSKEVerifyCbCompletion completion, @@ -288,7 +289,7 @@ typedef void (*SilcSKECompletionCb)(SilcSKE ske, * SYNOPSIS * * SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule, - * SilcPublicKey public_key, + * SilcSKR repository, SilcPublicKey public_key, * SilcPrivateKey private_key, void *context); * * DESCRIPTION @@ -302,10 +303,19 @@ typedef void (*SilcSKECompletionCb)(SilcSKE ske, * SKE session context is allocated application must call the * silc_ske_set_callbacks. * + * If the `repository' is non-NULL then the remote's public key will be + * verified from the repository. If it is not provided then the + * SilcSKEVerifyCb callback must be set, and it will be called to + * verify the key. If both `repository' and the callback is provided the + * callback is called only if the key is not found from the repository. + * + * The `public_key' and `private_key' is the caller's identity used + * during the key exchange. + * * EXMPALE * * // Initiator example - * ske = silc_ske_alloc(rng, scheduler, app); + * 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 | @@ -315,8 +325,8 @@ typedef void (*SilcSKECompletionCb)(SilcSKE ske, * ***/ SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule, - SilcPublicKey public_key, SilcPrivateKey private_key, - void *context); + SilcSKR repository, SilcPublicKey public_key, + SilcPrivateKey private_key, void *context); /****f* silcske/SilcSKEAPI/silc_ske_free * diff --git a/lib/silcske/silcske_i.h b/lib/silcske/silcske_i.h index 833d157f..e36fbdc9 100644 --- a/lib/silcske/silcske_i.h +++ b/lib/silcske/silcske_i.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2005 Pekka Riikonen + Copyright (C) 2005 - 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 @@ -27,6 +27,7 @@ struct SilcSKEStruct { SilcPacketStream stream; SilcRng rng; + SilcSKR repository; SilcSKECallbacks callbacks; void *user_data; SilcSKEStatus status; -- 2.24.0