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(hmac->hmac->name, 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(conn->hmac_receive->hmac->name, NULL, &conn->hmac_send);
772 silc_hmac_set_key(conn->hmac_send, keymat->hmac_key,
773 keymat->hmac_key_len);
775 silc_hmac_free(conn->hmac_receive);
776 conn->hmac_receive = conn->hmac_send;
779 /* Save the current sending encryption key */
781 memset(conn->rekey->send_enc_key, 0, conn->rekey->enc_key_len);
782 silc_free(conn->rekey->send_enc_key);
783 conn->rekey->send_enc_key =
784 silc_calloc(keymat->enc_key_len / 8,
785 sizeof(*conn->rekey->send_enc_key));
786 memcpy(conn->rekey->send_enc_key, 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();
917 ctx->ske->rng = client->rng;
918 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
919 silc_ske_get_group_by_number(conn->rekey->ske_group,
920 &ctx->ske->prop->group);
922 silc_ske_set_callbacks(ctx->ske,
923 silc_client_protocol_rekey_send_packet,
924 NULL, NULL, NULL, silc_ske_check_version,
927 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer);
928 if (status != SILC_SKE_STATUS_OK) {
929 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
932 protocol->state = SILC_PROTOCOL_STATE_ERROR;
933 silc_protocol_execute(protocol, client->schedule, 0, 300000);
937 /* Advance the protocol state */
939 silc_protocol_execute(protocol, client->schedule, 0, 0);
942 * Do normal and simple re-key.
945 /* Send the REKEY_DONE to indicate we will take new keys into use */
946 silc_client_packet_send(client, ctx->sock,
947 SILC_PACKET_REKEY_DONE,
948 NULL, 0, NULL, NULL, NULL, 0, FALSE);
950 /* After we send REKEY_DONE we must set the sending encryption
951 key to the new key since all packets after this packet must
952 encrypted with the new key. */
953 silc_client_protocol_rekey_generate(client, ctx, TRUE);
955 /* The protocol ends in next stage. */
956 protocol->state = SILC_PROTOCOL_STATE_END;
961 * We are the initiator of this protocol
964 /* Start the re-key by sending the REKEY packet */
965 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY,
966 NULL, 0, NULL, NULL, NULL, 0, FALSE);
968 if (ctx->pfs == TRUE) {
970 * Use Perfect Forward Secrecy, ie. negotiate the key material
971 * using the SKE protocol.
973 ctx->ske = silc_ske_alloc();
974 ctx->ske->rng = client->rng;
975 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
976 silc_ske_get_group_by_number(conn->rekey->ske_group,
977 &ctx->ske->prop->group);
979 silc_ske_set_callbacks(ctx->ske,
980 silc_client_protocol_rekey_send_packet,
981 NULL, NULL, NULL, silc_ske_check_version,
984 status = silc_ske_initiator_phase_2(ctx->ske, NULL, NULL);
985 if (status != SILC_SKE_STATUS_OK) {
986 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
989 protocol->state = SILC_PROTOCOL_STATE_ERROR;
990 silc_protocol_execute(protocol, client->schedule, 0, 300000);
994 /* Advance the protocol state */
998 * Do normal and simple re-key.
1001 /* Send the REKEY_DONE to indicate we will take new keys into use
1003 silc_client_packet_send(client, ctx->sock,
1004 SILC_PACKET_REKEY_DONE,
1005 NULL, 0, NULL, NULL, NULL, 0, FALSE);
1007 /* After we send REKEY_DONE we must set the sending encryption
1008 key to the new key since all packets after this packet must
1009 encrypted with the new key. */
1010 silc_client_protocol_rekey_generate(client, ctx, TRUE);
1012 /* The protocol ends in next stage. */
1013 protocol->state = SILC_PROTOCOL_STATE_END;
1021 * Second state, used only when oding re-key with PFS.
1023 if (ctx->responder == TRUE) {
1024 if (ctx->pfs == TRUE) {
1026 * Send our KE packe to the initiator now that we've processed
1027 * the initiator's KE packet.
1029 status = silc_ske_responder_finish(ctx->ske, NULL, NULL,
1030 SILC_SKE_PK_TYPE_SILC);
1032 if (status != SILC_SKE_STATUS_OK) {
1033 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
1036 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1037 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1043 if (ctx->pfs == TRUE) {
1045 * The packet type must be KE packet
1047 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
1048 /* Error in protocol */
1049 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1050 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1053 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer);
1054 if (status != SILC_SKE_STATUS_OK) {
1055 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
1058 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1059 silc_protocol_execute(protocol, client->schedule, 0, 300000);
1065 /* Send the REKEY_DONE to indicate we will take new keys into use
1067 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
1068 NULL, 0, NULL, NULL, NULL, 0, FALSE);
1070 /* After we send REKEY_DONE we must set the sending encryption
1071 key to the new key since all packets after this packet must
1072 encrypted with the new key. */
1073 silc_client_protocol_rekey_generate_pfs(client, ctx, TRUE);
1075 /* The protocol ends in next stage. */
1076 protocol->state = SILC_PROTOCOL_STATE_END;
1079 case SILC_PROTOCOL_STATE_END:
1084 if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
1085 /* Error in protocol */
1086 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1087 silc_protocol_execute(protocol, client->schedule, 0, 0);
1090 /* We received the REKEY_DONE packet and all packets after this is
1091 encrypted with the new key so set the decryption key to the new key */
1092 silc_client_protocol_rekey_generate(client, ctx, FALSE);
1094 /* Protocol has ended, call the final callback */
1095 if (protocol->final_callback)
1096 silc_protocol_execute_final(protocol, client->schedule);
1098 silc_protocol_free(protocol);
1101 case SILC_PROTOCOL_STATE_ERROR:
1106 if (ctx->pfs == TRUE) {
1107 /* Send abort notification */
1108 silc_ske_abort(ctx->ske, ctx->ske->status);
1111 /* On error the final callback is always called. */
1112 if (protocol->final_callback)
1113 silc_protocol_execute_final(protocol, client->schedule);
1115 silc_protocol_free(protocol);
1118 case SILC_PROTOCOL_STATE_FAILURE:
1120 * We have received failure from remote
1123 /* On error the final callback is always called. */
1124 if (protocol->final_callback)
1125 silc_protocol_execute_final(protocol, client->schedule);
1127 silc_protocol_free(protocol);
1130 case SILC_PROTOCOL_STATE_UNKNOWN:
1136 /* Registers protocols used in client */
1138 void silc_client_protocols_register(void)
1140 silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1141 silc_client_protocol_connection_auth);
1142 silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1143 silc_client_protocol_key_exchange);
1144 silc_protocol_register(SILC_PROTOCOL_CLIENT_REKEY,
1145 silc_client_protocol_rekey);
1148 /* Unregisters protocols */
1150 void silc_client_protocols_unregister(void)
1152 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1153 silc_client_protocol_connection_auth);
1154 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1155 silc_client_protocol_key_exchange);
1156 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_REKEY,
1157 silc_client_protocol_rekey);