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, min2, build2;
150 /* Check for initial version string */
151 if (!strstr(version, "SILC-1.0-"))
152 status = SILC_SKE_STATUS_BAD_VERSION;
154 /* Check software version */
156 if (len < strlen(silc_version_string))
157 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 cp = strchr(cp, '.');
177 cp = strchr(cp, '.');
179 build2 = atoi(cp + 1);
182 status = SILC_SKE_STATUS_BAD_VERSION;
185 status = SILC_SKE_STATUS_BAD_VERSION;
188 if (status != SILC_SKE_STATUS_OK)
189 client->ops->say(client, conn,
190 "We don't support server version `%s'", version);
195 /* Performs key exchange protocol. This is used for both initiator
196 and responder key exchange. This may be called recursively. */
198 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
200 SilcProtocol protocol = (SilcProtocol)context;
201 SilcClientKEInternalContext *ctx =
202 (SilcClientKEInternalContext *)protocol->context;
203 SilcClient client = (SilcClient)ctx->client;
204 SilcClientConnection conn = ctx->sock->user_data;
205 SilcSKEStatus status = 0;
207 SILC_LOG_DEBUG(("Start"));
209 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
210 protocol->state = SILC_PROTOCOL_STATE_START;
212 switch(protocol->state) {
213 case SILC_PROTOCOL_STATE_START:
220 /* Allocate Key Exchange object */
221 ske = silc_ske_alloc();
223 ske->rng = client->rng;
224 ske->user_data = (void *)client;
226 if (ctx->responder == TRUE) {
227 /* Start the key exchange by processing the received security
228 properties packet from initiator. */
229 status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
231 ctx->packet->buffer, TRUE,
234 SilcSKEStartPayload *start_payload;
236 /* Assemble security properties. */
237 silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE,
241 /* Start the key exchange by sending our security properties
242 to the remote end. */
243 status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
249 if (status != SILC_SKE_STATUS_OK) {
250 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
252 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
255 protocol->state = SILC_PROTOCOL_STATE_ERROR;
256 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
260 /* Advance protocol state and call the next state if we are responder */
262 if (ctx->responder == TRUE)
263 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
271 if (ctx->responder == TRUE) {
272 /* Sends the selected security properties to the initiator. */
274 silc_ske_responder_phase_1(ctx->ske,
275 ctx->ske->start_payload,
279 /* Call Phase-1 function. This processes the Key Exchange Start
280 paylaod reply we just got from the responder. The callback
281 function will receive the processed payload where we will
283 status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer,
287 if (status != SILC_SKE_STATUS_OK) {
288 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
290 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
293 protocol->state = SILC_PROTOCOL_STATE_ERROR;
294 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
298 /* Advance protocol state and call next state if we are initiator */
300 if (ctx->responder == FALSE)
301 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
309 if (ctx->responder == TRUE) {
310 /* Process the received Key Exchange 1 Payload packet from
311 the initiator. This also creates our parts of the Diffie
312 Hellman algorithm. */
313 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer,
314 ctx->verify, context, NULL, NULL);
316 /* Call the Phase-2 function. This creates Diffie Hellman
317 key exchange parameters and sends our public part inside
318 Key Exhange 1 Payload to the responder. */
319 status = silc_ske_initiator_phase_2(ctx->ske,
326 if (status != SILC_SKE_STATUS_OK) {
327 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
329 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
332 protocol->state = SILC_PROTOCOL_STATE_ERROR;
333 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
337 /* Advance protocol state and call the next state if we are responder */
339 if (ctx->responder == TRUE)
340 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
348 if (ctx->responder == TRUE) {
349 /* This creates the key exchange material and sends our
350 public parts to the initiator inside Key Exchange 2 Payload. */
352 silc_ske_responder_finish(ctx->ske,
353 client->public_key, client->private_key,
354 SILC_SKE_PK_TYPE_SILC,
359 /* Finish the protocol. This verifies the Key Exchange 2 payload
360 sent by responder. */
361 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
362 ctx->verify, context, NULL, NULL);
365 if (status != SILC_SKE_STATUS_OK) {
367 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
368 client->ops->say(client, conn,
369 "Received unsupported server %s public key",
370 ctx->sock->hostname);
372 client->ops->say(client, conn,
373 "Error during key exchange protocol with server %s",
374 ctx->sock->hostname);
376 protocol->state = SILC_PROTOCOL_STATE_ERROR;
377 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
381 /* Send Ok to the other end. We will end the protocol as server
382 sends Ok to us when we will take the new keys into use. */
383 if (ctx->responder == FALSE)
384 silc_ske_end(ctx->ske, ctx->send_packet, context);
386 /* End the protocol on the next round */
387 protocol->state = SILC_PROTOCOL_STATE_END;
391 case SILC_PROTOCOL_STATE_END:
396 SilcSKEKeyMaterial *keymat;
397 int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher);
398 int hash_len = ctx->ske->prop->hash->hash->hash_len;
400 /* Process the key material */
401 keymat = silc_calloc(1, sizeof(*keymat));
402 status = silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
404 if (status != SILC_SKE_STATUS_OK) {
405 protocol->state = SILC_PROTOCOL_STATE_ERROR;
406 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 300000);
407 silc_ske_free_key_material(keymat);
410 ctx->keymat = keymat;
412 /* Send Ok to the other end if we are responder. If we are initiator
413 we have sent this already. */
414 if (ctx->responder == TRUE)
415 silc_ske_end(ctx->ske, ctx->send_packet, context);
417 /* Unregister the timeout task since the protocol has ended.
418 This was the timeout task to be executed if the protocol is
419 not completed fast enough. */
420 if (ctx->timeout_task)
421 silc_task_unregister(client->timeout_queue, ctx->timeout_task);
423 /* Protocol has ended, call the final callback */
424 if (protocol->final_callback)
425 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
427 silc_protocol_free(protocol);
431 case SILC_PROTOCOL_STATE_ERROR:
433 * Error during protocol
436 /* Send abort notification */
437 silc_ske_abort(ctx->ske, ctx->ske->status,
438 ctx->send_packet, context);
440 /* On error the final callback is always called. */
441 if (protocol->final_callback)
442 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
444 silc_protocol_free(protocol);
447 case SILC_PROTOCOL_STATE_FAILURE:
449 * Received failure from remote.
452 /* Unregister the timeout task since the protocol has ended.
453 This was the timeout task to be executed if the protocol is
454 not completed fast enough. */
455 if (ctx->timeout_task)
456 silc_task_unregister(client->timeout_queue, ctx->timeout_task);
458 /* On error the final callback is always called. */
459 if (protocol->final_callback)
460 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
462 silc_protocol_free(protocol);
464 case SILC_PROTOCOL_STATE_UNKNOWN:
470 * Connection Authentication protocol functions
474 silc_client_get_public_key_auth(SilcClient client,
476 unsigned char *auth_data,
477 uint32 *auth_data_len,
483 SilcPublicKey pub_key;
485 if (!silc_pkcs_load_public_key(filepath,&pub_key, SILC_PKCS_FILE_PEM))
486 if (!silc_pkcs_load_public_key(filepath, &pub_key, SILC_PKCS_FILE_BIN))
489 silc_pkcs_alloc(pub_key->name, &pkcs);
490 if (!silc_pkcs_public_key_set(pkcs, pub_key)) {
491 silc_pkcs_free(pkcs);
492 silc_pkcs_public_key_free(pub_key);
496 /* Make the authentication data. Protocol says it is HASH plus
498 len = ske->hash_len + ske->start_payload_copy->len;
499 auth = silc_buffer_alloc(len);
500 silc_buffer_pull_tail(auth, len);
501 silc_buffer_format(auth,
502 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
503 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
504 ske->start_payload_copy->len),
507 if (silc_pkcs_sign(pkcs, auth->data, auth->len, auth_data, auth_data_len)) {
508 silc_pkcs_free(pkcs);
509 silc_buffer_free(auth);
510 silc_pkcs_public_key_free(pub_key);
514 silc_pkcs_free(pkcs);
515 silc_buffer_free(auth);
516 silc_pkcs_public_key_free(pub_key);
520 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
522 SilcProtocol protocol = (SilcProtocol)context;
523 SilcClientConnAuthInternalContext *ctx =
524 (SilcClientConnAuthInternalContext *)protocol->context;
525 SilcClient client = (SilcClient)ctx->client;
526 SilcClientConnection conn = ctx->sock->user_data;
528 SILC_LOG_DEBUG(("Start"));
530 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
531 protocol->state = SILC_PROTOCOL_STATE_START;
533 switch(protocol->state) {
534 case SILC_PROTOCOL_STATE_START:
537 * Start protocol. We send authentication data to the server
538 * to be authenticated.
542 unsigned char *auth_data = NULL;
543 uint32 auth_data_len = 0;
545 switch(ctx->auth_meth) {
547 /* No authentication required */
550 case SILC_AUTH_PASSWORD:
551 /* Password authentication */
552 if (ctx->auth_data && ctx->auth_data_len) {
553 auth_data = ctx->auth_data;
554 auth_data_len = ctx->auth_data_len;
558 client->ops->say(client, conn,
559 "Password authentication required by server %s",
560 ctx->sock->hostname);
561 auth_data = client->ops->ask_passphrase(client, conn);
562 auth_data_len = strlen(auth_data);
565 case SILC_AUTH_PUBLIC_KEY:
567 unsigned char sign[1024];
569 /* Public key authentication */
570 silc_client_get_public_key_auth(client, ctx->auth_data,
571 sign, &auth_data_len,
573 auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
574 memcpy(auth_data, sign, auth_data_len);
579 payload_len = 4 + auth_data_len;
580 packet = silc_buffer_alloc(payload_len);
581 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
582 silc_buffer_format(packet,
583 SILC_STR_UI_SHORT(payload_len),
584 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
585 SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
588 /* Send the packet to server */
589 silc_client_packet_send(client, ctx->sock,
590 SILC_PACKET_CONNECTION_AUTH,
592 packet->data, packet->len, TRUE);
595 memset(auth_data, 0, auth_data_len);
596 silc_free(auth_data);
598 silc_buffer_free(packet);
600 /* Next state is end of protocol */
601 protocol->state = SILC_PROTOCOL_STATE_END;
605 case SILC_PROTOCOL_STATE_END:
608 * End protocol. Nothing special to be done here.
611 /* Protocol has ended, call the final callback */
612 if (protocol->final_callback)
613 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
615 silc_protocol_free(protocol);
619 case SILC_PROTOCOL_STATE_ERROR:
622 * Error. Send notify to remote.
624 unsigned char error[4];
626 SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
628 /* Error in protocol. Send FAILURE packet. Although I don't think
629 this could ever happen on client side. */
630 silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
631 NULL, 0, NULL, NULL, error, 4, TRUE);
633 /* On error the final callback is always called. */
634 if (protocol->final_callback)
635 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
637 silc_protocol_free(protocol);
640 case SILC_PROTOCOL_STATE_FAILURE:
642 * Received failure from remote.
645 /* On error the final callback is always called. */
646 if (protocol->final_callback)
647 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
649 silc_protocol_free(protocol);
652 case SILC_PROTOCOL_STATE_UNKNOWN:
658 * Re-key protocol routines
661 /* Actually takes the new keys into use. */
664 silc_client_protocol_rekey_validate(SilcClient client,
665 SilcClientRekeyInternalContext *ctx,
666 SilcSocketConnection sock,
667 SilcSKEKeyMaterial *keymat,
670 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
672 if (ctx->responder == TRUE) {
674 silc_cipher_set_key(conn->send_key, keymat->receive_enc_key,
675 keymat->enc_key_len);
676 silc_cipher_set_iv(conn->send_key, keymat->receive_iv);
678 silc_cipher_set_key(conn->receive_key, keymat->send_enc_key,
679 keymat->enc_key_len);
680 silc_cipher_set_iv(conn->receive_key, keymat->send_iv);
684 silc_cipher_set_key(conn->send_key, keymat->send_enc_key,
685 keymat->enc_key_len);
686 silc_cipher_set_iv(conn->send_key, keymat->send_iv);
688 silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key,
689 keymat->enc_key_len);
690 silc_cipher_set_iv(conn->receive_key, keymat->receive_iv);
695 silc_hmac_alloc(conn->hmac_receive->hmac->name, NULL, &conn->hmac_send);
696 silc_hmac_set_key(conn->hmac_send, keymat->hmac_key,
697 keymat->hmac_key_len);
699 silc_hmac_free(conn->hmac_receive);
700 conn->hmac_receive = conn->hmac_send;
703 /* Save the current sending encryption key */
705 memset(conn->rekey->send_enc_key, 0, conn->rekey->enc_key_len);
706 silc_free(conn->rekey->send_enc_key);
707 conn->rekey->send_enc_key =
708 silc_calloc(keymat->enc_key_len / 8,
709 sizeof(*conn->rekey->send_enc_key));
710 memcpy(conn->rekey->send_enc_key, keymat->send_enc_key,
711 keymat->enc_key_len / 8);
712 conn->rekey->enc_key_len = keymat->enc_key_len / 8;
716 /* This function actually re-generates (when not using PFS) the keys and
717 takes them into use. */
720 silc_client_protocol_rekey_generate(SilcClient client,
721 SilcClientRekeyInternalContext *ctx,
724 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
725 SilcSKEKeyMaterial *keymat;
726 uint32 key_len = silc_cipher_get_key_len(conn->send_key);
727 uint32 hash_len = conn->hash->hash->hash_len;
729 SILC_LOG_DEBUG(("Generating new %s session keys (no PFS)",
730 send ? "sending" : "receiving"));
732 /* Generate the new key */
733 keymat = silc_calloc(1, sizeof(*keymat));
734 silc_ske_process_key_material_data(conn->rekey->send_enc_key,
735 conn->rekey->enc_key_len,
736 16, key_len, hash_len,
739 /* Set the keys into use */
740 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
742 silc_ske_free_key_material(keymat);
745 /* This function actually re-generates (with PFS) the keys and
746 takes them into use. */
749 silc_client_protocol_rekey_generate_pfs(SilcClient client,
750 SilcClientRekeyInternalContext *ctx,
753 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
754 SilcSKEKeyMaterial *keymat;
755 uint32 key_len = silc_cipher_get_key_len(conn->send_key);
756 uint32 hash_len = conn->hash->hash->hash_len;
757 unsigned char *tmpbuf;
760 SILC_LOG_DEBUG(("Generating new %s session keys (with PFS)",
761 send ? "sending" : "receiving"));
763 /* Encode KEY to binary data */
764 tmpbuf = silc_mp_mp2bin(ctx->ske->KEY, 0, &klen);
766 /* Generate the new key */
767 keymat = silc_calloc(1, sizeof(*keymat));
768 silc_ske_process_key_material_data(tmpbuf, klen, 16, key_len, hash_len,
771 /* Set the keys into use */
772 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
774 memset(tmpbuf, 0, klen);
776 silc_ske_free_key_material(keymat);
779 /* Packet sending callback. This function is provided as packet sending
780 routine to the Key Exchange functions. */
783 silc_client_protocol_rekey_send_packet(SilcSKE ske,
788 SilcProtocol protocol = (SilcProtocol)context;
789 SilcClientRekeyInternalContext *ctx =
790 (SilcClientRekeyInternalContext *)protocol->context;
791 SilcClient client = (SilcClient)ctx->client;
793 /* Send the packet immediately */
794 silc_client_packet_send(client, ctx->sock, type, NULL, 0, NULL, NULL,
795 packet->data, packet->len, FALSE);
798 /* Performs re-key as defined in the SILC protocol specification. */
800 SILC_TASK_CALLBACK(silc_client_protocol_rekey)
802 SilcProtocol protocol = (SilcProtocol)context;
803 SilcClientRekeyInternalContext *ctx =
804 (SilcClientRekeyInternalContext *)protocol->context;
805 SilcClient client = (SilcClient)ctx->client;
806 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
807 SilcSKEStatus status;
809 SILC_LOG_DEBUG(("Start"));
811 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
812 protocol->state = SILC_PROTOCOL_STATE_START;
814 SILC_LOG_DEBUG(("State=%d", protocol->state));
816 switch(protocol->state) {
817 case SILC_PROTOCOL_STATE_START:
823 if (ctx->responder == TRUE) {
825 * We are receiving party
828 if (ctx->pfs == TRUE) {
830 * Use Perfect Forward Secrecy, ie. negotiate the key material
831 * using the SKE protocol.
834 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
835 /* Error in protocol */
836 protocol->state = SILC_PROTOCOL_STATE_ERROR;
837 protocol->execute(client->timeout_queue, 0, protocol, fd,
841 ctx->ske = silc_ske_alloc();
842 ctx->ske->rng = client->rng;
843 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
844 silc_ske_get_group_by_number(conn->rekey->ske_group,
845 &ctx->ske->prop->group);
847 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer,
848 NULL, NULL, NULL, NULL);
849 if (status != SILC_SKE_STATUS_OK) {
850 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
853 protocol->state = SILC_PROTOCOL_STATE_ERROR;
854 protocol->execute(client->timeout_queue, 0,
855 protocol, fd, 0, 300000);
859 /* Advance the protocol state */
861 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
864 * Do normal and simple re-key.
867 /* Send the REKEY_DONE to indicate we will take new keys into use */
868 silc_client_packet_send(client, ctx->sock,
869 SILC_PACKET_REKEY_DONE,
870 NULL, 0, NULL, NULL, NULL, 0, FALSE);
872 /* After we send REKEY_DONE we must set the sending encryption
873 key to the new key since all packets after this packet must
874 encrypted with the new key. */
875 silc_client_protocol_rekey_generate(client, ctx, TRUE);
877 /* The protocol ends in next stage. */
878 protocol->state = SILC_PROTOCOL_STATE_END;
883 * We are the initiator of this protocol
886 /* Start the re-key by sending the REKEY packet */
887 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY,
888 NULL, 0, NULL, NULL, NULL, 0, FALSE);
890 if (ctx->pfs == TRUE) {
892 * Use Perfect Forward Secrecy, ie. negotiate the key material
893 * using the SKE protocol.
895 ctx->ske = silc_ske_alloc();
896 ctx->ske->rng = client->rng;
897 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
898 silc_ske_get_group_by_number(conn->rekey->ske_group,
899 &ctx->ske->prop->group);
902 silc_ske_initiator_phase_2(ctx->ske, NULL, NULL,
903 silc_client_protocol_rekey_send_packet,
906 if (status != SILC_SKE_STATUS_OK) {
907 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
910 protocol->state = SILC_PROTOCOL_STATE_ERROR;
911 protocol->execute(client->timeout_queue, 0,
912 protocol, fd, 0, 300000);
916 /* Advance the protocol state */
920 * Do normal and simple re-key.
923 /* Send the REKEY_DONE to indicate we will take new keys into use
925 silc_client_packet_send(client, ctx->sock,
926 SILC_PACKET_REKEY_DONE,
927 NULL, 0, NULL, NULL, NULL, 0, FALSE);
929 /* After we send REKEY_DONE we must set the sending encryption
930 key to the new key since all packets after this packet must
931 encrypted with the new key. */
932 silc_client_protocol_rekey_generate(client, ctx, TRUE);
934 /* The protocol ends in next stage. */
935 protocol->state = SILC_PROTOCOL_STATE_END;
943 * Second state, used only when oding re-key with PFS.
945 if (ctx->responder == TRUE) {
946 if (ctx->pfs == TRUE) {
948 * Send our KE packe to the initiator now that we've processed
949 * the initiator's KE packet.
952 silc_ske_responder_finish(ctx->ske, NULL, NULL,
953 SILC_SKE_PK_TYPE_SILC,
954 silc_client_protocol_rekey_send_packet,
957 if (status != SILC_SKE_STATUS_OK) {
958 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
961 protocol->state = SILC_PROTOCOL_STATE_ERROR;
962 protocol->execute(client->timeout_queue, 0,
963 protocol, fd, 0, 300000);
969 if (ctx->pfs == TRUE) {
971 * The packet type must be KE packet
973 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
974 /* Error in protocol */
975 protocol->state = SILC_PROTOCOL_STATE_ERROR;
976 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 300000);
979 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
980 NULL, NULL, NULL, NULL);
981 if (status != SILC_SKE_STATUS_OK) {
982 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
985 protocol->state = SILC_PROTOCOL_STATE_ERROR;
986 protocol->execute(client->timeout_queue, 0,
987 protocol, fd, 0, 300000);
993 /* Send the REKEY_DONE to indicate we will take new keys into use
995 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
996 NULL, 0, NULL, NULL, NULL, 0, FALSE);
998 /* After we send REKEY_DONE we must set the sending encryption
999 key to the new key since all packets after this packet must
1000 encrypted with the new key. */
1001 silc_client_protocol_rekey_generate_pfs(client, ctx, TRUE);
1003 /* The protocol ends in next stage. */
1004 protocol->state = SILC_PROTOCOL_STATE_END;
1007 case SILC_PROTOCOL_STATE_END:
1012 if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
1013 /* Error in protocol */
1014 protocol->state = SILC_PROTOCOL_STATE_ERROR;
1015 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
1018 /* We received the REKEY_DONE packet and all packets after this is
1019 encrypted with the new key so set the decryption key to the new key */
1020 silc_client_protocol_rekey_generate(client, ctx, FALSE);
1022 /* Protocol has ended, call the final callback */
1023 if (protocol->final_callback)
1024 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
1026 silc_protocol_free(protocol);
1029 case SILC_PROTOCOL_STATE_ERROR:
1034 if (ctx->pfs == TRUE) {
1035 /* Send abort notification */
1036 silc_ske_abort(ctx->ske, ctx->ske->status,
1037 silc_client_protocol_ke_send_packet,
1041 /* On error the final callback is always called. */
1042 if (protocol->final_callback)
1043 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
1045 silc_protocol_free(protocol);
1048 case SILC_PROTOCOL_STATE_FAILURE:
1050 * We have received failure from remote
1053 /* On error the final callback is always called. */
1054 if (protocol->final_callback)
1055 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
1057 silc_protocol_free(protocol);
1060 case SILC_PROTOCOL_STATE_UNKNOWN:
1066 /* Registers protocols used in client */
1068 void silc_client_protocols_register(void)
1070 silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1071 silc_client_protocol_connection_auth);
1072 silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1073 silc_client_protocol_key_exchange);
1074 silc_protocol_register(SILC_PROTOCOL_CLIENT_REKEY,
1075 silc_client_protocol_rekey);
1078 /* Unregisters protocols */
1080 void silc_client_protocols_unregister(void)
1082 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1083 silc_client_protocol_connection_auth);
1084 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1085 silc_client_protocol_key_exchange);
1086 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_REKEY,
1087 silc_client_protocol_rekey);