5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 /* This file includes channel message sending and receiving routines,
21 channel key receiving and setting, and channel private key handling
24 #include "silcincludes.h"
25 #include "silcclient.h"
26 #include "client_internal.h"
28 /* Sends packet to the `channel'. Packet to channel is always encrypted
29 differently from "normal" packets. SILC header of the packet is
30 encrypted with the next receiver's key and the rest of the packet is
31 encrypted with the channel specific key. Padding and HMAC is computed
32 with the next receiver's key. The `data' is the channel message. If
33 the `force_send' is TRUE then the packet is sent immediately. */
35 void silc_client_send_channel_message(SilcClient client,
36 SilcClientConnection conn,
37 SilcChannelEntry channel,
38 SilcChannelPrivateKey key,
39 SilcMessageFlags flags,
45 SilcSocketConnection sock;
47 SilcPacketContext packetdata;
48 const SilcBufferStruct packet;
51 unsigned char *id_string;
56 assert(client && conn && channel);
58 SILC_LOG_DEBUG(("Sending packet to channel"));
60 chu = silc_client_on_channel(channel, conn->local_entry);
62 SILC_LOG_ERROR(("Cannot send message to channel we are not joined"));
66 /* Check if it is allowed to send messages to this channel by us. */
67 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS && !chu->mode)
69 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS &&
70 chu->mode & SILC_CHANNEL_UMODE_CHANOP &&
71 !(chu->mode & SILC_CHANNEL_UMODE_CHANFO))
73 if (chu->mode & SILC_CHANNEL_UMODE_QUIET)
76 /* Take the key to be used */
77 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
79 /* Use key application specified */
82 } else if (channel->curr_key) {
83 /* Use current private key */
84 cipher = channel->curr_key->cipher;
85 hmac = channel->curr_key->hmac;
86 } else if (!channel->curr_key && channel->private_keys) {
87 /* Use just some private key since we don't know what to use
88 and private keys are set. */
89 silc_dlist_start(channel->private_keys);
90 key = silc_dlist_get(channel->private_keys);
94 /* Use this key as current private key */
95 channel->curr_key = key;
97 /* Use normal channel key generated by the server */
98 cipher = channel->channel_key;
102 /* Use normal channel key generated by the server */
103 cipher = channel->channel_key;
104 hmac = channel->hmac;
107 if (!cipher || !hmac)
110 block_len = silc_cipher_get_block_len(cipher);
113 iv_len = silc_cipher_get_block_len(cipher);
114 if (channel->iv[0] == '\0')
115 for (i = 0; i < iv_len; i++) channel->iv[i] =
116 silc_rng_get_byte(client->rng);
118 silc_hash_make(client->md5hash, channel->iv, iv_len, channel->iv);
120 /* Encode the channel payload. This also encrypts the message payload. */
121 payload = silc_channel_message_payload_encode(flags, data_len, data, iv_len,
122 channel->iv, cipher, hmac,
125 /* Get data used in packet header encryption, keys and stuff. */
126 cipher = conn->internal->send_key;
127 hmac = conn->internal->hmac_send;
128 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
130 /* Set the packet context pointers. The destination ID is always
131 the Channel ID of the channel. Server and router will handle the
132 distribution of the packet. */
133 data = payload->data;
134 data_len = payload->len;
135 packetdata.flags = 0;
136 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
137 packetdata.src_id = conn->local_id_data;
138 packetdata.src_id_len = silc_id_get_len(conn->local_id, SILC_ID_CLIENT);
139 packetdata.src_id_type = SILC_ID_CLIENT;
140 packetdata.dst_id = id_string;
141 packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
142 packetdata.dst_id_type = SILC_ID_CHANNEL;
143 data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
144 packetdata.src_id_len +
145 packetdata.dst_id_len);
146 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
147 packetdata.src_id_len + packetdata.dst_id_len;
148 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
149 packetdata.src_id_len +
150 packetdata.dst_id_len), block_len, packetdata.padlen);
152 /* Create the outgoing packet */
153 if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
154 data, data_len, (const SilcBuffer)&packet)) {
155 SILC_LOG_ERROR(("Error assembling packet"));
159 /* Encrypt the header and padding of the packet. This is encrypted
160 with normal session key shared with our server. */
161 silc_packet_encrypt(cipher, hmac, conn->internal->psn_send++,
162 (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN +
163 packetdata.src_id_len + packetdata.dst_id_len +
166 SILC_LOG_HEXDUMP(("Packet to channel, len %d", packet.len),
167 packet.data, packet.len);
169 /* Now actually send the packet */
170 silc_client_packet_send_real(client, sock, force_send);
172 /* Check for mandatory rekey */
173 if (conn->internal->psn_send == SILC_CLIENT_REKEY_THRESHOLD)
174 silc_schedule_task_add(client->schedule, sock->sock,
175 silc_client_rekey_callback, sock, 0, 1,
176 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
179 silc_buffer_free(payload);
180 silc_free(id_string);
184 SilcChannelMessagePayload payload;
185 SilcChannelID *channel_id;
186 } *SilcChannelClientResolve;
188 static void silc_client_channel_message_cb(SilcClient client,
189 SilcClientConnection conn,
190 SilcClientEntry *clients,
191 SilcUInt32 clients_count,
194 SilcChannelClientResolve res = (SilcChannelClientResolve)context;
196 if (clients_count == 1) {
197 SilcChannelEntry channel;
198 unsigned char *message;
199 SilcUInt32 message_len;
201 channel = silc_client_get_channel_by_id(client, conn, res->channel_id);
205 /* If this client is not on channel, add it there since it clearly
207 if (!silc_client_on_channel(channel, clients[0])) {
208 SilcChannelUser chu = silc_calloc(1, sizeof(*chu));
209 chu->client = clients[0];
210 chu->channel = channel;
211 silc_hash_table_add(channel->user_list, clients[0], chu);
212 silc_hash_table_add(clients[0]->channels, channel, chu);
215 message = silc_channel_message_get_data(res->payload, &message_len);
217 /* Pass the message to application */
218 client->internal->ops->channel_message(
219 client, conn, clients[0], channel,
220 silc_channel_message_get_flags(res->payload),
221 message, message_len);
225 silc_channel_message_payload_free(res->payload);
226 silc_free(res->channel_id);
230 /* Process received message to a channel (or from a channel, really). This
231 decrypts the channel message with channel specific key and parses the
232 channel payload. Finally it displays the message on the screen. */
234 void silc_client_channel_message(SilcClient client,
235 SilcSocketConnection sock,
236 SilcPacketContext *packet)
238 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
239 SilcBuffer buffer = packet->buffer;
240 SilcChannelMessagePayload payload = NULL;
241 SilcChannelID *id = NULL;
242 SilcChannelEntry channel;
243 SilcClientEntry client_entry;
244 SilcClientID *client_id = NULL;
245 unsigned char *message;
246 SilcUInt32 message_len;
248 SILC_LOG_DEBUG(("Start"));
251 if (packet->dst_id_type != SILC_ID_CHANNEL)
254 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
258 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
262 /* Find the channel entry from channels on this connection */
263 channel = silc_client_get_channel_by_id(client, conn, id);
267 /* If there is no channel private key then just decrypt the message
268 with the channel key. If private keys are set then just go through
269 all private keys and check what decrypts correctly. */
270 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
271 /* Parse the channel message payload. This also decrypts the payload */
272 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
273 channel->channel_key,
276 /* If decryption failed and we have just performed channel key rekey
277 we will use the old key in decryption. If that fails too then we
278 cannot do more and will drop the packet. */
280 if (!channel->old_channel_key) {
284 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
285 channel->old_channel_key,
291 } else if (channel->private_keys) {
292 SilcChannelPrivateKey entry;
294 silc_dlist_start(channel->private_keys);
295 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
296 /* Parse the channel message payload. This also decrypts the payload */
297 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
303 if (entry == SILC_LIST_END)
309 /* Find client entry */
310 client_entry = silc_client_get_client_by_id(client, conn, client_id);
311 if (!client_entry || !client_entry->nickname ||
312 !silc_client_on_channel(channel, client_entry)) {
313 /* Resolve the client info */
314 SilcChannelClientResolve res = silc_calloc(1, sizeof(*res));
315 res->payload = payload;
316 res->channel_id = id;
317 silc_client_get_client_by_id_resolve(client, conn, client_id, NULL,
318 silc_client_channel_message_cb,
325 message = silc_channel_message_get_data(payload, &message_len);
327 /* Pass the message to application */
328 client->internal->ops->channel_message(
329 client, conn, client_entry, channel,
330 silc_channel_message_get_flags(payload),
331 message, message_len);
335 silc_free(client_id);
337 silc_channel_message_payload_free(payload);
340 /* Timeout callback that is called after a short period of time after the
341 new channel key has been created. This removes the old channel key all
344 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
346 SilcChannelEntry channel = (SilcChannelEntry)context;
348 if (channel->old_channel_key)
349 silc_cipher_free(channel->old_channel_key);
350 if (channel->old_hmac)
351 silc_hmac_free(channel->old_hmac);
352 channel->old_channel_key = NULL;
353 channel->old_hmac = NULL;
354 channel->rekey_task = NULL;
357 /* Saves channel key from encoded `key_payload'. This is used when we
358 receive Channel Key Payload and when we are processing JOIN command
361 void silc_client_save_channel_key(SilcClient client,
362 SilcClientConnection conn,
363 SilcBuffer key_payload,
364 SilcChannelEntry channel)
366 unsigned char *id_string, *key, *cipher, *hmac, hash[32];
369 SilcChannelKeyPayload payload;
371 payload = silc_channel_key_payload_parse(key_payload->data,
376 id_string = silc_channel_key_get_id(payload, &tmp_len);
378 silc_channel_key_payload_free(payload);
382 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
384 silc_channel_key_payload_free(payload);
390 channel = silc_client_get_channel_by_id(client, conn, id);
395 hmac = (channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) :
398 /* Save the old key for a short period of time so that we can decrypt
399 channel message even after the rekey if some client would be sending
400 messages with the old key after the rekey. */
401 if (channel->old_channel_key)
402 silc_cipher_free(channel->old_channel_key);
403 if (channel->old_hmac)
404 silc_hmac_free(channel->old_hmac);
405 if (channel->rekey_task)
406 silc_schedule_task_del(client->schedule, channel->rekey_task);
407 channel->old_channel_key = channel->channel_key;
408 channel->old_hmac = channel->hmac;
409 channel->rekey_task =
410 silc_schedule_task_add(client->schedule, 0,
411 silc_client_save_channel_key_rekey, channel,
412 10, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
414 /* Free the old channel key data */
415 silc_free(channel->key);
418 key = silc_channel_key_get_key(payload, &tmp_len);
419 cipher = silc_channel_key_get_cipher(payload, NULL);
420 channel->key_len = tmp_len * 8;
421 channel->key = silc_memdup(key, tmp_len);
423 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
424 client->internal->ops->say(
426 SILC_CLIENT_MESSAGE_AUDIT,
427 "Cannot talk to channel: unsupported cipher %s",
432 /* Set the cipher key */
433 silc_cipher_set_key(channel->channel_key, key, channel->key_len);
435 /* Generate HMAC key from the channel key data and set it */
436 silc_hmac_alloc(hmac, NULL, &channel->hmac);
437 silc_hash_make(silc_hmac_get_hash(channel->hmac), key, tmp_len, hash);
438 silc_hmac_set_key(channel->hmac, hash,
439 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
440 memset(hash, 0, sizeof(hash));
444 silc_channel_key_payload_free(payload);
447 /* Processes received key for channel. The received key will be used
448 to protect the traffic on the channel for now on. Client must receive
449 the key to the channel before talking on the channel is possible.
450 This is the key that server has generated, this is not the channel
451 private key, it is entirely local setting. */
453 void silc_client_receive_channel_key(SilcClient client,
454 SilcSocketConnection sock,
457 SILC_LOG_DEBUG(("Received key for channel"));
460 silc_client_save_channel_key(client, sock->user_data, packet, NULL);
463 /* Adds private key for channel. This may be set only if the channel's mode
464 mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
465 mode is not set. When channel has private key then the messages are
466 encrypted using that key. All clients on the channel must also know the
467 key in order to decrypt the messages. However, it is possible to have
468 several private keys per one channel. In this case only some of the
469 clients on the channel may know the one key and only some the other key.
471 If `cipher' and/or `hmac' is NULL then default values will be used
472 (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
474 The private key for channel is optional. If it is not set then the
475 channel messages are encrypted using the channel key generated by the
476 server. However, setting the private key (or keys) for the channel
477 significantly adds security. If more than one key is set the library
478 will automatically try all keys at the message decryption phase. Note:
479 setting many keys slows down the decryption phase as all keys has to
480 be tried in order to find the correct decryption key. However, setting
481 a few keys does not have big impact to the decryption performace.
483 NOTE: that this is entirely local setting. The key set using this function
484 is not sent to the network at any phase.
486 NOTE: If the key material was originated by the SKE protocol (using
487 silc_client_send_key_agreement) then the `key' MUST be the
488 key->send_enc_key as this is dictated by the SILC protocol. However,
489 currently it is not expected that the SKE key material would be used
490 as channel private key. However, this API allows it. */
492 bool silc_client_add_channel_private_key(SilcClient client,
493 SilcClientConnection conn,
494 SilcChannelEntry channel,
501 SilcChannelPrivateKey entry;
502 unsigned char hash[32];
503 SilcSKEKeyMaterial *keymat;
505 assert(client && channel);
507 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
511 cipher = SILC_DEFAULT_CIPHER;
513 hmac = SILC_DEFAULT_HMAC;
515 if (!silc_cipher_is_supported(cipher))
518 if (!silc_hmac_is_supported(hmac))
521 /* Produce the key material */
522 keymat = silc_calloc(1, sizeof(*keymat));
523 if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
524 client->md5hash, keymat)
525 != SILC_SKE_STATUS_OK)
528 /* Remove the current key, if it exists. */
529 if (channel->channel_key) {
530 silc_cipher_free(channel->channel_key);
531 memset(channel->key, 0, channel->key_len / 8);
532 silc_free(channel->key);
533 channel->channel_key = NULL;
535 channel->key_len = 0;
538 silc_hmac_free(channel->hmac);
539 channel->hmac = NULL;
542 if (!channel->private_keys)
543 channel->private_keys = silc_dlist_init();
546 entry = silc_calloc(1, sizeof(*entry));
547 entry->name = name ? strdup(name) : NULL;
548 entry->key = silc_memdup(keymat->send_enc_key, keymat->enc_key_len / 8);
549 entry->key_len = keymat->enc_key_len / 8;
551 /* Allocate the cipher and set the key*/
552 silc_cipher_alloc(cipher, &entry->cipher);
553 silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
555 /* Generate HMAC key from the channel key data and set it */
556 silc_hmac_alloc(hmac, NULL, &entry->hmac);
557 silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key,
558 entry->key_len, hash);
559 silc_hmac_set_key(entry->hmac, hash,
560 silc_hash_len(silc_hmac_get_hash(entry->hmac)));
561 memset(hash, 0, sizeof(hash));
563 /* Add to the private keys list */
564 silc_dlist_add(channel->private_keys, entry);
566 if (!channel->curr_key)
567 channel->curr_key = entry;
569 /* Free the key material */
570 silc_ske_free_key_material(keymat);
575 /* Removes all private keys from the `channel'. The old channel key is used
576 after calling this to protect the channel messages. Returns FALSE on
577 on error, TRUE otherwise. */
579 bool silc_client_del_channel_private_keys(SilcClient client,
580 SilcClientConnection conn,
581 SilcChannelEntry channel)
583 SilcChannelPrivateKey entry;
585 assert(client && channel);
587 if (!channel->private_keys)
590 silc_dlist_start(channel->private_keys);
591 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
592 silc_dlist_del(channel->private_keys, entry);
593 memset(entry->key, 0, entry->key_len);
594 silc_free(entry->key);
595 silc_free(entry->name);
596 silc_cipher_free(entry->cipher);
597 silc_hmac_free(entry->hmac);
601 channel->curr_key = NULL;
603 silc_dlist_uninit(channel->private_keys);
604 channel->private_keys = NULL;
609 /* Removes and frees private key `key' from the channel `channel'. The `key'
610 is retrieved by calling the function silc_client_list_channel_private_keys.
611 The key is not used after this. If the key was last private key then the
612 old channel key is used hereafter to protect the channel messages. This
613 returns FALSE on error, TRUE otherwise. */
615 bool silc_client_del_channel_private_key(SilcClient client,
616 SilcClientConnection conn,
617 SilcChannelEntry channel,
618 SilcChannelPrivateKey key)
620 SilcChannelPrivateKey entry;
622 assert(client && channel);
624 if (!channel->private_keys)
627 silc_dlist_start(channel->private_keys);
628 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
630 if (channel->curr_key == entry)
631 channel->curr_key = NULL;
633 silc_dlist_del(channel->private_keys, entry);
634 memset(entry->key, 0, entry->key_len);
635 silc_free(entry->key);
636 silc_free(entry->name);
637 silc_cipher_free(entry->cipher);
638 silc_hmac_free(entry->hmac);
641 if (silc_dlist_count(channel->private_keys) == 0) {
642 silc_dlist_uninit(channel->private_keys);
643 channel->private_keys = NULL;
653 /* Returns array (pointers) of private keys associated to the `channel'.
654 The caller must free the array by calling the function
655 silc_client_free_channel_private_keys. The pointers in the array may be
656 used to delete the specific key by giving the pointer as argument to the
657 function silc_client_del_channel_private_key. */
659 SilcChannelPrivateKey *
660 silc_client_list_channel_private_keys(SilcClient client,
661 SilcClientConnection conn,
662 SilcChannelEntry channel,
663 SilcUInt32 *key_count)
665 SilcChannelPrivateKey *keys = NULL, entry;
666 SilcUInt32 count = 0;
668 assert(client && channel);
670 if (!channel->private_keys)
673 silc_dlist_start(channel->private_keys);
674 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
675 keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
686 /* Frees the SilcChannelPrivateKey array. */
688 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
689 SilcUInt32 key_count)
694 /* Sets the `key' to be used as current channel private key on the
695 `channel'. Packet sent after calling this function will be secured
698 void silc_client_current_channel_private_key(SilcClient client,
699 SilcClientConnection conn,
700 SilcChannelEntry channel,
701 SilcChannelPrivateKey key)
703 assert(client && channel);
704 channel->curr_key = key;
707 /* Returns the SilcChannelUser entry if the `client_entry' is joined on the
708 channel indicated by the `channel'. NULL if client is not joined on
711 SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
712 SilcClientEntry client_entry)
716 if (silc_hash_table_find(channel->user_list, client_entry, NULL,