5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2004 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 bool silc_client_send_channel_message(SilcClient client,
36 SilcClientConnection conn,
37 SilcChannelEntry channel,
38 SilcChannelPrivateKey key,
39 SilcMessageFlags flags,
44 SilcSocketConnection sock;
46 SilcPacketContext packetdata;
47 const SilcBufferStruct packet;
50 unsigned char *id_string;
55 assert(client && conn && channel);
57 SILC_LOG_DEBUG(("Sending packet to channel"));
59 chu = silc_client_on_channel(channel, conn->local_entry);
61 SILC_LOG_ERROR(("Cannot send message to channel we are not joined"));
65 /* Check if it is allowed to send messages to this channel by us. */
66 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS && !chu->mode)
68 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS &&
69 chu->mode & SILC_CHANNEL_UMODE_CHANOP &&
70 !(chu->mode & SILC_CHANNEL_UMODE_CHANFO))
72 if (chu->mode & SILC_CHANNEL_UMODE_QUIET)
75 /* Take the key to be used */
76 if (channel->private_keys) {
78 /* Use key application specified */
81 } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
83 /* Use current private key */
84 cipher = channel->curr_key->cipher;
85 hmac = channel->curr_key->hmac;
86 } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
87 !channel->curr_key && channel->private_keys) {
88 /* Use just some private key since we don't know what to use
89 and private keys are set. */
90 silc_dlist_start(channel->private_keys);
91 key = silc_dlist_get(channel->private_keys);
95 /* Use this key as current private key */
96 channel->curr_key = key;
98 /* Use normal channel key generated by the server */
99 cipher = channel->channel_key;
100 hmac = channel->hmac;
103 /* Use normal channel key generated by the server */
104 cipher = channel->channel_key;
105 hmac = channel->hmac;
108 if (!cipher || !hmac) {
109 SILC_LOG_ERROR(("No cipher and HMAC for channel"));
113 block_len = silc_cipher_get_block_len(cipher);
115 /* Encode the message payload. This also encrypts the message payload. */
116 payload = silc_message_payload_encode(flags, data, data_len, TRUE, FALSE,
117 cipher, hmac, client->rng, NULL,
118 client->private_key, client->sha1hash);
120 SILC_LOG_ERROR(("Error encoding channel message"));
124 /* Get data used in packet header encryption, keys and stuff. */
125 cipher = conn->internal->send_key;
126 hmac = conn->internal->hmac_send;
127 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
129 /* Set the packet context pointers. The destination ID is always
130 the Channel ID of the channel. Server and router will handle the
131 distribution of the packet. */
132 data = payload->data;
133 data_len = payload->len;
134 packetdata.flags = 0;
135 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
136 packetdata.src_id = conn->local_id_data;
137 packetdata.src_id_len = silc_id_get_len(conn->local_id, SILC_ID_CLIENT);
138 packetdata.src_id_type = SILC_ID_CLIENT;
139 packetdata.dst_id = id_string;
140 packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
141 packetdata.dst_id_type = SILC_ID_CHANNEL;
142 data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
143 packetdata.src_id_len +
144 packetdata.dst_id_len);
145 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
146 packetdata.src_id_len + packetdata.dst_id_len;
147 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
148 packetdata.src_id_len +
149 packetdata.dst_id_len), block_len, packetdata.padlen);
151 /* Create the outgoing packet */
152 if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
153 data, data_len, (const SilcBuffer)&packet)) {
154 SILC_LOG_ERROR(("Error assembling packet"));
158 /* Encrypt the header and padding of the packet. This is encrypted
159 with normal session key shared with our server. */
160 silc_packet_encrypt(cipher, hmac, conn->internal->psn_send++,
161 (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN +
162 packetdata.src_id_len + packetdata.dst_id_len +
165 SILC_LOG_HEXDUMP(("Packet to channel, len %d", packet.len),
166 packet.data, packet.len);
168 /* Now actually send the packet */
169 silc_client_packet_send_real(client, sock, force_send);
171 /* Check for mandatory rekey */
172 if (conn->internal->psn_send == SILC_CLIENT_REKEY_THRESHOLD)
173 silc_schedule_task_add(client->schedule, sock->sock,
174 silc_client_rekey_callback, sock, 0, 1,
175 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
180 silc_buffer_free(payload);
181 silc_free(id_string);
187 SilcMessagePayload payload;
188 SilcChannelID *channel_id;
189 SilcChannelPrivateKey key;
190 } *SilcChannelClientResolve;
192 static void silc_client_channel_message_cb(SilcClient client,
193 SilcClientConnection conn,
194 SilcClientEntry *clients,
195 SilcUInt32 clients_count,
198 SilcChannelClientResolve res = (SilcChannelClientResolve)context;
200 if (clients_count == 1) {
201 SilcChannelEntry channel;
202 unsigned char *message;
203 SilcUInt32 message_len;
205 channel = silc_client_get_channel_by_id(client, conn, res->channel_id);
209 /* If this client is not on channel, add it there since it clearly
211 if (!silc_client_on_channel(channel, clients[0])) {
212 SilcChannelUser chu = silc_calloc(1, sizeof(*chu));
213 chu->client = clients[0];
214 chu->channel = channel;
215 silc_hash_table_add(channel->user_list, clients[0], chu);
216 silc_hash_table_add(clients[0]->channels, channel, chu);
219 message = silc_message_get_data(res->payload, &message_len);
221 /* Pass the message to application */
222 client->internal->ops->channel_message(
223 client, conn, clients[0], channel, res->payload,
224 res->key, silc_message_get_flags(res->payload),
225 message, message_len);
229 silc_message_payload_free(res->payload);
230 silc_free(res->channel_id);
234 /* Process received message to a channel (or from a channel, really). This
235 decrypts the channel message with channel specific key and parses the
236 message payload. Finally it displays the message on the screen. */
238 void silc_client_channel_message(SilcClient client,
239 SilcSocketConnection sock,
240 SilcPacketContext *packet)
242 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
243 SilcBuffer buffer = packet->buffer;
244 SilcMessagePayload payload = NULL;
245 SilcChannelID *id = NULL;
246 SilcChannelEntry channel;
247 SilcClientEntry client_entry;
248 SilcClientID *client_id = NULL;
249 unsigned char *message;
250 SilcUInt32 message_len;
251 SilcChannelPrivateKey key = NULL;
253 SILC_LOG_DEBUG(("Received channel message"));
256 if (packet->dst_id_type != SILC_ID_CHANNEL)
259 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
263 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
267 /* Find the channel entry from channels on this connection */
268 channel = silc_client_get_channel_by_id(client, conn, id);
272 /* If there is no channel private key then just decrypt the message
273 with the channel key. If private keys are set then just go through
274 all private keys and check what decrypts correctly. */
275 if (!channel->private_keys) {
276 /* Parse the channel message payload. This also decrypts the payload */
277 payload = silc_message_payload_parse(buffer->data, buffer->len, FALSE,
278 FALSE, channel->channel_key,
281 /* If decryption failed and we have just performed channel key rekey
282 we will use the old key in decryption. If that fails too then we
283 cannot do more and will drop the packet. */
289 if (!channel->old_channel_keys ||
290 !silc_dlist_count(channel->old_channel_keys))
293 SILC_LOG_DEBUG(("Attempting to decrypt with old channel key(s)"));
295 silc_dlist_end(channel->old_channel_keys);
296 silc_dlist_end(channel->old_hmacs);
297 for (i = 0; i < silc_dlist_count(channel->old_channel_keys); i++) {
298 key = silc_dlist_get(channel->old_channel_keys);
299 hmac = silc_dlist_get(channel->old_hmacs);
303 payload = silc_message_payload_parse(buffer->data, buffer->len,
304 FALSE, FALSE, key, hmac);
312 /* If the private key mode, however is not set on the channel then
313 try the actual channel key first before trying private keys. */
314 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
315 payload = silc_message_payload_parse(buffer->data, buffer->len, FALSE,
316 FALSE, channel->channel_key,
320 silc_dlist_start(channel->private_keys);
321 while ((key = silc_dlist_get(channel->private_keys))
323 /* Parse the message payload. This also decrypts the payload */
324 payload = silc_message_payload_parse(buffer->data, buffer->len,
326 key->cipher, key->hmac);
330 if (key == SILC_LIST_END)
335 /* Find client entry */
336 client_entry = silc_client_get_client_by_id(client, conn, client_id);
337 if (!client_entry || !client_entry->nickname ||
338 !silc_client_on_channel(channel, client_entry)) {
339 /* Resolve the client info */
340 SilcChannelClientResolve res = silc_calloc(1, sizeof(*res));
341 res->payload = payload;
342 res->channel_id = id;
344 silc_client_get_client_by_id_resolve(client, conn, client_id, NULL,
345 silc_client_channel_message_cb,
352 message = silc_message_get_data(payload, &message_len);
354 /* Pass the message to application */
355 client->internal->ops->channel_message(
356 client, conn, client_entry, channel, payload,
357 key, silc_message_get_flags(payload),
358 message, message_len);
362 silc_free(client_id);
364 silc_message_payload_free(payload);
367 /* Timeout callback that is called after a short period of time after the
368 new channel key has been created. This removes the first channel key
371 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
373 SilcChannelEntry channel = (SilcChannelEntry)context;
377 if (channel->old_channel_keys) {
378 silc_dlist_start(channel->old_channel_keys);
379 key = silc_dlist_get(channel->old_channel_keys);
381 silc_dlist_del(channel->old_channel_keys, key);
382 silc_cipher_free(key);
386 if (channel->old_hmacs) {
387 silc_dlist_start(channel->old_hmacs);
388 hmac = silc_dlist_get(channel->old_hmacs);
390 silc_dlist_del(channel->old_hmacs, hmac);
391 silc_hmac_free(hmac);
396 /* Saves channel key from encoded `key_payload'. This is used when we
397 receive Channel Key Payload and when we are processing JOIN command
400 void silc_client_save_channel_key(SilcClient client,
401 SilcClientConnection conn,
402 SilcBuffer key_payload,
403 SilcChannelEntry channel)
405 unsigned char *id_string, *key, *cipher, *hmac, hash[32];
408 SilcChannelKeyPayload payload;
410 payload = silc_channel_key_payload_parse(key_payload->data,
415 id_string = silc_channel_key_get_id(payload, &tmp_len);
417 silc_channel_key_payload_free(payload);
421 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
423 silc_channel_key_payload_free(payload);
429 channel = silc_client_get_channel_by_id(client, conn, id);
434 hmac = (channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) :
437 /* Save the old key for a short period of time so that we can decrypt
438 channel message even after the rekey if some client would be sending
439 messages with the old key after the rekey. */
440 if (!channel->old_channel_keys)
441 channel->old_channel_keys = silc_dlist_init();
442 if (!channel->old_hmacs)
443 channel->old_hmacs = silc_dlist_init();
444 silc_dlist_add(channel->old_channel_keys, channel->channel_key);
445 silc_dlist_add(channel->old_hmacs, channel->hmac);
446 silc_schedule_task_add(client->schedule, 0,
447 silc_client_save_channel_key_rekey, channel,
448 10, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
450 /* Free the old channel key data */
451 silc_free(channel->key);
454 key = silc_channel_key_get_key(payload, &tmp_len);
455 cipher = silc_channel_key_get_cipher(payload, NULL);
456 channel->key_len = tmp_len * 8;
457 channel->key = silc_memdup(key, tmp_len);
459 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
460 client->internal->ops->say(
462 SILC_CLIENT_MESSAGE_AUDIT,
463 "Cannot talk to channel: unsupported cipher %s",
468 /* Set the cipher key */
469 silc_cipher_set_key(channel->channel_key, key, channel->key_len);
471 /* Generate HMAC key from the channel key data and set it */
472 silc_hmac_alloc(hmac, NULL, &channel->hmac);
473 silc_hash_make(silc_hmac_get_hash(channel->hmac), key, tmp_len, hash);
474 silc_hmac_set_key(channel->hmac, hash,
475 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
476 memset(hash, 0, sizeof(hash));
480 silc_channel_key_payload_free(payload);
483 /* Processes received key for channel. The received key will be used
484 to protect the traffic on the channel for now on. Client must receive
485 the key to the channel before talking on the channel is possible.
486 This is the key that server has generated, this is not the channel
487 private key, it is entirely local setting. */
489 void silc_client_receive_channel_key(SilcClient client,
490 SilcSocketConnection sock,
493 SILC_LOG_DEBUG(("Received key for channel"));
496 silc_client_save_channel_key(client, sock->user_data, packet, NULL);
499 /* Adds private key for channel. When channel has private key then the
500 messages are encrypted using that key. All clients on the channel must
501 also know the key in order to decrypt the messages. However, it is
502 possible to have several private keys per one channel. In this case
503 only some of the clients on the channel may know the one key and only
506 If `cipher' and/or `hmac' is NULL then default values will be used
507 (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
509 The private key for channel is optional. If it is not set then the
510 channel messages are encrypted using the channel key generated by the
511 server. However, setting the private key (or keys) for the channel
512 significantly adds security. If more than one key is set the library
513 will automatically try all keys at the message decryption phase. Note:
514 setting many keys slows down the decryption phase as all keys has to
515 be tried in order to find the correct decryption key. However, setting
516 a few keys does not have big impact to the decryption performace.
518 NOTE: that this is entirely local setting. The key set using this function
519 is not sent to the network at any phase.
521 NOTE: If the key material was originated by the SKE protocol (using
522 silc_client_send_key_agreement) then the `key' MUST be the
523 key->send_enc_key as this is dictated by the SILC protocol. However,
524 currently it is not expected that the SKE key material would be used
525 as channel private key. However, this API allows it. */
527 bool silc_client_add_channel_private_key(SilcClient client,
528 SilcClientConnection conn,
529 SilcChannelEntry channel,
535 SilcChannelPrivateKey *ret_key)
537 SilcChannelPrivateKey entry;
538 unsigned char hash[32];
539 SilcSKEKeyMaterial *keymat;
541 assert(client && channel);
544 cipher = SILC_DEFAULT_CIPHER;
546 hmac = SILC_DEFAULT_HMAC;
548 if (!silc_cipher_is_supported(cipher))
551 if (!silc_hmac_is_supported(hmac))
554 /* Produce the key material */
555 keymat = silc_calloc(1, sizeof(*keymat));
556 if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
557 client->sha1hash, keymat)
558 != SILC_SKE_STATUS_OK)
561 if (!channel->private_keys)
562 channel->private_keys = silc_dlist_init();
565 entry = silc_calloc(1, sizeof(*entry));
566 entry->name = name ? strdup(name) : NULL;
567 entry->key = silc_memdup(keymat->send_enc_key, keymat->enc_key_len / 8);
568 entry->key_len = keymat->enc_key_len / 8;
570 /* Allocate the cipher and set the key*/
571 silc_cipher_alloc(cipher, &entry->cipher);
572 silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
574 /* Generate HMAC key from the channel key data and set it */
575 silc_hmac_alloc(hmac, NULL, &entry->hmac);
576 silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key,
577 entry->key_len, hash);
578 silc_hmac_set_key(entry->hmac, hash,
579 silc_hash_len(silc_hmac_get_hash(entry->hmac)));
580 memset(hash, 0, sizeof(hash));
582 /* Add to the private keys list */
583 silc_dlist_add(channel->private_keys, entry);
585 if (!channel->curr_key)
586 channel->curr_key = entry;
588 /* Free the key material */
589 silc_ske_free_key_material(keymat);
597 /* Removes all private keys from the `channel'. The old channel key is used
598 after calling this to protect the channel messages. Returns FALSE on
599 on error, TRUE otherwise. */
601 bool silc_client_del_channel_private_keys(SilcClient client,
602 SilcClientConnection conn,
603 SilcChannelEntry channel)
605 SilcChannelPrivateKey entry;
607 assert(client && channel);
609 if (!channel->private_keys)
612 silc_dlist_start(channel->private_keys);
613 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
614 silc_dlist_del(channel->private_keys, entry);
615 memset(entry->key, 0, entry->key_len);
616 silc_free(entry->key);
617 silc_free(entry->name);
618 silc_cipher_free(entry->cipher);
619 silc_hmac_free(entry->hmac);
623 channel->curr_key = NULL;
625 silc_dlist_uninit(channel->private_keys);
626 channel->private_keys = NULL;
631 /* Removes and frees private key `key' from the channel `channel'. The `key'
632 is retrieved by calling the function silc_client_list_channel_private_keys.
633 The key is not used after this. If the key was last private key then the
634 old channel key is used hereafter to protect the channel messages. This
635 returns FALSE on error, TRUE otherwise. */
637 bool silc_client_del_channel_private_key(SilcClient client,
638 SilcClientConnection conn,
639 SilcChannelEntry channel,
640 SilcChannelPrivateKey key)
642 SilcChannelPrivateKey entry;
644 assert(client && channel);
646 if (!channel->private_keys)
649 silc_dlist_start(channel->private_keys);
650 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
652 if (channel->curr_key == entry)
653 channel->curr_key = NULL;
655 silc_dlist_del(channel->private_keys, entry);
656 memset(entry->key, 0, entry->key_len);
657 silc_free(entry->key);
658 silc_free(entry->name);
659 silc_cipher_free(entry->cipher);
660 silc_hmac_free(entry->hmac);
663 if (silc_dlist_count(channel->private_keys) == 0) {
664 silc_dlist_uninit(channel->private_keys);
665 channel->private_keys = NULL;
675 /* Returns array (pointers) of private keys associated to the `channel'.
676 The caller must free the array by calling the function
677 silc_client_free_channel_private_keys. The pointers in the array may be
678 used to delete the specific key by giving the pointer as argument to the
679 function silc_client_del_channel_private_key. */
681 SilcChannelPrivateKey *
682 silc_client_list_channel_private_keys(SilcClient client,
683 SilcClientConnection conn,
684 SilcChannelEntry channel,
685 SilcUInt32 *key_count)
687 SilcChannelPrivateKey *keys = NULL, entry;
688 SilcUInt32 count = 0;
690 assert(client && channel);
692 if (!channel->private_keys)
695 silc_dlist_start(channel->private_keys);
696 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
697 keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
708 /* Frees the SilcChannelPrivateKey array. */
710 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
711 SilcUInt32 key_count)
716 /* Sets the `key' to be used as current channel private key on the
717 `channel'. Packet sent after calling this function will be secured
720 void silc_client_current_channel_private_key(SilcClient client,
721 SilcClientConnection conn,
722 SilcChannelEntry channel,
723 SilcChannelPrivateKey key)
725 assert(client && channel);
726 channel->curr_key = key;
729 /* Returns the SilcChannelUser entry if the `client_entry' is joined on the
730 channel indicated by the `channel'. NULL if client is not joined on
733 SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
734 SilcClientEntry client_entry)
738 if (silc_hash_table_find(channel->user_list, client_entry, NULL,