Author: Pekka Riikonen <priikone@silcnet.org>
- 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
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)
SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
- if (silc_pkcs_is_supported(item) == TRUE) {
+ if (silc_pkcs_find_algorithm(item, NULL)) {
SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
payload->pkcs_alg_len = len;
return SILC_SKE_STATUS_ERROR;
}
+ SILC_LOG_HEXDUMP(("hash buf"), buf->data, silc_buffer_len(buf));
+
memset(e, 0, e_len);
silc_free(e);
}
/* 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;
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;
}
if (ske->prop) {
if (ske->prop->group)
silc_ske_group_free(ske->prop->group);
- if (ske->prop->pkcs)
- silc_pkcs_free(ske->prop->pkcs);
if (ske->prop->cipher)
silc_cipher_free(ske->prop->cipher);
if (ske->prop->hash)
prop->group = group;
- if (silc_pkcs_alloc(payload->pkcs_alg_list, ske->pk_type,
- &prop->pkcs) == FALSE) {
+ if (silc_pkcs_find_algorithm(payload->pkcs_alg_list, NULL) == NULL) {
status = SILC_SKE_STATUS_UNKNOWN_PKCS;
goto err;
}
silc_ske_group_free(group);
- if (prop->pkcs)
- silc_pkcs_free(prop->pkcs);
if (prop->cipher)
silc_cipher_free(prop->cipher);
if (prop->hash)
}
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 &&
SILC_LOG_DEBUG(("Signing HASH_i value"));
/* Sign the hash value */
- silc_pkcs_private_key_data_set(ske->prop->pkcs, ske->private_key->prv,
- ske->private_key->prv_len);
- if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
- !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
+ if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
+ sizeof(sign) - 1, &sign_len, NULL)) {
/** Error computing signature */
silc_mp_uninit(x);
silc_free(x);
}
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;
silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
ske->KEY = KEY;
- if (payload->pk_data && ske->callbacks->verify_key) {
+ /* Decode the remote's public key */
+ if (payload->pk_data &&
+ !silc_pkcs_public_key_alloc(payload->pk_type,
+ payload->pk_data, payload->pk_len,
+ &ske->prop->public_key)) {
+ SILC_LOG_ERROR(("Unsupported/malformed public key received"));
+ status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
+ goto err;
+ }
+
+ 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_data,
- payload->pk_len,
- payload->pk_type,
- 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 */
}
SilcSKEKEPayload payload;
unsigned char hash[SILC_HASH_MAXLEN];
SilcUInt32 hash_len;
- SilcPublicKey public_key = NULL;
int key_len, block_len;
if (ske->aborted) {
payload = ske->ke2_payload;
- if (payload->pk_data) {
- /* Decode the public key */
- if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
- &public_key)) {
- SILC_LOG_ERROR(("Unsupported/malformed public key received"));
- status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
- goto err;
- }
-
+ if (ske->prop->public_key) {
SILC_LOG_DEBUG(("Public key is authentic"));
/* Compute the hash value */
SILC_LOG_DEBUG(("Verifying signature (HASH)"));
/* Verify signature */
- silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
- if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
- payload->sign_len, hash, hash_len) == FALSE) {
+ if (!silc_pkcs_verify(ske->prop->public_key, payload->sign_data,
+ payload->sign_len, hash, hash_len, NULL)) {
SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
goto err;
SILC_LOG_DEBUG(("Signature is Ok"));
- silc_pkcs_public_key_free(public_key);
memset(hash, 'F', hash_len);
}
silc_free(ske->KEY);
ske->KEY = NULL;
- if (public_key)
- silc_pkcs_public_key_free(public_key);
-
if (ske->hash) {
memset(ske->hash, 'F', hash_len);
silc_free(ske->hash);
/* XXX these shouldn't be allocated before we know the remote's
public key type. It's unnecessary to allocate these because the
select_security_properties has succeeded already. */
- if (silc_pkcs_alloc(ske->start_payload->pkcs_alg_list,
- SILC_PKCS_SILC, &prop->pkcs) == FALSE) {
+ if (!silc_pkcs_find_algorithm(ske->start_payload->pkcs_alg_list, NULL)) {
status = SILC_SKE_STATUS_UNKNOWN_PKCS;
goto err;
}
if (group)
silc_ske_group_free(group);
- if (prop->pkcs)
- silc_pkcs_free(prop->pkcs);
if (prop->cipher)
silc_cipher_free(prop->cipher);
if (prop->hash)
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"));
return SILC_FSM_CONTINUE;
}
- if (recv_payload->pk_data && ske->callbacks->verify_key) {
+ /* Decode the remote's public key */
+ if (recv_payload->pk_data &&
+ !silc_pkcs_public_key_alloc(recv_payload->pk_type,
+ recv_payload->pk_data,
+ recv_payload->pk_len,
+ &ske->prop->public_key)) {
+ /** Error decoding public key */
+ SILC_LOG_ERROR(("Unsupported/malformed public key received"));
+ ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
+ silc_fsm_next(fsm, silc_ske_st_responder_error);
+ return SILC_FSM_CONTINUE;
+ }
+
+ 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_data,
- recv_payload->pk_len,
- recv_payload->pk_type,
- 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 */
}
}
Authentication flag is set. */
if (ske->start_payload &&
ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
- SilcPublicKey public_key = NULL;
unsigned char hash[SILC_HASH_MAXLEN];
SilcUInt32 hash_len;
- /* Decode the public key */
- if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
- recv_payload->pk_len,
- &public_key)) {
- /** Error decoding public key */
- SILC_LOG_ERROR(("Unsupported/malformed public key received"));
- ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
- silc_fsm_next(fsm, silc_ske_st_responder_error);
- return SILC_FSM_CONTINUE;
- }
-
SILC_LOG_DEBUG(("Public key is authentic"));
/* Compute the hash value */
SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
/* Verify signature */
- silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
- if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
- recv_payload->sign_len, hash, hash_len) == FALSE) {
+ if (!silc_pkcs_verify(ske->prop->public_key, recv_payload->sign_data,
+ recv_payload->sign_len, hash, hash_len, NULL)) {
/** Incorrect signature */
SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
SILC_LOG_DEBUG(("Signature is Ok"));
- silc_pkcs_public_key_free(public_key);
memset(hash, 'F', hash_len);
}
SILC_LOG_DEBUG(("Signing HASH value"));
/* Sign the hash value */
- silc_pkcs_private_key_data_set(ske->prop->pkcs, ske->private_key->prv,
- ske->private_key->prv_len);
- if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
- !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
+ if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
+ sizeof(sign) - 1, &sign_len, NULL)) {
/** Error computing signature */
status = SILC_SKE_STATUS_SIGNATURE_ERROR;
silc_fsm_next(fsm, silc_ske_st_responder_error);
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,