+Fri Apr 13 00:09:08 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Ok, rewrote the logic of the re-key and now it seems to work.
+ I tested it on high traffic with frequent re-keys without
+ problems. Added hmac_receive (and renamed hmac to hmac_send)
+ in SilcClientConnection in lib/silcclient/client.h and
+ in SilcIDListData in silcd/idlist.h. Also, removed the
+ SilcPacketParserContext's cipher and hmac fields as they are
+ not needed anymore and actually caused some problems when
+ the ciphers and hmac's changed underneath the packet parser.
+
Thu Apr 12 14:42:51 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
* If re-key protocol is active then process the incoming packets
(*cmd->cb)(ctx);
} else {
- if (app->conn->current_channel)
- silc_client_send_channel_message(app->client,
- app->conn,
- app->conn->current_channel, NULL,
- 0, "HALOO", 5, TRUE);
-
-#if 0
/* Normal message to a channel */
if (len && app->conn && app->conn->current_channel &&
app->conn->current_channel->on_channel == TRUE) {
app->conn->current_channel, NULL,
0, data, strlen(data), TRUE);
}
-#endif
}
out:
SilcIDListData data = (SilcIDListData)entry;
data->send_key = idata->send_key;
data->receive_key = idata->receive_key;
- data->send_enc_key = idata->send_enc_key;
- data->enc_key_len = idata->enc_key_len;
- data->pfs = idata->pfs;
+ data->rekey = idata->rekey;
data->hash = idata->hash;
- data->hmac = idata->hmac;
+ data->hmac_send = idata->hmac_send;
+ data->hmac_receive = idata->hmac_receive;
data->public_key = idata->public_key;
data->last_receive = idata->last_receive;
data->last_sent = idata->last_sent;
silc_cipher_free(idata->send_key);
if (idata->receive_key)
silc_cipher_free(idata->receive_key);
- if (idata->send_enc_key) {
- memset(idata->send_enc_key, 0, idata->enc_key_len);
- silc_free(idata->send_enc_key);
+ if (idata->rekey) {
+ if (idata->rekey->send_enc_key) {
+ memset(idata->rekey->send_enc_key, 0, idata->rekey->enc_key_len);
+ silc_free(idata->rekey->send_enc_key);
+ }
+ silc_free(idata->rekey);
}
- if (idata->hmac)
- silc_hmac_free(idata->hmac);
+ if (idata->hmac_send) /* Same as idata->hmac_receive */
+ silc_hmac_free(idata->hmac_send);
if (idata->public_key)
silc_pkcs_public_key_free(idata->public_key);
}
int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
{
+ SILC_LOG_DEBUG(("Start"));
+
if (entry) {
/* Remove from cache */
if (entry->id)
int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
{
+ SILC_LOG_DEBUG(("Start"));
+
if (entry) {
/* Remove from cache */
if (entry->id)
int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
{
+ SILC_LOG_DEBUG(("Start"));
+
if (entry) {
SilcChannelClientEntry chl;
SilcHash hash;
/* HMAC */
- SilcHmac hmac;
+ SilcHmac hmac_send;
+ SilcHmac hmac_receive;
/* Public key */
SilcPublicKey public_key;
if (dst_sock)
/* Relay the packet */
silc_server_relay_packet(server, dst_sock, idata->send_key,
- idata->hmac, packet, TRUE);
+ idata->hmac_receive, packet, TRUE);
}
/* If we are router and this packet is not already broadcast packet
/* Send the private message */
silc_server_send_private_message(server, dst_sock, idata->send_key,
- idata->hmac, packet);
+ idata->hmac_send, packet);
}
/* Received private message key packet.. This packet is never for us. It is to
/* Relay the packet */
silc_server_relay_packet(server, dst_sock, idata->send_key,
- idata->hmac, packet, FALSE);
+ idata->hmac_send, packet, FALSE);
}
/* Processes incoming command reply packet. The command reply packet may
idata = (SilcIDListData)client;
/* Encrypt packet */
- silc_packet_encrypt(idata->send_key, idata->hmac, dst_sock->outbuf,
+ silc_packet_encrypt(idata->send_key, idata->hmac_send, dst_sock->outbuf,
buffer->len);
/* Send the packet */
/* Relay the packet */
silc_server_relay_packet(server, dst_sock, idata->send_key,
- idata->hmac, packet, FALSE);
+ idata->hmac_send, packet, FALSE);
}
/* Received connection auth request packet that is used during connection
if (proto_ctx->pfs == FALSE)
/* Run the protocol */
- protocol->execute(server->timeout_queue, 0, protocol, sock->sock, 0, 1);
+ protocol->execute(server->timeout_queue, 0, protocol, sock->sock, 0, 0);
}
if (idata) {
cipher = idata->send_key;
- hmac = idata->hmac;
+ hmac = idata->hmac_send;
}
/* Encrypt the packet */
if (idata) {
cipher = idata->send_key;
- hmac = idata->hmac;
+ hmac = idata->hmac_send;
}
/* Encrypt the packet */
silc_buffer_push(buffer, buffer->data - buffer->head);
silc_packet_send_prepare(sock, 0, 0, buffer->len);
silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
- silc_packet_encrypt(idata->send_key, idata->hmac,
+ silc_packet_encrypt(idata->send_key, idata->hmac_send,
sock->outbuf, sock->outbuf->len);
SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", sock->outbuf->len),
silc_buffer_push(buffer, buffer->data - buffer->head);
silc_packet_send_prepare(sock, 0, 0, buffer->len);
silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
- silc_packet_encrypt(idata->send_key, idata->hmac,
+ silc_packet_encrypt(idata->send_key, idata->hmac_send,
sock->outbuf, sock->outbuf->len);
SILC_LOG_HEXDUMP(("Routed packet, len %d", sock->outbuf->len),
SILC_LOG_DEBUG(("Sending channel message to router for routing"));
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, FALSE,
force_send);
}
/* Send the packet */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, FALSE,
force_send);
/* Send the packet */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, FALSE,
force_send);
}
SILC_LOG_DEBUG(("Sending channel message to router for routing"));
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, TRUE,
force_send);
}
/* Send the packet (to normal server) */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, TRUE,
force_send);
/* Send the packet */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, TRUE,
force_send);
}
/* Send the packet */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, FALSE,
force_send);
/* Send the packet */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key, idata->hmac,
+ idata->send_key,
+ idata->hmac_send,
data, data_len, FALSE,
force_send);
}
/* Save HMAC key to be used in the communication. */
- if (!silc_hmac_alloc(hmac->hmac->name, NULL, &idata->hmac)) {
+ if (!silc_hmac_alloc(hmac->hmac->name, NULL, &idata->hmac_send)) {
silc_cipher_free(idata->send_key);
silc_cipher_free(idata->receive_key);
silc_hash_free(idata->hash);
silc_free(conn_data);
return FALSE;
}
- silc_hmac_set_key(idata->hmac, keymat->hmac_key, keymat->hmac_key_len);
+ silc_hmac_set_key(idata->hmac_send, keymat->hmac_key, keymat->hmac_key_len);
+ idata->hmac_receive = idata->hmac_send;
sock->user_data = (void *)conn_data;
silc_server_protocol_rekey_validate(SilcServer server,
SilcServerRekeyInternalContext *ctx,
SilcIDListData idata,
- SilcSKEKeyMaterial *keymat)
+ SilcSKEKeyMaterial *keymat,
+ bool send)
{
if (ctx->responder == TRUE) {
- silc_cipher_set_key(idata->send_key, keymat->receive_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(idata->send_key, keymat->receive_iv);
- silc_cipher_set_key(idata->receive_key, keymat->send_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(idata->receive_key, keymat->send_iv);
+ if (send) {
+ silc_cipher_set_key(idata->send_key, keymat->receive_enc_key,
+ keymat->enc_key_len);
+ silc_cipher_set_iv(idata->send_key, keymat->receive_iv);
+ } else {
+ silc_cipher_set_key(idata->receive_key, keymat->send_enc_key,
+ keymat->enc_key_len);
+ silc_cipher_set_iv(idata->receive_key, keymat->send_iv);
+ }
} else {
- silc_cipher_set_key(idata->send_key, keymat->send_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(idata->send_key, keymat->send_iv);
- silc_cipher_set_key(idata->receive_key, keymat->receive_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(idata->receive_key, keymat->receive_iv);
+ if (send) {
+ silc_cipher_set_key(idata->send_key, keymat->send_enc_key,
+ keymat->enc_key_len);
+ silc_cipher_set_iv(idata->send_key, keymat->send_iv);
+ } else {
+ silc_cipher_set_key(idata->receive_key, keymat->receive_enc_key,
+ keymat->enc_key_len);
+ silc_cipher_set_iv(idata->receive_key, keymat->receive_iv);
+ }
}
- silc_hmac_set_key(idata->hmac, keymat->hmac_key, keymat->hmac_key_len);
+ if (send) {
+ silc_hmac_alloc(idata->hmac_send->hmac->name, NULL, &idata->hmac_send);
+ silc_hmac_set_key(idata->hmac_send, keymat->hmac_key,
+ keymat->hmac_key_len);
+ } else {
+ silc_hmac_free(idata->hmac_receive);
+ idata->hmac_receive = idata->hmac_send;
+ }
/* Save the current sending encryption key */
- memset(idata->rekey->send_enc_key, 0, idata->rekey->enc_key_len);
- silc_free(idata->rekey->send_enc_key);
- idata->rekey->send_enc_key =
- silc_calloc(keymat->enc_key_len / 8,
- sizeof(*idata->rekey->send_enc_key));
- memcpy(idata->rekey->send_enc_key, keymat->send_enc_key,
- keymat->enc_key_len / 8);
- idata->rekey->enc_key_len = keymat->enc_key_len / 8;
+ if (!send) {
+ memset(idata->rekey->send_enc_key, 0, idata->rekey->enc_key_len);
+ silc_free(idata->rekey->send_enc_key);
+ idata->rekey->send_enc_key =
+ silc_calloc(keymat->enc_key_len / 8,
+ sizeof(*idata->rekey->send_enc_key));
+ memcpy(idata->rekey->send_enc_key, keymat->send_enc_key,
+ keymat->enc_key_len / 8);
+ idata->rekey->enc_key_len = keymat->enc_key_len / 8;
+ }
}
/* This function actually re-generates (when not using PFS) the keys and
takes them into use. */
void silc_server_protocol_rekey_generate(SilcServer server,
- SilcServerRekeyInternalContext *ctx)
+ SilcServerRekeyInternalContext *ctx,
+ bool send)
{
SilcIDListData idata = (SilcIDListData)ctx->sock->user_data;
SilcSKEKeyMaterial *keymat;
uint32 key_len = silc_cipher_get_key_len(idata->send_key);
uint32 hash_len = idata->hash->hash->hash_len;
- SILC_LOG_DEBUG(("Generating new session keys (no PFS)"));
+ SILC_LOG_DEBUG(("Generating new %s session keys (no PFS)",
+ send ? "sending" : "receiving"));
/* Generate the new key */
keymat = silc_calloc(1, sizeof(*keymat));
idata->hash, keymat);
/* Set the keys into use */
- silc_server_protocol_rekey_validate(server, ctx, idata, keymat);
+ silc_server_protocol_rekey_validate(server, ctx, idata, keymat, send);
silc_ske_free_key_material(keymat);
}
void
silc_server_protocol_rekey_generate_pfs(SilcServer server,
- SilcServerRekeyInternalContext *ctx)
+ SilcServerRekeyInternalContext *ctx,
+ bool send)
{
SilcIDListData idata = (SilcIDListData)ctx->sock->user_data;
SilcSKEKeyMaterial *keymat;
unsigned char *tmpbuf;
uint32 klen;
- SILC_LOG_DEBUG(("Generating new session keys (with PFS)"));
+ SILC_LOG_DEBUG(("Generating new %s session keys (with PFS)",
+ send ? "sending" : "receiving"));
/* Encode KEY to binary data */
tmpbuf = silc_mp_mp2bin(ctx->ske->KEY, 0, &klen);
idata->hash, keymat);
/* Set the keys into use */
- silc_server_protocol_rekey_validate(server, ctx, idata, keymat);
+ silc_server_protocol_rekey_validate(server, ctx, idata, keymat, send);
memset(tmpbuf, 0, klen);
silc_free(tmpbuf);
silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
0, NULL, 0, FALSE);
+ /* After we send REKEY_DONE we must set the sending encryption
+ key to the new key since all packets after this packet must
+ encrypted with the new key. */
+ silc_server_protocol_rekey_generate(server, ctx, TRUE);
+
/* The protocol ends in next stage. */
protocol->state = SILC_PROTOCOL_STATE_END;
}
silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
0, NULL, 0, FALSE);
+ /* After we send REKEY_DONE we must set the sending encryption
+ key to the new key since all packets after this packet must
+ encrypted with the new key. */
+ silc_server_protocol_rekey_generate(server, ctx, TRUE);
+
/* The protocol ends in next stage. */
protocol->state = SILC_PROTOCOL_STATE_END;
}
silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
0, NULL, 0, FALSE);
+ /* After we send REKEY_DONE we must set the sending encryption
+ key to the new key since all packets after this packet must
+ encrypted with the new key. */
+ silc_server_protocol_rekey_generate_pfs(server, ctx, TRUE);
+
/* The protocol ends in next stage. */
protocol->state = SILC_PROTOCOL_STATE_END;
break;
protocol->execute(server->timeout_queue, 0, protocol, fd, 0, 0);
}
+ /* We received the REKEY_DONE packet and all packets after this is
+ encrypted with the new key so set the decryption key to the new key */
+ silc_server_protocol_rekey_generate(server, ctx, FALSE);
+
/* Protocol has ended, call the final callback */
if (protocol->final_callback)
protocol->execute_final(server->timeout_queue, 0, protocol, fd);
SilcHmac hmac,
SilcSKEDiffieHellmanGroup group,
bool is_responder);
-void silc_server_protocol_rekey_generate(SilcServer server,
- SilcServerRekeyInternalContext *ctx);
-void
-silc_server_protocol_rekey_generate_pfs(SilcServer server,
- SilcServerRekeyInternalContext *ctx);
#endif
timeout!! */
hb_context = silc_calloc(1, sizeof(*hb_context));
hb_context->server = server;
- silc_socket_set_heartbeat(sock, 30, hb_context,
+ silc_socket_set_heartbeat(sock, 600, hb_context,
silc_server_perform_heartbeat,
server->timeout_queue);
/* Register re-key timeout */
- idata->rekey->timeout = 60; /* XXX hardcoded */
+ idata->rekey->timeout = 3600; /* XXX hardcoded */
idata->rekey->context = (void *)server;
silc_task_register(server->timeout_queue, sock->sock,
silc_server_rekey_callback,
timeout!! */
hb_context = silc_calloc(1, sizeof(*hb_context));
hb_context->server = server;
- silc_socket_set_heartbeat(sock, 30, hb_context,
+ silc_socket_set_heartbeat(sock, 600, hb_context,
silc_server_perform_heartbeat,
server->timeout_queue);
if (idata) {
idata->last_receive = time(NULL);
cipher = idata->receive_key;
- hmac = idata->hmac;
+ hmac = idata->hmac_receive;
}
/* Process the packet. This will call the parser that will then
SilcServer server = (SilcServer)parse_ctx->context;
SilcSocketConnection sock = parse_ctx->sock;
SilcPacketContext *packet = parse_ctx->packet;
+ SilcIDListData idata = (SilcIDListData)sock->user_data;
int ret;
SILC_LOG_DEBUG(("Start"));
/* Decrypt the received packet */
- ret = silc_packet_decrypt(parse_ctx->cipher, parse_ctx->hmac,
+ ret = silc_packet_decrypt(idata ? idata->receive_key : NULL,
+ idata ? idata->hmac_receive : NULL,
packet->buffer, packet,
silc_server_packet_decrypt_check, parse_ctx);
if (ret < 0)
/* Let the protocol handle the packet */
sock->protocol->execute(server->timeout_queue, 0,
- sock->protocol, sock->sock, 0, 1);
+ sock->protocol, sock->sock, 0, 0);
} else {
SilcServerKEInternalContext *proto_ctx =
(SilcServerKEInternalContext *)sock->protocol->context;
/* Let the protocol handle the packet */
sock->protocol->execute(server->timeout_queue, 0,
- sock->protocol, sock->sock, 0, 1);
+ sock->protocol, sock->sock, 0, 0);
} else {
SilcServerKEInternalContext *proto_ctx =
(SilcServerKEInternalContext *)sock->protocol->context;
proto_ctx->packet = silc_packet_context_dup(packet);
/* Let the protocol handle the packet */
- if (proto_ctx->responder == FALSE)
- sock->protocol->execute(server->timeout_queue, 0,
- sock->protocol, sock->sock,
- 0, 0);
- else
- sock->protocol->execute(server->timeout_queue, 0,
- sock->protocol, sock->sock,
- 0, 100000);
+ sock->protocol->execute(server->timeout_queue, 0,
+ sock->protocol, sock->sock, 0, 0);
} else {
SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
"protocol active, packet dropped."));
silc_task_register(server->timeout_queue, 0,
silc_server_channel_key_rekey,
- (void *)rekey, 30, 0,
+ (void *)rekey, 3600, 0,
SILC_TASK_TIMEOUT,
SILC_TASK_PRI_NORMAL);
}
silc_server_channel_key_rekey);
silc_task_register(server->timeout_queue, 0,
silc_server_channel_key_rekey,
- (void *)channel->rekey, 30, 0,
+ (void *)channel->rekey, 3600, 0,
SILC_TASK_TIMEOUT,
SILC_TASK_PRI_NORMAL);
}
silc_server_channel_key_rekey);
silc_task_register(server->timeout_queue, 0,
silc_server_channel_key_rekey,
- (void *)channel->rekey, 30, 0,
+ (void *)channel->rekey, 3600, 0,
SILC_TASK_TIMEOUT,
SILC_TASK_PRI_NORMAL);
}
return;
}
+#if 0
/* Take the keys into use */
if (ctx->pfs == TRUE)
silc_server_protocol_rekey_generate_pfs(server, ctx);
else
silc_server_protocol_rekey_generate(server, ctx);
+#endif
/* Cleanup */
silc_protocol_free(protocol);
conn->remote_id_data_len = SILC_ID_SERVER_LEN;
/* Register re-key timeout */
- conn->rekey->timeout = 30; /* XXX hardcoded */
+ conn->rekey->timeout = 3600; /* XXX hardcoded */
conn->rekey->context = (void *)client;
silc_task_register(client->timeout_queue, conn->sock->sock,
silc_client_rekey_callback,
silc_buffer_push(sock->outbuf,
sock->outbuf->data - sock->outbuf->head);
- ret = silc_client_packet_send_real(client, sock, TRUE, FALSE);
+ ret = silc_client_packet_send_real(client, sock, TRUE, TRUE);
/* If returned -2 could not write to connection now, will do
it later. */
/* Process the packet. This will call the parser that will then
decrypt and parse the packet. */
if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
- silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
+ silc_packet_receive_process(sock, conn->receive_key, conn->hmac_receive,
silc_client_packet_parse, client);
else
silc_packet_receive_process(sock, NULL, NULL,
/* Decrypt the received packet */
if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
- ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet,
+ ret = silc_packet_decrypt(conn->receive_key, conn->hmac_receive,
+ buffer, packet,
silc_client_packet_decrypt_check, parse_ctx);
else
ret = silc_packet_decrypt(NULL, NULL, buffer, packet,
if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
cipher = ((SilcClientConnection)sock->user_data)->send_key;
- if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
- hmac = ((SilcClientConnection)sock->user_data)->hmac;
+ if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
+ hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
cipher = ((SilcClientConnection)sock->user_data)->send_key;
- if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
- hmac = ((SilcClientConnection)sock->user_data)->hmac;
+ if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
+ hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
silc_cipher_free(conn->send_key);
if (conn->receive_key)
silc_cipher_free(conn->receive_key);
- if (conn->hmac)
- silc_hmac_free(conn->hmac);
+ if (conn->hmac_send) /* conn->hmac_receive is same */
+ silc_hmac_free(conn->hmac_send);
if (conn->pending_commands)
silc_dlist_uninit(conn->pending_commands);
if (conn->rekey)
conn->remote_type = 0;
conn->send_key = NULL;
conn->receive_key = NULL;
- conn->hmac = NULL;
+ conn->hmac_send = NULL;
+ conn->hmac_receive = NULL;
conn->local_id = NULL;
conn->local_id_data = NULL;
conn->remote_host = NULL;
return;
}
+#if 0
/* Take the keys into use */
if (ctx->pfs == TRUE)
silc_client_protocol_rekey_generate_pfs(client, ctx);
else
silc_client_protocol_rekey_generate(client, ctx);
+#endif
/* Cleanup */
silc_protocol_free(protocol);