Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2000 - 2007 Pekka Riikonen
+ Copyright (C) 2000 - 2008 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
/* Sign the hash value */
SILC_FSM_CALL(ske->key_op =
- silc_pkcs_sign(ske->private_key, hash, hash_len, FALSE,
- ske->prop->hash, ske->rng,
- silc_ske_initiator_sign_cb, ske));
+ silc_pkcs_sign_async(ske->private_key, hash, hash_len, FALSE,
+ ske->prop->hash, ske->rng,
+ silc_ske_initiator_sign_cb, ske));
/* NOT REACHED */
}
/* Verify signature */
SILC_FSM_CALL(ske->key_op =
- silc_pkcs_verify(ske->prop->public_key, payload->sign_data,
- payload->sign_len, hash, hash_len, NULL,
- ske->rng, silc_ske_verify_cb, ske));
+ silc_pkcs_verify_async(ske->prop->public_key,
+ payload->sign_data,
+ payload->sign_len, hash,
+ hash_len, FALSE, NULL,
+ silc_ske_verify_cb, ske));
/* NOT REACHED */
}
-
- return SILC_FSM_CONTINUE;
-
err:
memset(hash, 'F', sizeof(hash));
silc_ske_payload_ke_free(payload);
SilcSKE ske = fsm_context;
SilcUInt32 error = SILC_SKE_STATUS_ERROR;
- if (ske->packet && silc_buffer_len(&ske->packet->buffer) == 4) {
+ if (ske->packet && ske->packet->type == SILC_PACKET_FAILURE &&
+ silc_buffer_len(&ske->packet->buffer) == 4) {
SILC_GET32_MSB(error, ske->packet->buffer.data);
ske->status = error;
silc_packet_free(ske->packet);
silc_packet_free(ske->packet);
ske->packet = NULL;
- /* Verify the received public key and verify the signature if we are
- doing mutual authentication. */
- if (ske->start_payload &&
- ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
-
- SILC_LOG_DEBUG(("We are doing mutual authentication"));
-
- if (!recv_payload->pk_data && (ske->callbacks->verify_key ||
- ske->repository)) {
+ /* Verify public key, except in rekey, when it is not sent */
+ if (!ske->rekey) {
+ if (!recv_payload->pk_data) {
/** Public key not provided */
SILC_LOG_ERROR(("Remote end did not send its public key (or "
"certificate), even though we require it"));
}
/* Decode the remote's public key */
- if (recv_payload->pk_data &&
- !silc_pkcs_public_key_alloc(recv_payload->pk_type,
+ if (!silc_pkcs_public_key_alloc(recv_payload->pk_type,
recv_payload->pk_data,
recv_payload->pk_len,
&ske->prop->public_key)) {
return SILC_FSM_CONTINUE;
}
- if (ske->prop->public_key && (ske->callbacks->verify_key ||
- ske->repository)) {
- SILC_LOG_DEBUG(("Verifying public key"));
+ SILC_LOG_DEBUG(("Verifying public key"));
- /** Waiting public key verification */
- silc_fsm_next(fsm, silc_ske_st_responder_phase4);
+ /** Waiting public key verification */
+ silc_fsm_next(fsm, silc_ske_st_responder_phase4);
- /* If repository is provided, verify the key from there. */
- if (ske->repository) {
- SilcSKRFind find;
+ /* 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);
- silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT);
-
- /* Find key from repository */
- SILC_FSM_CALL(silc_skr_find(ske->repository,
- silc_fsm_get_schedule(fsm), find,
- silc_ske_skr_callback, ske));
- } else {
- /* Verify from application */
+ 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);
+ silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT);
+
+ /* Find key from repository */
+ SILC_FSM_CALL(silc_skr_find(ske->repository,
+ silc_fsm_get_schedule(fsm), find,
+ silc_ske_skr_callback, ske));
+ } else {
+ /* Verify from application */
+ if (ske->callbacks->verify_key)
SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key,
ske->callbacks->context,
silc_ske_pk_verified, NULL));
- }
- /* NOT REACHED */
}
}
unsigned char hash[SILC_HASH_MAXLEN];
SilcUInt32 hash_len;
- SILC_LOG_DEBUG(("Public key is authentic"));
+ SILC_LOG_DEBUG(("We are doing mutual authentication"));
/* Compute the hash value */
status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
/* Verify signature */
SILC_FSM_CALL(ske->key_op =
- silc_pkcs_verify(ske->prop->public_key,
- recv_payload->sign_data,
- recv_payload->sign_len,
- hash, hash_len, NULL, ske->rng,
- silc_ske_verify_cb, ske));
+ silc_pkcs_verify_async(ske->prop->public_key,
+ recv_payload->sign_data,
+ recv_payload->sign_len,
+ hash, hash_len, FALSE, NULL,
+ silc_ske_verify_cb, ske));
/* NOT REACHED */
}
/* Sign the hash value */
SILC_FSM_CALL(ske->key_op =
- silc_pkcs_sign(ske->private_key, hash, hash_len, FALSE,
- ske->prop->hash, ske->rng,
- silc_ske_responder_sign_cb, ske));
+ silc_pkcs_sign_async(ske->private_key, hash, hash_len, FALSE,
+ ske->prop->hash, ske->rng,
+ silc_ske_responder_sign_cb, ske));
/* NOT REACHED */
}
SILC_LOG_DEBUG(("Key exchange protocol failed"));
- if (ske->packet && silc_buffer_len(&ske->packet->buffer) == 4) {
+ if (ske->packet && ske->packet->type == SILC_PACKET_FAILURE &&
+ silc_buffer_len(&ske->packet->buffer) == 4) {
SILC_GET32_MSB(error, ske->packet->buffer.data);
ske->status = error;
silc_packet_free(ske->packet);
SilcHmac *ret_hmac_receive,
SilcHash *ret_hash)
{
- unsigned char iv[32];
+ unsigned char iv[SILC_HASH_MAXLEN];
SilcBool iv_included = (prop->flags & SILC_SKE_SP_FLAG_IV_INCLUDED);
/* Allocate ciphers to be used in the communication */
return FALSE;
}
+ /* Allocate hash */
+ if (ret_hash) {
+ if (!silc_hash_alloc(silc_hash_get_name(prop->hash), ret_hash))
+ return FALSE;
+ }
+
/* Set key material */
memset(iv, 0, sizeof(iv));
if (ske->responder) {
keymat->enc_key_len, TRUE);
if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) {
- memcpy(iv, ske->hash, 4);
- memcpy(iv + 4, keymat->receive_iv, iv_included ? 4 : 8);
+ /* Counter mode */
+ if (!ske->rekeying) {
+ /* Set IV. */
+ memcpy(iv, ske->hash, 4);
+ if (!iv_included)
+ memcpy(iv + 4, keymat->receive_iv, 8);
+ } else {
+ /* Rekey, recompute the truncated hash value. */
+ silc_hash_make(prop->hash, keymat->receive_iv, 8, iv);
+ if (!iv_included)
+ memcpy(iv + 4, keymat->receive_iv, 8);
+ else
+ memset(iv + 4, 0, 12);
+ }
+
silc_cipher_set_iv(*ret_send_key, iv);
} else {
+ /* Other modes */
silc_cipher_set_iv(*ret_send_key, keymat->receive_iv);
}
}
keymat->enc_key_len, FALSE);
if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) {
- memcpy(iv, ske->hash, 4);
- memcpy(iv + 4, keymat->send_iv, iv_included ? 4 : 8);
+ /* Counter mode */
+ if (!ske->rekeying) {
+ /* Set IV. */
+ memcpy(iv, ske->hash, 4);
+ if (!iv_included)
+ memcpy(iv + 4, keymat->send_iv, 8);
+ } else {
+ /* Rekey, recompute the truncated hash value. */
+ silc_hash_make(prop->hash, keymat->send_iv, 8, iv);
+ if (!iv_included)
+ memcpy(iv + 4, keymat->send_iv, 8);
+ else
+ memset(iv + 4, 0, 12);
+ }
+
silc_cipher_set_iv(*ret_receive_key, iv);
} else {
+ /* Other modes */
silc_cipher_set_iv(*ret_receive_key, keymat->send_iv);
}
}
keymat->enc_key_len, TRUE);
if (silc_cipher_get_mode(*ret_send_key) == SILC_CIPHER_MODE_CTR) {
- memcpy(iv, ske->hash, 4);
- memcpy(iv + 4, keymat->send_iv, iv_included ? 4 : 8);
+ /* Counter mode */
+ if (!ske->rekeying) {
+ /* Set IV. */
+ memcpy(iv, ske->hash, 4);
+ if (!iv_included)
+ memcpy(iv + 4, keymat->send_iv, 8);
+ } else {
+ /* Rekey, recompute the truncated hash value. */
+ silc_hash_make(prop->hash, keymat->send_iv, 8, iv);
+ if (!iv_included)
+ memcpy(iv + 4, keymat->send_iv, 8);
+ else
+ memset(iv + 4, 0, 12);
+ }
+
silc_cipher_set_iv(*ret_send_key, iv);
} else {
+ /* Other modes */
silc_cipher_set_iv(*ret_send_key, keymat->send_iv);
}
}
keymat->enc_key_len, FALSE);
if (silc_cipher_get_mode(*ret_receive_key) == SILC_CIPHER_MODE_CTR) {
- memcpy(iv, ske->hash, 4);
- memcpy(iv + 4, keymat->receive_iv, iv_included ? 4 : 8);
+ /* Counter mode */
+ if (!ske->rekeying) {
+ /* Set IV. If IV Included flag was negotiated we only set the
+ truncated hash value. */
+ memcpy(iv, ske->hash, 4);
+ if (!iv_included)
+ memcpy(iv + 4, keymat->receive_iv, 8);
+ } else {
+ /* Rekey, recompute the truncated hash value. */
+ silc_hash_make(prop->hash, keymat->receive_iv, 8, iv);
+ if (!iv_included)
+ memcpy(iv + 4, keymat->receive_iv, 8);
+ else
+ memset(iv + 4, 0, 12);
+ }
+
silc_cipher_set_iv(*ret_receive_key, iv);
} else {
+ /* Other modes */
silc_cipher_set_iv(*ret_receive_key, keymat->receive_iv);
}
}
keymat->hmac_key_len);
}
- /* Allocate hash */
- if (ret_hash) {
- if (!silc_hash_alloc(silc_hash_get_name(prop->hash), ret_hash))
- return FALSE;
- }
-
return TRUE;
}