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);
132 silc_hmac_set_key(conn->hmac, keymat->hmac_key, keymat->hmac_key_len);
134 /* Save the HASH function */
135 silc_hash_alloc(hash->hash->name, &conn->hash);
138 /* Checks the version string of the server. */
140 SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
143 SilcClientConnection conn = (SilcClientConnection)ske->sock->user_data;
144 SilcClient client = (SilcClient)ske->user_data;
145 SilcSKEStatus status = SILC_SKE_STATUS_OK;
147 /* Check for initial version string */
148 if (!strstr(version, "SILC-1.0-"))
149 status = SILC_SKE_STATUS_BAD_VERSION;
151 /* Check software version */
153 if (len < strlen(silc_version_string))
154 status = SILC_SKE_STATUS_BAD_VERSION;
156 /* XXX for now there is no other tests due to the abnormal version
157 string that is used */
159 if (status != SILC_SKE_STATUS_OK)
160 client->ops->say(client, conn,
161 "We don't support server version `%s'", version);
166 /* Performs key exchange protocol. This is used for both initiator
167 and responder key exchange. This may be called recursively. */
169 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
171 SilcProtocol protocol = (SilcProtocol)context;
172 SilcClientKEInternalContext *ctx =
173 (SilcClientKEInternalContext *)protocol->context;
174 SilcClient client = (SilcClient)ctx->client;
175 SilcClientConnection conn = ctx->sock->user_data;
176 SilcSKEStatus status = 0;
178 SILC_LOG_DEBUG(("Start"));
180 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
181 protocol->state = SILC_PROTOCOL_STATE_START;
183 switch(protocol->state) {
184 case SILC_PROTOCOL_STATE_START:
191 /* Allocate Key Exchange object */
192 ske = silc_ske_alloc();
194 ske->rng = client->rng;
195 ske->user_data = (void *)client;
197 if (ctx->responder == TRUE) {
198 /* Start the key exchange by processing the received security
199 properties packet from initiator. */
200 status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
202 ctx->packet->buffer, TRUE,
205 SilcSKEStartPayload *start_payload;
207 /* Assemble security properties. */
208 silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE,
212 /* Start the key exchange by sending our security properties
213 to the remote end. */
214 status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
220 if (status != SILC_SKE_STATUS_OK) {
221 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
223 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
226 protocol->state = SILC_PROTOCOL_STATE_ERROR;
227 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
231 /* Advance protocol state and call the next state if we are responder */
233 if (ctx->responder == TRUE)
234 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
242 if (ctx->responder == TRUE) {
243 /* Sends the selected security properties to the initiator. */
245 silc_ske_responder_phase_1(ctx->ske,
246 ctx->ske->start_payload,
250 /* Call Phase-1 function. This processes the Key Exchange Start
251 paylaod reply we just got from the responder. The callback
252 function will receive the processed payload where we will
254 status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer,
258 if (status != SILC_SKE_STATUS_OK) {
259 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
261 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
264 protocol->state = SILC_PROTOCOL_STATE_ERROR;
265 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
269 /* Advance protocol state and call next state if we are initiator */
271 if (ctx->responder == FALSE)
272 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
280 if (ctx->responder == TRUE) {
281 /* Process the received Key Exchange 1 Payload packet from
282 the initiator. This also creates our parts of the Diffie
283 Hellman algorithm. */
284 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer,
285 ctx->verify, context, NULL, NULL);
287 /* Call the Phase-2 function. This creates Diffie Hellman
288 key exchange parameters and sends our public part inside
289 Key Exhange 1 Payload to the responder. */
290 status = silc_ske_initiator_phase_2(ctx->ske,
297 if (status != SILC_SKE_STATUS_OK) {
298 SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
300 SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
303 protocol->state = SILC_PROTOCOL_STATE_ERROR;
304 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
308 /* Advance protocol state and call the next state if we are responder */
310 if (ctx->responder == TRUE)
311 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
319 if (ctx->responder == TRUE) {
320 /* This creates the key exchange material and sends our
321 public parts to the initiator inside Key Exchange 2 Payload. */
323 silc_ske_responder_finish(ctx->ske,
324 client->public_key, client->private_key,
325 SILC_SKE_PK_TYPE_SILC,
330 /* Finish the protocol. This verifies the Key Exchange 2 payload
331 sent by responder. */
332 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
333 ctx->verify, context, NULL, NULL);
336 if (status != SILC_SKE_STATUS_OK) {
338 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
339 client->ops->say(client, conn,
340 "Received unsupported server %s public key",
341 ctx->sock->hostname);
343 client->ops->say(client, conn,
344 "Error during key exchange protocol with server %s",
345 ctx->sock->hostname);
347 protocol->state = SILC_PROTOCOL_STATE_ERROR;
348 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
352 /* Send Ok to the other end. We will end the protocol as server
353 sends Ok to us when we will take the new keys into use. */
354 if (ctx->responder == FALSE)
355 silc_ske_end(ctx->ske, ctx->send_packet, context);
357 /* End the protocol on the next round */
358 protocol->state = SILC_PROTOCOL_STATE_END;
362 case SILC_PROTOCOL_STATE_END:
367 SilcSKEKeyMaterial *keymat;
368 int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher);
369 int hash_len = ctx->ske->prop->hash->hash->hash_len;
371 /* Process the key material */
372 keymat = silc_calloc(1, sizeof(*keymat));
373 status = silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
375 if (status != SILC_SKE_STATUS_OK) {
376 protocol->state = SILC_PROTOCOL_STATE_ERROR;
377 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 300000);
378 silc_ske_free_key_material(keymat);
381 ctx->keymat = keymat;
383 /* Send Ok to the other end if we are responder. If we are initiator
384 we have sent this already. */
385 if (ctx->responder == TRUE)
386 silc_ske_end(ctx->ske, ctx->send_packet, context);
388 /* Unregister the timeout task since the protocol has ended.
389 This was the timeout task to be executed if the protocol is
390 not completed fast enough. */
391 if (ctx->timeout_task)
392 silc_task_unregister(client->timeout_queue, ctx->timeout_task);
394 /* Protocol has ended, call the final callback */
395 if (protocol->final_callback)
396 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
398 silc_protocol_free(protocol);
402 case SILC_PROTOCOL_STATE_ERROR:
404 * Error during protocol
407 /* Send abort notification */
408 silc_ske_abort(ctx->ske, ctx->ske->status,
409 ctx->send_packet, context);
411 /* On error the final callback is always called. */
412 if (protocol->final_callback)
413 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
415 silc_protocol_free(protocol);
418 case SILC_PROTOCOL_STATE_FAILURE:
420 * Received failure from remote.
423 /* Unregister the timeout task since the protocol has ended.
424 This was the timeout task to be executed if the protocol is
425 not completed fast enough. */
426 if (ctx->timeout_task)
427 silc_task_unregister(client->timeout_queue, ctx->timeout_task);
429 /* On error the final callback is always called. */
430 if (protocol->final_callback)
431 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
433 silc_protocol_free(protocol);
435 case SILC_PROTOCOL_STATE_UNKNOWN:
441 * Connection Authentication protocol functions
445 silc_client_get_public_key_auth(SilcClient client,
447 unsigned char *auth_data,
448 uint32 *auth_data_len,
454 SilcPublicKey pub_key;
456 if (!silc_pkcs_load_public_key(filepath,&pub_key, SILC_PKCS_FILE_PEM))
457 if (!silc_pkcs_load_public_key(filepath, &pub_key, SILC_PKCS_FILE_BIN))
460 silc_pkcs_alloc(pub_key->name, &pkcs);
461 if (!silc_pkcs_public_key_set(pkcs, pub_key)) {
462 silc_pkcs_free(pkcs);
463 silc_pkcs_public_key_free(pub_key);
467 /* Make the authentication data. Protocol says it is HASH plus
469 len = ske->hash_len + ske->start_payload_copy->len;
470 auth = silc_buffer_alloc(len);
471 silc_buffer_pull_tail(auth, len);
472 silc_buffer_format(auth,
473 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
474 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
475 ske->start_payload_copy->len),
478 if (silc_pkcs_sign(pkcs, auth->data, auth->len, auth_data, auth_data_len)) {
479 silc_pkcs_free(pkcs);
480 silc_buffer_free(auth);
481 silc_pkcs_public_key_free(pub_key);
485 silc_pkcs_free(pkcs);
486 silc_buffer_free(auth);
487 silc_pkcs_public_key_free(pub_key);
491 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
493 SilcProtocol protocol = (SilcProtocol)context;
494 SilcClientConnAuthInternalContext *ctx =
495 (SilcClientConnAuthInternalContext *)protocol->context;
496 SilcClient client = (SilcClient)ctx->client;
497 SilcClientConnection conn = ctx->sock->user_data;
499 SILC_LOG_DEBUG(("Start"));
501 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
502 protocol->state = SILC_PROTOCOL_STATE_START;
504 switch(protocol->state) {
505 case SILC_PROTOCOL_STATE_START:
508 * Start protocol. We send authentication data to the server
509 * to be authenticated.
513 unsigned char *auth_data = NULL;
514 uint32 auth_data_len = 0;
516 switch(ctx->auth_meth) {
518 /* No authentication required */
521 case SILC_AUTH_PASSWORD:
522 /* Password authentication */
523 if (ctx->auth_data && ctx->auth_data_len) {
524 auth_data = ctx->auth_data;
525 auth_data_len = ctx->auth_data_len;
529 client->ops->say(client, conn,
530 "Password authentication required by server %s",
531 ctx->sock->hostname);
532 auth_data = client->ops->ask_passphrase(client, conn);
533 auth_data_len = strlen(auth_data);
536 case SILC_AUTH_PUBLIC_KEY:
538 unsigned char sign[1024];
540 /* Public key authentication */
541 silc_client_get_public_key_auth(client, ctx->auth_data,
542 sign, &auth_data_len,
544 auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
545 memcpy(auth_data, sign, auth_data_len);
550 payload_len = 4 + auth_data_len;
551 packet = silc_buffer_alloc(payload_len);
552 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
553 silc_buffer_format(packet,
554 SILC_STR_UI_SHORT(payload_len),
555 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
556 SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
559 /* Send the packet to server */
560 silc_client_packet_send(client, ctx->sock,
561 SILC_PACKET_CONNECTION_AUTH,
563 packet->data, packet->len, TRUE);
566 memset(auth_data, 0, auth_data_len);
567 silc_free(auth_data);
569 silc_buffer_free(packet);
571 /* Next state is end of protocol */
572 protocol->state = SILC_PROTOCOL_STATE_END;
576 case SILC_PROTOCOL_STATE_END:
579 * End protocol. Nothing special to be done here.
582 /* Protocol has ended, call the final callback */
583 if (protocol->final_callback)
584 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
586 silc_protocol_free(protocol);
590 case SILC_PROTOCOL_STATE_ERROR:
593 * Error. Send notify to remote.
595 unsigned char error[4];
597 SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
599 /* Error in protocol. Send FAILURE packet. Although I don't think
600 this could ever happen on client side. */
601 silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
602 NULL, 0, NULL, NULL, error, 4, TRUE);
604 /* On error the final callback is always called. */
605 if (protocol->final_callback)
606 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
608 silc_protocol_free(protocol);
611 case SILC_PROTOCOL_STATE_FAILURE:
613 * Received failure from remote.
616 /* On error the final callback is always called. */
617 if (protocol->final_callback)
618 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
620 silc_protocol_free(protocol);
623 case SILC_PROTOCOL_STATE_UNKNOWN:
629 * Re-key protocol routines
632 /* Actually takes the new keys into use. */
635 silc_client_protocol_rekey_validate(SilcClient client,
636 SilcClientRekeyInternalContext *ctx,
637 SilcSocketConnection sock,
638 SilcSKEKeyMaterial *keymat)
640 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
642 if (ctx->responder == TRUE) {
643 silc_cipher_set_key(conn->send_key, keymat->receive_enc_key,
644 keymat->enc_key_len);
645 silc_cipher_set_iv(conn->send_key, keymat->receive_iv);
646 silc_cipher_set_key(conn->receive_key, keymat->send_enc_key,
647 keymat->enc_key_len);
648 silc_cipher_set_iv(conn->receive_key, keymat->send_iv);
650 silc_cipher_set_key(conn->send_key, keymat->send_enc_key,
651 keymat->enc_key_len);
652 silc_cipher_set_iv(conn->send_key, keymat->send_iv);
653 silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key,
654 keymat->enc_key_len);
655 silc_cipher_set_iv(conn->receive_key, keymat->receive_iv);
658 silc_hmac_set_key(conn->hmac, keymat->hmac_key, keymat->hmac_key_len);
660 /* Save the current sending encryption key */
661 memset(conn->rekey->send_enc_key, 0, conn->rekey->enc_key_len);
662 silc_free(conn->rekey->send_enc_key);
663 conn->rekey->send_enc_key =
664 silc_calloc(keymat->enc_key_len / 8,
665 sizeof(*conn->rekey->send_enc_key));
666 memcpy(conn->rekey->send_enc_key, keymat->send_enc_key,
667 keymat->enc_key_len / 8);
668 conn->rekey->enc_key_len = keymat->enc_key_len / 8;
671 /* This function actually re-generates (when not using PFS) the keys and
672 takes them into use. */
674 void silc_client_protocol_rekey_generate(SilcClient client,
675 SilcClientRekeyInternalContext *ctx)
677 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
678 SilcSKEKeyMaterial *keymat;
679 uint32 key_len = silc_cipher_get_key_len(conn->send_key);
680 uint32 hash_len = conn->hash->hash->hash_len;
682 SILC_LOG_DEBUG(("Generating new session keys (no PFS)"));
684 /* Generate the new key */
685 keymat = silc_calloc(1, sizeof(*keymat));
686 silc_ske_process_key_material_data(conn->rekey->send_enc_key,
687 conn->rekey->enc_key_len,
688 16, key_len, hash_len,
691 /* Set the keys into use */
692 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat);
694 silc_ske_free_key_material(keymat);
697 /* This function actually re-generates (with PFS) the keys and
698 takes them into use. */
701 silc_client_protocol_rekey_generate_pfs(SilcClient client,
702 SilcClientRekeyInternalContext *ctx)
704 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
705 SilcSKEKeyMaterial *keymat;
706 uint32 key_len = silc_cipher_get_key_len(conn->send_key);
707 uint32 hash_len = conn->hash->hash->hash_len;
708 unsigned char *tmpbuf;
711 SILC_LOG_DEBUG(("Generating new session keys (with PFS)"));
713 /* Encode KEY to binary data */
714 tmpbuf = silc_mp_mp2bin(ctx->ske->KEY, 0, &klen);
716 /* Generate the new key */
717 keymat = silc_calloc(1, sizeof(*keymat));
718 silc_ske_process_key_material_data(tmpbuf, klen, 16, key_len, hash_len,
721 /* Set the keys into use */
722 silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat);
724 memset(tmpbuf, 0, klen);
726 silc_ske_free_key_material(keymat);
729 /* Packet sending callback. This function is provided as packet sending
730 routine to the Key Exchange functions. */
733 silc_client_protocol_rekey_send_packet(SilcSKE ske,
738 SilcProtocol protocol = (SilcProtocol)context;
739 SilcClientRekeyInternalContext *ctx =
740 (SilcClientRekeyInternalContext *)protocol->context;
741 SilcClient client = (SilcClient)ctx->client;
743 /* Send the packet immediately */
744 silc_client_packet_send(client, ctx->sock, type, NULL, 0, NULL, NULL,
745 packet->data, packet->len, TRUE);
748 /* Performs re-key as defined in the SILC protocol specification. */
750 SILC_TASK_CALLBACK(silc_client_protocol_rekey)
752 SilcProtocol protocol = (SilcProtocol)context;
753 SilcClientRekeyInternalContext *ctx =
754 (SilcClientRekeyInternalContext *)protocol->context;
755 SilcClient client = (SilcClient)ctx->client;
756 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
757 SilcSKEStatus status;
759 SILC_LOG_DEBUG(("Start"));
761 if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
762 protocol->state = SILC_PROTOCOL_STATE_START;
764 SILC_LOG_DEBUG(("State=%d", protocol->state));
766 switch(protocol->state) {
767 case SILC_PROTOCOL_STATE_START:
773 if (ctx->responder == TRUE) {
775 * We are receiving party
778 if (ctx->pfs == TRUE) {
780 * Use Perfect Forward Secrecy, ie. negotiate the key material
781 * using the SKE protocol.
784 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
785 /* Error in protocol */
786 protocol->state = SILC_PROTOCOL_STATE_ERROR;
787 protocol->execute(client->timeout_queue, 0, protocol, fd,
791 ctx->ske = silc_ske_alloc();
792 ctx->ske->rng = client->rng;
793 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
794 silc_ske_get_group_by_number(conn->rekey->ske_group,
795 &ctx->ske->prop->group);
797 status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer,
798 NULL, NULL, NULL, NULL);
799 if (status != SILC_SKE_STATUS_OK) {
800 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
803 protocol->state = SILC_PROTOCOL_STATE_ERROR;
804 protocol->execute(client->timeout_queue, 0,
805 protocol, fd, 0, 300000);
809 /* Advance the protocol state */
811 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
814 * Do normal and simple re-key.
817 /* Send the REKEY_DONE to indicate we will take new keys into use */
818 silc_client_packet_send(client, ctx->sock,
819 SILC_PACKET_REKEY_DONE,
820 NULL, 0, NULL, NULL, NULL, 0, TRUE);
822 /* The protocol ends in next stage. */
823 protocol->state = SILC_PROTOCOL_STATE_END;
828 * We are the initiator of this protocol
831 /* Start the re-key by sending the REKEY packet */
832 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY,
833 NULL, 0, NULL, NULL, NULL, 0, TRUE);
835 if (ctx->pfs == TRUE) {
837 * Use Perfect Forward Secrecy, ie. negotiate the key material
838 * using the SKE protocol.
840 ctx->ske = silc_ske_alloc();
841 ctx->ske->rng = client->rng;
842 ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
843 silc_ske_get_group_by_number(conn->rekey->ske_group,
844 &ctx->ske->prop->group);
847 silc_ske_initiator_phase_2(ctx->ske, NULL, NULL,
848 silc_client_protocol_rekey_send_packet,
851 if (status != SILC_SKE_STATUS_OK) {
852 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
855 protocol->state = SILC_PROTOCOL_STATE_ERROR;
856 protocol->execute(client->timeout_queue, 0,
857 protocol, fd, 0, 300000);
861 /* Advance the protocol state */
865 * Do normal and simple re-key.
868 /* The protocol ends in next stage. We have sent the REKEY packet
869 and now we just wait that the responder send REKEY_DONE and
870 the we'll generate the new key, simple. */
871 protocol->state = SILC_PROTOCOL_STATE_END;
879 * Second state, used only when oding re-key with PFS.
881 if (ctx->responder == TRUE) {
882 if (ctx->pfs == TRUE) {
884 * Send our KE packe to the initiator now that we've processed
885 * the initiator's KE packet.
888 silc_ske_responder_finish(ctx->ske, NULL, NULL,
889 SILC_SKE_PK_TYPE_SILC,
890 silc_client_protocol_rekey_send_packet,
893 if (status != SILC_SKE_STATUS_OK) {
894 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
897 protocol->state = SILC_PROTOCOL_STATE_ERROR;
898 protocol->execute(client->timeout_queue, 0,
899 protocol, fd, 0, 300000);
905 if (ctx->pfs == TRUE) {
907 * The packet type must be KE packet
909 if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
910 /* Error in protocol */
911 protocol->state = SILC_PROTOCOL_STATE_ERROR;
912 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 300000);
915 status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
916 NULL, NULL, NULL, NULL);
917 if (status != SILC_SKE_STATUS_OK) {
918 SILC_LOG_WARNING(("Error (type %d) during Re-key (PFS)",
921 protocol->state = SILC_PROTOCOL_STATE_ERROR;
922 protocol->execute(client->timeout_queue, 0,
923 protocol, fd, 0, 300000);
929 /* Send the REKEY_DONE to indicate we will take new keys into use
931 silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
932 NULL, 0, NULL, NULL, NULL, 0, TRUE);
934 /* The protocol ends in next stage. */
935 protocol->state = SILC_PROTOCOL_STATE_END;
938 case SILC_PROTOCOL_STATE_END:
943 if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
944 /* Error in protocol */
945 protocol->state = SILC_PROTOCOL_STATE_ERROR;
946 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
949 if (ctx->responder == FALSE) {
950 if (ctx->pfs == FALSE) {
951 /* Send the REKEY_DONE to indicate we will take new keys into use
953 silc_client_packet_send(client, ctx->sock,
954 SILC_PACKET_REKEY_DONE,
955 NULL, 0, NULL, NULL, NULL, 0, TRUE);
959 /* Protocol has ended, call the final callback */
960 if (protocol->final_callback)
961 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
963 silc_protocol_free(protocol);
966 case SILC_PROTOCOL_STATE_ERROR:
971 if (ctx->pfs == TRUE) {
972 /* Send abort notification */
973 silc_ske_abort(ctx->ske, ctx->ske->status,
974 silc_client_protocol_ke_send_packet,
978 /* On error the final callback is always called. */
979 if (protocol->final_callback)
980 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
982 silc_protocol_free(protocol);
985 case SILC_PROTOCOL_STATE_FAILURE:
987 * We have received failure from remote
990 /* On error the final callback is always called. */
991 if (protocol->final_callback)
992 protocol->execute_final(client->timeout_queue, 0, protocol, fd);
994 silc_protocol_free(protocol);
997 case SILC_PROTOCOL_STATE_UNKNOWN:
1003 /* Registers protocols used in client */
1005 void silc_client_protocols_register(void)
1007 silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1008 silc_client_protocol_connection_auth);
1009 silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1010 silc_client_protocol_key_exchange);
1011 silc_protocol_register(SILC_PROTOCOL_CLIENT_REKEY,
1012 silc_client_protocol_rekey);
1015 /* Unregisters protocols */
1017 void silc_client_protocols_unregister(void)
1019 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
1020 silc_client_protocol_connection_auth);
1021 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
1022 silc_client_protocol_key_exchange);
1023 silc_protocol_unregister(SILC_PROTOCOL_CLIENT_REKEY,
1024 silc_client_protocol_rekey);