SilcSKEStatus silc_client_protocol_ke_verify_key(SilcSKE ske,
unsigned char *pk_data,
- unsigned int pk_len,
+ uint32 pk_len,
SilcSKEPKType pk_type,
void *context)
{
SILC_LOG_DEBUG(("Start"));
- /* Verify server key from user. */
- if (!client->ops->verify_server_key(client, ctx->sock->user_data,
+ /* Verify public key from user. */
+ if (!client->ops->verify_public_key(client, ctx->sock->user_data,
+ ctx->sock->type,
pk_data, pk_len, pk_type))
return SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
/* Save HMAC key to be used in the communication. */
silc_hmac_alloc(hmac->hmac->name, NULL, &conn->hmac);
silc_hmac_set_key(conn->hmac, keymat->hmac_key, keymat->hmac_key_len);
+
+ /* Save the HASH function */
+ silc_hash_alloc(hash->hash->name, &conn->hash);
}
/* Checks the version string of the server. */
SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
- unsigned int len)
+ uint32 len)
{
SilcClientConnection conn = (SilcClientConnection)ske->sock->user_data;
SilcClient client = (SilcClient)ske->user_data;
properties packet from initiator. */
status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
silc_version_string,
- ctx->packet->buffer, NULL, NULL);
+ ctx->packet->buffer, TRUE,
+ NULL, NULL);
} else {
SilcSKEStartPayload *start_payload;
the initiator. This also creates our parts of the Diffie
Hellman algorithm. */
status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer,
- NULL, NULL);
+ ctx->verify, context, NULL, NULL);
} else {
/* Call the Phase-2 function. This creates Diffie Hellman
key exchange parameters and sends our public part inside
Key Exhange 1 Payload to the responder. */
- status =
- silc_ske_initiator_phase_2(ctx->ske,
- client->public_key,
- ctx->send_packet,
- context);
+ status = silc_ske_initiator_phase_2(ctx->ske,
+ client->public_key,
+ client->private_key,
+ ctx->send_packet,
+ context);
}
if (status != SILC_SKE_STATUS_OK) {
* Connection Authentication protocol functions
*/
+static int
+silc_client_get_public_key_auth(SilcClient client,
+ char *filepath,
+ unsigned char *auth_data,
+ uint32 *auth_data_len,
+ SilcSKE ske)
+{
+ 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;
+ }
+
+ /* Make the authentication data. Protocol says it is HASH plus
+ KE Start Payload. */
+ len = ske->hash_len + ske->start_payload_copy->len;
+ auth = silc_buffer_alloc(len);
+ silc_buffer_pull_tail(auth, len);
+ silc_buffer_format(auth,
+ SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
+ SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
+ 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);
+ 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;
+}
+
SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
{
SilcProtocol protocol = (SilcProtocol)context;
SilcBuffer packet;
int payload_len = 0;
unsigned char *auth_data = NULL;
- unsigned int auth_data_len = 0;
+ uint32 auth_data_len = 0;
switch(ctx->auth_meth) {
case SILC_AUTH_NONE:
break;
case SILC_AUTH_PUBLIC_KEY:
- /* XXX */
- break;
+ {
+ unsigned char sign[1024];
+
+ /* Public key authentication */
+ silc_client_get_public_key_auth(client, ctx->auth_data,
+ sign, &auth_data_len,
+ ctx->ske);
+ auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
+ memcpy(auth_data, sign, auth_data_len);
+ break;
+ }
}
payload_len = 4 + auth_data_len;