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 "silcincludes.h"
26 #include "silcclient.h"
27 #include "client_internal.h"
29 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth);
30 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange);
31 SILC_TASK_CALLBACK(silc_client_protocol_rekey);
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);
54 /* Public key verification callback. Called by the application. */
58 SilcSKEVerifyCbCompletion completion;
59 void *completion_context;
62 static void silc_client_verify_key_cb(bool success, void *context)
64 VerifyKeyContext verify = (VerifyKeyContext)context;
66 SILC_LOG_DEBUG(("Start"));
68 /* Call the completion callback back to the SKE */
69 verify->completion(verify->ske, success ? SILC_SKE_STATUS_OK :
70 SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
71 verify->completion_context);
76 /* Callback that is called when we have received KE payload from
77 responder. We try to verify the public key now. */
79 void silc_client_protocol_ke_verify_key(SilcSKE ske,
80 unsigned char *pk_data,
82 SilcSKEPKType pk_type,
84 SilcSKEVerifyCbCompletion completion,
85 void *completion_context)
87 SilcProtocol protocol = (SilcProtocol)context;
88 SilcClientKEInternalContext *ctx =
89 (SilcClientKEInternalContext *)protocol->context;
90 SilcClient client = (SilcClient)ctx->client;
91 VerifyKeyContext verify;
93 SILC_LOG_DEBUG(("Start"));
95 verify = silc_calloc(1, sizeof(*verify));
97 verify->completion = completion;
98 verify->completion_context = completion_context;
100 /* Verify public key from user. */
101 client->internal->ops->verify_public_key(client, ctx->sock->user_data,
103 pk_data, pk_len, pk_type,
104 silc_client_verify_key_cb, verify);
107 /* Sets the negotiated key material into use for particular connection. */
109 void silc_client_protocol_ke_set_keys(SilcSKE ske,
110 SilcSocketConnection sock,
111 SilcSKEKeyMaterial *keymat,
116 SilcSKEDiffieHellmanGroup group,
119 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
121 SILC_LOG_DEBUG(("Setting new keys into use"));
123 /* Allocate cipher to be used in the communication */
124 silc_cipher_alloc(cipher->cipher->name, &conn->send_key);
125 silc_cipher_alloc(cipher->cipher->name, &conn->receive_key);
126 silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL, &conn->hmac_send);
127 silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL, &conn->hmac_receive);
129 if (is_responder == TRUE) {
130 silc_cipher_set_key(conn->send_key, keymat->receive_enc_key,
131 keymat->enc_key_len);
132 silc_cipher_set_iv(conn->send_key, keymat->receive_iv);
133 silc_cipher_set_key(conn->receive_key, keymat->send_enc_key,
134 keymat->enc_key_len);
135 silc_cipher_set_iv(conn->receive_key, keymat->send_iv);
136 silc_hmac_set_key(conn->hmac_send, keymat->receive_hmac_key,
137 keymat->hmac_key_len);
138 silc_hmac_set_key(conn->hmac_receive, keymat->send_hmac_key,
139 keymat->hmac_key_len);
141 silc_cipher_set_key(conn->send_key, keymat->send_enc_key,
142 keymat->enc_key_len);
143 silc_cipher_set_iv(conn->send_key, keymat->send_iv);
144 silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key,
145 keymat->enc_key_len);
146 silc_cipher_set_iv(conn->receive_key, keymat->receive_iv);
147 silc_hmac_set_key(conn->hmac_send, keymat->send_hmac_key,
148 keymat->hmac_key_len);
149 silc_hmac_set_key(conn->hmac_receive, keymat->receive_hmac_key,
150 keymat->hmac_key_len);
154 conn->rekey = silc_calloc(1, sizeof(*conn->rekey));
155 conn->rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
156 keymat->enc_key_len / 8);
157 conn->rekey->enc_key_len = keymat->enc_key_len / 8;
159 if (ske->start_payload->flags & SILC_SKE_SP_FLAG_PFS)
160 conn->rekey->pfs = TRUE;
161 conn->rekey->ske_group = silc_ske_group_get_number(group);
163 /* Save the HASH function */
164 silc_hash_alloc(hash->hash->name, &conn->hash);
167 /* Checks the version string of the server. */
169 SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
170 SilcUInt32 len, void *context)
172 SilcClientConnection conn = (SilcClientConnection)ske->sock->user_data;
173 SilcClient client = (SilcClient)ske->user_data;
174 SilcUInt32 l_protocol_version = 0, r_protocol_version = 0;
176 if (!silc_parse_version_string(version, &r_protocol_version, NULL, NULL,
178 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
179 "We don't support server version `%s'",
181 return SILC_SKE_STATUS_BAD_VERSION;
184 if (!silc_parse_version_string(client->internal->silc_client_version,
185 &l_protocol_version, NULL, NULL,
187 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
188 "We don't support server version `%s'",
190 return SILC_SKE_STATUS_BAD_VERSION;
193 /* If remote is too new, don't connect */
194 if (l_protocol_version < r_protocol_version) {
195 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
196 "We don't support server version `%s'",
198 return SILC_SKE_STATUS_BAD_VERSION;
201 ske->sock->version = r_protocol_version;
203 return SILC_SKE_STATUS_OK;
206 /* Callback that is called by the SKE to indicate that it is safe to
207 continue the execution of the protocol. Is given as argument to the
208 silc_ske_initiator_finish or silc_ske_responder_phase_2 functions.
209 This is called due to the fact that the public key verification
210 process is asynchronous and we must not continue the protocl until
211 the public key has been verified and this callback is called. */
213 static void silc_client_protocol_ke_continue(SilcSKE ske,
216 SilcProtocol protocol = (SilcProtocol)context;
217 SilcClientKEInternalContext *ctx =
218 (SilcClientKEInternalContext *)protocol->context;
219 SilcClient client = (SilcClient)ctx->client;
220 SilcClientConnection conn = ctx->sock->user_data;
222 SILC_LOG_DEBUG(("Start"));
224 if (ske->status != SILC_SKE_STATUS_OK) {
225 /* Call failure client operation */
226 client->internal->ops->failure(client, conn, protocol,
227 (void *)ske->status);
228 protocol->state = SILC_PROTOCOL_STATE_ERROR;
229 silc_protocol_execute(protocol, client->schedule, 0, 0);
233 /* Send Ok to the other end. We will end the protocol as server
234 sends Ok to us when we will take the new keys into use. Do this
235 if we are initiator. This is happens when this callback was sent
236 to silc_ske_initiator_finish function. */
237 if (ctx->responder == FALSE) {
238 silc_ske_end(ctx->ske);
240 /* End the protocol on the next round */
241 protocol->state = SILC_PROTOCOL_STATE_END;
244 /* Advance protocol state and call the next state if we are responder.
245 This happens when this callback was sent to silc_ske_responder_phase_2
247 if (ctx->responder == TRUE) {
249 silc_protocol_execute(protocol, client->schedule, 0, 100000);
253 /* Performs key exchange protocol. This is used for both initiator
254 and responder key exchange. This may be called recursively. */
256 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
258 SilcProtocol protocol = (SilcProtocol)context;
259 SilcClientKEInternalContext *ctx =
260 (SilcClientKEInternalContext *)protocol->context;
261 SilcClient client = (SilcClient)ctx->client;
262 SilcClientConnection conn = ctx->sock->user_data;
263 SilcSKEStatus status = SILC_SKE_STATUS_OK;
265 SILC_LOG_DEBUG(("Start"));
267 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
268 protocol->state = SILC_PROTOCOL_STATE_START;
270 switch(protocol->state) {
271 case SILC_PROTOCOL_STATE_START:
278 /* Allocate Key Exchange object */
279 ctx->ske = ske = silc_ske_alloc(client->rng, client);
281 silc_ske_set_callbacks(ske, ctx->send_packet, NULL,
283 silc_client_protocol_ke_continue,
284 silc_ske_check_version,
287 if (ctx->responder == TRUE) {
288 /* Start the key exchange by processing the received security
289 properties packet from initiator. */
291 silc_ske_responder_start(ske, ctx->rng, ctx->sock,
292 client->internal->silc_client_version,
293 ctx->packet->buffer, TRUE);
295 SilcSKEStartPayload *start_payload;
297 /* Assemble security properties. */
298 silc_ske_assemble_security_properties(
299 ske, SILC_SKE_SP_FLAG_MUTUAL,
300 client->internal->silc_client_version,
303 /* Start the key exchange by sending our security properties
304 to the remote end. */
305 status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
309 /* Return now if the procedure is pending */
310 if (status == SILC_SKE_STATUS_PENDING)
313 if (status != SILC_SKE_STATUS_OK) {
314 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
316 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
319 protocol->state = SILC_PROTOCOL_STATE_ERROR;
320 silc_protocol_execute(protocol, client->schedule, 0, 0);
324 /* Advance protocol state and call the next state if we are responder */
326 if (ctx->responder == TRUE)
327 silc_protocol_execute(protocol, client->schedule, 0, 100000);
335 if (ctx->responder == TRUE) {
336 /* Sends the selected security properties to the initiator. */
337 status = silc_ske_responder_phase_1(ctx->ske);
339 /* Call Phase-1 function. This processes the Key Exchange Start
340 paylaod reply we just got from the responder. The callback
341 function will receive the processed payload where we will
343 status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer);
346 if (status != SILC_SKE_STATUS_OK) {
347 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
349 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
352 protocol->state = SILC_PROTOCOL_STATE_ERROR;
353 silc_protocol_execute(protocol, client->schedule, 0, 0);
357 /* Advance protocol state and call next state if we are initiator */
359 if (ctx->responder == FALSE)
360 silc_protocol_execute(protocol, client->schedule, 0, 100000);
368 if (ctx->responder == TRUE) {
369 /* Process the received Key Exchange 1 Payload packet from
370 the initiator. This also creates our parts of the Diffie
371 Hellman algorithm. The silc_client_protocol_ke_continue will
372 be called after the public key has been verified. */
373 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer);
375 /* Call the Phase-2 function. This creates Diffie Hellman
376 key exchange parameters and sends our public part inside
377 Key Exhange 1 Payload to the responder. */
378 status = silc_ske_initiator_phase_2(ctx->ske,
381 SILC_SKE_PK_TYPE_SILC);
385 /* Return now if the procedure is pending */
386 if (status == SILC_SKE_STATUS_PENDING)
389 if (status != SILC_SKE_STATUS_OK) {
390 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
392 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
395 protocol->state = SILC_PROTOCOL_STATE_ERROR;
396 silc_protocol_execute(protocol, client->schedule, 0, 0);
406 if (ctx->responder == TRUE) {
407 /* This creates the key exchange material and sends our
408 public parts to the initiator inside Key Exchange 2 Payload. */
410 silc_ske_responder_finish(ctx->ske,
411 client->public_key, client->private_key,
412 SILC_SKE_PK_TYPE_SILC);
414 /* End the protocol on the next round */
415 protocol->state = SILC_PROTOCOL_STATE_END;
417 /* Finish the protocol. This verifies the Key Exchange 2 payload
418 sent by responder. The silc_client_protocol_ke_continue will
419 be called after the public key has been verified. */
420 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer);
423 /* Return now if the procedure is pending */
424 if (status == SILC_SKE_STATUS_PENDING)
427 if (status != SILC_SKE_STATUS_OK) {
428 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
429 client->internal->ops->say(
430 client, conn, SILC_CLIENT_MESSAGE_AUDIT,
431 "Received unsupported server %s public key",
432 ctx->sock->hostname);
434 client->internal->ops->say(
435 client, conn, SILC_CLIENT_MESSAGE_AUDIT,
436 "Error during key exchange protocol with server %s",
437 ctx->sock->hostname);
439 protocol->state = SILC_PROTOCOL_STATE_ERROR;
440 silc_protocol_execute(protocol, client->schedule, 0, 0);
446 case SILC_PROTOCOL_STATE_END:
451 SilcSKEKeyMaterial *keymat;
452 int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher);
453 int hash_len = ctx->ske->prop->hash->hash->hash_len;
455 /* Process the key material */
456 keymat = silc_calloc(1, sizeof(*keymat));
457 status = silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
459 if (status != SILC_SKE_STATUS_OK) {
460 protocol->state = SILC_PROTOCOL_STATE_ERROR;
461 silc_protocol_execute(protocol, client->schedule, 0, 300000);
462 silc_ske_free_key_material(keymat);
465 ctx->keymat = keymat;
467 /* Send Ok to the other end if we are responder. If we are initiator
468 we have sent this already. */
469 if (ctx->responder == TRUE)
470 silc_ske_end(ctx->ske);
472 /* Unregister the timeout task since the protocol has ended.
473 This was the timeout task to be executed if the protocol is
474 not completed fast enough. */
475 if (ctx->timeout_task)
476 silc_schedule_task_del(client->schedule, ctx->timeout_task);
478 /* Protocol has ended, call the final callback */
479 if (protocol->final_callback)
480 silc_protocol_execute_final(protocol, client->schedule);
482 silc_protocol_free(protocol);
486 case SILC_PROTOCOL_STATE_ERROR:
488 * Error during protocol
491 /* Send abort notification */
492 silc_ske_abort(ctx->ske, ctx->ske->status);
494 /* On error the final callback is always called. */
495 if (protocol->final_callback)
496 silc_protocol_execute_final(protocol, client->schedule);
498 silc_protocol_free(protocol);
501 case SILC_PROTOCOL_STATE_FAILURE:
503 * Received failure from remote.
506 /* Unregister the timeout task since the protocol has ended.
507 This was the timeout task to be executed if the protocol is
508 not completed fast enough. */
509 if (ctx->timeout_task)
510 silc_schedule_task_del(client->schedule, ctx->timeout_task);
512 /* On error the final callback is always called. */
513 if (protocol->final_callback)
514 silc_protocol_execute_final(protocol, client->schedule);
516 silc_protocol_free(protocol);
518 case SILC_PROTOCOL_STATE_UNKNOWN:
524 * Connection Authentication protocol functions
528 silc_client_get_public_key_auth(SilcClient client,
529 SilcClientConnection conn,
530 unsigned char *auth_data,
531 SilcUInt32 *auth_data_len,
538 /* Use our default key */
541 /* Make the authentication data. Protocol says it is HASH plus
543 len = ske->hash_len + ske->start_payload_copy->len;
544 auth = silc_buffer_alloc(len);
545 silc_buffer_pull_tail(auth, len);
546 silc_buffer_format(auth,
547 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
548 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
549 ske->start_payload_copy->len),
552 if (silc_pkcs_sign_with_hash(pkcs, ske->prop->hash, auth->data,
553 auth->len, auth_data, auth_data_len)) {
554 silc_buffer_free(auth);
558 silc_buffer_free(auth);
562 /* Continues the connection authentication protocol. This funtion may
563 be called directly or used as SilcAskPassphrase callback. */
566 silc_client_conn_auth_continue(unsigned char *auth_data,
567 SilcUInt32 auth_data_len, void *context)
569 SilcProtocol protocol = (SilcProtocol)context;
570 SilcClientConnAuthInternalContext *ctx =
571 (SilcClientConnAuthInternalContext *)protocol->context;
572 SilcClient client = (SilcClient)ctx->client;
576 SILC_LOG_DEBUG(("Start"));
578 payload_len = 4 + auth_data_len;
579 packet = silc_buffer_alloc(payload_len);
580 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
581 silc_buffer_format(packet,
582 SILC_STR_UI_SHORT(payload_len),
583 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
584 SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
587 /* Send the packet to server */
588 silc_client_packet_send(client, ctx->sock,
589 SILC_PACKET_CONNECTION_AUTH,
591 packet->data, packet->len, TRUE);
592 silc_buffer_free(packet);
594 /* Next state is end of protocol */
595 protocol->state = SILC_PROTOCOL_STATE_END;
598 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
600 SilcProtocol protocol = (SilcProtocol)context;
601 SilcClientConnAuthInternalContext *ctx =
602 (SilcClientConnAuthInternalContext *)protocol->context;
603 SilcClient client = (SilcClient)ctx->client;
604 SilcClientConnection conn = ctx->sock->user_data;
606 SILC_LOG_DEBUG(("Start"));
608 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
609 protocol->state = SILC_PROTOCOL_STATE_START;
611 switch(protocol->state) {
612 case SILC_PROTOCOL_STATE_START:
615 * Start protocol. We send authentication data to the server
616 * to be authenticated.
618 unsigned char *auth_data = NULL;
619 SilcUInt32 auth_data_len = 0;
620 unsigned char sign[1024];
622 switch(ctx->auth_meth) {
624 /* No authentication required */
627 case SILC_AUTH_PASSWORD:
628 /* Password authentication */
629 if (ctx->auth_data && ctx->auth_data_len) {
630 auth_data = ctx->auth_data;
631 auth_data_len = ctx->auth_data_len;
635 client->internal->ops->say(
636 client, conn, SILC_CLIENT_MESSAGE_INFO,
637 "Password authentication required by server %s",
638 ctx->sock->hostname);
639 client->internal->ops->ask_passphrase(client, conn,
640 silc_client_conn_auth_continue,
645 case SILC_AUTH_PUBLIC_KEY:
646 if (!ctx->auth_data) {
647 /* Public key authentication */
648 silc_client_get_public_key_auth(client, conn, sign, &auth_data_len,
652 auth_data = ctx->auth_data;
653 auth_data_len = ctx->auth_data_len;
659 silc_client_conn_auth_continue(auth_data,
660 auth_data_len, protocol);
664 case SILC_PROTOCOL_STATE_END:
667 * End protocol. Nothing special to be done here.
670 /* Protocol has ended, call the final callback */
671 if (protocol->final_callback)
672 silc_protocol_execute_final(protocol, client->schedule);
674 silc_protocol_free(protocol);
678 case SILC_PROTOCOL_STATE_ERROR:
681 * Error. Send notify to remote.
683 unsigned char error[4];
685 SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
687 /* Error in protocol. Send FAILURE packet. Although I don't think
688 this could ever happen on client side. */
689 silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
690 NULL, 0, NULL, NULL, error, 4, TRUE);
692 /* On error the final callback is always called. */
693 if (protocol->final_callback)
694 silc_protocol_execute_final(protocol, client->schedule);
696 silc_protocol_free(protocol);
699 case SILC_PROTOCOL_STATE_FAILURE:
701 * Received failure from remote.
704 /* On error the final callback is always called. */
705 if (protocol->final_callback)
706 silc_protocol_execute_final(protocol, client->schedule);
708 silc_protocol_free(protocol);
711 case SILC_PROTOCOL_STATE_UNKNOWN:
717 * Re-key protocol routines
720 /* Actually takes the new keys into use. */
723 silc_client_protocol_rekey_validate(SilcClient client,
724 SilcClientRekeyInternalContext *ctx,
725 SilcSocketConnection sock,
726 SilcSKEKeyMaterial *keymat,
729 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
731 if (ctx->responder == TRUE) {
733 silc_cipher_set_key(conn->send_key, keymat->receive_enc_key,
734 keymat->enc_key_len);
735 silc_cipher_set_iv(conn->send_key, keymat->receive_iv);
736 silc_hmac_set_key(conn->hmac_send, keymat->receive_hmac_key,
737 keymat->hmac_key_len);
739 silc_cipher_set_key(conn->receive_key, keymat->send_enc_key,
740 keymat->enc_key_len);
741 silc_cipher_set_iv(conn->receive_key, keymat->send_iv);
742 silc_hmac_set_key(conn->hmac_receive, keymat->send_hmac_key,
743 keymat->hmac_key_len);
747 silc_cipher_set_key(conn->send_key, keymat->send_enc_key,
748 keymat->enc_key_len);
749 silc_cipher_set_iv(conn->send_key, keymat->send_iv);
750 silc_hmac_set_key(conn->hmac_send, keymat->send_hmac_key,
751 keymat->hmac_key_len);
753 silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key,
754 keymat->enc_key_len);
755 silc_cipher_set_iv(conn->receive_key, keymat->receive_iv);
756 silc_hmac_set_key(conn->hmac_receive, keymat->receive_hmac_key,
757 keymat->hmac_key_len);
761 /* Save the current sending encryption key */
763 memset(conn->rekey->send_enc_key, 0, conn->rekey->enc_key_len);
764 silc_free(conn->rekey->send_enc_key);
765 conn->rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
766 keymat->enc_key_len / 8);
767 conn->rekey->enc_key_len = keymat->enc_key_len / 8;
771 /* This function actually re-generates (when not using PFS) the keys and
772 takes them into use. */
775 silc_client_protocol_rekey_generate(SilcClient client,
776 SilcClientRekeyInternalContext *ctx,
779 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
780 SilcSKEKeyMaterial *keymat;
781 SilcUInt32 key_len = silc_cipher_get_key_len(conn->send_key);
782 SilcUInt32 hash_len = conn->hash->hash->hash_len;
784 SILC_LOG_DEBUG(("Generating new %s session keys (no PFS)",
785 send ? "sending" : "receiving"));
787 /* Generate the new key */
788 keymat = silc_calloc(1, sizeof(*keymat));
789 silc_ske_process_key_material_data(conn->rekey->send_enc_key,
790 conn->rekey->enc_key_len,
791 16, key_len, hash_len,
794 /* Set the keys into use */
795 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
797 silc_ske_free_key_material(keymat);
800 /* This function actually re-generates (with PFS) the keys and
801 takes them into use. */
804 silc_client_protocol_rekey_generate_pfs(SilcClient client,
805 SilcClientRekeyInternalContext *ctx,
808 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
809 SilcSKEKeyMaterial *keymat;
810 SilcUInt32 key_len = silc_cipher_get_key_len(conn->send_key);
811 SilcUInt32 hash_len = conn->hash->hash->hash_len;
812 unsigned char *tmpbuf;
815 SILC_LOG_DEBUG(("Generating new %s session keys (with PFS)",
816 send ? "sending" : "receiving"));
818 /* Encode KEY to binary data */
819 tmpbuf = silc_mp_mp2bin(ctx->ske->KEY, 0, &klen);
821 /* Generate the new key */
822 keymat = silc_calloc(1, sizeof(*keymat));
823 silc_ske_process_key_material_data(tmpbuf, klen, 16, key_len, hash_len,
826 /* Set the keys into use */
827 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
829 memset(tmpbuf, 0, klen);
831 silc_ske_free_key_material(keymat);
834 /* Packet sending callback. This function is provided as packet sending
835 routine to the Key Exchange functions. */
838 silc_client_protocol_rekey_send_packet(SilcSKE ske,
843 SilcProtocol protocol = (SilcProtocol)context;
844 SilcClientRekeyInternalContext *ctx =
845 (SilcClientRekeyInternalContext *)protocol->context;
846 SilcClient client = (SilcClient)ctx->client;
848 /* Send the packet immediately */
849 silc_client_packet_send(client, ctx->sock, type, NULL, 0, NULL, NULL,
850 packet->data, packet->len, FALSE);
853 /* Performs re-key as defined in the SILC protocol specification. */
855 SILC_TASK_CALLBACK(silc_client_protocol_rekey)
857 SilcProtocol protocol = (SilcProtocol)context;
858 SilcClientRekeyInternalContext *ctx =
859 (SilcClientRekeyInternalContext *)protocol->context;
860 SilcClient client = (SilcClient)ctx->client;
861 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
862 SilcSKEStatus status;
864 SILC_LOG_DEBUG(("Start"));
866 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
867 protocol->state = SILC_PROTOCOL_STATE_START;
869 SILC_LOG_DEBUG(("State=%d", protocol->state));
871 switch(protocol->state) {
872 case SILC_PROTOCOL_STATE_START:
878 if (ctx->responder == TRUE) {
880 * We are receiving party
883 if (ctx->pfs == TRUE) {
885 * Use Perfect Forward Secrecy, ie. negotiate the key material
886 * using the SKE protocol.
889 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
890 /* Error in protocol */
891 protocol->state = SILC_PROTOCOL_STATE_ERROR;
892 silc_protocol_execute(protocol, client->schedule, 0, 300000);
895 ctx->ske = silc_ske_alloc(client->rng, client);
896 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
897 silc_ske_group_get_by_number(conn->rekey->ske_group,
898 &ctx->ske->prop->group);
900 silc_ske_set_callbacks(ctx->ske,
901 silc_client_protocol_rekey_send_packet,
902 NULL, NULL, NULL, silc_ske_check_version,
905 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer);
906 if (status != SILC_SKE_STATUS_OK) {
907 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
910 protocol->state = SILC_PROTOCOL_STATE_ERROR;
911 silc_protocol_execute(protocol, client->schedule, 0, 300000);
915 /* Advance the protocol state */
917 silc_protocol_execute(protocol, client->schedule, 0, 0);
920 * Do normal and simple re-key.
923 /* Send the REKEY_DONE to indicate we will take new keys into use */
924 silc_client_packet_send(client, ctx->sock,
925 SILC_PACKET_REKEY_DONE,
926 NULL, 0, NULL, NULL, NULL, 0, FALSE);
928 /* After we send REKEY_DONE we must set the sending encryption
929 key to the new key since all packets after this packet must
930 encrypted with the new key. */
931 silc_client_protocol_rekey_generate(client, ctx, TRUE);
933 /* The protocol ends in next stage. */
934 protocol->state = SILC_PROTOCOL_STATE_END;
939 * We are the initiator of this protocol
942 /* Start the re-key by sending the REKEY packet */
943 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY,
944 NULL, 0, NULL, NULL, NULL, 0, FALSE);
946 if (ctx->pfs == TRUE) {
948 * Use Perfect Forward Secrecy, ie. negotiate the key material
949 * using the SKE protocol.
951 ctx->ske = silc_ske_alloc(client->rng, client);
952 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
953 silc_ske_group_get_by_number(conn->rekey->ske_group,
954 &ctx->ske->prop->group);
956 silc_ske_set_callbacks(ctx->ske,
957 silc_client_protocol_rekey_send_packet,
958 NULL, NULL, NULL, silc_ske_check_version,
961 status = silc_ske_initiator_phase_2(ctx->ske, NULL, NULL, 0);
962 if (status != SILC_SKE_STATUS_OK) {
963 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
966 protocol->state = SILC_PROTOCOL_STATE_ERROR;
967 silc_protocol_execute(protocol, client->schedule, 0, 300000);
971 /* Advance the protocol state */
975 * Do normal and simple re-key.
978 /* Send the REKEY_DONE to indicate we will take new keys into use
980 silc_client_packet_send(client, ctx->sock,
981 SILC_PACKET_REKEY_DONE,
982 NULL, 0, NULL, NULL, NULL, 0, FALSE);
984 /* After we send REKEY_DONE we must set the sending encryption
985 key to the new key since all packets after this packet must
986 encrypted with the new key. */
987 silc_client_protocol_rekey_generate(client, ctx, TRUE);
989 /* The protocol ends in next stage. */
990 protocol->state = SILC_PROTOCOL_STATE_END;
998 * Second state, used only when oding re-key with PFS.
1000 if (ctx->responder == TRUE) {
1001 if (ctx->pfs == TRUE) {
1003 * Send our KE packe to the initiator now that we've processed
1004 * the initiator's KE packet.
1006 status = silc_ske_responder_finish(ctx->ske, NULL, NULL,
1007 SILC_SKE_PK_TYPE_SILC);
1009 if (status != SILC_SKE_STATUS_OK) {
1010 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
1013 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1014 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1020 if (ctx->pfs == TRUE) {
1022 * The packet type must be KE packet
1024 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
1025 /* Error in protocol */
1026 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1027 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1030 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer);
1031 if (status != SILC_SKE_STATUS_OK) {
1032 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
1035 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1036 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1042 /* Send the REKEY_DONE to indicate we will take new keys into use
1044 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
1045 NULL, 0, NULL, NULL, NULL, 0, FALSE);
1047 /* After we send REKEY_DONE we must set the sending encryption
1048 key to the new key since all packets after this packet must
1049 encrypted with the new key. */
1050 silc_client_protocol_rekey_generate_pfs(client, ctx, TRUE);
1052 /* The protocol ends in next stage. */
1053 protocol->state = SILC_PROTOCOL_STATE_END;
1056 case SILC_PROTOCOL_STATE_END:
1061 if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
1062 /* Error in protocol */
1063 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1064 silc_protocol_execute(protocol, client->schedule, 0, 0);
1067 /* We received the REKEY_DONE packet and all packets after this is
1068 encrypted with the new key so set the decryption key to the new key */
1069 silc_client_protocol_rekey_generate(client, ctx, FALSE);
1071 /* Protocol has ended, call the final callback */
1072 if (protocol->final_callback)
1073 silc_protocol_execute_final(protocol, client->schedule);
1075 silc_protocol_free(protocol);
1078 case SILC_PROTOCOL_STATE_ERROR:
1083 if (ctx->pfs == TRUE) {
1084 /* Send abort notification */
1085 silc_ske_abort(ctx->ske, ctx->ske->status);
1088 /* On error the final callback is always called. */
1089 if (protocol->final_callback)
1090 silc_protocol_execute_final(protocol, client->schedule);
1092 silc_protocol_free(protocol);
1095 case SILC_PROTOCOL_STATE_FAILURE:
1097 * We have received failure from remote
1100 /* On error the final callback is always called. */
1101 if (protocol->final_callback)
1102 silc_protocol_execute_final(protocol, client->schedule);
1104 silc_protocol_free(protocol);
1107 case SILC_PROTOCOL_STATE_UNKNOWN:
1113 /* Registers protocols used in client */
1115 void silc_client_protocols_register(void)
1117 silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1118 silc_client_protocol_connection_auth);
1119 silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1120 silc_client_protocol_key_exchange);
1121 silc_protocol_register(SILC_PROTOCOL_CLIENT_REKEY,
1122 silc_client_protocol_rekey);
1125 /* Unregisters protocols */
1127 void silc_client_protocols_unregister(void)
1129 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1130 silc_client_protocol_connection_auth);
1131 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1132 silc_client_protocol_key_exchange);
1133 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_REKEY,
1134 silc_client_protocol_rekey);