X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcclient%2Fprotocol.c;h=da7bc07fb352423627398550db7c670bd609cb86;hb=386c883d8774999c6e74d7c6c37e52e4163a4cb1;hp=5ba28db6e17e507543753da37c5ec0e8539636e6;hpb=0d83f43ff41af4950a7cda27a59fce6f8973311e;p=silc.git diff --git a/lib/silcclient/protocol.c b/lib/silcclient/protocol.c index 5ba28db6..da7bc07f 100644 --- a/lib/silcclient/protocol.c +++ b/lib/silcclient/protocol.c @@ -97,10 +97,10 @@ void silc_client_protocol_ke_verify_key(SilcSKE ske, verify->completion_context = completion_context; /* Verify public key from user. */ - client->ops->verify_public_key(client, ctx->sock->user_data, - ctx->sock->type, - pk_data, pk_len, pk_type, - silc_client_verify_key_cb, verify); + client->internal->ops->verify_public_key(client, ctx->sock->user_data, + ctx->sock->type, + pk_data, pk_len, pk_type, + silc_client_verify_key_cb, verify); } /* Sets the negotiated key material into use for particular connection. */ @@ -112,7 +112,8 @@ void silc_client_protocol_ke_set_keys(SilcSKE ske, SilcPKCS pkcs, SilcHash hash, SilcHmac hmac, - SilcSKEDiffieHellmanGroup group) + SilcSKEDiffieHellmanGroup group, + bool is_responder) { SilcClientConnection conn = (SilcClientConnection)sock->user_data; @@ -121,34 +122,43 @@ void silc_client_protocol_ke_set_keys(SilcSKE ske, /* Allocate cipher to be used in the communication */ silc_cipher_alloc(cipher->cipher->name, &conn->send_key); silc_cipher_alloc(cipher->cipher->name, &conn->receive_key); - - conn->send_key->cipher->set_key(conn->send_key->context, - keymat->send_enc_key, - keymat->enc_key_len); - conn->send_key->set_iv(conn->send_key, keymat->send_iv); - conn->receive_key->cipher->set_key(conn->receive_key->context, - keymat->receive_enc_key, - keymat->enc_key_len); - conn->receive_key->set_iv(conn->receive_key, keymat->receive_iv); + silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL, &conn->hmac_send); + silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL, &conn->hmac_receive); + + if (is_responder == TRUE) { + silc_cipher_set_key(conn->send_key, keymat->receive_enc_key, + keymat->enc_key_len); + silc_cipher_set_iv(conn->send_key, keymat->receive_iv); + silc_cipher_set_key(conn->receive_key, keymat->send_enc_key, + keymat->enc_key_len); + silc_cipher_set_iv(conn->receive_key, keymat->send_iv); + silc_hmac_set_key(conn->hmac_send, keymat->receive_hmac_key, + keymat->hmac_key_len); + silc_hmac_set_key(conn->hmac_receive, keymat->send_hmac_key, + keymat->hmac_key_len); + } else { + silc_cipher_set_key(conn->send_key, keymat->send_enc_key, + keymat->enc_key_len); + silc_cipher_set_iv(conn->send_key, keymat->send_iv); + silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key, + keymat->enc_key_len); + silc_cipher_set_iv(conn->receive_key, keymat->receive_iv); + silc_hmac_set_key(conn->hmac_send, keymat->send_hmac_key, + keymat->hmac_key_len); + silc_hmac_set_key(conn->hmac_receive, keymat->receive_hmac_key, + keymat->hmac_key_len); + } /* Rekey stuff */ conn->rekey = silc_calloc(1, sizeof(*conn->rekey)); - conn->rekey->send_enc_key = - silc_calloc(keymat->enc_key_len / 8, - sizeof(*conn->rekey->send_enc_key)); - memcpy(conn->rekey->send_enc_key, - keymat->send_enc_key, keymat->enc_key_len / 8); + conn->rekey->send_enc_key = silc_memdup(keymat->send_enc_key, + keymat->enc_key_len / 8); conn->rekey->enc_key_len = keymat->enc_key_len / 8; if (ske->start_payload->flags & SILC_SKE_SP_FLAG_PFS) conn->rekey->pfs = TRUE; conn->rekey->ske_group = silc_ske_group_get_number(group); - /* Save HMAC key to be used in the communication. */ - silc_hmac_alloc(hmac->hmac->name, NULL, &conn->hmac_send); - silc_hmac_set_key(conn->hmac_send, keymat->hmac_key, keymat->hmac_key_len); - conn->hmac_receive = conn->hmac_send; - /* Save the HASH function */ silc_hash_alloc(hash->hash->name, &conn->hash); } @@ -184,7 +194,7 @@ SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version, if (cp) build = atoi(cp + 1); - cp = client->silc_client_version + 9; + cp = client->internal->silc_client_version + 9; if (!cp) status = SILC_SKE_STATUS_BAD_VERSION; @@ -200,12 +210,15 @@ SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version, if (maj != maj2) status = SILC_SKE_STATUS_BAD_VERSION; - if (min < min2) - status = SILC_SKE_STATUS_BAD_VERSION; + + /* XXX backward support for 0.6.1 */ + if (maj == 0 && min == 6 && build < 2) + ske->backward_version = 1; if (status != SILC_SKE_STATUS_OK) - client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, - "We don't support server version `%s'", version); + client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, + "We don't support server version `%s'", + version); return status; } @@ -229,20 +242,9 @@ static void silc_client_protocol_ke_continue(SilcSKE ske, SILC_LOG_DEBUG(("Start")); if (ske->status != SILC_SKE_STATUS_OK) { - if (ske->status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) { - client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, - "Received unsupported server %s public key", - ctx->sock->hostname); - } else if (ske->status == SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED) { - client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, - "Remote host did not send its public key, even though " - "it must send it"); - } else { - client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR, - "Error during key exchange protocol with server %s", - ctx->sock->hostname); - } - + /* Call failure client operation */ + client->internal->ops->failure(client, conn, protocol, + (void *)ske->status); protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute(protocol, client->schedule, 0, 0); return; @@ -294,10 +296,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange) SilcSKE ske; /* Allocate Key Exchange object */ - ske = silc_ske_alloc(); - ctx->ske = ske; - ske->rng = client->rng; - ske->user_data = (void *)client; + ctx->ske = ske = silc_ske_alloc(client->rng, client); silc_ske_set_callbacks(ske, ctx->send_packet, NULL, ctx->verify, @@ -308,16 +307,18 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange) if (ctx->responder == TRUE) { /* Start the key exchange by processing the received security properties packet from initiator. */ - status = silc_ske_responder_start(ske, ctx->rng, ctx->sock, - client->silc_client_version, - ctx->packet->buffer, TRUE); + status = + silc_ske_responder_start(ske, ctx->rng, ctx->sock, + client->internal->silc_client_version, + ctx->packet->buffer, TRUE); } else { SilcSKEStartPayload *start_payload; /* Assemble security properties. */ - silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE, - client->silc_client_version, - &start_payload); + silc_ske_assemble_security_properties( + ske, SILC_SKE_SP_FLAG_MUTUAL, + client->internal->silc_client_version, + &start_payload); /* Start the key exchange by sending our security properties to the remote end. */ @@ -353,9 +354,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange) */ if (ctx->responder == TRUE) { /* Sends the selected security properties to the initiator. */ - status = - silc_ske_responder_phase_1(ctx->ske, - ctx->ske->start_payload); + status = silc_ske_responder_phase_1(ctx->ske); } else { /* Call Phase-1 function. This processes the Key Exchange Start paylaod reply we just got from the responder. The callback @@ -398,7 +397,8 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange) Key Exhange 1 Payload to the responder. */ status = silc_ske_initiator_phase_2(ctx->ske, client->public_key, - client->private_key); + client->private_key, + SILC_SKE_PK_TYPE_SILC); protocol->state++; } @@ -446,11 +446,13 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange) if (status != SILC_SKE_STATUS_OK) { if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) { - client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, - "Received unsupported server %s public key", - ctx->sock->hostname); + client->internal->ops->say( + client, conn, SILC_CLIENT_MESSAGE_AUDIT, + "Received unsupported server %s public key", + ctx->sock->hostname); } else { - client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, + client->internal->ops->say( + client, conn, SILC_CLIENT_MESSAGE_AUDIT, "Error during key exchange protocol with server %s", ctx->sock->hostname); } @@ -544,7 +546,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange) static int silc_client_get_public_key_auth(SilcClient client, - char *filepath, + SilcClientConnection conn, unsigned char *auth_data, uint32 *auth_data_len, SilcSKE ske) @@ -552,18 +554,9 @@ silc_client_get_public_key_auth(SilcClient client, int len; SilcPKCS pkcs; SilcBuffer auth; - SilcPublicKey pub_key; - if (!silc_pkcs_load_public_key(filepath,&pub_key, SILC_PKCS_FILE_PEM)) - if (!silc_pkcs_load_public_key(filepath, &pub_key, SILC_PKCS_FILE_BIN)) - return FALSE; - - silc_pkcs_alloc(pub_key->name, &pkcs); - if (!silc_pkcs_public_key_set(pkcs, pub_key)) { - silc_pkcs_free(pkcs); - silc_pkcs_public_key_free(pub_key); - return FALSE; - } + /* Use our default key */ + pkcs = client->pkcs; /* Make the authentication data. Protocol says it is HASH plus KE Start Payload. */ @@ -576,16 +569,13 @@ silc_client_get_public_key_auth(SilcClient client, ske->start_payload_copy->len), SILC_STR_END); - if (silc_pkcs_sign(pkcs, auth->data, auth->len, auth_data, auth_data_len)) { - silc_pkcs_free(pkcs); + if (silc_pkcs_sign_with_hash(pkcs, ske->prop->hash, auth->data, + auth->len, auth_data, auth_data_len)) { silc_buffer_free(auth); - silc_pkcs_public_key_free(pub_key); return TRUE; } - silc_pkcs_free(pkcs); silc_buffer_free(auth); - silc_pkcs_public_key_free(pub_key); return FALSE; } @@ -619,11 +609,6 @@ silc_client_conn_auth_continue(unsigned char *auth_data, SILC_PACKET_CONNECTION_AUTH, NULL, 0, NULL, NULL, packet->data, packet->len, TRUE); - - if (auth_data) { - memset(auth_data, 0, auth_data_len); - silc_free(auth_data); - } silc_buffer_free(packet); /* Next state is end of protocol */ @@ -652,6 +637,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_connection_auth) */ unsigned char *auth_data = NULL; uint32 auth_data_len = 0; + unsigned char sign[1024]; switch(ctx->auth_meth) { case SILC_AUTH_NONE: @@ -666,27 +652,28 @@ SILC_TASK_CALLBACK(silc_client_protocol_connection_auth) break; } - client->ops->say(client, conn, SILC_CLIENT_MESSAGE_INFO, - "Password authentication required by server %s", - ctx->sock->hostname); - client->ops->ask_passphrase(client, conn, - silc_client_conn_auth_continue, - protocol); + client->internal->ops->say( + client, conn, SILC_CLIENT_MESSAGE_INFO, + "Password authentication required by server %s", + ctx->sock->hostname); + client->internal->ops->ask_passphrase(client, conn, + silc_client_conn_auth_continue, + protocol); return; break; case SILC_AUTH_PUBLIC_KEY: - { - unsigned char sign[1024]; - + if (!ctx->auth_data) { /* Public key authentication */ - silc_client_get_public_key_auth(client, ctx->auth_data, - sign, &auth_data_len, + silc_client_get_public_key_auth(client, conn, sign, &auth_data_len, ctx->ske); - auth_data = silc_calloc(auth_data_len, sizeof(*auth_data)); - memcpy(auth_data, sign, auth_data_len); - break; + auth_data = sign; + } else { + auth_data = ctx->auth_data; + auth_data_len = ctx->auth_data_len; } + + break; } silc_client_conn_auth_continue(auth_data, @@ -766,41 +753,37 @@ silc_client_protocol_rekey_validate(SilcClient client, silc_cipher_set_key(conn->send_key, keymat->receive_enc_key, keymat->enc_key_len); silc_cipher_set_iv(conn->send_key, keymat->receive_iv); + silc_hmac_set_key(conn->hmac_send, keymat->receive_hmac_key, + keymat->hmac_key_len); } else { silc_cipher_set_key(conn->receive_key, keymat->send_enc_key, keymat->enc_key_len); silc_cipher_set_iv(conn->receive_key, keymat->send_iv); + silc_hmac_set_key(conn->hmac_receive, keymat->send_hmac_key, + keymat->hmac_key_len); } } else { if (send) { silc_cipher_set_key(conn->send_key, keymat->send_enc_key, keymat->enc_key_len); silc_cipher_set_iv(conn->send_key, keymat->send_iv); + silc_hmac_set_key(conn->hmac_send, keymat->send_hmac_key, + keymat->hmac_key_len); } else { silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key, keymat->enc_key_len); silc_cipher_set_iv(conn->receive_key, keymat->receive_iv); + silc_hmac_set_key(conn->hmac_receive, keymat->receive_hmac_key, + keymat->hmac_key_len); } } - if (send) { - silc_hmac_alloc(conn->hmac_receive->hmac->name, NULL, &conn->hmac_send); - silc_hmac_set_key(conn->hmac_send, keymat->hmac_key, - keymat->hmac_key_len); - } else { - silc_hmac_free(conn->hmac_receive); - conn->hmac_receive = conn->hmac_send; - } - /* Save the current sending encryption key */ if (!send) { memset(conn->rekey->send_enc_key, 0, conn->rekey->enc_key_len); silc_free(conn->rekey->send_enc_key); - conn->rekey->send_enc_key = - silc_calloc(keymat->enc_key_len / 8, - sizeof(*conn->rekey->send_enc_key)); - memcpy(conn->rekey->send_enc_key, keymat->send_enc_key, - keymat->enc_key_len / 8); + conn->rekey->send_enc_key = silc_memdup(keymat->send_enc_key, + keymat->enc_key_len / 8); conn->rekey->enc_key_len = keymat->enc_key_len / 8; } } @@ -929,10 +912,9 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey) silc_protocol_execute(protocol, client->schedule, 0, 300000); } - ctx->ske = silc_ske_alloc(); - ctx->ske->rng = client->rng; + ctx->ske = silc_ske_alloc(client->rng, client); ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop)); - silc_ske_get_group_by_number(conn->rekey->ske_group, + silc_ske_group_get_by_number(conn->rekey->ske_group, &ctx->ske->prop->group); silc_ske_set_callbacks(ctx->ske, @@ -986,10 +968,9 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey) * Use Perfect Forward Secrecy, ie. negotiate the key material * using the SKE protocol. */ - ctx->ske = silc_ske_alloc(); - ctx->ske->rng = client->rng; + ctx->ske = silc_ske_alloc(client->rng, client); ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop)); - silc_ske_get_group_by_number(conn->rekey->ske_group, + silc_ske_group_get_by_number(conn->rekey->ske_group, &ctx->ske->prop->group); silc_ske_set_callbacks(ctx->ske, @@ -997,7 +978,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey) NULL, NULL, NULL, silc_ske_check_version, context); - status = silc_ske_initiator_phase_2(ctx->ske, NULL, NULL); + status = silc_ske_initiator_phase_2(ctx->ske, NULL, NULL, 0); if (status != SILC_SKE_STATUS_OK) { SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)", status));