From: Pekka Riikonen Date: Sun, 8 Jul 2007 17:28:02 +0000 (+0000) Subject: Changed PKCS API asynchronous. X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=2f5e32c640b3b17fc27ddfcc8e9e3de6ee3b6765 Changed PKCS API asynchronous. --- diff --git a/lib/silcske/silcconnauth.c b/lib/silcske/silcconnauth.c index c3799a81..3d50902d 100644 --- a/lib/silcske/silcconnauth.c +++ b/lib/silcske/silcconnauth.c @@ -22,6 +22,16 @@ /************************** Types and definitions ***************************/ +SILC_FSM_STATE(silc_connauth_st_initiator_start); +SILC_FSM_STATE(silc_connauth_st_initiator_auth_send); +SILC_FSM_STATE(silc_connauth_st_initiator_result); +SILC_FSM_STATE(silc_connauth_st_initiator_failure); +SILC_FSM_STATE(silc_connauth_st_responder_start); +SILC_FSM_STATE(silc_connauth_st_responder_authenticate); +SILC_FSM_STATE(silc_connauth_st_responder_authenticate_pk); +SILC_FSM_STATE(silc_connauth_st_responder_success); +SILC_FSM_STATE(silc_connauth_st_responder_failure); + static SilcBool silc_connauth_packet_receive(SilcPacketEngine engine, SilcPacketStream stream, SilcPacket packet, @@ -33,6 +43,7 @@ struct SilcConnAuthStruct { SilcSKE ske; SilcFSM fsm; SilcAsyncOperationStruct op; + SilcAsyncOperation key_op; SilcConnectionType conn_type; SilcAuthMethod auth_method; void *auth_data; @@ -76,19 +87,44 @@ static SilcBool silc_connauth_packet_receive(SilcPacketEngine engine, static void silc_connauth_abort(SilcAsyncOperation op, void *context) { SilcConnAuth connauth = context; + if (connauth->key_op) + silc_async_abort(connauth->key_op, NULL, NULL); connauth->aborted = TRUE; } +/* Signature callback */ + +static void silc_connauth_get_signature_cb(SilcBool success, + const unsigned char *signature, + SilcUInt32 signature_len, + void *context) +{ + SilcConnAuth connauth = context; + + connauth->key_op = NULL; + + if (!success) { + silc_fsm_next(connauth->fsm, silc_connauth_st_initiator_failure); + SILC_FSM_CALL_CONTINUE(connauth->fsm); + return; + } + + connauth->auth_data = silc_memdup(signature, signature_len); + connauth->auth_data_len = signature_len; + + SILC_FSM_CALL_CONTINUE(connauth->fsm); +} + /* Generates signature for public key based authentication */ -static SilcBool silc_connauth_get_signature(SilcConnAuth connauth, - unsigned char **auth_data, - SilcUInt32 *auth_data_len) +static SilcAsyncOperation +silc_connauth_get_signature(SilcConnAuth connauth) { - int len; + SilcAsyncOperation op; SilcSKE ske; SilcPrivateKey private_key; SilcBuffer auth; + int len; SILC_LOG_DEBUG(("Compute signature")); @@ -99,54 +135,72 @@ static SilcBool silc_connauth_get_signature(SilcConnAuth connauth, KE Start Payload. */ len = ske->hash_len + silc_buffer_len(ske->start_payload_copy); auth = silc_buffer_alloc_size(len); - if (!auth) - return FALSE; + if (!auth) { + silc_connauth_get_signature_cb(FALSE, NULL, 0, connauth); + return NULL; + } silc_buffer_format(auth, - SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len), - SILC_STR_UI_XNSTRING( - ske->start_payload_copy->data, - silc_buffer_len(ske->start_payload_copy)), + SILC_STR_DATA(ske->hash, ske->hash_len), + SILC_STR_DATA(ske->start_payload_copy->data, + silc_buffer_len(ske->start_payload_copy)), SILC_STR_END); - len = ((silc_pkcs_private_key_get_len(private_key) + 7) / 8) + 1; - *auth_data = silc_calloc(len, sizeof(**auth_data)); - if (*auth_data == NULL) { - silc_buffer_free(auth); - return FALSE; - } - /* Compute signature */ - if (!silc_pkcs_sign(private_key, auth->data, silc_buffer_len(auth), - *auth_data, len, auth_data_len, TRUE, ske->prop->hash)) { - silc_free(*auth_data); - silc_buffer_free(auth); - return FALSE; - } + op = silc_pkcs_sign(private_key, auth->data, silc_buffer_len(auth), + TRUE, ske->prop->hash, + silc_connauth_get_signature_cb, connauth); silc_buffer_free(auth); - return TRUE; + + return op; +} + +/* Verify callback */ + +static void silc_connauth_verify_signature_cb(SilcBool success, + void *context) +{ + SilcConnAuth connauth = context; + + connauth->key_op = NULL; + silc_free(connauth->auth_data); + + if (!success) { + SILC_LOG_DEBUG(("Invalid signature")); + silc_fsm_next(connauth->fsm, silc_connauth_st_responder_failure); + SILC_FSM_CALL_CONTINUE(connauth->fsm); + return; + } + + SILC_FSM_CALL_CONTINUE(connauth->fsm); } /* Verifies digital signature */ -static SilcBool silc_connauth_verify_signature(SilcConnAuth connauth, - SilcPublicKey pub_key, - unsigned char *sign, - SilcUInt32 sign_len) +static SilcAsyncOperation +silc_connauth_verify_signature(SilcConnAuth connauth, + SilcPublicKey pub_key, + unsigned char *sign, + SilcUInt32 sign_len) { - int len; + SilcAsyncOperation op; SilcBuffer auth; SilcSKE ske = connauth->ske; + int len; - if (!pub_key || !sign) - return FALSE; + if (!pub_key || !sign) { + silc_connauth_verify_signature_cb(FALSE, connauth); + return NULL; + } /* Make the authentication data. Protocol says it is HASH plus KE Start Payload. */ len = ske->hash_len + silc_buffer_len(ske->start_payload_copy); auth = silc_buffer_alloc_size(len); - if (!auth) - return FALSE; + if (!auth) { + silc_connauth_verify_signature_cb(FALSE, connauth); + return NULL; + } silc_buffer_format(auth, SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len), SILC_STR_UI_XNSTRING( @@ -155,15 +209,13 @@ static SilcBool silc_connauth_verify_signature(SilcConnAuth connauth, SILC_STR_END); /* Verify signature */ - if (!silc_pkcs_verify(pub_key, sign, sign_len, auth->data, - silc_buffer_len(auth), ske->prop->hash)) { - silc_buffer_free(auth); - return FALSE; - } + op = silc_pkcs_verify(pub_key, sign, sign_len, auth->data, + silc_buffer_len(auth), ske->prop->hash, + silc_connauth_verify_signature_cb, connauth); silc_buffer_free(auth); - return TRUE; + return op; } /* Timeout */ @@ -172,6 +224,8 @@ SILC_TASK_CALLBACK(silc_connauth_timeout) { SilcConnAuth connauth = context; SILC_LOG_DEBUG(("Protocol timeout")); + if (connauth->key_op) + silc_async_abort(connauth->key_op, NULL, NULL); connauth->aborted = TRUE; silc_fsm_continue_sync(connauth->fsm); } @@ -255,18 +309,9 @@ SilcSKE silc_connauth_get_ske(SilcConnAuth connauth) /******************************** Initiator *********************************/ -SILC_FSM_STATE(silc_connauth_st_initiator_start); -SILC_FSM_STATE(silc_connauth_st_initiator_result); -SILC_FSM_STATE(silc_connauth_st_initiator_failure); - SILC_FSM_STATE(silc_connauth_st_initiator_start) { SilcConnAuth connauth = fsm_context; - SilcBuffer packet; - int payload_len = 0; - unsigned char *auth_data = NULL; - SilcUInt32 auth_data_len = 0; - SilcPacketFlags flags = 0; SILC_LOG_DEBUG(("Start")); @@ -282,32 +327,45 @@ SILC_FSM_STATE(silc_connauth_st_initiator_start) silc_connauth_timeout, connauth, connauth->timeout_secs, 0); + /** Generate auth data */ + silc_fsm_next(fsm, silc_connauth_st_initiator_auth_send); + + /* Get authentication data */ switch (connauth->auth_method) { case SILC_AUTH_NONE: /* No authentication required */ + connauth->auth_data = NULL; + connauth->auth_data_len = 0; + return SILC_FSM_CONTINUE; break; case SILC_AUTH_PASSWORD: - auth_data = silc_memdup(connauth->auth_data, connauth->auth_data_len); - if (!auth_data) { - /** Out of memory */ - silc_fsm_next(fsm, silc_connauth_st_initiator_failure); - return SILC_FSM_CONTINUE; - } - auth_data_len = connauth->auth_data_len; - flags = SILC_PACKET_FLAG_LONG_PAD; + /* We have authentication data already */ + return SILC_FSM_CONTINUE; break; case SILC_AUTH_PUBLIC_KEY: - if (!silc_connauth_get_signature(connauth, &auth_data, &auth_data_len)) { - /** Error computing signature */ - silc_fsm_next(fsm, silc_connauth_st_initiator_failure); - return SILC_FSM_CONTINUE; - } + /* Compute signature */ + SILC_FSM_CALL(connauth->key_op = silc_connauth_get_signature(connauth)); + /* NOT REACHED */ break; } - payload_len = 4 + auth_data_len; + silc_fsm_next(fsm, silc_connauth_st_initiator_failure); + return SILC_FSM_CONTINUE; +} + +SILC_FSM_STATE(silc_connauth_st_initiator_auth_send) +{ + SilcConnAuth connauth = fsm_context; + SilcBuffer packet; + int payload_len ; + SilcPacketFlags flags = 0; + + if (connauth->auth_method == SILC_AUTH_PASSWORD) + flags |= SILC_PACKET_FLAG_LONG_PAD; + + payload_len = 4 + connauth->auth_data_len; packet = silc_buffer_alloc_size(payload_len); if (!packet) { /** Out of memory */ @@ -318,9 +376,12 @@ SILC_FSM_STATE(silc_connauth_st_initiator_start) silc_buffer_format(packet, SILC_STR_UI_SHORT(payload_len), SILC_STR_UI_SHORT(connauth->conn_type), - SILC_STR_UI_XNSTRING(auth_data, auth_data_len), + SILC_STR_DATA(connauth->auth_data, + connauth->auth_data_len), SILC_STR_END); + silc_free(connauth->auth_data); + /* Send the packet */ if (!silc_packet_send(connauth->ske->stream, SILC_PACKET_CONNECTION_AUTH, flags, packet->data, silc_buffer_len(packet))) { @@ -329,10 +390,6 @@ SILC_FSM_STATE(silc_connauth_st_initiator_start) return SILC_FSM_CONTINUE; } - if (auth_data) { - memset(auth_data, 0, auth_data_len); - silc_free(auth_data); - } silc_buffer_free(packet); /** Wait for responder */ @@ -423,10 +480,14 @@ silc_connauth_initiator(SilcConnAuth connauth, connauth->conn_type = conn_type; connauth->auth_method = auth_method; - connauth->auth_data = auth_data; - connauth->auth_data_len = auth_data_len; connauth->completion = completion; connauth->context = context; + connauth->auth_data = auth_data; + connauth->auth_data_len = auth_data_len; + + if (connauth->auth_method == SILC_AUTH_PASSWORD) + connauth->auth_data = silc_memdup(connauth->auth_data, + connauth->auth_data_len); /* Link to packet stream to get packets */ silc_packet_stream_link(connauth->ske->stream, @@ -444,12 +505,6 @@ silc_connauth_initiator(SilcConnAuth connauth, /******************************** Responder *********************************/ -SILC_FSM_STATE(silc_connauth_st_responder_start); -SILC_FSM_STATE(silc_connauth_st_responder_authenticate); -SILC_FSM_STATE(silc_connauth_st_responder_authenticate_pk); -SILC_FSM_STATE(silc_connauth_st_responder_success); -SILC_FSM_STATE(silc_connauth_st_responder_failure); - SILC_FSM_STATE(silc_connauth_st_responder_start) { SilcConnAuth connauth = fsm_context; @@ -604,7 +659,8 @@ SILC_FSM_STATE(silc_connauth_st_responder_authenticate) /** Find public key */ silc_fsm_next(fsm, silc_connauth_st_responder_authenticate_pk); - SILC_FSM_CALL(silc_skr_find(repository, silc_fsm_get_schedule(fsm), + SILC_FSM_CALL(connauth->key_op = + silc_skr_find(repository, silc_fsm_get_schedule(fsm), find, silc_connauth_skr_callback, connauth)); /* NOT REACHED */ @@ -638,23 +694,14 @@ SILC_FSM_STATE(silc_connauth_st_responder_authenticate_pk) SILC_LOG_DEBUG(("Found %d public keys", silc_dlist_count(connauth->public_keys))); - /* Verify signature */ + /** Verify signature */ key = silc_dlist_get(connauth->public_keys); - if (!silc_connauth_verify_signature(connauth, key->key, - connauth->auth_data, - connauth->auth_data_len)) { - /** Invalid signature */ - SILC_LOG_DEBUG(("Invalid signature")); - silc_free(connauth->auth_data); - silc_fsm_next(fsm, silc_connauth_st_responder_failure); - return SILC_FSM_CONTINUE; - } - - silc_free(connauth->auth_data); - - /** Authentication successful */ silc_fsm_next(fsm, silc_connauth_st_responder_success); - return SILC_FSM_CONTINUE; + SILC_FSM_CALL(connauth->key_op = + silc_connauth_verify_signature(connauth, key->key, + connauth->auth_data, + connauth->auth_data_len)); + /* NOT REACHED */ } SILC_FSM_STATE(silc_connauth_st_responder_success) diff --git a/lib/silcske/silcske.c b/lib/silcske/silcske.c index 4db20986..a447123f 100644 --- a/lib/silcske/silcske.c +++ b/lib/silcske/silcske.c @@ -37,8 +37,10 @@ struct SilcSKECallbacksStruct { SILC_FSM_STATE(silc_ske_st_initiator_start); SILC_FSM_STATE(silc_ske_st_initiator_phase1); SILC_FSM_STATE(silc_ske_st_initiator_phase2); +SILC_FSM_STATE(silc_ske_st_initiator_phase2_send); SILC_FSM_STATE(silc_ske_st_initiator_phase3); SILC_FSM_STATE(silc_ske_st_initiator_phase4); +SILC_FSM_STATE(silc_ske_st_initiator_phase5); SILC_FSM_STATE(silc_ske_st_initiator_end); SILC_FSM_STATE(silc_ske_st_initiator_aborted); SILC_FSM_STATE(silc_ske_st_initiator_error); @@ -48,6 +50,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase1); SILC_FSM_STATE(silc_ske_st_responder_phase2); SILC_FSM_STATE(silc_ske_st_responder_phase4); SILC_FSM_STATE(silc_ske_st_responder_phase5); +SILC_FSM_STATE(silc_ske_st_responder_phase5_send); SILC_FSM_STATE(silc_ske_st_responder_end); SILC_FSM_STATE(silc_ske_st_responder_aborted); SILC_FSM_STATE(silc_ske_st_responder_failure); @@ -136,6 +139,8 @@ static SilcPacketCallbacks silc_ske_stream_cbs = static void silc_ske_abort(SilcAsyncOperation op, void *context) { SilcSKE ske = context; + if (ske->key_op) + silc_async_abort(ske->key_op, NULL, NULL); ske->aborted = TRUE; } @@ -628,7 +633,7 @@ static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n, SilcMPInt *rnd) { SilcSKEStatus status = SILC_SKE_STATUS_OK; - unsigned char *string; + unsigned char string[2048]; SilcUInt32 l; if (!len) @@ -639,8 +644,7 @@ static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n, l = ((len - 1) / 8); /* Get the random number as string */ - string = silc_rng_get_rn_data(ske->rng, l); - if (!string) + if (!silc_rng_get_rn_data(ske->rng, l, string, sizeof(string))) return SILC_SKE_STATUS_OUT_OF_MEMORY; /* Decode the string into a MP integer */ @@ -1000,6 +1004,86 @@ SILC_TASK_CALLBACK(silc_ske_timeout) silc_fsm_continue_sync(&ske->fsm); } +/* Initiator signature callback */ + +static void silc_ske_initiator_sign_cb(SilcBool success, + const unsigned char *signature, + SilcUInt32 signature_len, + void *context) +{ + SilcSKE ske = context; + + ske->key_op = NULL; + + if (ske->aborted) { + silc_fsm_next(&ske->fsm, silc_ske_st_initiator_failure); + SILC_FSM_CALL_CONTINUE(&ske->fsm); + return; + } + + ske->ke1_payload->sign_data = silc_memdup(signature, signature_len); + if (ske->ke1_payload->sign_data) + ske->ke1_payload->sign_len = signature_len; + + SILC_FSM_CALL_CONTINUE(&ske->fsm); +} + +/* Responder signature callback */ + +static void silc_ske_responder_sign_cb(SilcBool success, + const unsigned char *signature, + SilcUInt32 signature_len, + void *context) +{ + SilcSKE ske = context; + + ske->key_op = NULL; + + if (ske->aborted) { + silc_fsm_next(&ske->fsm, silc_ske_st_responder_failure); + SILC_FSM_CALL_CONTINUE(&ske->fsm); + return; + } + + ske->ke2_payload->sign_data = silc_memdup(signature, signature_len); + if (ske->ke2_payload->sign_data) + ske->ke2_payload->sign_len = signature_len; + + SILC_FSM_CALL_CONTINUE(&ske->fsm); +} + +/* Verify callback */ + +static void silc_ske_verify_cb(SilcBool success, void *context) +{ + SilcSKE ske = context; + + ske->key_op = NULL; + + if (ske->aborted) { + if (ske->responder) + silc_fsm_next(&ske->fsm, silc_ske_st_responder_failure); + else + silc_fsm_next(&ske->fsm, silc_ske_st_initiator_failure); + SILC_FSM_CALL_CONTINUE(&ske->fsm); + return; + } + + if (!success) { + SILC_LOG_ERROR(("Signature verification failed, incorrect signature")); + ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE; + if (ske->responder) + silc_fsm_next(&ske->fsm, silc_ske_st_responder_error); + else + silc_fsm_next(&ske->fsm, silc_ske_st_initiator_error); + SILC_FSM_CALL_CONTINUE(&ske->fsm); + return; + } + + SILC_LOG_DEBUG(("Signature is Ok")); + SILC_FSM_CALL_CONTINUE(&ske->fsm); +} + /******************************* Protocol API *******************************/ /* Allocates new SKE object. */ @@ -1337,7 +1421,6 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) { SilcSKE ske = fsm_context; SilcSKEStatus status; - SilcBuffer payload_buf; SilcMPInt *x; SilcSKEKEPayload payload; SilcUInt32 pk_len; @@ -1385,13 +1468,16 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) silc_mp_init(&payload->x); silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x, &ske->prop->group->group); + ske->x = x; /* Get public key */ - payload->pk_data = silc_pkcs_public_key_encode(ske->public_key, &pk_len); + payload->pk_data = silc_pkcs_public_key_encode(NULL, ske->public_key, + &pk_len); if (!payload->pk_data) { /** Error encoding public key */ silc_mp_uninit(x); silc_free(x); + ske->x = NULL; silc_mp_uninit(&payload->x); silc_free(payload); ske->ke1_payload = NULL; @@ -1402,10 +1488,13 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) payload->pk_len = pk_len; payload->pk_type = silc_pkcs_get_type(ske->public_key); + /** Send KE1 packet */ + silc_fsm_next(fsm, silc_ske_st_initiator_phase2_send); + /* Compute signature data if we are doing mutual authentication */ if (ske->private_key && ske->prop->flags & SILC_SKE_SP_FLAG_MUTUAL) { - unsigned char hash[SILC_HASH_MAXLEN], sign[2048 + 1]; - SilcUInt32 hash_len, sign_len; + unsigned char hash[SILC_HASH_MAXLEN]; + SilcUInt32 hash_len; SILC_LOG_DEBUG(("We are doing mutual authentication")); SILC_LOG_DEBUG(("Computing HASH_i value")); @@ -1417,30 +1506,32 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) SILC_LOG_DEBUG(("Signing HASH_i value")); /* Sign the hash value */ - if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign, - sizeof(sign) - 1, &sign_len, FALSE, ske->prop->hash)) { - /** Error computing signature */ - silc_mp_uninit(x); - silc_free(x); - silc_mp_uninit(&payload->x); - silc_free(payload->pk_data); - silc_free(payload); - ske->ke1_payload = NULL; - ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR; - silc_fsm_next(fsm, silc_ske_st_initiator_error); - return SILC_FSM_CONTINUE; - } - payload->sign_data = silc_memdup(sign, sign_len); - if (payload->sign_data) - payload->sign_len = sign_len; - memset(sign, 0, sizeof(sign)); + SILC_FSM_CALL(ske->key_op = + silc_pkcs_sign(ske->private_key, hash, hash_len, FALSE, + ske->prop->hash, + silc_ske_initiator_sign_cb, ske)); + /* NOT REACHED */ } + return SILC_FSM_CONTINUE; +} + +/* Send KE1 packet */ + +SILC_FSM_STATE(silc_ske_st_initiator_phase2_send) +{ + SilcSKE ske = fsm_context; + SilcSKEStatus status; + SilcBuffer payload_buf; + SilcSKEKEPayload payload; + + SILC_LOG_DEBUG(("Start")); + + payload = ske->ke1_payload; + status = silc_ske_payload_ke_encode(ske, payload, &payload_buf); if (status != SILC_SKE_STATUS_OK) { /** Error encoding KE payload */ - silc_mp_uninit(x); - silc_free(x); silc_mp_uninit(&payload->x); silc_free(payload->pk_data); silc_free(payload->sign_data); @@ -1451,10 +1542,6 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase2) return SILC_FSM_CONTINUE; } - ske->x = x; - - /* Check for backwards compatibility */ - /* Send the packet. */ if (!silc_ske_packet_send(ske, SILC_PACKET_KEY_EXCHANGE_1, 0, silc_buffer_data(payload_buf), @@ -1595,7 +1682,6 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase4) SilcSKEKEPayload payload; unsigned char hash[SILC_HASH_MAXLEN]; SilcUInt32 hash_len; - int key_len, block_len; if (ske->aborted) { /** Aborted */ @@ -1621,22 +1707,57 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase4) ske->hash = silc_memdup(hash, hash_len); ske->hash_len = hash_len; + /** Send reply */ + silc_fsm_next(fsm, silc_ske_st_initiator_phase5); + if (ske->prop->public_key) { SILC_LOG_DEBUG(("Public key is authentic")); SILC_LOG_DEBUG(("Verifying signature (HASH)")); /* Verify signature */ - 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_FSM_CALL(ske->key_op = + silc_pkcs_verify(ske->prop->public_key, payload->sign_data, + payload->sign_len, hash, hash_len, NULL, + silc_ske_verify_cb, ske)); + /* NOT REACHED */ + } - SILC_LOG_DEBUG(("Signature is Ok")); - memset(hash, 'F', hash_len); + return SILC_FSM_CONTINUE; + + err: + memset(hash, 'F', sizeof(hash)); + silc_ske_payload_ke_free(payload); + ske->ke2_payload = NULL; + + silc_mp_uninit(ske->KEY); + silc_free(ske->KEY); + ske->KEY = NULL; + + if (ske->hash) { + memset(ske->hash, 'F', hash_len); + silc_free(ske->hash); + ske->hash = NULL; } + if (status == SILC_SKE_STATUS_OK) + status = SILC_SKE_STATUS_ERROR; + + /** Error */ + ske->status = status; + silc_fsm_next(fsm, silc_ske_st_initiator_error); + return SILC_FSM_CONTINUE; +} + +/* Process key material */ + +SILC_FSM_STATE(silc_ske_st_initiator_phase5) +{ + SilcSKE ske = fsm_context; + SilcSKEStatus status; + unsigned char tmp[4]; + SilcUInt32 hash_len; + int key_len, block_len; + ske->status = SILC_SKE_STATUS_OK; /* In case we are doing rekey move to finish it. */ @@ -1656,12 +1777,13 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase4) if (!ske->keymat) { SILC_LOG_ERROR(("Error processing key material")); status = SILC_SKE_STATUS_ERROR; - goto err; + silc_fsm_next(fsm, silc_ske_st_initiator_error); + return SILC_FSM_CONTINUE; } /* Send SUCCESS packet */ - SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, hash); - if (!silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, hash, 4)) { + SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, tmp); + if (!silc_ske_packet_send(ske, SILC_PACKET_SUCCESS, 0, tmp, 4)) { /** Error sending packet */ SILC_LOG_DEBUG(("Error sending packet")); ske->status = SILC_SKE_STATUS_ERROR; @@ -1672,29 +1794,6 @@ SILC_FSM_STATE(silc_ske_st_initiator_phase4) /** Waiting completion */ silc_fsm_next(fsm, silc_ske_st_initiator_end); return SILC_FSM_WAIT; - - err: - memset(hash, 'F', sizeof(hash)); - silc_ske_payload_ke_free(payload); - ske->ke2_payload = NULL; - - silc_mp_uninit(ske->KEY); - silc_free(ske->KEY); - ske->KEY = NULL; - - if (ske->hash) { - memset(ske->hash, 'F', hash_len); - silc_free(ske->hash); - ske->hash = NULL; - } - - if (status == SILC_SKE_STATUS_OK) - status = SILC_SKE_STATUS_ERROR; - - /** Error */ - ske->status = status; - silc_fsm_next(fsm, silc_ske_st_initiator_error); - return SILC_FSM_CONTINUE; } /* Protocol completed */ @@ -2097,14 +2196,13 @@ SILC_FSM_STATE(silc_ske_st_responder_phase2) return SILC_FSM_CONTINUE; } -/* Phase-4. Generate KE2 payload */ +/* Phase-4. Generate KE2 payload, verify signature */ SILC_FSM_STATE(silc_ske_st_responder_phase4) { SilcSKE ske = fsm_context; SilcSKEStatus status; - SilcSKEKEPayload recv_payload, send_payload; - SilcMPInt *x, *KEY; + SilcSKEKEPayload recv_payload; if (ske->aborted) { /** Aborted */ @@ -2122,6 +2220,9 @@ SILC_FSM_STATE(silc_ske_st_responder_phase4) recv_payload = ske->ke1_payload; + /** Send KE2 packet */ + silc_fsm_next(fsm, silc_ske_st_responder_phase5); + /* The public key verification was performed only if the Mutual Authentication flag is set. */ if (ske->start_payload && @@ -2143,19 +2244,30 @@ SILC_FSM_STATE(silc_ske_st_responder_phase4) SILC_LOG_DEBUG(("Verifying signature (HASH_i)")); /* Verify signature */ - 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_fsm_next(fsm, silc_ske_st_responder_error); - return SILC_FSM_CONTINUE; - } + 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, + silc_ske_verify_cb, ske)); + /* NOT REACHED */ + } - SILC_LOG_DEBUG(("Signature is Ok")); + return SILC_FSM_CONTINUE; +} - memset(hash, 'F', hash_len); - } +/* Phase-5. Send KE2 payload */ + +SILC_FSM_STATE(silc_ske_st_responder_phase5) +{ + SilcSKE ske = fsm_context; + SilcSKEStatus status; + unsigned char hash[SILC_HASH_MAXLEN], *pk; + SilcUInt32 hash_len, pk_len; + SilcMPInt *x, *KEY; + SilcSKEKEPayload send_payload; + + SILC_LOG_DEBUG(("Start")); /* Create the random number x, 1 < x < q. */ x = silc_calloc(1, sizeof(*x)); @@ -2194,28 +2306,11 @@ SILC_FSM_STATE(silc_ske_st_responder_phase4) &ske->prop->group->group); ske->KEY = KEY; - /** Send KE2 payload */ - silc_fsm_next(fsm, silc_ske_st_responder_phase5); - return SILC_FSM_CONTINUE; -} - -/* Phase-5. Send KE2 payload */ - -SILC_FSM_STATE(silc_ske_st_responder_phase5) -{ - SilcSKE ske = fsm_context; - SilcSKEStatus status; - SilcBuffer payload_buf; - unsigned char hash[SILC_HASH_MAXLEN], sign[2048 + 1], *pk; - SilcUInt32 hash_len, sign_len, pk_len; - - SILC_LOG_DEBUG(("Start")); - if (ske->public_key && ske->private_key) { SILC_LOG_DEBUG(("Getting public key")); /* Get the public key */ - pk = silc_pkcs_public_key_encode(ske->public_key, &pk_len); + pk = silc_pkcs_public_key_encode(NULL, ske->public_key, &pk_len); if (!pk) { /** Error encoding public key */ status = SILC_SKE_STATUS_OUT_OF_MEMORY; @@ -2240,21 +2335,31 @@ SILC_FSM_STATE(silc_ske_st_responder_phase5) ske->hash = silc_memdup(hash, hash_len); ske->hash_len = hash_len; + /** Send KE2 packet */ + silc_fsm_next(fsm, silc_ske_st_responder_phase5_send); + if (ske->public_key && ske->private_key) { SILC_LOG_DEBUG(("Signing HASH value")); /* Sign the hash value */ - if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign, - sizeof(sign) - 1, &sign_len, FALSE, ske->prop->hash)) { - /** Error computing signature */ - status = SILC_SKE_STATUS_SIGNATURE_ERROR; - silc_fsm_next(fsm, silc_ske_st_responder_error); - return SILC_FSM_CONTINUE; - } - ske->ke2_payload->sign_data = silc_memdup(sign, sign_len); - ske->ke2_payload->sign_len = sign_len; - memset(sign, 0, sizeof(sign)); + SILC_FSM_CALL(ske->key_op = + silc_pkcs_sign(ske->private_key, hash, hash_len, FALSE, + ske->prop->hash, + silc_ske_responder_sign_cb, ske)); + /* NOT REACHED */ } + + return SILC_FSM_CONTINUE; +} + +/* Send KE2 packet */ + +SILC_FSM_STATE(silc_ske_st_responder_phase5_send) +{ + SilcSKE ske = fsm_context; + SilcSKEStatus status; + SilcBuffer payload_buf; + ske->ke2_payload->pk_type = silc_pkcs_get_type(ske->public_key); /* Encode the Key Exchange Payload */ diff --git a/lib/silcske/silcske_i.h b/lib/silcske/silcske_i.h index 05132455..caa491a9 100644 --- a/lib/silcske/silcske_i.h +++ b/lib/silcske/silcske_i.h @@ -75,6 +75,7 @@ struct SilcSKEStruct { SilcSchedule schedule; SilcFSMStruct fsm; SilcAsyncOperationStruct op; + SilcAsyncOperation key_op; SilcUInt16 session_port; /* Packet retransmission */