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);
30 SILC_TASK_CALLBACK(silc_client_protocol_rekey);
33 * Key Exhange protocol functions
36 /* Function that is called when SKE protocol sends packets to network. */
38 void silc_client_protocol_ke_send_packet(SilcSKE ske,
43 SilcProtocol protocol = (SilcProtocol)context;
44 SilcClientKEInternalContext *ctx =
45 (SilcClientKEInternalContext *)protocol->context;
46 SilcClient client = (SilcClient)ctx->client;
48 /* Send the packet immediately */
49 silc_client_packet_send(client, ske->sock, type, NULL, 0, NULL, NULL,
50 packet->data, packet->len, TRUE);
53 /* Public key verification callback. Called by the application. */
57 SilcSKEVerifyCbCompletion completion;
58 void *completion_context;
61 static void silc_client_verify_key_cb(bool success, void *context)
63 VerifyKeyContext verify = (VerifyKeyContext)context;
65 SILC_LOG_DEBUG(("Start"));
67 /* Call the completion callback back to the SKE */
68 verify->completion(verify->ske, success ? SILC_SKE_STATUS_OK :
69 SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
70 verify->completion_context);
75 /* Callback that is called when we have received KE payload from
76 responder. We try to verify the public key now. */
78 void silc_client_protocol_ke_verify_key(SilcSKE ske,
79 unsigned char *pk_data,
81 SilcSKEPKType pk_type,
83 SilcSKEVerifyCbCompletion completion,
84 void *completion_context)
86 SilcProtocol protocol = (SilcProtocol)context;
87 SilcClientKEInternalContext *ctx =
88 (SilcClientKEInternalContext *)protocol->context;
89 SilcClient client = (SilcClient)ctx->client;
90 VerifyKeyContext verify;
92 SILC_LOG_DEBUG(("Start"));
94 verify = silc_calloc(1, sizeof(*verify));
96 verify->completion = completion;
97 verify->completion_context = completion_context;
99 /* Verify public key from user. */
100 client->ops->verify_public_key(client, ctx->sock->user_data,
102 pk_data, pk_len, pk_type,
103 silc_client_verify_key_cb, verify);
106 /* Sets the negotiated key material into use for particular connection. */
108 void silc_client_protocol_ke_set_keys(SilcSKE ske,
109 SilcSocketConnection sock,
110 SilcSKEKeyMaterial *keymat,
115 SilcSKEDiffieHellmanGroup group,
118 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
120 SILC_LOG_DEBUG(("Setting new keys into use"));
122 /* Allocate cipher to be used in the communication */
123 silc_cipher_alloc(cipher->cipher->name, &conn->send_key);
124 silc_cipher_alloc(cipher->cipher->name, &conn->receive_key);
125 silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL, &conn->hmac_send);
126 silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL, &conn->hmac_receive);
128 if (is_responder == TRUE) {
129 silc_cipher_set_key(conn->send_key, keymat->receive_enc_key,
130 keymat->enc_key_len);
131 silc_cipher_set_iv(conn->send_key, keymat->receive_iv);
132 silc_cipher_set_key(conn->receive_key, keymat->send_enc_key,
133 keymat->enc_key_len);
134 silc_cipher_set_iv(conn->receive_key, keymat->send_iv);
135 silc_hmac_set_key(conn->hmac_send, keymat->receive_hmac_key,
136 keymat->hmac_key_len);
137 silc_hmac_set_key(conn->hmac_receive, keymat->send_hmac_key,
138 keymat->hmac_key_len);
140 silc_cipher_set_key(conn->send_key, keymat->send_enc_key,
141 keymat->enc_key_len);
142 silc_cipher_set_iv(conn->send_key, keymat->send_iv);
143 silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key,
144 keymat->enc_key_len);
145 silc_cipher_set_iv(conn->receive_key, keymat->receive_iv);
146 silc_hmac_set_key(conn->hmac_send, keymat->send_hmac_key,
147 keymat->hmac_key_len);
148 silc_hmac_set_key(conn->hmac_receive, keymat->receive_hmac_key,
149 keymat->hmac_key_len);
153 conn->rekey = silc_calloc(1, sizeof(*conn->rekey));
154 conn->rekey->send_enc_key =
155 silc_calloc(keymat->enc_key_len / 8,
156 sizeof(*conn->rekey->send_enc_key));
157 memcpy(conn->rekey->send_enc_key,
158 keymat->send_enc_key, keymat->enc_key_len / 8);
159 conn->rekey->enc_key_len = keymat->enc_key_len / 8;
161 if (ske->start_payload->flags & SILC_SKE_SP_FLAG_PFS)
162 conn->rekey->pfs = TRUE;
163 conn->rekey->ske_group = silc_ske_group_get_number(group);
165 /* Save the HASH function */
166 silc_hash_alloc(hash->hash->name, &conn->hash);
169 /* Checks the version string of the server. */
171 SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
172 uint32 len, void *context)
174 SilcClientConnection conn = (SilcClientConnection)ske->sock->user_data;
175 SilcClient client = (SilcClient)ske->user_data;
176 SilcSKEStatus status = SILC_SKE_STATUS_OK;
178 int maj = 0, min = 0, build = 0, maj2 = 0, min2 = 0, build2 = 0;
180 /* Check for initial version string */
181 if (!strstr(version, "SILC-1.0-"))
182 status = SILC_SKE_STATUS_BAD_VERSION;
184 /* Check software version */
188 status = SILC_SKE_STATUS_BAD_VERSION;
191 cp = strchr(cp, '.');
196 cp = strchr(cp, '.');
198 build = atoi(cp + 1);
200 cp = client->silc_client_version + 9;
202 status = SILC_SKE_STATUS_BAD_VERSION;
205 cp = strchr(cp, '.');
210 cp = strchr(cp, '.');
212 build2 = atoi(cp + 1);
215 status = SILC_SKE_STATUS_BAD_VERSION;
217 /* XXX backward support for 0.6.1 */
218 if (maj == 0 && min == 6 && build < 2)
219 ske->backward_version = 1;
221 if (status != SILC_SKE_STATUS_OK)
222 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
223 "We don't support server version `%s'", version);
228 /* Callback that is called by the SKE to indicate that it is safe to
229 continue the execution of the protocol. Is given as argument to the
230 silc_ske_initiator_finish or silc_ske_responder_phase_2 functions.
231 This is called due to the fact that the public key verification
232 process is asynchronous and we must not continue the protocl until
233 the public key has been verified and this callback is called. */
235 static void silc_client_protocol_ke_continue(SilcSKE ske,
238 SilcProtocol protocol = (SilcProtocol)context;
239 SilcClientKEInternalContext *ctx =
240 (SilcClientKEInternalContext *)protocol->context;
241 SilcClient client = (SilcClient)ctx->client;
242 SilcClientConnection conn = ctx->sock->user_data;
244 SILC_LOG_DEBUG(("Start"));
246 if (ske->status != SILC_SKE_STATUS_OK) {
247 if (ske->status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
248 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
249 "Received unsupported server %s public key",
250 ctx->sock->hostname);
251 } else if (ske->status == SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED) {
252 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
253 "Remote host did not send its public key, even though "
256 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
257 "Error during key exchange protocol with server %s",
258 ctx->sock->hostname);
261 protocol->state = SILC_PROTOCOL_STATE_ERROR;
262 silc_protocol_execute(protocol, client->schedule, 0, 0);
266 /* Send Ok to the other end. We will end the protocol as server
267 sends Ok to us when we will take the new keys into use. Do this
268 if we are initiator. This is happens when this callback was sent
269 to silc_ske_initiator_finish function. */
270 if (ctx->responder == FALSE) {
271 silc_ske_end(ctx->ske);
273 /* End the protocol on the next round */
274 protocol->state = SILC_PROTOCOL_STATE_END;
277 /* Advance protocol state and call the next state if we are responder.
278 This happens when this callback was sent to silc_ske_responder_phase_2
280 if (ctx->responder == TRUE) {
282 silc_protocol_execute(protocol, client->schedule, 0, 100000);
286 /* Performs key exchange protocol. This is used for both initiator
287 and responder key exchange. This may be called recursively. */
289 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
291 SilcProtocol protocol = (SilcProtocol)context;
292 SilcClientKEInternalContext *ctx =
293 (SilcClientKEInternalContext *)protocol->context;
294 SilcClient client = (SilcClient)ctx->client;
295 SilcClientConnection conn = ctx->sock->user_data;
296 SilcSKEStatus status = SILC_SKE_STATUS_OK;
298 SILC_LOG_DEBUG(("Start"));
300 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
301 protocol->state = SILC_PROTOCOL_STATE_START;
303 switch(protocol->state) {
304 case SILC_PROTOCOL_STATE_START:
311 /* Allocate Key Exchange object */
312 ske = silc_ske_alloc();
314 ske->rng = client->rng;
315 ske->user_data = (void *)client;
317 silc_ske_set_callbacks(ske, ctx->send_packet, NULL,
319 silc_client_protocol_ke_continue,
320 silc_ske_check_version,
323 if (ctx->responder == TRUE) {
324 /* Start the key exchange by processing the received security
325 properties packet from initiator. */
326 status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
327 client->silc_client_version,
328 ctx->packet->buffer, TRUE);
330 SilcSKEStartPayload *start_payload;
332 /* Assemble security properties. */
333 silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_MUTUAL,
334 client->silc_client_version,
337 /* Start the key exchange by sending our security properties
338 to the remote end. */
339 status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
343 /* Return now if the procedure is pending */
344 if (status == SILC_SKE_STATUS_PENDING)
347 if (status != SILC_SKE_STATUS_OK) {
348 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
350 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
353 protocol->state = SILC_PROTOCOL_STATE_ERROR;
354 silc_protocol_execute(protocol, client->schedule, 0, 0);
358 /* Advance protocol state and call the next state if we are responder */
360 if (ctx->responder == TRUE)
361 silc_protocol_execute(protocol, client->schedule, 0, 100000);
369 if (ctx->responder == TRUE) {
370 /* Sends the selected security properties to the initiator. */
372 silc_ske_responder_phase_1(ctx->ske,
373 ctx->ske->start_payload);
375 /* Call Phase-1 function. This processes the Key Exchange Start
376 paylaod reply we just got from the responder. The callback
377 function will receive the processed payload where we will
379 status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer);
382 if (status != SILC_SKE_STATUS_OK) {
383 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
385 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
388 protocol->state = SILC_PROTOCOL_STATE_ERROR;
389 silc_protocol_execute(protocol, client->schedule, 0, 0);
393 /* Advance protocol state and call next state if we are initiator */
395 if (ctx->responder == FALSE)
396 silc_protocol_execute(protocol, client->schedule, 0, 100000);
404 if (ctx->responder == TRUE) {
405 /* Process the received Key Exchange 1 Payload packet from
406 the initiator. This also creates our parts of the Diffie
407 Hellman algorithm. The silc_client_protocol_ke_continue will
408 be called after the public key has been verified. */
409 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer);
411 /* Call the Phase-2 function. This creates Diffie Hellman
412 key exchange parameters and sends our public part inside
413 Key Exhange 1 Payload to the responder. */
414 status = silc_ske_initiator_phase_2(ctx->ske,
416 client->private_key);
420 /* Return now if the procedure is pending */
421 if (status == SILC_SKE_STATUS_PENDING)
424 if (status != SILC_SKE_STATUS_OK) {
425 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
427 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
430 protocol->state = SILC_PROTOCOL_STATE_ERROR;
431 silc_protocol_execute(protocol, client->schedule, 0, 0);
441 if (ctx->responder == TRUE) {
442 /* This creates the key exchange material and sends our
443 public parts to the initiator inside Key Exchange 2 Payload. */
445 silc_ske_responder_finish(ctx->ske,
446 client->public_key, client->private_key,
447 SILC_SKE_PK_TYPE_SILC);
449 /* End the protocol on the next round */
450 protocol->state = SILC_PROTOCOL_STATE_END;
452 /* Finish the protocol. This verifies the Key Exchange 2 payload
453 sent by responder. The silc_client_protocol_ke_continue will
454 be called after the public key has been verified. */
455 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer);
458 /* Return now if the procedure is pending */
459 if (status == SILC_SKE_STATUS_PENDING)
462 if (status != SILC_SKE_STATUS_OK) {
463 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
464 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
465 "Received unsupported server %s public key",
466 ctx->sock->hostname);
468 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
469 "Error during key exchange protocol with server %s",
470 ctx->sock->hostname);
472 protocol->state = SILC_PROTOCOL_STATE_ERROR;
473 silc_protocol_execute(protocol, client->schedule, 0, 0);
479 case SILC_PROTOCOL_STATE_END:
484 SilcSKEKeyMaterial *keymat;
485 int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher);
486 int hash_len = ctx->ske->prop->hash->hash->hash_len;
488 /* Process the key material */
489 keymat = silc_calloc(1, sizeof(*keymat));
490 status = silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
492 if (status != SILC_SKE_STATUS_OK) {
493 protocol->state = SILC_PROTOCOL_STATE_ERROR;
494 silc_protocol_execute(protocol, client->schedule, 0, 300000);
495 silc_ske_free_key_material(keymat);
498 ctx->keymat = keymat;
500 /* Send Ok to the other end if we are responder. If we are initiator
501 we have sent this already. */
502 if (ctx->responder == TRUE)
503 silc_ske_end(ctx->ske);
505 /* Unregister the timeout task since the protocol has ended.
506 This was the timeout task to be executed if the protocol is
507 not completed fast enough. */
508 if (ctx->timeout_task)
509 silc_schedule_task_del(client->schedule, ctx->timeout_task);
511 /* Protocol has ended, call the final callback */
512 if (protocol->final_callback)
513 silc_protocol_execute_final(protocol, client->schedule);
515 silc_protocol_free(protocol);
519 case SILC_PROTOCOL_STATE_ERROR:
521 * Error during protocol
524 /* Send abort notification */
525 silc_ske_abort(ctx->ske, ctx->ske->status);
527 /* On error the final callback is always called. */
528 if (protocol->final_callback)
529 silc_protocol_execute_final(protocol, client->schedule);
531 silc_protocol_free(protocol);
534 case SILC_PROTOCOL_STATE_FAILURE:
536 * Received failure from remote.
539 /* Unregister the timeout task since the protocol has ended.
540 This was the timeout task to be executed if the protocol is
541 not completed fast enough. */
542 if (ctx->timeout_task)
543 silc_schedule_task_del(client->schedule, ctx->timeout_task);
545 /* On error the final callback is always called. */
546 if (protocol->final_callback)
547 silc_protocol_execute_final(protocol, client->schedule);
549 silc_protocol_free(protocol);
551 case SILC_PROTOCOL_STATE_UNKNOWN:
557 * Connection Authentication protocol functions
561 silc_client_get_public_key_auth(SilcClient client,
562 SilcClientConnection conn,
563 unsigned char *auth_data,
564 uint32 *auth_data_len,
571 /* Use our default key */
574 /* Make the authentication data. Protocol says it is HASH plus
576 len = ske->hash_len + ske->start_payload_copy->len;
577 auth = silc_buffer_alloc(len);
578 silc_buffer_pull_tail(auth, len);
579 silc_buffer_format(auth,
580 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
581 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
582 ske->start_payload_copy->len),
585 if (silc_pkcs_sign_with_hash(pkcs, ske->prop->hash, auth->data,
586 auth->len, auth_data, auth_data_len)) {
587 silc_buffer_free(auth);
591 silc_buffer_free(auth);
595 /* Continues the connection authentication protocol. This funtion may
596 be called directly or used as SilcAskPassphrase callback. */
599 silc_client_conn_auth_continue(unsigned char *auth_data,
600 uint32 auth_data_len, void *context)
602 SilcProtocol protocol = (SilcProtocol)context;
603 SilcClientConnAuthInternalContext *ctx =
604 (SilcClientConnAuthInternalContext *)protocol->context;
605 SilcClient client = (SilcClient)ctx->client;
609 SILC_LOG_DEBUG(("Start"));
611 payload_len = 4 + auth_data_len;
612 packet = silc_buffer_alloc(payload_len);
613 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
614 silc_buffer_format(packet,
615 SILC_STR_UI_SHORT(payload_len),
616 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
617 SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
620 /* Send the packet to server */
621 silc_client_packet_send(client, ctx->sock,
622 SILC_PACKET_CONNECTION_AUTH,
624 packet->data, packet->len, TRUE);
625 silc_buffer_free(packet);
627 /* Next state is end of protocol */
628 protocol->state = SILC_PROTOCOL_STATE_END;
631 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
633 SilcProtocol protocol = (SilcProtocol)context;
634 SilcClientConnAuthInternalContext *ctx =
635 (SilcClientConnAuthInternalContext *)protocol->context;
636 SilcClient client = (SilcClient)ctx->client;
637 SilcClientConnection conn = ctx->sock->user_data;
639 SILC_LOG_DEBUG(("Start"));
641 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
642 protocol->state = SILC_PROTOCOL_STATE_START;
644 switch(protocol->state) {
645 case SILC_PROTOCOL_STATE_START:
648 * Start protocol. We send authentication data to the server
649 * to be authenticated.
651 unsigned char *auth_data = NULL;
652 uint32 auth_data_len = 0;
653 unsigned char sign[1024];
655 switch(ctx->auth_meth) {
657 /* No authentication required */
660 case SILC_AUTH_PASSWORD:
661 /* Password authentication */
662 if (ctx->auth_data && ctx->auth_data_len) {
663 auth_data = ctx->auth_data;
664 auth_data_len = ctx->auth_data_len;
668 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_INFO,
669 "Password authentication required by server %s",
670 ctx->sock->hostname);
671 client->ops->ask_passphrase(client, conn,
672 silc_client_conn_auth_continue,
677 case SILC_AUTH_PUBLIC_KEY:
678 if (!ctx->auth_data) {
679 /* Public key authentication */
680 silc_client_get_public_key_auth(client, conn, sign, &auth_data_len,
684 auth_data = ctx->auth_data;
685 auth_data_len = ctx->auth_data_len;
691 silc_client_conn_auth_continue(auth_data,
692 auth_data_len, protocol);
696 case SILC_PROTOCOL_STATE_END:
699 * End protocol. Nothing special to be done here.
702 /* Protocol has ended, call the final callback */
703 if (protocol->final_callback)
704 silc_protocol_execute_final(protocol, client->schedule);
706 silc_protocol_free(protocol);
710 case SILC_PROTOCOL_STATE_ERROR:
713 * Error. Send notify to remote.
715 unsigned char error[4];
717 SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
719 /* Error in protocol. Send FAILURE packet. Although I don't think
720 this could ever happen on client side. */
721 silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
722 NULL, 0, NULL, NULL, error, 4, TRUE);
724 /* On error the final callback is always called. */
725 if (protocol->final_callback)
726 silc_protocol_execute_final(protocol, client->schedule);
728 silc_protocol_free(protocol);
731 case SILC_PROTOCOL_STATE_FAILURE:
733 * Received failure from remote.
736 /* On error the final callback is always called. */
737 if (protocol->final_callback)
738 silc_protocol_execute_final(protocol, client->schedule);
740 silc_protocol_free(protocol);
743 case SILC_PROTOCOL_STATE_UNKNOWN:
749 * Re-key protocol routines
752 /* Actually takes the new keys into use. */
755 silc_client_protocol_rekey_validate(SilcClient client,
756 SilcClientRekeyInternalContext *ctx,
757 SilcSocketConnection sock,
758 SilcSKEKeyMaterial *keymat,
761 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
763 if (ctx->responder == TRUE) {
765 silc_cipher_set_key(conn->send_key, keymat->receive_enc_key,
766 keymat->enc_key_len);
767 silc_cipher_set_iv(conn->send_key, keymat->receive_iv);
768 silc_hmac_set_key(conn->hmac_send, keymat->receive_hmac_key,
769 keymat->hmac_key_len);
771 silc_cipher_set_key(conn->receive_key, keymat->send_enc_key,
772 keymat->enc_key_len);
773 silc_cipher_set_iv(conn->receive_key, keymat->send_iv);
774 silc_hmac_set_key(conn->hmac_receive, keymat->send_hmac_key,
775 keymat->hmac_key_len);
779 silc_cipher_set_key(conn->send_key, keymat->send_enc_key,
780 keymat->enc_key_len);
781 silc_cipher_set_iv(conn->send_key, keymat->send_iv);
782 silc_hmac_set_key(conn->hmac_send, keymat->send_hmac_key,
783 keymat->hmac_key_len);
785 silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key,
786 keymat->enc_key_len);
787 silc_cipher_set_iv(conn->receive_key, keymat->receive_iv);
788 silc_hmac_set_key(conn->hmac_receive, keymat->receive_hmac_key,
789 keymat->hmac_key_len);
793 /* Save the current sending encryption key */
795 memset(conn->rekey->send_enc_key, 0, conn->rekey->enc_key_len);
796 silc_free(conn->rekey->send_enc_key);
797 conn->rekey->send_enc_key =
798 silc_calloc(keymat->enc_key_len / 8,
799 sizeof(*conn->rekey->send_enc_key));
800 memcpy(conn->rekey->send_enc_key, keymat->send_enc_key,
801 keymat->enc_key_len / 8);
802 conn->rekey->enc_key_len = keymat->enc_key_len / 8;
806 /* This function actually re-generates (when not using PFS) the keys and
807 takes them into use. */
810 silc_client_protocol_rekey_generate(SilcClient client,
811 SilcClientRekeyInternalContext *ctx,
814 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
815 SilcSKEKeyMaterial *keymat;
816 uint32 key_len = silc_cipher_get_key_len(conn->send_key);
817 uint32 hash_len = conn->hash->hash->hash_len;
819 SILC_LOG_DEBUG(("Generating new %s session keys (no PFS)",
820 send ? "sending" : "receiving"));
822 /* Generate the new key */
823 keymat = silc_calloc(1, sizeof(*keymat));
824 silc_ske_process_key_material_data(conn->rekey->send_enc_key,
825 conn->rekey->enc_key_len,
826 16, key_len, hash_len,
829 /* Set the keys into use */
830 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
832 silc_ske_free_key_material(keymat);
835 /* This function actually re-generates (with PFS) the keys and
836 takes them into use. */
839 silc_client_protocol_rekey_generate_pfs(SilcClient client,
840 SilcClientRekeyInternalContext *ctx,
843 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
844 SilcSKEKeyMaterial *keymat;
845 uint32 key_len = silc_cipher_get_key_len(conn->send_key);
846 uint32 hash_len = conn->hash->hash->hash_len;
847 unsigned char *tmpbuf;
850 SILC_LOG_DEBUG(("Generating new %s session keys (with PFS)",
851 send ? "sending" : "receiving"));
853 /* Encode KEY to binary data */
854 tmpbuf = silc_mp_mp2bin(ctx->ske->KEY, 0, &klen);
856 /* Generate the new key */
857 keymat = silc_calloc(1, sizeof(*keymat));
858 silc_ske_process_key_material_data(tmpbuf, klen, 16, key_len, hash_len,
861 /* Set the keys into use */
862 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
864 memset(tmpbuf, 0, klen);
866 silc_ske_free_key_material(keymat);
869 /* Packet sending callback. This function is provided as packet sending
870 routine to the Key Exchange functions. */
873 silc_client_protocol_rekey_send_packet(SilcSKE ske,
878 SilcProtocol protocol = (SilcProtocol)context;
879 SilcClientRekeyInternalContext *ctx =
880 (SilcClientRekeyInternalContext *)protocol->context;
881 SilcClient client = (SilcClient)ctx->client;
883 /* Send the packet immediately */
884 silc_client_packet_send(client, ctx->sock, type, NULL, 0, NULL, NULL,
885 packet->data, packet->len, FALSE);
888 /* Performs re-key as defined in the SILC protocol specification. */
890 SILC_TASK_CALLBACK(silc_client_protocol_rekey)
892 SilcProtocol protocol = (SilcProtocol)context;
893 SilcClientRekeyInternalContext *ctx =
894 (SilcClientRekeyInternalContext *)protocol->context;
895 SilcClient client = (SilcClient)ctx->client;
896 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
897 SilcSKEStatus status;
899 SILC_LOG_DEBUG(("Start"));
901 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
902 protocol->state = SILC_PROTOCOL_STATE_START;
904 SILC_LOG_DEBUG(("State=%d", protocol->state));
906 switch(protocol->state) {
907 case SILC_PROTOCOL_STATE_START:
913 if (ctx->responder == TRUE) {
915 * We are receiving party
918 if (ctx->pfs == TRUE) {
920 * Use Perfect Forward Secrecy, ie. negotiate the key material
921 * using the SKE protocol.
924 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
925 /* Error in protocol */
926 protocol->state = SILC_PROTOCOL_STATE_ERROR;
927 silc_protocol_execute(protocol, client->schedule, 0, 300000);
930 ctx->ske = silc_ske_alloc();
931 ctx->ske->rng = client->rng;
932 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
933 silc_ske_get_group_by_number(conn->rekey->ske_group,
934 &ctx->ske->prop->group);
936 silc_ske_set_callbacks(ctx->ske,
937 silc_client_protocol_rekey_send_packet,
938 NULL, NULL, NULL, silc_ske_check_version,
941 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer);
942 if (status != SILC_SKE_STATUS_OK) {
943 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
946 protocol->state = SILC_PROTOCOL_STATE_ERROR;
947 silc_protocol_execute(protocol, client->schedule, 0, 300000);
951 /* Advance the protocol state */
953 silc_protocol_execute(protocol, client->schedule, 0, 0);
956 * Do normal and simple re-key.
959 /* Send the REKEY_DONE to indicate we will take new keys into use */
960 silc_client_packet_send(client, ctx->sock,
961 SILC_PACKET_REKEY_DONE,
962 NULL, 0, NULL, NULL, NULL, 0, FALSE);
964 /* After we send REKEY_DONE we must set the sending encryption
965 key to the new key since all packets after this packet must
966 encrypted with the new key. */
967 silc_client_protocol_rekey_generate(client, ctx, TRUE);
969 /* The protocol ends in next stage. */
970 protocol->state = SILC_PROTOCOL_STATE_END;
975 * We are the initiator of this protocol
978 /* Start the re-key by sending the REKEY packet */
979 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY,
980 NULL, 0, NULL, NULL, NULL, 0, FALSE);
982 if (ctx->pfs == TRUE) {
984 * Use Perfect Forward Secrecy, ie. negotiate the key material
985 * using the SKE protocol.
987 ctx->ske = silc_ske_alloc();
988 ctx->ske->rng = client->rng;
989 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
990 silc_ske_get_group_by_number(conn->rekey->ske_group,
991 &ctx->ske->prop->group);
993 silc_ske_set_callbacks(ctx->ske,
994 silc_client_protocol_rekey_send_packet,
995 NULL, NULL, NULL, silc_ske_check_version,
998 status = silc_ske_initiator_phase_2(ctx->ske, NULL, NULL);
999 if (status != SILC_SKE_STATUS_OK) {
1000 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
1003 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1004 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1008 /* Advance the protocol state */
1012 * Do normal and simple re-key.
1015 /* Send the REKEY_DONE to indicate we will take new keys into use
1017 silc_client_packet_send(client, ctx->sock,
1018 SILC_PACKET_REKEY_DONE,
1019 NULL, 0, NULL, NULL, NULL, 0, FALSE);
1021 /* After we send REKEY_DONE we must set the sending encryption
1022 key to the new key since all packets after this packet must
1023 encrypted with the new key. */
1024 silc_client_protocol_rekey_generate(client, ctx, TRUE);
1026 /* The protocol ends in next stage. */
1027 protocol->state = SILC_PROTOCOL_STATE_END;
1035 * Second state, used only when oding re-key with PFS.
1037 if (ctx->responder == TRUE) {
1038 if (ctx->pfs == TRUE) {
1040 * Send our KE packe to the initiator now that we've processed
1041 * the initiator's KE packet.
1043 status = silc_ske_responder_finish(ctx->ske, NULL, NULL,
1044 SILC_SKE_PK_TYPE_SILC);
1046 if (status != SILC_SKE_STATUS_OK) {
1047 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
1050 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1051 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1057 if (ctx->pfs == TRUE) {
1059 * The packet type must be KE packet
1061 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
1062 /* Error in protocol */
1063 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1064 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1067 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer);
1068 if (status != SILC_SKE_STATUS_OK) {
1069 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
1072 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1073 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1079 /* Send the REKEY_DONE to indicate we will take new keys into use
1081 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
1082 NULL, 0, NULL, NULL, NULL, 0, FALSE);
1084 /* After we send REKEY_DONE we must set the sending encryption
1085 key to the new key since all packets after this packet must
1086 encrypted with the new key. */
1087 silc_client_protocol_rekey_generate_pfs(client, ctx, TRUE);
1089 /* The protocol ends in next stage. */
1090 protocol->state = SILC_PROTOCOL_STATE_END;
1093 case SILC_PROTOCOL_STATE_END:
1098 if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
1099 /* Error in protocol */
1100 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1101 silc_protocol_execute(protocol, client->schedule, 0, 0);
1104 /* We received the REKEY_DONE packet and all packets after this is
1105 encrypted with the new key so set the decryption key to the new key */
1106 silc_client_protocol_rekey_generate(client, ctx, FALSE);
1108 /* Protocol has ended, call the final callback */
1109 if (protocol->final_callback)
1110 silc_protocol_execute_final(protocol, client->schedule);
1112 silc_protocol_free(protocol);
1115 case SILC_PROTOCOL_STATE_ERROR:
1120 if (ctx->pfs == TRUE) {
1121 /* Send abort notification */
1122 silc_ske_abort(ctx->ske, ctx->ske->status);
1125 /* On error the final callback is always called. */
1126 if (protocol->final_callback)
1127 silc_protocol_execute_final(protocol, client->schedule);
1129 silc_protocol_free(protocol);
1132 case SILC_PROTOCOL_STATE_FAILURE:
1134 * We have received failure from remote
1137 /* On error the final callback is always called. */
1138 if (protocol->final_callback)
1139 silc_protocol_execute_final(protocol, client->schedule);
1141 silc_protocol_free(protocol);
1144 case SILC_PROTOCOL_STATE_UNKNOWN:
1150 /* Registers protocols used in client */
1152 void silc_client_protocols_register(void)
1154 silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1155 silc_client_protocol_connection_auth);
1156 silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1157 silc_client_protocol_key_exchange);
1158 silc_protocol_register(SILC_PROTOCOL_CLIENT_REKEY,
1159 silc_client_protocol_rekey);
1162 /* Unregisters protocols */
1164 void silc_client_protocols_unregister(void)
1166 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1167 silc_client_protocol_connection_auth);
1168 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1169 silc_client_protocol_key_exchange);
1170 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_REKEY,
1171 silc_client_protocol_rekey);