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)
117 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
119 SILC_LOG_DEBUG(("Setting new keys into use"));
121 /* Allocate cipher to be used in the communication */
122 silc_cipher_alloc(cipher->cipher->name, &conn->send_key);
123 silc_cipher_alloc(cipher->cipher->name, &conn->receive_key);
125 conn->send_key->cipher->set_key(conn->send_key->context,
126 keymat->send_enc_key,
127 keymat->enc_key_len);
128 conn->send_key->set_iv(conn->send_key, keymat->send_iv);
129 conn->receive_key->cipher->set_key(conn->receive_key->context,
130 keymat->receive_enc_key,
131 keymat->enc_key_len);
132 conn->receive_key->set_iv(conn->receive_key, keymat->receive_iv);
135 conn->rekey = silc_calloc(1, sizeof(*conn->rekey));
136 conn->rekey->send_enc_key =
137 silc_calloc(keymat->enc_key_len / 8,
138 sizeof(*conn->rekey->send_enc_key));
139 memcpy(conn->rekey->send_enc_key,
140 keymat->send_enc_key, keymat->enc_key_len / 8);
141 conn->rekey->enc_key_len = keymat->enc_key_len / 8;
143 if (ske->start_payload->flags & SILC_SKE_SP_FLAG_PFS)
144 conn->rekey->pfs = TRUE;
145 conn->rekey->ske_group = silc_ske_group_get_number(group);
147 /* Save HMAC key to be used in the communication. */
148 silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL, &conn->hmac_send);
149 silc_hmac_set_key(conn->hmac_send, keymat->hmac_key, keymat->hmac_key_len);
150 conn->hmac_receive = conn->hmac_send;
152 /* Save the HASH function */
153 silc_hash_alloc(hash->hash->name, &conn->hash);
156 /* Checks the version string of the server. */
158 SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
159 uint32 len, void *context)
161 SilcClientConnection conn = (SilcClientConnection)ske->sock->user_data;
162 SilcClient client = (SilcClient)ske->user_data;
163 SilcSKEStatus status = SILC_SKE_STATUS_OK;
165 int maj = 0, min = 0, build = 0, maj2 = 0, min2 = 0, build2 = 0;
167 /* Check for initial version string */
168 if (!strstr(version, "SILC-1.0-"))
169 status = SILC_SKE_STATUS_BAD_VERSION;
171 /* Check software version */
175 status = SILC_SKE_STATUS_BAD_VERSION;
178 cp = strchr(cp, '.');
183 cp = strchr(cp, '.');
185 build = atoi(cp + 1);
187 cp = client->silc_client_version + 9;
189 status = SILC_SKE_STATUS_BAD_VERSION;
192 cp = strchr(cp, '.');
197 cp = strchr(cp, '.');
199 build2 = atoi(cp + 1);
202 status = SILC_SKE_STATUS_BAD_VERSION;
204 status = SILC_SKE_STATUS_BAD_VERSION;
206 if (status != SILC_SKE_STATUS_OK)
207 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
208 "We don't support server version `%s'", version);
213 /* Callback that is called by the SKE to indicate that it is safe to
214 continue the execution of the protocol. Is given as argument to the
215 silc_ske_initiator_finish or silc_ske_responder_phase_2 functions.
216 This is called due to the fact that the public key verification
217 process is asynchronous and we must not continue the protocl until
218 the public key has been verified and this callback is called. */
220 static void silc_client_protocol_ke_continue(SilcSKE ske,
223 SilcProtocol protocol = (SilcProtocol)context;
224 SilcClientKEInternalContext *ctx =
225 (SilcClientKEInternalContext *)protocol->context;
226 SilcClient client = (SilcClient)ctx->client;
227 SilcClientConnection conn = ctx->sock->user_data;
229 SILC_LOG_DEBUG(("Start"));
231 if (ske->status != SILC_SKE_STATUS_OK) {
232 if (ske->status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
233 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
234 "Received unsupported server %s public key",
235 ctx->sock->hostname);
236 } else if (ske->status == SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED) {
237 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
238 "Remote host did not send its public key, even though "
241 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
242 "Error during key exchange protocol with server %s",
243 ctx->sock->hostname);
246 protocol->state = SILC_PROTOCOL_STATE_ERROR;
247 silc_protocol_execute(protocol, client->schedule, 0, 0);
251 /* Send Ok to the other end. We will end the protocol as server
252 sends Ok to us when we will take the new keys into use. Do this
253 if we are initiator. This is happens when this callback was sent
254 to silc_ske_initiator_finish function. */
255 if (ctx->responder == FALSE) {
256 silc_ske_end(ctx->ske);
258 /* End the protocol on the next round */
259 protocol->state = SILC_PROTOCOL_STATE_END;
262 /* Advance protocol state and call the next state if we are responder.
263 This happens when this callback was sent to silc_ske_responder_phase_2
265 if (ctx->responder == TRUE) {
267 silc_protocol_execute(protocol, client->schedule, 0, 100000);
271 /* Performs key exchange protocol. This is used for both initiator
272 and responder key exchange. This may be called recursively. */
274 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
276 SilcProtocol protocol = (SilcProtocol)context;
277 SilcClientKEInternalContext *ctx =
278 (SilcClientKEInternalContext *)protocol->context;
279 SilcClient client = (SilcClient)ctx->client;
280 SilcClientConnection conn = ctx->sock->user_data;
281 SilcSKEStatus status = SILC_SKE_STATUS_OK;
283 SILC_LOG_DEBUG(("Start"));
285 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
286 protocol->state = SILC_PROTOCOL_STATE_START;
288 switch(protocol->state) {
289 case SILC_PROTOCOL_STATE_START:
296 /* Allocate Key Exchange object */
297 ske = silc_ske_alloc();
299 ske->rng = client->rng;
300 ske->user_data = (void *)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. */
311 status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
312 client->silc_client_version,
313 ctx->packet->buffer, TRUE);
315 SilcSKEStartPayload *start_payload;
317 /* Assemble security properties. */
318 silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE,
319 client->silc_client_version,
322 /* Start the key exchange by sending our security properties
323 to the remote end. */
324 status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
328 /* Return now if the procedure is pending */
329 if (status == SILC_SKE_STATUS_PENDING)
332 if (status != SILC_SKE_STATUS_OK) {
333 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
335 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
338 protocol->state = SILC_PROTOCOL_STATE_ERROR;
339 silc_protocol_execute(protocol, client->schedule, 0, 0);
343 /* Advance protocol state and call the next state if we are responder */
345 if (ctx->responder == TRUE)
346 silc_protocol_execute(protocol, client->schedule, 0, 100000);
354 if (ctx->responder == TRUE) {
355 /* Sends the selected security properties to the initiator. */
357 silc_ske_responder_phase_1(ctx->ske,
358 ctx->ske->start_payload);
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,
401 client->private_key);
405 /* Return now if the procedure is pending */
406 if (status == SILC_SKE_STATUS_PENDING)
409 if (status != SILC_SKE_STATUS_OK) {
410 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
412 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
415 protocol->state = SILC_PROTOCOL_STATE_ERROR;
416 silc_protocol_execute(protocol, client->schedule, 0, 0);
426 if (ctx->responder == TRUE) {
427 /* This creates the key exchange material and sends our
428 public parts to the initiator inside Key Exchange 2 Payload. */
430 silc_ske_responder_finish(ctx->ske,
431 client->public_key, client->private_key,
432 SILC_SKE_PK_TYPE_SILC);
434 /* End the protocol on the next round */
435 protocol->state = SILC_PROTOCOL_STATE_END;
437 /* Finish the protocol. This verifies the Key Exchange 2 payload
438 sent by responder. The silc_client_protocol_ke_continue will
439 be called after the public key has been verified. */
440 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer);
443 /* Return now if the procedure is pending */
444 if (status == SILC_SKE_STATUS_PENDING)
447 if (status != SILC_SKE_STATUS_OK) {
448 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
449 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
450 "Received unsupported server %s public key",
451 ctx->sock->hostname);
453 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
454 "Error during key exchange protocol with server %s",
455 ctx->sock->hostname);
457 protocol->state = SILC_PROTOCOL_STATE_ERROR;
458 silc_protocol_execute(protocol, client->schedule, 0, 0);
464 case SILC_PROTOCOL_STATE_END:
469 SilcSKEKeyMaterial *keymat;
470 int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher);
471 int hash_len = ctx->ske->prop->hash->hash->hash_len;
473 /* Process the key material */
474 keymat = silc_calloc(1, sizeof(*keymat));
475 status = silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
477 if (status != SILC_SKE_STATUS_OK) {
478 protocol->state = SILC_PROTOCOL_STATE_ERROR;
479 silc_protocol_execute(protocol, client->schedule, 0, 300000);
480 silc_ske_free_key_material(keymat);
483 ctx->keymat = keymat;
485 /* Send Ok to the other end if we are responder. If we are initiator
486 we have sent this already. */
487 if (ctx->responder == TRUE)
488 silc_ske_end(ctx->ske);
490 /* Unregister the timeout task since the protocol has ended.
491 This was the timeout task to be executed if the protocol is
492 not completed fast enough. */
493 if (ctx->timeout_task)
494 silc_schedule_task_del(client->schedule, ctx->timeout_task);
496 /* Protocol has ended, call the final callback */
497 if (protocol->final_callback)
498 silc_protocol_execute_final(protocol, client->schedule);
500 silc_protocol_free(protocol);
504 case SILC_PROTOCOL_STATE_ERROR:
506 * Error during protocol
509 /* Send abort notification */
510 silc_ske_abort(ctx->ske, ctx->ske->status);
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);
519 case SILC_PROTOCOL_STATE_FAILURE:
521 * Received failure from remote.
524 /* Unregister the timeout task since the protocol has ended.
525 This was the timeout task to be executed if the protocol is
526 not completed fast enough. */
527 if (ctx->timeout_task)
528 silc_schedule_task_del(client->schedule, ctx->timeout_task);
530 /* On error the final callback is always called. */
531 if (protocol->final_callback)
532 silc_protocol_execute_final(protocol, client->schedule);
534 silc_protocol_free(protocol);
536 case SILC_PROTOCOL_STATE_UNKNOWN:
542 * Connection Authentication protocol functions
546 silc_client_get_public_key_auth(SilcClient client,
547 SilcClientConnection conn,
548 unsigned char *auth_data,
549 uint32 *auth_data_len,
556 /* Use our default key */
559 /* Make the authentication data. Protocol says it is HASH plus
561 len = ske->hash_len + ske->start_payload_copy->len;
562 auth = silc_buffer_alloc(len);
563 silc_buffer_pull_tail(auth, len);
564 silc_buffer_format(auth,
565 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
566 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
567 ske->start_payload_copy->len),
570 if (silc_pkcs_sign_with_hash(pkcs, ske->prop->hash, auth->data,
571 auth->len, auth_data, auth_data_len)) {
572 silc_buffer_free(auth);
576 silc_buffer_free(auth);
580 /* Continues the connection authentication protocol. This funtion may
581 be called directly or used as SilcAskPassphrase callback. */
584 silc_client_conn_auth_continue(unsigned char *auth_data,
585 uint32 auth_data_len, void *context)
587 SilcProtocol protocol = (SilcProtocol)context;
588 SilcClientConnAuthInternalContext *ctx =
589 (SilcClientConnAuthInternalContext *)protocol->context;
590 SilcClient client = (SilcClient)ctx->client;
594 SILC_LOG_DEBUG(("Start"));
596 payload_len = 4 + auth_data_len;
597 packet = silc_buffer_alloc(payload_len);
598 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
599 silc_buffer_format(packet,
600 SILC_STR_UI_SHORT(payload_len),
601 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
602 SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
605 /* Send the packet to server */
606 silc_client_packet_send(client, ctx->sock,
607 SILC_PACKET_CONNECTION_AUTH,
609 packet->data, packet->len, TRUE);
610 silc_buffer_free(packet);
612 /* Next state is end of protocol */
613 protocol->state = SILC_PROTOCOL_STATE_END;
616 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
618 SilcProtocol protocol = (SilcProtocol)context;
619 SilcClientConnAuthInternalContext *ctx =
620 (SilcClientConnAuthInternalContext *)protocol->context;
621 SilcClient client = (SilcClient)ctx->client;
622 SilcClientConnection conn = ctx->sock->user_data;
624 SILC_LOG_DEBUG(("Start"));
626 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
627 protocol->state = SILC_PROTOCOL_STATE_START;
629 switch(protocol->state) {
630 case SILC_PROTOCOL_STATE_START:
633 * Start protocol. We send authentication data to the server
634 * to be authenticated.
636 unsigned char *auth_data = NULL;
637 uint32 auth_data_len = 0;
638 unsigned char sign[1024];
640 switch(ctx->auth_meth) {
642 /* No authentication required */
645 case SILC_AUTH_PASSWORD:
646 /* Password authentication */
647 if (ctx->auth_data && ctx->auth_data_len) {
648 auth_data = ctx->auth_data;
649 auth_data_len = ctx->auth_data_len;
653 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_INFO,
654 "Password authentication required by server %s",
655 ctx->sock->hostname);
656 client->ops->ask_passphrase(client, conn,
657 silc_client_conn_auth_continue,
662 case SILC_AUTH_PUBLIC_KEY:
663 if (!ctx->auth_data) {
664 /* Public key authentication */
665 silc_client_get_public_key_auth(client, conn, sign, &auth_data_len,
669 auth_data = ctx->auth_data;
670 auth_data_len = ctx->auth_data_len;
676 silc_client_conn_auth_continue(auth_data,
677 auth_data_len, protocol);
681 case SILC_PROTOCOL_STATE_END:
684 * End protocol. Nothing special to be done here.
687 /* Protocol has ended, call the final callback */
688 if (protocol->final_callback)
689 silc_protocol_execute_final(protocol, client->schedule);
691 silc_protocol_free(protocol);
695 case SILC_PROTOCOL_STATE_ERROR:
698 * Error. Send notify to remote.
700 unsigned char error[4];
702 SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
704 /* Error in protocol. Send FAILURE packet. Although I don't think
705 this could ever happen on client side. */
706 silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
707 NULL, 0, NULL, NULL, error, 4, TRUE);
709 /* On error the final callback is always called. */
710 if (protocol->final_callback)
711 silc_protocol_execute_final(protocol, client->schedule);
713 silc_protocol_free(protocol);
716 case SILC_PROTOCOL_STATE_FAILURE:
718 * Received failure from remote.
721 /* On error the final callback is always called. */
722 if (protocol->final_callback)
723 silc_protocol_execute_final(protocol, client->schedule);
725 silc_protocol_free(protocol);
728 case SILC_PROTOCOL_STATE_UNKNOWN:
734 * Re-key protocol routines
737 /* Actually takes the new keys into use. */
740 silc_client_protocol_rekey_validate(SilcClient client,
741 SilcClientRekeyInternalContext *ctx,
742 SilcSocketConnection sock,
743 SilcSKEKeyMaterial *keymat,
746 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
748 if (ctx->responder == TRUE) {
750 silc_cipher_set_key(conn->send_key, keymat->receive_enc_key,
751 keymat->enc_key_len);
752 silc_cipher_set_iv(conn->send_key, keymat->receive_iv);
754 silc_cipher_set_key(conn->receive_key, keymat->send_enc_key,
755 keymat->enc_key_len);
756 silc_cipher_set_iv(conn->receive_key, keymat->send_iv);
760 silc_cipher_set_key(conn->send_key, keymat->send_enc_key,
761 keymat->enc_key_len);
762 silc_cipher_set_iv(conn->send_key, keymat->send_iv);
764 silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key,
765 keymat->enc_key_len);
766 silc_cipher_set_iv(conn->receive_key, keymat->receive_iv);
771 silc_hmac_alloc((char *)silc_hmac_get_name(conn->hmac_receive), NULL,
773 silc_hmac_set_key(conn->hmac_send, keymat->hmac_key,
774 keymat->hmac_key_len);
776 silc_hmac_free(conn->hmac_receive);
777 conn->hmac_receive = conn->hmac_send;
780 /* Save the current sending encryption key */
782 memset(conn->rekey->send_enc_key, 0, conn->rekey->enc_key_len);
783 silc_free(conn->rekey->send_enc_key);
784 conn->rekey->send_enc_key =
785 silc_calloc(keymat->enc_key_len / 8,
786 sizeof(*conn->rekey->send_enc_key));
787 memcpy(conn->rekey->send_enc_key, keymat->send_enc_key,
788 keymat->enc_key_len / 8);
789 conn->rekey->enc_key_len = keymat->enc_key_len / 8;
793 /* This function actually re-generates (when not using PFS) the keys and
794 takes them into use. */
797 silc_client_protocol_rekey_generate(SilcClient client,
798 SilcClientRekeyInternalContext *ctx,
801 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
802 SilcSKEKeyMaterial *keymat;
803 uint32 key_len = silc_cipher_get_key_len(conn->send_key);
804 uint32 hash_len = conn->hash->hash->hash_len;
806 SILC_LOG_DEBUG(("Generating new %s session keys (no PFS)",
807 send ? "sending" : "receiving"));
809 /* Generate the new key */
810 keymat = silc_calloc(1, sizeof(*keymat));
811 silc_ske_process_key_material_data(conn->rekey->send_enc_key,
812 conn->rekey->enc_key_len,
813 16, key_len, hash_len,
816 /* Set the keys into use */
817 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
819 silc_ske_free_key_material(keymat);
822 /* This function actually re-generates (with PFS) the keys and
823 takes them into use. */
826 silc_client_protocol_rekey_generate_pfs(SilcClient client,
827 SilcClientRekeyInternalContext *ctx,
830 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
831 SilcSKEKeyMaterial *keymat;
832 uint32 key_len = silc_cipher_get_key_len(conn->send_key);
833 uint32 hash_len = conn->hash->hash->hash_len;
834 unsigned char *tmpbuf;
837 SILC_LOG_DEBUG(("Generating new %s session keys (with PFS)",
838 send ? "sending" : "receiving"));
840 /* Encode KEY to binary data */
841 tmpbuf = silc_mp_mp2bin(ctx->ske->KEY, 0, &klen);
843 /* Generate the new key */
844 keymat = silc_calloc(1, sizeof(*keymat));
845 silc_ske_process_key_material_data(tmpbuf, klen, 16, key_len, hash_len,
848 /* Set the keys into use */
849 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
851 memset(tmpbuf, 0, klen);
853 silc_ske_free_key_material(keymat);
856 /* Packet sending callback. This function is provided as packet sending
857 routine to the Key Exchange functions. */
860 silc_client_protocol_rekey_send_packet(SilcSKE ske,
865 SilcProtocol protocol = (SilcProtocol)context;
866 SilcClientRekeyInternalContext *ctx =
867 (SilcClientRekeyInternalContext *)protocol->context;
868 SilcClient client = (SilcClient)ctx->client;
870 /* Send the packet immediately */
871 silc_client_packet_send(client, ctx->sock, type, NULL, 0, NULL, NULL,
872 packet->data, packet->len, FALSE);
875 /* Performs re-key as defined in the SILC protocol specification. */
877 SILC_TASK_CALLBACK(silc_client_protocol_rekey)
879 SilcProtocol protocol = (SilcProtocol)context;
880 SilcClientRekeyInternalContext *ctx =
881 (SilcClientRekeyInternalContext *)protocol->context;
882 SilcClient client = (SilcClient)ctx->client;
883 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
884 SilcSKEStatus status;
886 SILC_LOG_DEBUG(("Start"));
888 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
889 protocol->state = SILC_PROTOCOL_STATE_START;
891 SILC_LOG_DEBUG(("State=%d", protocol->state));
893 switch(protocol->state) {
894 case SILC_PROTOCOL_STATE_START:
900 if (ctx->responder == TRUE) {
902 * We are receiving party
905 if (ctx->pfs == TRUE) {
907 * Use Perfect Forward Secrecy, ie. negotiate the key material
908 * using the SKE protocol.
911 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
912 /* Error in protocol */
913 protocol->state = SILC_PROTOCOL_STATE_ERROR;
914 silc_protocol_execute(protocol, client->schedule, 0, 300000);
917 ctx->ske = silc_ske_alloc();
918 ctx->ske->rng = client->rng;
919 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
920 silc_ske_get_group_by_number(conn->rekey->ske_group,
921 &ctx->ske->prop->group);
923 silc_ske_set_callbacks(ctx->ske,
924 silc_client_protocol_rekey_send_packet,
925 NULL, NULL, NULL, silc_ske_check_version,
928 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer);
929 if (status != SILC_SKE_STATUS_OK) {
930 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
933 protocol->state = SILC_PROTOCOL_STATE_ERROR;
934 silc_protocol_execute(protocol, client->schedule, 0, 300000);
938 /* Advance the protocol state */
940 silc_protocol_execute(protocol, client->schedule, 0, 0);
943 * Do normal and simple re-key.
946 /* Send the REKEY_DONE to indicate we will take new keys into use */
947 silc_client_packet_send(client, ctx->sock,
948 SILC_PACKET_REKEY_DONE,
949 NULL, 0, NULL, NULL, NULL, 0, FALSE);
951 /* After we send REKEY_DONE we must set the sending encryption
952 key to the new key since all packets after this packet must
953 encrypted with the new key. */
954 silc_client_protocol_rekey_generate(client, ctx, TRUE);
956 /* The protocol ends in next stage. */
957 protocol->state = SILC_PROTOCOL_STATE_END;
962 * We are the initiator of this protocol
965 /* Start the re-key by sending the REKEY packet */
966 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY,
967 NULL, 0, NULL, NULL, NULL, 0, FALSE);
969 if (ctx->pfs == TRUE) {
971 * Use Perfect Forward Secrecy, ie. negotiate the key material
972 * using the SKE protocol.
974 ctx->ske = silc_ske_alloc();
975 ctx->ske->rng = client->rng;
976 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
977 silc_ske_get_group_by_number(conn->rekey->ske_group,
978 &ctx->ske->prop->group);
980 silc_ske_set_callbacks(ctx->ske,
981 silc_client_protocol_rekey_send_packet,
982 NULL, NULL, NULL, silc_ske_check_version,
985 status = silc_ske_initiator_phase_2(ctx->ske, NULL, NULL);
986 if (status != SILC_SKE_STATUS_OK) {
987 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
990 protocol->state = SILC_PROTOCOL_STATE_ERROR;
991 silc_protocol_execute(protocol, client->schedule, 0, 300000);
995 /* Advance the protocol state */
999 * Do normal and simple re-key.
1002 /* Send the REKEY_DONE to indicate we will take new keys into use
1004 silc_client_packet_send(client, ctx->sock,
1005 SILC_PACKET_REKEY_DONE,
1006 NULL, 0, NULL, NULL, NULL, 0, FALSE);
1008 /* After we send REKEY_DONE we must set the sending encryption
1009 key to the new key since all packets after this packet must
1010 encrypted with the new key. */
1011 silc_client_protocol_rekey_generate(client, ctx, TRUE);
1013 /* The protocol ends in next stage. */
1014 protocol->state = SILC_PROTOCOL_STATE_END;
1022 * Second state, used only when oding re-key with PFS.
1024 if (ctx->responder == TRUE) {
1025 if (ctx->pfs == TRUE) {
1027 * Send our KE packe to the initiator now that we've processed
1028 * the initiator's KE packet.
1030 status = silc_ske_responder_finish(ctx->ske, NULL, NULL,
1031 SILC_SKE_PK_TYPE_SILC);
1033 if (status != SILC_SKE_STATUS_OK) {
1034 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
1037 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1038 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1044 if (ctx->pfs == TRUE) {
1046 * The packet type must be KE packet
1048 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
1049 /* Error in protocol */
1050 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1051 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1054 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer);
1055 if (status != SILC_SKE_STATUS_OK) {
1056 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
1059 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1060 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1066 /* Send the REKEY_DONE to indicate we will take new keys into use
1068 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
1069 NULL, 0, NULL, NULL, NULL, 0, FALSE);
1071 /* After we send REKEY_DONE we must set the sending encryption
1072 key to the new key since all packets after this packet must
1073 encrypted with the new key. */
1074 silc_client_protocol_rekey_generate_pfs(client, ctx, TRUE);
1076 /* The protocol ends in next stage. */
1077 protocol->state = SILC_PROTOCOL_STATE_END;
1080 case SILC_PROTOCOL_STATE_END:
1085 if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
1086 /* Error in protocol */
1087 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1088 silc_protocol_execute(protocol, client->schedule, 0, 0);
1091 /* We received the REKEY_DONE packet and all packets after this is
1092 encrypted with the new key so set the decryption key to the new key */
1093 silc_client_protocol_rekey_generate(client, ctx, FALSE);
1095 /* Protocol has ended, call the final callback */
1096 if (protocol->final_callback)
1097 silc_protocol_execute_final(protocol, client->schedule);
1099 silc_protocol_free(protocol);
1102 case SILC_PROTOCOL_STATE_ERROR:
1107 if (ctx->pfs == TRUE) {
1108 /* Send abort notification */
1109 silc_ske_abort(ctx->ske, ctx->ske->status);
1112 /* On error the final callback is always called. */
1113 if (protocol->final_callback)
1114 silc_protocol_execute_final(protocol, client->schedule);
1116 silc_protocol_free(protocol);
1119 case SILC_PROTOCOL_STATE_FAILURE:
1121 * We have received failure from remote
1124 /* On error the final callback is always called. */
1125 if (protocol->final_callback)
1126 silc_protocol_execute_final(protocol, client->schedule);
1128 silc_protocol_free(protocol);
1131 case SILC_PROTOCOL_STATE_UNKNOWN:
1137 /* Registers protocols used in client */
1139 void silc_client_protocols_register(void)
1141 silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1142 silc_client_protocol_connection_auth);
1143 silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1144 silc_client_protocol_key_exchange);
1145 silc_protocol_register(SILC_PROTOCOL_CLIENT_REKEY,
1146 silc_client_protocol_rekey);
1149 /* Unregisters protocols */
1151 void silc_client_protocols_unregister(void)
1153 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1154 silc_client_protocol_connection_auth);
1155 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1156 silc_client_protocol_key_exchange);
1157 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_REKEY,
1158 silc_client_protocol_rekey);