5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
21 * Client side of the protocols.
25 #include "clientlibincludes.h"
26 #include "client_internal.h"
28 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth);
29 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange);
31 extern char *silc_version_string;
34 * Key Exhange protocol functions
37 /* Function that is called when SKE protocol sends packets to network. */
39 void silc_client_protocol_ke_send_packet(SilcSKE ske,
44 SilcProtocol protocol = (SilcProtocol)context;
45 SilcClientKEInternalContext *ctx =
46 (SilcClientKEInternalContext *)protocol->context;
47 SilcClient client = (SilcClient)ctx->client;
49 /* Send the packet immediately */
50 silc_client_packet_send(client, ske->sock, type, NULL, 0, NULL, NULL,
51 packet->data, packet->len, TRUE);
55 /* Callback that is called when we have received KE2 payload from
56 responder. We try to verify the public key now. */
58 SilcSKEStatus silc_client_protocol_ke_verify_key(SilcSKE ske,
59 unsigned char *pk_data,
61 SilcSKEPKType pk_type,
64 SilcProtocol protocol = (SilcProtocol)context;
65 SilcClientKEInternalContext *ctx =
66 (SilcClientKEInternalContext *)protocol->context;
67 SilcClient client = (SilcClient)ctx->client;
69 SILC_LOG_DEBUG(("Start"));
71 /* Verify public key from user. */
72 if (!client->ops->verify_public_key(client, ctx->sock->user_data,
74 pk_data, pk_len, pk_type))
75 return SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
77 return SILC_SKE_STATUS_OK;
80 /* Sets the negotiated key material into use for particular connection. */
82 void silc_client_protocol_ke_set_keys(SilcSKE ske,
83 SilcSocketConnection sock,
84 SilcSKEKeyMaterial *keymat,
90 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
92 SILC_LOG_DEBUG(("Setting new keys into use"));
94 /* Allocate cipher to be used in the communication */
95 silc_cipher_alloc(cipher->cipher->name, &conn->send_key);
96 silc_cipher_alloc(cipher->cipher->name, &conn->receive_key);
98 conn->send_key->cipher->set_key(conn->send_key->context,
100 keymat->enc_key_len);
101 conn->send_key->set_iv(conn->send_key, keymat->send_iv);
102 conn->receive_key->cipher->set_key(conn->receive_key->context,
103 keymat->receive_enc_key,
104 keymat->enc_key_len);
105 conn->receive_key->set_iv(conn->receive_key, keymat->receive_iv);
107 /* Allocate PKCS to be used */
109 /* XXX Do we ever need to allocate PKCS for the connection??
110 If yes, we need to change KE protocol to get the initiators
112 silc_pkcs_alloc(pkcs->pkcs->name, &conn->public_Key);
113 silc_pkcs_set_public_key(conn->public_key, ske->ke2_payload->pk_data,
114 ske->ke2_payload->pk_len);
117 /* Save HMAC key to be used in the communication. */
118 silc_hmac_alloc(hmac->hmac->name, NULL, &conn->hmac);
119 silc_hmac_set_key(conn->hmac, keymat->hmac_key, keymat->hmac_key_len);
121 /* Save the HASH function */
122 silc_hash_alloc(hash->hash->name, &conn->hash);
125 /* Checks the version string of the server. */
127 SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
130 SilcClientConnection conn = (SilcClientConnection)ske->sock->user_data;
131 SilcClient client = (SilcClient)ske->user_data;
132 SilcSKEStatus status = SILC_SKE_STATUS_OK;
134 /* Check for initial version string */
135 if (!strstr(version, "SILC-1.0-"))
136 status = SILC_SKE_STATUS_BAD_VERSION;
138 /* Check software version */
140 if (len < strlen(silc_version_string))
141 status = SILC_SKE_STATUS_BAD_VERSION;
143 /* XXX for now there is no other tests due to the abnormal version
144 string that is used */
146 if (status != SILC_SKE_STATUS_OK)
147 client->ops->say(client, conn,
148 "We don't support server version `%s'", version);
153 /* Performs key exchange protocol. This is used for both initiator
154 and responder key exchange. This may be called recursively. */
156 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
158 SilcProtocol protocol = (SilcProtocol)context;
159 SilcClientKEInternalContext *ctx =
160 (SilcClientKEInternalContext *)protocol->context;
161 SilcClient client = (SilcClient)ctx->client;
162 SilcClientConnection conn = ctx->sock->user_data;
163 SilcSKEStatus status = 0;
165 SILC_LOG_DEBUG(("Start"));
167 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
168 protocol->state = SILC_PROTOCOL_STATE_START;
170 switch(protocol->state) {
171 case SILC_PROTOCOL_STATE_START:
178 /* Allocate Key Exchange object */
179 ske = silc_ske_alloc();
181 ske->rng = client->rng;
182 ske->user_data = (void *)client;
184 if (ctx->responder == TRUE) {
185 /* Start the key exchange by processing the received security
186 properties packet from initiator. */
187 status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
189 ctx->packet->buffer, TRUE,
192 SilcSKEStartPayload *start_payload;
194 /* Assemble security properties. */
195 silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE,
199 /* Start the key exchange by sending our security properties
200 to the remote end. */
201 status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
207 if (status != SILC_SKE_STATUS_OK) {
208 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
210 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
213 protocol->state = SILC_PROTOCOL_STATE_ERROR;
214 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
218 /* Advance protocol state and call the next state if we are responder */
220 if (ctx->responder == TRUE)
221 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
229 if (ctx->responder == TRUE) {
230 /* Sends the selected security properties to the initiator. */
232 silc_ske_responder_phase_1(ctx->ske,
233 ctx->ske->start_payload,
237 /* Call Phase-1 function. This processes the Key Exchange Start
238 paylaod reply we just got from the responder. The callback
239 function will receive the processed payload where we will
241 status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer,
245 if (status != SILC_SKE_STATUS_OK) {
246 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
248 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
251 protocol->state = SILC_PROTOCOL_STATE_ERROR;
252 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
256 /* Advance protocol state and call next state if we are initiator */
258 if (ctx->responder == FALSE)
259 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
267 if (ctx->responder == TRUE) {
268 /* Process the received Key Exchange 1 Payload packet from
269 the initiator. This also creates our parts of the Diffie
270 Hellman algorithm. */
271 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer,
272 ctx->verify, context, NULL, NULL);
274 /* Call the Phase-2 function. This creates Diffie Hellman
275 key exchange parameters and sends our public part inside
276 Key Exhange 1 Payload to the responder. */
277 status = silc_ske_initiator_phase_2(ctx->ske,
284 if (status != SILC_SKE_STATUS_OK) {
285 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
287 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
290 protocol->state = SILC_PROTOCOL_STATE_ERROR;
291 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
295 /* Advance protocol state and call the next state if we are responder */
297 if (ctx->responder == TRUE)
298 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
306 if (ctx->responder == TRUE) {
307 /* This creates the key exchange material and sends our
308 public parts to the initiator inside Key Exchange 2 Payload. */
310 silc_ske_responder_finish(ctx->ske,
311 client->public_key, client->private_key,
312 SILC_SKE_PK_TYPE_SILC,
317 /* Finish the protocol. This verifies the Key Exchange 2 payload
318 sent by responder. */
319 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
320 ctx->verify, context, NULL, NULL);
323 if (status != SILC_SKE_STATUS_OK) {
325 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
326 client->ops->say(client, conn,
327 "Received unsupported server %s public key",
328 ctx->sock->hostname);
330 client->ops->say(client, conn,
331 "Error during key exchange protocol with server %s",
332 ctx->sock->hostname);
334 protocol->state = SILC_PROTOCOL_STATE_ERROR;
335 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
339 /* Send Ok to the other end. We will end the protocol as server
340 sends Ok to us when we will take the new keys into use. */
341 if (ctx->responder == FALSE)
342 silc_ske_end(ctx->ske, ctx->send_packet, context);
344 /* End the protocol on the next round */
345 protocol->state = SILC_PROTOCOL_STATE_END;
349 case SILC_PROTOCOL_STATE_END:
354 SilcSKEKeyMaterial *keymat;
355 int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher);
356 int hash_len = ctx->ske->prop->hash->hash->hash_len;
358 /* Process the key material */
359 keymat = silc_calloc(1, sizeof(*keymat));
360 status = silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
362 if (status != SILC_SKE_STATUS_OK) {
363 protocol->state = SILC_PROTOCOL_STATE_ERROR;
364 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 300000);
365 silc_ske_free_key_material(keymat);
368 ctx->keymat = keymat;
370 /* Send Ok to the other end if we are responder. If we are initiator
371 we have sent this already. */
372 if (ctx->responder == TRUE)
373 silc_ske_end(ctx->ske, ctx->send_packet, context);
375 /* Unregister the timeout task since the protocol has ended.
376 This was the timeout task to be executed if the protocol is
377 not completed fast enough. */
378 if (ctx->timeout_task)
379 silc_task_unregister(client->timeout_queue, ctx->timeout_task);
381 /* Protocol has ended, call the final callback */
382 if (protocol->final_callback)
383 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
385 silc_protocol_free(protocol);
389 case SILC_PROTOCOL_STATE_ERROR:
391 * Error during protocol
394 /* Send abort notification */
395 silc_ske_abort(ctx->ske, ctx->ske->status,
396 ctx->send_packet, context);
398 /* On error the final callback is always called. */
399 if (protocol->final_callback)
400 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
402 silc_protocol_free(protocol);
405 case SILC_PROTOCOL_STATE_FAILURE:
407 * Received failure from remote.
410 /* Unregister the timeout task since the protocol has ended.
411 This was the timeout task to be executed if the protocol is
412 not completed fast enough. */
413 if (ctx->timeout_task)
414 silc_task_unregister(client->timeout_queue, ctx->timeout_task);
416 /* On error the final callback is always called. */
417 if (protocol->final_callback)
418 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
420 silc_protocol_free(protocol);
422 case SILC_PROTOCOL_STATE_UNKNOWN:
428 * Connection Authentication protocol functions
432 silc_client_get_public_key_auth(SilcClient client,
434 unsigned char *auth_data,
435 uint32 *auth_data_len,
441 SilcPublicKey pub_key;
443 if (!silc_pkcs_load_public_key(filepath,&pub_key, SILC_PKCS_FILE_PEM))
444 if (!silc_pkcs_load_public_key(filepath, &pub_key, SILC_PKCS_FILE_BIN))
447 silc_pkcs_alloc(pub_key->name, &pkcs);
448 if (!silc_pkcs_public_key_set(pkcs, pub_key)) {
449 silc_pkcs_free(pkcs);
450 silc_pkcs_public_key_free(pub_key);
454 /* Make the authentication data. Protocol says it is HASH plus
456 len = ske->hash_len + ske->start_payload_copy->len;
457 auth = silc_buffer_alloc(len);
458 silc_buffer_pull_tail(auth, len);
459 silc_buffer_format(auth,
460 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
461 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
462 ske->start_payload_copy->len),
465 if (silc_pkcs_sign(pkcs, auth->data, auth->len, auth_data, auth_data_len)) {
466 silc_pkcs_free(pkcs);
467 silc_buffer_free(auth);
468 silc_pkcs_public_key_free(pub_key);
472 silc_pkcs_free(pkcs);
473 silc_buffer_free(auth);
474 silc_pkcs_public_key_free(pub_key);
478 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
480 SilcProtocol protocol = (SilcProtocol)context;
481 SilcClientConnAuthInternalContext *ctx =
482 (SilcClientConnAuthInternalContext *)protocol->context;
483 SilcClient client = (SilcClient)ctx->client;
484 SilcClientConnection conn = ctx->sock->user_data;
486 SILC_LOG_DEBUG(("Start"));
488 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
489 protocol->state = SILC_PROTOCOL_STATE_START;
491 switch(protocol->state) {
492 case SILC_PROTOCOL_STATE_START:
495 * Start protocol. We send authentication data to the server
496 * to be authenticated.
500 unsigned char *auth_data = NULL;
501 uint32 auth_data_len = 0;
503 switch(ctx->auth_meth) {
505 /* No authentication required */
508 case SILC_AUTH_PASSWORD:
509 /* Password authentication */
510 if (ctx->auth_data && ctx->auth_data_len) {
511 auth_data = ctx->auth_data;
512 auth_data_len = ctx->auth_data_len;
516 client->ops->say(client, conn,
517 "Password authentication required by server %s",
518 ctx->sock->hostname);
519 auth_data = client->ops->ask_passphrase(client, conn);
520 auth_data_len = strlen(auth_data);
523 case SILC_AUTH_PUBLIC_KEY:
525 unsigned char sign[1024];
527 /* Public key authentication */
528 silc_client_get_public_key_auth(client, ctx->auth_data,
529 sign, &auth_data_len,
531 auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
532 memcpy(auth_data, sign, auth_data_len);
537 payload_len = 4 + auth_data_len;
538 packet = silc_buffer_alloc(payload_len);
539 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
540 silc_buffer_format(packet,
541 SILC_STR_UI_SHORT(payload_len),
542 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
543 SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
546 /* Send the packet to server */
547 silc_client_packet_send(client, ctx->sock,
548 SILC_PACKET_CONNECTION_AUTH,
550 packet->data, packet->len, TRUE);
553 memset(auth_data, 0, auth_data_len);
554 silc_free(auth_data);
556 silc_buffer_free(packet);
558 /* Next state is end of protocol */
559 protocol->state = SILC_PROTOCOL_STATE_END;
563 case SILC_PROTOCOL_STATE_END:
566 * End protocol. Nothing special to be done here.
569 /* Protocol has ended, call the final callback */
570 if (protocol->final_callback)
571 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
573 silc_protocol_free(protocol);
577 case SILC_PROTOCOL_STATE_ERROR:
580 * Error. Send notify to remote.
582 unsigned char error[4];
584 SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
586 /* Error in protocol. Send FAILURE packet. Although I don't think
587 this could ever happen on client side. */
588 silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
589 NULL, 0, NULL, NULL, error, 4, TRUE);
591 /* On error the final callback is always called. */
592 if (protocol->final_callback)
593 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
595 silc_protocol_free(protocol);
598 case SILC_PROTOCOL_STATE_FAILURE:
600 * Received failure from remote.
603 /* On error the final callback is always called. */
604 if (protocol->final_callback)
605 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
607 silc_protocol_free(protocol);
610 case SILC_PROTOCOL_STATE_UNKNOWN:
615 /* Registers protocols used in client */
617 void silc_client_protocols_register(void)
619 silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
620 silc_client_protocol_connection_auth);
621 silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
622 silc_client_protocol_key_exchange);
625 /* Unregisters protocols */
627 void silc_client_protocols_unregister(void)
629 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
630 silc_client_protocol_connection_auth);
631 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
632 silc_client_protocol_key_exchange);