From: Pekka Riikonen Date: Thu, 13 Sep 2001 18:55:09 +0000 (+0000) Subject: updates. X-Git-Tag: silcertest~111 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=205916687fdc130a3c5d7e8f66c74973975f4bca updates. --- diff --git a/CHANGES b/CHANGES index 307d1f20..6d19d98d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,21 @@ +Thu Sep 13 20:24:52 EEST 2001 Pekka Riikonen + + * Added defines SILC_DEFAULT_CIPHER, SILC_DEFAULT_HMAC, + SILC_DEFAULT_HASH and SILC_DEFAULT_PKCS in the file + lib/silccrypt/[silccipher.h|silchmac.h|silchash.h|silcpkcs.h]. + + * Removed channel key rekey task deleting from the function + silc_server_save_channel_key. Affected file silcd/server.c. + Added explicit timeout task context instead that is used to + delete the task if we are registering a new task before the + new task has elapsed. + + * When channel key rekey occurs the client library now saves + the old channel key for a short period of time (10 seconds) and + is able to use it in case some is still sending channel + messages encrypted with the old key after the rekey. Affected + file lib/silcclient/[idlist.h|client_channel.c]. + Sun Sep 9 15:49:16 EEST 2001 Pekka Riikonen * Added check to the silc_server_new_id_real to not accept diff --git a/TODO b/TODO index 9a07d6bd..78e31ea0 100644 --- a/TODO +++ b/TODO @@ -48,9 +48,6 @@ TODO/bugs In SILC Client Library TODO/bugs In SILC Server ======================== - o When the primary router connection is lost the server should be marked - standalone again untill the connection is resumed back to the router. - o Add perhaps /var/run/silcd.pid for PID information for the server. o Add a timeout to handling incmoing JOIN commands. It should be diff --git a/apps/silcd/command.c b/apps/silcd/command.c index e70478a0..2828d81b 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -3811,7 +3811,7 @@ SILC_SERVER_CMD_FUNC(cmode) /* Delete old cipher and allocate default one */ silc_cipher_free(channel->channel_key); - if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc", + if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &channel->channel_key)) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, SILC_STATUS_ERR_UNKNOWN_ALGORITHM); @@ -3868,7 +3868,7 @@ SILC_SERVER_CMD_FUNC(cmode) /* Delete old hmac and allocate default one */ silc_hmac_free(channel->hmac); - if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL, + if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &channel->hmac)) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, SILC_STATUS_ERR_UNKNOWN_ALGORITHM); diff --git a/apps/silcd/idlist.c b/apps/silcd/idlist.c index 0360ad37..5788e656 100644 --- a/apps/silcd/idlist.c +++ b/apps/silcd/idlist.c @@ -576,7 +576,7 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode, channel->channel_key = channel_key; channel->hmac = hmac; if (!channel->hmac) - if (!silc_hmac_alloc("hmac-sha1-96", NULL, &channel->hmac)) { + if (!silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac)) { silc_free(channel); return NULL; } diff --git a/apps/silcd/idlist.h b/apps/silcd/idlist.h index 10bf4e32..89b00f88 100644 --- a/apps/silcd/idlist.h +++ b/apps/silcd/idlist.h @@ -38,6 +38,7 @@ typedef struct { void *context; SilcChannelEntry channel; uint32 key_len; + SilcTask task; } *SilcServerChannelRekey; /* Generic rekey context for connections */ diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 6f66e32c..02b1cc89 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -1241,7 +1241,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final) return; } - switch(ctx->conn_type) { + switch (ctx->conn_type) { case SILC_SOCKET_TYPE_CLIENT: { SilcClientEntry client; @@ -1646,19 +1646,19 @@ void silc_server_packet_parse(SilcPacketParserContext *parser_context) case SILC_SOCKET_TYPE_CLIENT: /* Parse the packet with timeout */ silc_schedule_task_add(server->schedule, sock->sock, - silc_server_packet_parse_real, - (void *)parser_context, 0, 100000, - SILC_TASK_TIMEOUT, - SILC_TASK_PRI_NORMAL); + silc_server_packet_parse_real, + (void *)parser_context, 0, 100000, + SILC_TASK_TIMEOUT, + SILC_TASK_PRI_NORMAL); break; case SILC_SOCKET_TYPE_SERVER: case SILC_SOCKET_TYPE_ROUTER: /* Packets from servers are parsed as soon as possible */ silc_schedule_task_add(server->schedule, sock->sock, - silc_server_packet_parse_real, - (void *)parser_context, 0, 1, - SILC_TASK_TIMEOUT, - SILC_TASK_PRI_NORMAL); + silc_server_packet_parse_real, + (void *)parser_context, 0, 1, + SILC_TASK_TIMEOUT, + SILC_TASK_PRI_NORMAL); break; default: return; @@ -1677,7 +1677,7 @@ void silc_server_packet_parse_type(SilcServer server, SILC_LOG_DEBUG(("Parsing packet type %d", type)); /* Parse the packet type */ - switch(type) { + switch (type) { case SILC_PACKET_DISCONNECT: SILC_LOG_DEBUG(("Disconnect packet")); if (packet->flags & SILC_PACKET_FLAG_LIST) @@ -2094,9 +2094,9 @@ void silc_server_create_connection(SilcServer server, sconn->remote_port = port; silc_schedule_task_add(server->schedule, 0, - silc_server_connect_router, - (void *)sconn, 0, 1, SILC_TASK_TIMEOUT, - SILC_TASK_PRI_NORMAL); + silc_server_connect_router, + (void *)sconn, 0, 1, SILC_TASK_TIMEOUT, + SILC_TASK_PRI_NORMAL); } SILC_TASK_CALLBACK(silc_server_close_connection_final) @@ -2236,9 +2236,9 @@ void silc_server_free_client_data(SilcServer server, i->server = server; i->client = client; silc_schedule_task_add(server->schedule, 0, - silc_server_free_client_data_timeout, - (void *)i, 300, 0, - SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW); + silc_server_free_client_data_timeout, + (void *)i, 300, 0, + SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW); client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED; client->router = NULL; client->connection = NULL; @@ -2259,7 +2259,7 @@ void silc_server_free_sock_user_data(SilcServer server, { SILC_LOG_DEBUG(("Start")); - switch(sock->type) { + switch (sock->type) { case SILC_SOCKET_TYPE_CLIENT: { SilcClientEntry user_data = (SilcClientEntry)sock->user_data; @@ -2606,6 +2606,11 @@ int silc_server_remove_clients_by_server(SilcServer server, while (silc_hash_table_get(&htl, NULL, (void *)&channel)) { if (!silc_server_create_channel_key(server, channel, 0)) return FALSE; + + /* Do not send the channel key if private channel key mode is set */ + if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) + continue; + silc_server_send_channel_key(server, NULL, channel, server->server_type == SILC_ROUTER ? FALSE : !server->standalone); @@ -2935,9 +2940,9 @@ SilcChannelEntry silc_server_create_new_channel(SilcServer server, SILC_LOG_DEBUG(("Creating new channel")); if (!cipher) - cipher = "aes-256-cbc"; + cipher = SILC_DEFAULT_CIPHER; if (!hmac) - hmac = "hmac-sha1-96"; + hmac = SILC_DEFAULT_HMAC; /* Allocate cipher */ if (!silc_cipher_alloc(cipher, &key)) @@ -3013,9 +3018,9 @@ silc_server_create_new_channel_with_id(SilcServer server, SILC_LOG_DEBUG(("Creating new channel")); if (!cipher) - cipher = "aes-256-cbc"; + cipher = SILC_DEFAULT_CIPHER; if (!hmac) - hmac = "hmac-sha1-96"; + hmac = SILC_DEFAULT_HMAC; /* Allocate cipher */ if (!silc_cipher_alloc(cipher, &key)) @@ -3065,8 +3070,11 @@ SILC_TASK_CALLBACK(silc_server_channel_key_rekey) SilcServerChannelRekey rekey = (SilcServerChannelRekey)context; SilcServer server = (SilcServer)rekey->context; + rekey->task = NULL; + if (!silc_server_create_channel_key(server, rekey->channel, rekey->key_len)) return; + silc_server_send_channel_key(server, NULL, rekey->channel, FALSE); } @@ -3090,7 +3098,7 @@ bool silc_server_create_channel_key(SilcServer server, } if (!channel->channel_key) - if (!silc_cipher_alloc("aes-256-cbc", &channel->channel_key)) + if (!silc_cipher_alloc(SILC_DEFAULT_CIPHER, &channel->channel_key)) return FALSE; if (key_len) @@ -3120,7 +3128,7 @@ bool silc_server_create_channel_key(SilcServer server, /* Generate HMAC key from the channel key data and set it */ if (!channel->hmac) - silc_hmac_alloc("hmac-sha1-96", NULL, &channel->hmac); + silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac); silc_hash_make(channel->hmac->hash, channel->key, len, hash); silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash)); memset(hash, 0, sizeof(hash)); @@ -3131,12 +3139,15 @@ bool silc_server_create_channel_key(SilcServer server, channel->rekey->context = (void *)server; channel->rekey->channel = channel; channel->rekey->key_len = key_len; + if (channel->rekey->task) + silc_schedule_task_del(server->schedule, channel->rekey->task); - silc_schedule_task_add(server->schedule, 0, - silc_server_channel_key_rekey, - (void *)channel->rekey, 3600, 0, - SILC_TASK_TIMEOUT, - SILC_TASK_PRI_NORMAL); + channel->rekey->task = + silc_schedule_task_add(server->schedule, 0, + silc_server_channel_key_rekey, + (void *)channel->rekey, 3600, 0, + SILC_TASK_TIMEOUT, + SILC_TASK_PRI_NORMAL); } return TRUE; @@ -3224,7 +3235,7 @@ SilcChannelEntry silc_server_save_channel_key(SilcServer server, /* Generate HMAC key from the channel key data and set it */ if (!channel->hmac) - silc_hmac_alloc("hmac-sha1-96", NULL, &channel->hmac); + silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac); silc_hash_make(channel->hmac->hash, tmp, tmp_len, hash); silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash)); @@ -3236,19 +3247,19 @@ SilcChannelEntry silc_server_save_channel_key(SilcServer server, channel->rekey = silc_calloc(1, sizeof(*channel->rekey)); channel->rekey->context = (void *)server; channel->rekey->channel = channel; + if (channel->rekey->task) + silc_schedule_task_del(server->schedule, channel->rekey->task); - silc_schedule_task_del_by_callback(server->schedule, - silc_server_channel_key_rekey); - silc_schedule_task_add(server->schedule, 0, - silc_server_channel_key_rekey, - (void *)channel->rekey, 3600, 0, - SILC_TASK_TIMEOUT, - SILC_TASK_PRI_NORMAL); + channel->rekey->task = + silc_schedule_task_add(server->schedule, 0, + silc_server_channel_key_rekey, + (void *)channel->rekey, 3600, 0, + SILC_TASK_TIMEOUT, + SILC_TASK_PRI_NORMAL); } out: - if (id) - silc_free(id); + silc_free(id); if (payload) silc_channel_key_payload_free(payload); @@ -3290,7 +3301,7 @@ static void silc_server_announce_get_servers(SilcServer server, while (id_cache) { entry = (SilcServerEntry)id_cache->context; - /* Do not announce the one we've sending our announcments and + /* Do not announce the one we've sending our announcements and do not announce ourself. */ if (entry == remote || entry == server->id_entry) { if (!silc_idcache_list_next(list, &id_cache)) @@ -3722,9 +3733,6 @@ void silc_server_save_users_on_channel(SilcServer server, { int i; - /* Cache the received Client ID's and modes. This cache expires - whenever server sends notify message to channel. It means two things; - some user has joined or leaved the channel. XXX TODO! */ for (i = 0; i < user_count; i++) { uint16 idp_len; uint32 mode; diff --git a/lib/silcclient/client_channel.c b/lib/silcclient/client_channel.c index 2f681192..376572ca 100644 --- a/lib/silcclient/client_channel.c +++ b/lib/silcclient/client_channel.c @@ -210,8 +210,20 @@ void silc_client_channel_message(SilcClient client, /* Parse the channel message payload. This also decrypts the payload */ payload = silc_channel_message_payload_parse(buffer, channel->channel_key, channel->hmac); - if (!payload) - goto out; + + /* If decryption failed and we have just performed channel key rekey + we will use the old key in decryption. If that fails too then we + cannot do more and will drop the packet. */ + if (!payload) { + if (!channel->old_channel_key) + goto out; + + payload = silc_channel_message_payload_parse(buffer, + channel->old_channel_key, + channel->old_hmac); + if (!payload) + goto out; + } } else if (channel->private_keys) { SilcChannelPrivateKey entry; @@ -262,6 +274,23 @@ void silc_client_channel_message(SilcClient client, silc_channel_message_payload_free(payload); } +/* Timeout callback that is called after a short period of time after the + new channel key has been created. This removes the old channel key all + together. */ + +SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey) +{ + SilcChannelEntry channel = (SilcChannelEntry)context; + + if (channel->old_channel_key) + silc_cipher_free(channel->old_channel_key); + if (channel->old_hmac) + silc_hmac_free(channel->old_hmac); + channel->old_channel_key = NULL; + channel->old_hmac = NULL; + channel->rekey_task = NULL; +} + /* Saves channel key from encoded `key_payload'. This is used when we receive Channel Key Payload and when we are processing JOIN command reply. */ @@ -270,7 +299,7 @@ void silc_client_save_channel_key(SilcClientConnection conn, SilcBuffer key_payload, SilcChannelEntry channel) { - unsigned char *id_string, *key, *cipher, hash[32]; + unsigned char *id_string, *key, *cipher, *hmac, hash[32]; uint32 tmp_len; SilcChannelID *id; SilcIDCacheEntry id_cache = NULL; @@ -302,6 +331,27 @@ void silc_client_save_channel_key(SilcClientConnection conn, channel = (SilcChannelEntry)id_cache->context; } + hmac = channel->hmac ? channel->hmac->hmac->name : SILC_DEFAULT_HMAC; + + /* Save the old key for a short period of time so that we can decrypt + channel message even after the rekey if some client would be sending + messages with the old key after the rekey. */ + if (channel->old_channel_key) + silc_cipher_free(channel->old_channel_key); + if (channel->old_hmac) + silc_hmac_free(channel->old_hmac); + if (channel->rekey_task) + silc_schedule_task_del(conn->client->schedule, channel->rekey_task); + channel->old_channel_key = channel->channel_key; + channel->old_hmac = channel->hmac; + channel->rekey_task = + silc_schedule_task_add(conn->client->schedule, 0, + silc_client_save_channel_key_rekey, channel, + 10, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); + + /* Free the old channel key data */ + silc_free(channel->key); + /* Save the key */ key = silc_channel_key_get_key(payload, &tmp_len); cipher = silc_channel_key_get_cipher(payload, NULL); @@ -311,7 +361,8 @@ void silc_client_save_channel_key(SilcClientConnection conn, if (!silc_cipher_alloc(cipher, &channel->channel_key)) { conn->client->ops->say(conn->client, conn, SILC_CLIENT_MESSAGE_AUDIT, - "Cannot talk to channel: unsupported cipher %s", cipher); + "Cannot talk to channel: unsupported cipher %s", + cipher); goto out; } @@ -319,8 +370,7 @@ void silc_client_save_channel_key(SilcClientConnection conn, silc_cipher_set_key(channel->channel_key, key, channel->key_len); /* Generate HMAC key from the channel key data and set it */ - if (!channel->hmac) - silc_hmac_alloc("hmac-sha1-96", NULL, &channel->hmac); + silc_hmac_alloc(hmac, NULL, &channel->hmac); silc_hash_make(channel->hmac->hash, key, tmp_len, hash); silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash)); memset(hash, 0, sizeof(hash)); @@ -391,9 +441,9 @@ int silc_client_add_channel_private_key(SilcClient client, return FALSE; if (!cipher) - cipher = "aes-256-cbc"; + cipher = SILC_DEFAULT_CIPHER; if (!hmac) - hmac = "hmac-sha1-96"; + hmac = SILC_DEFAULT_HMAC; if (!silc_cipher_is_supported(cipher)) return FALSE; diff --git a/lib/silcclient/client_prvmsg.c b/lib/silcclient/client_prvmsg.c index d0695efd..dbc9e152 100644 --- a/lib/silcclient/client_prvmsg.c +++ b/lib/silcclient/client_prvmsg.c @@ -320,7 +320,7 @@ int silc_client_add_private_message_key(SilcClient client, return FALSE; if (!cipher) - cipher = "aes-256-cbc"; + cipher = SILC_DEFAULT_CIPHER; /* Check the requested cipher */ if (!silc_cipher_is_supported(cipher)) @@ -394,7 +394,7 @@ int silc_client_add_private_message_key_ske(SilcClient client, return FALSE; if (!cipher) - cipher = "aes-256-cbc"; + cipher = SILC_DEFAULT_CIPHER; /* Check the requested cipher */ if (!silc_cipher_is_supported(cipher)) diff --git a/lib/silcclient/idlist.c b/lib/silcclient/idlist.c index ffbcf29b..af4d3476 100644 --- a/lib/silcclient/idlist.c +++ b/lib/silcclient/idlist.c @@ -642,6 +642,12 @@ bool silc_client_del_channel(SilcClient client, SilcClientConnection conn, silc_cipher_free(channel->channel_key); if (channel->hmac) silc_hmac_free(channel->hmac); + if (channel->old_channel_key) + silc_cipher_free(channel->old_channel_key); + if (channel->old_hmac) + silc_hmac_free(channel->old_hmac); + if (channel->rekey_task) + silc_schedule_task_del(conn->client->schedule, channel->rekey_task); silc_client_del_channel_private_keys(client, conn, channel); silc_free(channel); return ret; diff --git a/lib/silcclient/idlist.h b/lib/silcclient/idlist.h index c120ff29..6ff551ca 100644 --- a/lib/silcclient/idlist.h +++ b/lib/silcclient/idlist.h @@ -78,6 +78,13 @@ typedef struct SilcChannelEntryStruct { SilcHmac hmac; /* Current HMAC */ SilcDList private_keys; /* List of private keys or NULL */ SilcChannelPrivateKey curr_key; /* Current private key */ + + /* Old channel key is saved for a short period of time when rekey occurs + in case if someone is sending messages after the rekey encrypted with + the old key, we can still decrypt them. */ + SilcCipher old_channel_key; + SilcHmac old_hmac; + SilcTask rekey_task; } *SilcChannelEntry; /* Server entry context. This represents one server. When server information diff --git a/lib/silccore/silcchannel.h b/lib/silccore/silcchannel.h index c615d84d..fdd8e663 100644 --- a/lib/silccore/silcchannel.h +++ b/lib/silccore/silcchannel.h @@ -383,7 +383,7 @@ silc_channel_message_get_flags(SilcChannelMessagePayload payload); * ***/ unsigned char *silc_channel_message_get_data(SilcChannelMessagePayload payload, - uint32 *data_len); + uint32 *data_len); /****f* silccore/SilcChannelAPI/silc_channel_message_get_mac * diff --git a/lib/silccrypt/silccipher.h b/lib/silccrypt/silccipher.h index b6134ecc..709c8411 100644 --- a/lib/silccrypt/silccipher.h +++ b/lib/silccrypt/silccipher.h @@ -77,6 +77,9 @@ typedef struct SilcCipherStruct { /* Static list of ciphers for silc_cipher_register_default(). */ extern SilcCipherObject silc_default_ciphers[]; +/* Default cipher in the SILC protocol */ +#define SILC_DEFAULT_CIPHER "aes-256-cbc" + /* Macros */ /* Function names in SILC Crypto modules. The name of the cipher diff --git a/lib/silccrypt/silchash.h b/lib/silccrypt/silchash.h index d922d052..1c2317e8 100644 --- a/lib/silccrypt/silchash.h +++ b/lib/silccrypt/silchash.h @@ -51,6 +51,9 @@ typedef struct SilcHashStruct { /* Default hash functions for silc_hash_register_default(). */ extern SilcHashObject silc_default_hash[]; +/* Default HASH function in the SILC protocol */ +#define SILC_DEFAULT_HASH "sha1" + /* Macros */ /* Following macros are used to implement the SILC Hash API. These diff --git a/lib/silccrypt/silchmac.h b/lib/silccrypt/silchmac.h index 532c1b68..7394390a 100644 --- a/lib/silccrypt/silchmac.h +++ b/lib/silccrypt/silchmac.h @@ -81,6 +81,9 @@ struct SilcHmacStruct { /* Default hmacs for silc_hmac_register_default(). */ extern SilcHmacObject silc_default_hmacs[]; +/* Default HMAC in the SILC protocol */ +#define SILC_DEFAULT_HMAC "hmac-sha1-96" + /* Prototypes */ bool silc_hmac_register(SilcHmacObject *hmac); bool silc_hmac_unregister(SilcHmacObject *hmac); diff --git a/lib/silccrypt/silcpkcs.h b/lib/silccrypt/silcpkcs.h index 92b42038..4cf89666 100644 --- a/lib/silccrypt/silcpkcs.h +++ b/lib/silccrypt/silcpkcs.h @@ -99,6 +99,9 @@ typedef struct { /* Static list of PKCS for silc_pkcs_register_default(). */ extern SilcPKCSObject silc_default_pkcs[]; +/* Default PKXS in the SILC protocol */ +#define SILC_DEFAULT_PKCS "rsa" + /* Macros */ /* Macros used to implement the SILC PKCS API */