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);
32 extern char *silc_version_string;
35 * Key Exhange protocol functions
38 /* Function that is called when SKE protocol sends packets to network. */
40 void silc_client_protocol_ke_send_packet(SilcSKE ske,
45 SilcProtocol protocol = (SilcProtocol)context;
46 SilcClientKEInternalContext *ctx =
47 (SilcClientKEInternalContext *)protocol->context;
48 SilcClient client = (SilcClient)ctx->client;
50 /* Send the packet immediately */
51 silc_client_packet_send(client, ske->sock, type, NULL, 0, NULL, NULL,
52 packet->data, packet->len, TRUE);
55 /* Callback that is called when we have received KE2 payload from
56 responder. We try to verify the public key now. */
58 SilcSKEStatus silc_client_protocol_ke_verify_key(SilcSKE ske,
59 unsigned char *pk_data,
61 SilcSKEPKType pk_type,
64 SilcProtocol protocol = (SilcProtocol)context;
65 SilcClientKEInternalContext *ctx =
66 (SilcClientKEInternalContext *)protocol->context;
67 SilcClient client = (SilcClient)ctx->client;
69 SILC_LOG_DEBUG(("Start"));
71 /* Verify public key from user. */
72 if (!client->ops->verify_public_key(client, ctx->sock->user_data,
74 pk_data, pk_len, pk_type))
75 return SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
77 return SILC_SKE_STATUS_OK;
80 /* Sets the negotiated key material into use for particular connection. */
82 void silc_client_protocol_ke_set_keys(SilcSKE ske,
83 SilcSocketConnection sock,
84 SilcSKEKeyMaterial *keymat,
89 SilcSKEDiffieHellmanGroup group)
91 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
93 SILC_LOG_DEBUG(("Setting new keys into use"));
95 /* Allocate cipher to be used in the communication */
96 silc_cipher_alloc(cipher->cipher->name, &conn->send_key);
97 silc_cipher_alloc(cipher->cipher->name, &conn->receive_key);
99 conn->send_key->cipher->set_key(conn->send_key->context,
100 keymat->send_enc_key,
101 keymat->enc_key_len);
102 conn->send_key->set_iv(conn->send_key, keymat->send_iv);
103 conn->receive_key->cipher->set_key(conn->receive_key->context,
104 keymat->receive_enc_key,
105 keymat->enc_key_len);
106 conn->receive_key->set_iv(conn->receive_key, keymat->receive_iv);
108 /* Allocate PKCS to be used */
110 /* XXX Do we ever need to allocate PKCS for the connection??
111 If yes, we need to change KE protocol to get the initiators
113 silc_pkcs_alloc(pkcs->pkcs->name, &conn->public_Key);
114 silc_pkcs_set_public_key(conn->public_key, ske->ke2_payload->pk_data,
115 ske->ke2_payload->pk_len);
118 conn->rekey = silc_calloc(1, sizeof(*conn->rekey));
119 conn->rekey->send_enc_key =
120 silc_calloc(keymat->enc_key_len / 8,
121 sizeof(*conn->rekey->send_enc_key));
122 memcpy(conn->rekey->send_enc_key,
123 keymat->send_enc_key, keymat->enc_key_len / 8);
124 conn->rekey->enc_key_len = keymat->enc_key_len / 8;
126 if (ske->start_payload->flags & SILC_SKE_SP_FLAG_PFS)
127 conn->rekey->pfs = TRUE;
128 conn->rekey->ske_group = silc_ske_group_get_number(group);
130 /* Save HMAC key to be used in the communication. */
131 silc_hmac_alloc(hmac->hmac->name, NULL, &conn->hmac_send);
132 silc_hmac_set_key(conn->hmac_send, keymat->hmac_key, keymat->hmac_key_len);
133 conn->hmac_receive = conn->hmac_send;
135 /* Save the HASH function */
136 silc_hash_alloc(hash->hash->name, &conn->hash);
139 /* Checks the version string of the server. */
141 SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
144 SilcClientConnection conn = (SilcClientConnection)ske->sock->user_data;
145 SilcClient client = (SilcClient)ske->user_data;
146 SilcSKEStatus status = SILC_SKE_STATUS_OK;
148 int maj = 0, min = 0, build = 0, maj2 = 0, min2 = 0, build2 = 0;
150 /* Check for initial version string */
151 if (!strstr(version, "SILC-1.0-"))
152 status = SILC_SKE_STATUS_BAD_VERSION;
154 /* Check software version */
158 status = SILC_SKE_STATUS_BAD_VERSION;
161 cp = strchr(cp, '.');
166 cp = strchr(cp, '.');
168 build = atoi(cp + 1);
170 cp = silc_version_string + 9;
172 status = SILC_SKE_STATUS_BAD_VERSION;
175 cp = strchr(cp, '.');
180 cp = strchr(cp, '.');
182 build2 = atoi(cp + 1);
185 status = SILC_SKE_STATUS_BAD_VERSION;
187 status = SILC_SKE_STATUS_BAD_VERSION;
189 if (status != SILC_SKE_STATUS_OK)
190 client->ops->say(client, conn,
191 "We don't support server version `%s'", version);
196 /* Performs key exchange protocol. This is used for both initiator
197 and responder key exchange. This may be called recursively. */
199 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
201 SilcProtocol protocol = (SilcProtocol)context;
202 SilcClientKEInternalContext *ctx =
203 (SilcClientKEInternalContext *)protocol->context;
204 SilcClient client = (SilcClient)ctx->client;
205 SilcClientConnection conn = ctx->sock->user_data;
206 SilcSKEStatus status = 0;
208 SILC_LOG_DEBUG(("Start"));
210 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
211 protocol->state = SILC_PROTOCOL_STATE_START;
213 switch(protocol->state) {
214 case SILC_PROTOCOL_STATE_START:
221 /* Allocate Key Exchange object */
222 ske = silc_ske_alloc();
224 ske->rng = client->rng;
225 ske->user_data = (void *)client;
227 if (ctx->responder == TRUE) {
228 /* Start the key exchange by processing the received security
229 properties packet from initiator. */
230 status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
232 ctx->packet->buffer, TRUE,
235 SilcSKEStartPayload *start_payload;
237 /* Assemble security properties. */
238 silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE,
242 /* Start the key exchange by sending our security properties
243 to the remote end. */
244 status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
250 if (status != SILC_SKE_STATUS_OK) {
251 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
253 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
256 protocol->state = SILC_PROTOCOL_STATE_ERROR;
257 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
261 /* Advance protocol state and call the next state if we are responder */
263 if (ctx->responder == TRUE)
264 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
272 if (ctx->responder == TRUE) {
273 /* Sends the selected security properties to the initiator. */
275 silc_ske_responder_phase_1(ctx->ske,
276 ctx->ske->start_payload,
280 /* Call Phase-1 function. This processes the Key Exchange Start
281 paylaod reply we just got from the responder. The callback
282 function will receive the processed payload where we will
284 status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer,
288 if (status != SILC_SKE_STATUS_OK) {
289 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
291 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
294 protocol->state = SILC_PROTOCOL_STATE_ERROR;
295 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
299 /* Advance protocol state and call next state if we are initiator */
301 if (ctx->responder == FALSE)
302 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
310 if (ctx->responder == TRUE) {
311 /* Process the received Key Exchange 1 Payload packet from
312 the initiator. This also creates our parts of the Diffie
313 Hellman algorithm. */
314 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer,
315 ctx->verify, context, NULL, NULL);
317 /* Call the Phase-2 function. This creates Diffie Hellman
318 key exchange parameters and sends our public part inside
319 Key Exhange 1 Payload to the responder. */
320 status = silc_ske_initiator_phase_2(ctx->ske,
327 if (status != SILC_SKE_STATUS_OK) {
328 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
330 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
333 protocol->state = SILC_PROTOCOL_STATE_ERROR;
334 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
338 /* Advance protocol state and call the next state if we are responder */
340 if (ctx->responder == TRUE)
341 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
349 if (ctx->responder == TRUE) {
350 /* This creates the key exchange material and sends our
351 public parts to the initiator inside Key Exchange 2 Payload. */
353 silc_ske_responder_finish(ctx->ske,
354 client->public_key, client->private_key,
355 SILC_SKE_PK_TYPE_SILC,
360 /* Finish the protocol. This verifies the Key Exchange 2 payload
361 sent by responder. */
362 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
363 ctx->verify, context, NULL, NULL);
366 if (status != SILC_SKE_STATUS_OK) {
368 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
369 client->ops->say(client, conn,
370 "Received unsupported server %s public key",
371 ctx->sock->hostname);
373 client->ops->say(client, conn,
374 "Error during key exchange protocol with server %s",
375 ctx->sock->hostname);
377 protocol->state = SILC_PROTOCOL_STATE_ERROR;
378 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
382 /* Send Ok to the other end. We will end the protocol as server
383 sends Ok to us when we will take the new keys into use. */
384 if (ctx->responder == FALSE)
385 silc_ske_end(ctx->ske, ctx->send_packet, context);
387 /* End the protocol on the next round */
388 protocol->state = SILC_PROTOCOL_STATE_END;
392 case SILC_PROTOCOL_STATE_END:
397 SilcSKEKeyMaterial *keymat;
398 int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher);
399 int hash_len = ctx->ske->prop->hash->hash->hash_len;
401 /* Process the key material */
402 keymat = silc_calloc(1, sizeof(*keymat));
403 status = silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
405 if (status != SILC_SKE_STATUS_OK) {
406 protocol->state = SILC_PROTOCOL_STATE_ERROR;
407 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 300000);
408 silc_ske_free_key_material(keymat);
411 ctx->keymat = keymat;
413 /* Send Ok to the other end if we are responder. If we are initiator
414 we have sent this already. */
415 if (ctx->responder == TRUE)
416 silc_ske_end(ctx->ske, ctx->send_packet, context);
418 /* Unregister the timeout task since the protocol has ended.
419 This was the timeout task to be executed if the protocol is
420 not completed fast enough. */
421 if (ctx->timeout_task)
422 silc_task_unregister(client->timeout_queue, ctx->timeout_task);
424 /* Protocol has ended, call the final callback */
425 if (protocol->final_callback)
426 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
428 silc_protocol_free(protocol);
432 case SILC_PROTOCOL_STATE_ERROR:
434 * Error during protocol
437 /* Send abort notification */
438 silc_ske_abort(ctx->ske, ctx->ske->status,
439 ctx->send_packet, context);
441 /* On error the final callback is always called. */
442 if (protocol->final_callback)
443 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
445 silc_protocol_free(protocol);
448 case SILC_PROTOCOL_STATE_FAILURE:
450 * Received failure from remote.
453 /* Unregister the timeout task since the protocol has ended.
454 This was the timeout task to be executed if the protocol is
455 not completed fast enough. */
456 if (ctx->timeout_task)
457 silc_task_unregister(client->timeout_queue, ctx->timeout_task);
459 /* On error the final callback is always called. */
460 if (protocol->final_callback)
461 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
463 silc_protocol_free(protocol);
465 case SILC_PROTOCOL_STATE_UNKNOWN:
471 * Connection Authentication protocol functions
475 silc_client_get_public_key_auth(SilcClient client,
477 unsigned char *auth_data,
478 uint32 *auth_data_len,
484 SilcPublicKey pub_key;
486 if (!silc_pkcs_load_public_key(filepath,&pub_key, SILC_PKCS_FILE_PEM))
487 if (!silc_pkcs_load_public_key(filepath, &pub_key, SILC_PKCS_FILE_BIN))
490 silc_pkcs_alloc(pub_key->name, &pkcs);
491 if (!silc_pkcs_public_key_set(pkcs, pub_key)) {
492 silc_pkcs_free(pkcs);
493 silc_pkcs_public_key_free(pub_key);
497 /* Make the authentication data. Protocol says it is HASH plus
499 len = ske->hash_len + ske->start_payload_copy->len;
500 auth = silc_buffer_alloc(len);
501 silc_buffer_pull_tail(auth, len);
502 silc_buffer_format(auth,
503 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
504 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
505 ske->start_payload_copy->len),
508 if (silc_pkcs_sign(pkcs, auth->data, auth->len, auth_data, auth_data_len)) {
509 silc_pkcs_free(pkcs);
510 silc_buffer_free(auth);
511 silc_pkcs_public_key_free(pub_key);
515 silc_pkcs_free(pkcs);
516 silc_buffer_free(auth);
517 silc_pkcs_public_key_free(pub_key);
521 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
523 SilcProtocol protocol = (SilcProtocol)context;
524 SilcClientConnAuthInternalContext *ctx =
525 (SilcClientConnAuthInternalContext *)protocol->context;
526 SilcClient client = (SilcClient)ctx->client;
527 SilcClientConnection conn = ctx->sock->user_data;
529 SILC_LOG_DEBUG(("Start"));
531 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
532 protocol->state = SILC_PROTOCOL_STATE_START;
534 switch(protocol->state) {
535 case SILC_PROTOCOL_STATE_START:
538 * Start protocol. We send authentication data to the server
539 * to be authenticated.
543 unsigned char *auth_data = NULL;
544 uint32 auth_data_len = 0;
546 switch(ctx->auth_meth) {
548 /* No authentication required */
551 case SILC_AUTH_PASSWORD:
552 /* Password authentication */
553 if (ctx->auth_data && ctx->auth_data_len) {
554 auth_data = ctx->auth_data;
555 auth_data_len = ctx->auth_data_len;
559 client->ops->say(client, conn,
560 "Password authentication required by server %s",
561 ctx->sock->hostname);
562 auth_data = client->ops->ask_passphrase(client, conn);
563 auth_data_len = strlen(auth_data);
566 case SILC_AUTH_PUBLIC_KEY:
568 unsigned char sign[1024];
570 /* Public key authentication */
571 silc_client_get_public_key_auth(client, ctx->auth_data,
572 sign, &auth_data_len,
574 auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
575 memcpy(auth_data, sign, auth_data_len);
580 payload_len = 4 + auth_data_len;
581 packet = silc_buffer_alloc(payload_len);
582 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
583 silc_buffer_format(packet,
584 SILC_STR_UI_SHORT(payload_len),
585 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
586 SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
589 /* Send the packet to server */
590 silc_client_packet_send(client, ctx->sock,
591 SILC_PACKET_CONNECTION_AUTH,
593 packet->data, packet->len, TRUE);
596 memset(auth_data, 0, auth_data_len);
597 silc_free(auth_data);
599 silc_buffer_free(packet);
601 /* Next state is end of protocol */
602 protocol->state = SILC_PROTOCOL_STATE_END;
606 case SILC_PROTOCOL_STATE_END:
609 * End protocol. Nothing special to be done here.
612 /* Protocol has ended, call the final callback */
613 if (protocol->final_callback)
614 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
616 silc_protocol_free(protocol);
620 case SILC_PROTOCOL_STATE_ERROR:
623 * Error. Send notify to remote.
625 unsigned char error[4];
627 SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
629 /* Error in protocol. Send FAILURE packet. Although I don't think
630 this could ever happen on client side. */
631 silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
632 NULL, 0, NULL, NULL, error, 4, TRUE);
634 /* On error the final callback is always called. */
635 if (protocol->final_callback)
636 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
638 silc_protocol_free(protocol);
641 case SILC_PROTOCOL_STATE_FAILURE:
643 * Received failure from remote.
646 /* On error the final callback is always called. */
647 if (protocol->final_callback)
648 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
650 silc_protocol_free(protocol);
653 case SILC_PROTOCOL_STATE_UNKNOWN:
659 * Re-key protocol routines
662 /* Actually takes the new keys into use. */
665 silc_client_protocol_rekey_validate(SilcClient client,
666 SilcClientRekeyInternalContext *ctx,
667 SilcSocketConnection sock,
668 SilcSKEKeyMaterial *keymat,
671 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
673 if (ctx->responder == TRUE) {
675 silc_cipher_set_key(conn->send_key, keymat->receive_enc_key,
676 keymat->enc_key_len);
677 silc_cipher_set_iv(conn->send_key, keymat->receive_iv);
679 silc_cipher_set_key(conn->receive_key, keymat->send_enc_key,
680 keymat->enc_key_len);
681 silc_cipher_set_iv(conn->receive_key, keymat->send_iv);
685 silc_cipher_set_key(conn->send_key, keymat->send_enc_key,
686 keymat->enc_key_len);
687 silc_cipher_set_iv(conn->send_key, keymat->send_iv);
689 silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key,
690 keymat->enc_key_len);
691 silc_cipher_set_iv(conn->receive_key, keymat->receive_iv);
696 silc_hmac_alloc(conn->hmac_receive->hmac->name, NULL, &conn->hmac_send);
697 silc_hmac_set_key(conn->hmac_send, keymat->hmac_key,
698 keymat->hmac_key_len);
700 silc_hmac_free(conn->hmac_receive);
701 conn->hmac_receive = conn->hmac_send;
704 /* Save the current sending encryption key */
706 memset(conn->rekey->send_enc_key, 0, conn->rekey->enc_key_len);
707 silc_free(conn->rekey->send_enc_key);
708 conn->rekey->send_enc_key =
709 silc_calloc(keymat->enc_key_len / 8,
710 sizeof(*conn->rekey->send_enc_key));
711 memcpy(conn->rekey->send_enc_key, keymat->send_enc_key,
712 keymat->enc_key_len / 8);
713 conn->rekey->enc_key_len = keymat->enc_key_len / 8;
717 /* This function actually re-generates (when not using PFS) the keys and
718 takes them into use. */
721 silc_client_protocol_rekey_generate(SilcClient client,
722 SilcClientRekeyInternalContext *ctx,
725 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
726 SilcSKEKeyMaterial *keymat;
727 uint32 key_len = silc_cipher_get_key_len(conn->send_key);
728 uint32 hash_len = conn->hash->hash->hash_len;
730 SILC_LOG_DEBUG(("Generating new %s session keys (no PFS)",
731 send ? "sending" : "receiving"));
733 /* Generate the new key */
734 keymat = silc_calloc(1, sizeof(*keymat));
735 silc_ske_process_key_material_data(conn->rekey->send_enc_key,
736 conn->rekey->enc_key_len,
737 16, key_len, hash_len,
740 /* Set the keys into use */
741 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
743 silc_ske_free_key_material(keymat);
746 /* This function actually re-generates (with PFS) the keys and
747 takes them into use. */
750 silc_client_protocol_rekey_generate_pfs(SilcClient client,
751 SilcClientRekeyInternalContext *ctx,
754 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
755 SilcSKEKeyMaterial *keymat;
756 uint32 key_len = silc_cipher_get_key_len(conn->send_key);
757 uint32 hash_len = conn->hash->hash->hash_len;
758 unsigned char *tmpbuf;
761 SILC_LOG_DEBUG(("Generating new %s session keys (with PFS)",
762 send ? "sending" : "receiving"));
764 /* Encode KEY to binary data */
765 tmpbuf = silc_mp_mp2bin(ctx->ske->KEY, 0, &klen);
767 /* Generate the new key */
768 keymat = silc_calloc(1, sizeof(*keymat));
769 silc_ske_process_key_material_data(tmpbuf, klen, 16, key_len, hash_len,
772 /* Set the keys into use */
773 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
775 memset(tmpbuf, 0, klen);
777 silc_ske_free_key_material(keymat);
780 /* Packet sending callback. This function is provided as packet sending
781 routine to the Key Exchange functions. */
784 silc_client_protocol_rekey_send_packet(SilcSKE ske,
789 SilcProtocol protocol = (SilcProtocol)context;
790 SilcClientRekeyInternalContext *ctx =
791 (SilcClientRekeyInternalContext *)protocol->context;
792 SilcClient client = (SilcClient)ctx->client;
794 /* Send the packet immediately */
795 silc_client_packet_send(client, ctx->sock, type, NULL, 0, NULL, NULL,
796 packet->data, packet->len, FALSE);
799 /* Performs re-key as defined in the SILC protocol specification. */
801 SILC_TASK_CALLBACK(silc_client_protocol_rekey)
803 SilcProtocol protocol = (SilcProtocol)context;
804 SilcClientRekeyInternalContext *ctx =
805 (SilcClientRekeyInternalContext *)protocol->context;
806 SilcClient client = (SilcClient)ctx->client;
807 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
808 SilcSKEStatus status;
810 SILC_LOG_DEBUG(("Start"));
812 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
813 protocol->state = SILC_PROTOCOL_STATE_START;
815 SILC_LOG_DEBUG(("State=%d", protocol->state));
817 switch(protocol->state) {
818 case SILC_PROTOCOL_STATE_START:
824 if (ctx->responder == TRUE) {
826 * We are receiving party
829 if (ctx->pfs == TRUE) {
831 * Use Perfect Forward Secrecy, ie. negotiate the key material
832 * using the SKE protocol.
835 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
836 /* Error in protocol */
837 protocol->state = SILC_PROTOCOL_STATE_ERROR;
838 protocol->execute(client->timeout_queue, 0, protocol, fd,
842 ctx->ske = silc_ske_alloc();
843 ctx->ske->rng = client->rng;
844 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
845 silc_ske_get_group_by_number(conn->rekey->ske_group,
846 &ctx->ske->prop->group);
848 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer,
849 NULL, NULL, NULL, NULL);
850 if (status != SILC_SKE_STATUS_OK) {
851 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
854 protocol->state = SILC_PROTOCOL_STATE_ERROR;
855 protocol->execute(client->timeout_queue, 0,
856 protocol, fd, 0, 300000);
860 /* Advance the protocol state */
862 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
865 * Do normal and simple re-key.
868 /* Send the REKEY_DONE to indicate we will take new keys into use */
869 silc_client_packet_send(client, ctx->sock,
870 SILC_PACKET_REKEY_DONE,
871 NULL, 0, NULL, NULL, NULL, 0, FALSE);
873 /* After we send REKEY_DONE we must set the sending encryption
874 key to the new key since all packets after this packet must
875 encrypted with the new key. */
876 silc_client_protocol_rekey_generate(client, ctx, TRUE);
878 /* The protocol ends in next stage. */
879 protocol->state = SILC_PROTOCOL_STATE_END;
884 * We are the initiator of this protocol
887 /* Start the re-key by sending the REKEY packet */
888 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY,
889 NULL, 0, NULL, NULL, NULL, 0, FALSE);
891 if (ctx->pfs == TRUE) {
893 * Use Perfect Forward Secrecy, ie. negotiate the key material
894 * using the SKE protocol.
896 ctx->ske = silc_ske_alloc();
897 ctx->ske->rng = client->rng;
898 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
899 silc_ske_get_group_by_number(conn->rekey->ske_group,
900 &ctx->ske->prop->group);
903 silc_ske_initiator_phase_2(ctx->ske, NULL, NULL,
904 silc_client_protocol_rekey_send_packet,
907 if (status != SILC_SKE_STATUS_OK) {
908 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
911 protocol->state = SILC_PROTOCOL_STATE_ERROR;
912 protocol->execute(client->timeout_queue, 0,
913 protocol, fd, 0, 300000);
917 /* Advance the protocol state */
921 * Do normal and simple re-key.
924 /* Send the REKEY_DONE to indicate we will take new keys into use
926 silc_client_packet_send(client, ctx->sock,
927 SILC_PACKET_REKEY_DONE,
928 NULL, 0, NULL, NULL, NULL, 0, FALSE);
930 /* After we send REKEY_DONE we must set the sending encryption
931 key to the new key since all packets after this packet must
932 encrypted with the new key. */
933 silc_client_protocol_rekey_generate(client, ctx, TRUE);
935 /* The protocol ends in next stage. */
936 protocol->state = SILC_PROTOCOL_STATE_END;
944 * Second state, used only when oding re-key with PFS.
946 if (ctx->responder == TRUE) {
947 if (ctx->pfs == TRUE) {
949 * Send our KE packe to the initiator now that we've processed
950 * the initiator's KE packet.
953 silc_ske_responder_finish(ctx->ske, NULL, NULL,
954 SILC_SKE_PK_TYPE_SILC,
955 silc_client_protocol_rekey_send_packet,
958 if (status != SILC_SKE_STATUS_OK) {
959 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
962 protocol->state = SILC_PROTOCOL_STATE_ERROR;
963 protocol->execute(client->timeout_queue, 0,
964 protocol, fd, 0, 300000);
970 if (ctx->pfs == TRUE) {
972 * The packet type must be KE packet
974 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
975 /* Error in protocol */
976 protocol->state = SILC_PROTOCOL_STATE_ERROR;
977 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 300000);
980 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
981 NULL, NULL, NULL, NULL);
982 if (status != SILC_SKE_STATUS_OK) {
983 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
986 protocol->state = SILC_PROTOCOL_STATE_ERROR;
987 protocol->execute(client->timeout_queue, 0,
988 protocol, fd, 0, 300000);
994 /* Send the REKEY_DONE to indicate we will take new keys into use
996 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
997 NULL, 0, NULL, NULL, NULL, 0, FALSE);
999 /* After we send REKEY_DONE we must set the sending encryption
1000 key to the new key since all packets after this packet must
1001 encrypted with the new key. */
1002 silc_client_protocol_rekey_generate_pfs(client, ctx, TRUE);
1004 /* The protocol ends in next stage. */
1005 protocol->state = SILC_PROTOCOL_STATE_END;
1008 case SILC_PROTOCOL_STATE_END:
1013 if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
1014 /* Error in protocol */
1015 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1016 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
1019 /* We received the REKEY_DONE packet and all packets after this is
1020 encrypted with the new key so set the decryption key to the new key */
1021 silc_client_protocol_rekey_generate(client, ctx, FALSE);
1023 /* Protocol has ended, call the final callback */
1024 if (protocol->final_callback)
1025 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
1027 silc_protocol_free(protocol);
1030 case SILC_PROTOCOL_STATE_ERROR:
1035 if (ctx->pfs == TRUE) {
1036 /* Send abort notification */
1037 silc_ske_abort(ctx->ske, ctx->ske->status,
1038 silc_client_protocol_ke_send_packet,
1042 /* On error the final callback is always called. */
1043 if (protocol->final_callback)
1044 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
1046 silc_protocol_free(protocol);
1049 case SILC_PROTOCOL_STATE_FAILURE:
1051 * We have received failure from remote
1054 /* On error the final callback is always called. */
1055 if (protocol->final_callback)
1056 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
1058 silc_protocol_free(protocol);
1061 case SILC_PROTOCOL_STATE_UNKNOWN:
1067 /* Registers protocols used in client */
1069 void silc_client_protocols_register(void)
1071 silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1072 silc_client_protocol_connection_auth);
1073 silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1074 silc_client_protocol_key_exchange);
1075 silc_protocol_register(SILC_PROTOCOL_CLIENT_REKEY,
1076 silc_client_protocol_rekey);
1079 /* Unregisters protocols */
1081 void silc_client_protocols_unregister(void)
1083 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1084 silc_client_protocol_connection_auth);
1085 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1086 silc_client_protocol_key_exchange);
1087 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_REKEY,
1088 silc_client_protocol_rekey);