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 uint32 len, void *context)
172 SilcClientConnection conn = (SilcClientConnection)ske->sock->user_data;
173 SilcClient client = (SilcClient)ske->user_data;
174 SilcSKEStatus status = SILC_SKE_STATUS_OK;
176 int maj = 0, min = 0, build = 0, maj2 = 0, min2 = 0, build2 = 0;
178 /* Check for initial version string */
179 if (!strstr(version, "SILC-1.0-"))
180 status = SILC_SKE_STATUS_BAD_VERSION;
182 /* Check software version */
186 status = SILC_SKE_STATUS_BAD_VERSION;
189 cp = strchr(cp, '.');
194 cp = strchr(cp, '.');
196 build = atoi(cp + 1);
198 cp = client->internal->silc_client_version + 9;
200 status = SILC_SKE_STATUS_BAD_VERSION;
203 cp = strchr(cp, '.');
208 cp = strchr(cp, '.');
210 build2 = atoi(cp + 1);
213 status = SILC_SKE_STATUS_BAD_VERSION;
215 /* XXX backward support for 0.6.1 */
216 if (maj == 0 && min == 6 && build < 2)
217 ske->backward_version = 1;
219 if (status != SILC_SKE_STATUS_OK)
220 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
221 "We don't support server version `%s'",
227 /* Callback that is called by the SKE to indicate that it is safe to
228 continue the execution of the protocol. Is given as argument to the
229 silc_ske_initiator_finish or silc_ske_responder_phase_2 functions.
230 This is called due to the fact that the public key verification
231 process is asynchronous and we must not continue the protocl until
232 the public key has been verified and this callback is called. */
234 static void silc_client_protocol_ke_continue(SilcSKE ske,
237 SilcProtocol protocol = (SilcProtocol)context;
238 SilcClientKEInternalContext *ctx =
239 (SilcClientKEInternalContext *)protocol->context;
240 SilcClient client = (SilcClient)ctx->client;
241 SilcClientConnection conn = ctx->sock->user_data;
243 SILC_LOG_DEBUG(("Start"));
245 if (ske->status != SILC_SKE_STATUS_OK) {
246 /* Call failure client operation */
247 client->internal->ops->failure(client, conn, protocol,
248 (void *)ske->status);
249 protocol->state = SILC_PROTOCOL_STATE_ERROR;
250 silc_protocol_execute(protocol, client->schedule, 0, 0);
254 /* Send Ok to the other end. We will end the protocol as server
255 sends Ok to us when we will take the new keys into use. Do this
256 if we are initiator. This is happens when this callback was sent
257 to silc_ske_initiator_finish function. */
258 if (ctx->responder == FALSE) {
259 silc_ske_end(ctx->ske);
261 /* End the protocol on the next round */
262 protocol->state = SILC_PROTOCOL_STATE_END;
265 /* Advance protocol state and call the next state if we are responder.
266 This happens when this callback was sent to silc_ske_responder_phase_2
268 if (ctx->responder == TRUE) {
270 silc_protocol_execute(protocol, client->schedule, 0, 100000);
274 /* Performs key exchange protocol. This is used for both initiator
275 and responder key exchange. This may be called recursively. */
277 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
279 SilcProtocol protocol = (SilcProtocol)context;
280 SilcClientKEInternalContext *ctx =
281 (SilcClientKEInternalContext *)protocol->context;
282 SilcClient client = (SilcClient)ctx->client;
283 SilcClientConnection conn = ctx->sock->user_data;
284 SilcSKEStatus status = SILC_SKE_STATUS_OK;
286 SILC_LOG_DEBUG(("Start"));
288 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
289 protocol->state = SILC_PROTOCOL_STATE_START;
291 switch(protocol->state) {
292 case SILC_PROTOCOL_STATE_START:
299 /* Allocate Key Exchange object */
300 ctx->ske = ske = silc_ske_alloc(client->rng, client);
302 silc_ske_set_callbacks(ske, ctx->send_packet, NULL,
304 silc_client_protocol_ke_continue,
305 silc_ske_check_version,
308 if (ctx->responder == TRUE) {
309 /* Start the key exchange by processing the received security
310 properties packet from initiator. */
312 silc_ske_responder_start(ske, ctx->rng, ctx->sock,
313 client->internal->silc_client_version,
314 ctx->packet->buffer, TRUE);
316 SilcSKEStartPayload *start_payload;
318 /* Assemble security properties. */
319 silc_ske_assemble_security_properties(
320 ske, SILC_SKE_SP_FLAG_MUTUAL,
321 client->internal->silc_client_version,
324 /* Start the key exchange by sending our security properties
325 to the remote end. */
326 status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
330 /* Return now if the procedure is pending */
331 if (status == SILC_SKE_STATUS_PENDING)
334 if (status != SILC_SKE_STATUS_OK) {
335 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
337 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
340 protocol->state = SILC_PROTOCOL_STATE_ERROR;
341 silc_protocol_execute(protocol, client->schedule, 0, 0);
345 /* Advance protocol state and call the next state if we are responder */
347 if (ctx->responder == TRUE)
348 silc_protocol_execute(protocol, client->schedule, 0, 100000);
356 if (ctx->responder == TRUE) {
357 /* Sends the selected security properties to the initiator. */
358 status = silc_ske_responder_phase_1(ctx->ske);
360 /* Call Phase-1 function. This processes the Key Exchange Start
361 paylaod reply we just got from the responder. The callback
362 function will receive the processed payload where we will
364 status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer);
367 if (status != SILC_SKE_STATUS_OK) {
368 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
370 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
373 protocol->state = SILC_PROTOCOL_STATE_ERROR;
374 silc_protocol_execute(protocol, client->schedule, 0, 0);
378 /* Advance protocol state and call next state if we are initiator */
380 if (ctx->responder == FALSE)
381 silc_protocol_execute(protocol, client->schedule, 0, 100000);
389 if (ctx->responder == TRUE) {
390 /* Process the received Key Exchange 1 Payload packet from
391 the initiator. This also creates our parts of the Diffie
392 Hellman algorithm. The silc_client_protocol_ke_continue will
393 be called after the public key has been verified. */
394 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer);
396 /* Call the Phase-2 function. This creates Diffie Hellman
397 key exchange parameters and sends our public part inside
398 Key Exhange 1 Payload to the responder. */
399 status = silc_ske_initiator_phase_2(ctx->ske,
402 SILC_SKE_PK_TYPE_SILC);
406 /* Return now if the procedure is pending */
407 if (status == SILC_SKE_STATUS_PENDING)
410 if (status != SILC_SKE_STATUS_OK) {
411 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
413 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
416 protocol->state = SILC_PROTOCOL_STATE_ERROR;
417 silc_protocol_execute(protocol, client->schedule, 0, 0);
427 if (ctx->responder == TRUE) {
428 /* This creates the key exchange material and sends our
429 public parts to the initiator inside Key Exchange 2 Payload. */
431 silc_ske_responder_finish(ctx->ske,
432 client->public_key, client->private_key,
433 SILC_SKE_PK_TYPE_SILC);
435 /* End the protocol on the next round */
436 protocol->state = SILC_PROTOCOL_STATE_END;
438 /* Finish the protocol. This verifies the Key Exchange 2 payload
439 sent by responder. The silc_client_protocol_ke_continue will
440 be called after the public key has been verified. */
441 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer);
444 /* Return now if the procedure is pending */
445 if (status == SILC_SKE_STATUS_PENDING)
448 if (status != SILC_SKE_STATUS_OK) {
449 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
450 client->internal->ops->say(
451 client, conn, SILC_CLIENT_MESSAGE_AUDIT,
452 "Received unsupported server %s public key",
453 ctx->sock->hostname);
455 client->internal->ops->say(
456 client, conn, SILC_CLIENT_MESSAGE_AUDIT,
457 "Error during key exchange protocol with server %s",
458 ctx->sock->hostname);
460 protocol->state = SILC_PROTOCOL_STATE_ERROR;
461 silc_protocol_execute(protocol, client->schedule, 0, 0);
467 case SILC_PROTOCOL_STATE_END:
472 SilcSKEKeyMaterial *keymat;
473 int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher);
474 int hash_len = ctx->ske->prop->hash->hash->hash_len;
476 /* Process the key material */
477 keymat = silc_calloc(1, sizeof(*keymat));
478 status = silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
480 if (status != SILC_SKE_STATUS_OK) {
481 protocol->state = SILC_PROTOCOL_STATE_ERROR;
482 silc_protocol_execute(protocol, client->schedule, 0, 300000);
483 silc_ske_free_key_material(keymat);
486 ctx->keymat = keymat;
488 /* Send Ok to the other end if we are responder. If we are initiator
489 we have sent this already. */
490 if (ctx->responder == TRUE)
491 silc_ske_end(ctx->ske);
493 /* Unregister the timeout task since the protocol has ended.
494 This was the timeout task to be executed if the protocol is
495 not completed fast enough. */
496 if (ctx->timeout_task)
497 silc_schedule_task_del(client->schedule, ctx->timeout_task);
499 /* Protocol has ended, call the final callback */
500 if (protocol->final_callback)
501 silc_protocol_execute_final(protocol, client->schedule);
503 silc_protocol_free(protocol);
507 case SILC_PROTOCOL_STATE_ERROR:
509 * Error during protocol
512 /* Send abort notification */
513 silc_ske_abort(ctx->ske, ctx->ske->status);
515 /* On error the final callback is always called. */
516 if (protocol->final_callback)
517 silc_protocol_execute_final(protocol, client->schedule);
519 silc_protocol_free(protocol);
522 case SILC_PROTOCOL_STATE_FAILURE:
524 * Received failure from remote.
527 /* Unregister the timeout task since the protocol has ended.
528 This was the timeout task to be executed if the protocol is
529 not completed fast enough. */
530 if (ctx->timeout_task)
531 silc_schedule_task_del(client->schedule, ctx->timeout_task);
533 /* On error the final callback is always called. */
534 if (protocol->final_callback)
535 silc_protocol_execute_final(protocol, client->schedule);
537 silc_protocol_free(protocol);
539 case SILC_PROTOCOL_STATE_UNKNOWN:
545 * Connection Authentication protocol functions
549 silc_client_get_public_key_auth(SilcClient client,
550 SilcClientConnection conn,
551 unsigned char *auth_data,
552 uint32 *auth_data_len,
559 /* Use our default key */
562 /* Make the authentication data. Protocol says it is HASH plus
564 len = ske->hash_len + ske->start_payload_copy->len;
565 auth = silc_buffer_alloc(len);
566 silc_buffer_pull_tail(auth, len);
567 silc_buffer_format(auth,
568 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
569 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
570 ske->start_payload_copy->len),
573 if (silc_pkcs_sign_with_hash(pkcs, ske->prop->hash, auth->data,
574 auth->len, auth_data, auth_data_len)) {
575 silc_buffer_free(auth);
579 silc_buffer_free(auth);
583 /* Continues the connection authentication protocol. This funtion may
584 be called directly or used as SilcAskPassphrase callback. */
587 silc_client_conn_auth_continue(unsigned char *auth_data,
588 uint32 auth_data_len, void *context)
590 SilcProtocol protocol = (SilcProtocol)context;
591 SilcClientConnAuthInternalContext *ctx =
592 (SilcClientConnAuthInternalContext *)protocol->context;
593 SilcClient client = (SilcClient)ctx->client;
597 SILC_LOG_DEBUG(("Start"));
599 payload_len = 4 + auth_data_len;
600 packet = silc_buffer_alloc(payload_len);
601 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
602 silc_buffer_format(packet,
603 SILC_STR_UI_SHORT(payload_len),
604 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
605 SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
608 /* Send the packet to server */
609 silc_client_packet_send(client, ctx->sock,
610 SILC_PACKET_CONNECTION_AUTH,
612 packet->data, packet->len, TRUE);
613 silc_buffer_free(packet);
615 /* Next state is end of protocol */
616 protocol->state = SILC_PROTOCOL_STATE_END;
619 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
621 SilcProtocol protocol = (SilcProtocol)context;
622 SilcClientConnAuthInternalContext *ctx =
623 (SilcClientConnAuthInternalContext *)protocol->context;
624 SilcClient client = (SilcClient)ctx->client;
625 SilcClientConnection conn = ctx->sock->user_data;
627 SILC_LOG_DEBUG(("Start"));
629 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
630 protocol->state = SILC_PROTOCOL_STATE_START;
632 switch(protocol->state) {
633 case SILC_PROTOCOL_STATE_START:
636 * Start protocol. We send authentication data to the server
637 * to be authenticated.
639 unsigned char *auth_data = NULL;
640 uint32 auth_data_len = 0;
641 unsigned char sign[1024];
643 switch(ctx->auth_meth) {
645 /* No authentication required */
648 case SILC_AUTH_PASSWORD:
649 /* Password authentication */
650 if (ctx->auth_data && ctx->auth_data_len) {
651 auth_data = ctx->auth_data;
652 auth_data_len = ctx->auth_data_len;
656 client->internal->ops->say(
657 client, conn, SILC_CLIENT_MESSAGE_INFO,
658 "Password authentication required by server %s",
659 ctx->sock->hostname);
660 client->internal->ops->ask_passphrase(client, conn,
661 silc_client_conn_auth_continue,
666 case SILC_AUTH_PUBLIC_KEY:
667 if (!ctx->auth_data) {
668 /* Public key authentication */
669 silc_client_get_public_key_auth(client, conn, sign, &auth_data_len,
673 auth_data = ctx->auth_data;
674 auth_data_len = ctx->auth_data_len;
680 silc_client_conn_auth_continue(auth_data,
681 auth_data_len, protocol);
685 case SILC_PROTOCOL_STATE_END:
688 * End protocol. Nothing special to be done here.
691 /* Protocol has ended, call the final callback */
692 if (protocol->final_callback)
693 silc_protocol_execute_final(protocol, client->schedule);
695 silc_protocol_free(protocol);
699 case SILC_PROTOCOL_STATE_ERROR:
702 * Error. Send notify to remote.
704 unsigned char error[4];
706 SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
708 /* Error in protocol. Send FAILURE packet. Although I don't think
709 this could ever happen on client side. */
710 silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
711 NULL, 0, NULL, NULL, error, 4, TRUE);
713 /* On error the final callback is always called. */
714 if (protocol->final_callback)
715 silc_protocol_execute_final(protocol, client->schedule);
717 silc_protocol_free(protocol);
720 case SILC_PROTOCOL_STATE_FAILURE:
722 * Received failure from remote.
725 /* On error the final callback is always called. */
726 if (protocol->final_callback)
727 silc_protocol_execute_final(protocol, client->schedule);
729 silc_protocol_free(protocol);
732 case SILC_PROTOCOL_STATE_UNKNOWN:
738 * Re-key protocol routines
741 /* Actually takes the new keys into use. */
744 silc_client_protocol_rekey_validate(SilcClient client,
745 SilcClientRekeyInternalContext *ctx,
746 SilcSocketConnection sock,
747 SilcSKEKeyMaterial *keymat,
750 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
752 if (ctx->responder == TRUE) {
754 silc_cipher_set_key(conn->send_key, keymat->receive_enc_key,
755 keymat->enc_key_len);
756 silc_cipher_set_iv(conn->send_key, keymat->receive_iv);
757 silc_hmac_set_key(conn->hmac_send, keymat->receive_hmac_key,
758 keymat->hmac_key_len);
760 silc_cipher_set_key(conn->receive_key, keymat->send_enc_key,
761 keymat->enc_key_len);
762 silc_cipher_set_iv(conn->receive_key, keymat->send_iv);
763 silc_hmac_set_key(conn->hmac_receive, keymat->send_hmac_key,
764 keymat->hmac_key_len);
768 silc_cipher_set_key(conn->send_key, keymat->send_enc_key,
769 keymat->enc_key_len);
770 silc_cipher_set_iv(conn->send_key, keymat->send_iv);
771 silc_hmac_set_key(conn->hmac_send, keymat->send_hmac_key,
772 keymat->hmac_key_len);
774 silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key,
775 keymat->enc_key_len);
776 silc_cipher_set_iv(conn->receive_key, keymat->receive_iv);
777 silc_hmac_set_key(conn->hmac_receive, keymat->receive_hmac_key,
778 keymat->hmac_key_len);
782 /* Save the current sending encryption key */
784 memset(conn->rekey->send_enc_key, 0, conn->rekey->enc_key_len);
785 silc_free(conn->rekey->send_enc_key);
786 conn->rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
787 keymat->enc_key_len / 8);
788 conn->rekey->enc_key_len = keymat->enc_key_len / 8;
792 /* This function actually re-generates (when not using PFS) the keys and
793 takes them into use. */
796 silc_client_protocol_rekey_generate(SilcClient client,
797 SilcClientRekeyInternalContext *ctx,
800 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
801 SilcSKEKeyMaterial *keymat;
802 uint32 key_len = silc_cipher_get_key_len(conn->send_key);
803 uint32 hash_len = conn->hash->hash->hash_len;
805 SILC_LOG_DEBUG(("Generating new %s session keys (no PFS)",
806 send ? "sending" : "receiving"));
808 /* Generate the new key */
809 keymat = silc_calloc(1, sizeof(*keymat));
810 silc_ske_process_key_material_data(conn->rekey->send_enc_key,
811 conn->rekey->enc_key_len,
812 16, key_len, hash_len,
815 /* Set the keys into use */
816 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
818 silc_ske_free_key_material(keymat);
821 /* This function actually re-generates (with PFS) the keys and
822 takes them into use. */
825 silc_client_protocol_rekey_generate_pfs(SilcClient client,
826 SilcClientRekeyInternalContext *ctx,
829 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
830 SilcSKEKeyMaterial *keymat;
831 uint32 key_len = silc_cipher_get_key_len(conn->send_key);
832 uint32 hash_len = conn->hash->hash->hash_len;
833 unsigned char *tmpbuf;
836 SILC_LOG_DEBUG(("Generating new %s session keys (with PFS)",
837 send ? "sending" : "receiving"));
839 /* Encode KEY to binary data */
840 tmpbuf = silc_mp_mp2bin(ctx->ske->KEY, 0, &klen);
842 /* Generate the new key */
843 keymat = silc_calloc(1, sizeof(*keymat));
844 silc_ske_process_key_material_data(tmpbuf, klen, 16, key_len, hash_len,
847 /* Set the keys into use */
848 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
850 memset(tmpbuf, 0, klen);
852 silc_ske_free_key_material(keymat);
855 /* Packet sending callback. This function is provided as packet sending
856 routine to the Key Exchange functions. */
859 silc_client_protocol_rekey_send_packet(SilcSKE ske,
864 SilcProtocol protocol = (SilcProtocol)context;
865 SilcClientRekeyInternalContext *ctx =
866 (SilcClientRekeyInternalContext *)protocol->context;
867 SilcClient client = (SilcClient)ctx->client;
869 /* Send the packet immediately */
870 silc_client_packet_send(client, ctx->sock, type, NULL, 0, NULL, NULL,
871 packet->data, packet->len, FALSE);
874 /* Performs re-key as defined in the SILC protocol specification. */
876 SILC_TASK_CALLBACK(silc_client_protocol_rekey)
878 SilcProtocol protocol = (SilcProtocol)context;
879 SilcClientRekeyInternalContext *ctx =
880 (SilcClientRekeyInternalContext *)protocol->context;
881 SilcClient client = (SilcClient)ctx->client;
882 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
883 SilcSKEStatus status;
885 SILC_LOG_DEBUG(("Start"));
887 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
888 protocol->state = SILC_PROTOCOL_STATE_START;
890 SILC_LOG_DEBUG(("State=%d", protocol->state));
892 switch(protocol->state) {
893 case SILC_PROTOCOL_STATE_START:
899 if (ctx->responder == TRUE) {
901 * We are receiving party
904 if (ctx->pfs == TRUE) {
906 * Use Perfect Forward Secrecy, ie. negotiate the key material
907 * using the SKE protocol.
910 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
911 /* Error in protocol */
912 protocol->state = SILC_PROTOCOL_STATE_ERROR;
913 silc_protocol_execute(protocol, client->schedule, 0, 300000);
916 ctx->ske = silc_ske_alloc(client->rng, client);
917 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
918 silc_ske_group_get_by_number(conn->rekey->ske_group,
919 &ctx->ske->prop->group);
921 silc_ske_set_callbacks(ctx->ske,
922 silc_client_protocol_rekey_send_packet,
923 NULL, NULL, NULL, silc_ske_check_version,
926 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer);
927 if (status != SILC_SKE_STATUS_OK) {
928 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
931 protocol->state = SILC_PROTOCOL_STATE_ERROR;
932 silc_protocol_execute(protocol, client->schedule, 0, 300000);
936 /* Advance the protocol state */
938 silc_protocol_execute(protocol, client->schedule, 0, 0);
941 * Do normal and simple re-key.
944 /* Send the REKEY_DONE to indicate we will take new keys into use */
945 silc_client_packet_send(client, ctx->sock,
946 SILC_PACKET_REKEY_DONE,
947 NULL, 0, NULL, NULL, NULL, 0, FALSE);
949 /* After we send REKEY_DONE we must set the sending encryption
950 key to the new key since all packets after this packet must
951 encrypted with the new key. */
952 silc_client_protocol_rekey_generate(client, ctx, TRUE);
954 /* The protocol ends in next stage. */
955 protocol->state = SILC_PROTOCOL_STATE_END;
960 * We are the initiator of this protocol
963 /* Start the re-key by sending the REKEY packet */
964 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY,
965 NULL, 0, NULL, NULL, NULL, 0, FALSE);
967 if (ctx->pfs == TRUE) {
969 * Use Perfect Forward Secrecy, ie. negotiate the key material
970 * using the SKE protocol.
972 ctx->ske = silc_ske_alloc(client->rng, client);
973 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
974 silc_ske_group_get_by_number(conn->rekey->ske_group,
975 &ctx->ske->prop->group);
977 silc_ske_set_callbacks(ctx->ske,
978 silc_client_protocol_rekey_send_packet,
979 NULL, NULL, NULL, silc_ske_check_version,
982 status = silc_ske_initiator_phase_2(ctx->ske, NULL, NULL, 0);
983 if (status != SILC_SKE_STATUS_OK) {
984 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
987 protocol->state = SILC_PROTOCOL_STATE_ERROR;
988 silc_protocol_execute(protocol, client->schedule, 0, 300000);
992 /* Advance the protocol state */
996 * Do normal and simple re-key.
999 /* Send the REKEY_DONE to indicate we will take new keys into use
1001 silc_client_packet_send(client, ctx->sock,
1002 SILC_PACKET_REKEY_DONE,
1003 NULL, 0, NULL, NULL, NULL, 0, FALSE);
1005 /* After we send REKEY_DONE we must set the sending encryption
1006 key to the new key since all packets after this packet must
1007 encrypted with the new key. */
1008 silc_client_protocol_rekey_generate(client, ctx, TRUE);
1010 /* The protocol ends in next stage. */
1011 protocol->state = SILC_PROTOCOL_STATE_END;
1019 * Second state, used only when oding re-key with PFS.
1021 if (ctx->responder == TRUE) {
1022 if (ctx->pfs == TRUE) {
1024 * Send our KE packe to the initiator now that we've processed
1025 * the initiator's KE packet.
1027 status = silc_ske_responder_finish(ctx->ske, NULL, NULL,
1028 SILC_SKE_PK_TYPE_SILC);
1030 if (status != SILC_SKE_STATUS_OK) {
1031 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
1034 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1035 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1041 if (ctx->pfs == TRUE) {
1043 * The packet type must be KE packet
1045 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
1046 /* Error in protocol */
1047 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1048 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1051 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer);
1052 if (status != SILC_SKE_STATUS_OK) {
1053 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
1056 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1057 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1063 /* Send the REKEY_DONE to indicate we will take new keys into use
1065 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
1066 NULL, 0, NULL, NULL, NULL, 0, FALSE);
1068 /* After we send REKEY_DONE we must set the sending encryption
1069 key to the new key since all packets after this packet must
1070 encrypted with the new key. */
1071 silc_client_protocol_rekey_generate_pfs(client, ctx, TRUE);
1073 /* The protocol ends in next stage. */
1074 protocol->state = SILC_PROTOCOL_STATE_END;
1077 case SILC_PROTOCOL_STATE_END:
1082 if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
1083 /* Error in protocol */
1084 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1085 silc_protocol_execute(protocol, client->schedule, 0, 0);
1088 /* We received the REKEY_DONE packet and all packets after this is
1089 encrypted with the new key so set the decryption key to the new key */
1090 silc_client_protocol_rekey_generate(client, ctx, FALSE);
1092 /* Protocol has ended, call the final callback */
1093 if (protocol->final_callback)
1094 silc_protocol_execute_final(protocol, client->schedule);
1096 silc_protocol_free(protocol);
1099 case SILC_PROTOCOL_STATE_ERROR:
1104 if (ctx->pfs == TRUE) {
1105 /* Send abort notification */
1106 silc_ske_abort(ctx->ske, ctx->ske->status);
1109 /* On error the final callback is always called. */
1110 if (protocol->final_callback)
1111 silc_protocol_execute_final(protocol, client->schedule);
1113 silc_protocol_free(protocol);
1116 case SILC_PROTOCOL_STATE_FAILURE:
1118 * We have received failure from remote
1121 /* On error the final callback is always called. */
1122 if (protocol->final_callback)
1123 silc_protocol_execute_final(protocol, client->schedule);
1125 silc_protocol_free(protocol);
1128 case SILC_PROTOCOL_STATE_UNKNOWN:
1134 /* Registers protocols used in client */
1136 void silc_client_protocols_register(void)
1138 silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1139 silc_client_protocol_connection_auth);
1140 silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1141 silc_client_protocol_key_exchange);
1142 silc_protocol_register(SILC_PROTOCOL_CLIENT_REKEY,
1143 silc_client_protocol_rekey);
1146 /* Unregisters protocols */
1148 void silc_client_protocols_unregister(void)
1150 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1151 silc_client_protocol_connection_auth);
1152 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1153 silc_client_protocol_key_exchange);
1154 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_REKEY,
1155 silc_client_protocol_rekey);