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 /* This file includes channel message sending and receiving routines,
22 channel key receiving and setting, and channel private key handling
25 #include "silcincludes.h"
26 #include "silcclient.h"
27 #include "client_internal.h"
29 /* Sends packet to the `channel'. Packet to channel is always encrypted
30 differently from "normal" packets. SILC header of the packet is
31 encrypted with the next receiver's key and the rest of the packet is
32 encrypted with the channel specific key. Padding and HMAC is computed
33 with the next receiver's key. The `data' is the channel message. If
34 the `force_send' is TRUE then the packet is sent immediately. */
36 void silc_client_send_channel_message(SilcClient client,
37 SilcClientConnection conn,
38 SilcChannelEntry channel,
39 SilcChannelPrivateKey key,
40 SilcMessageFlags flags,
46 SilcSocketConnection sock = conn->sock;
48 SilcPacketContext packetdata;
49 const SilcBufferStruct packet;
52 unsigned char *id_string;
56 SILC_LOG_DEBUG(("Sending packet to channel"));
58 /* Take the key to be used */
59 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
61 /* Use key application specified */
64 } else if (channel->curr_key) {
65 /* Use current private key */
66 cipher = channel->curr_key->cipher;
67 hmac = channel->curr_key->hmac;
68 } else if (!channel->curr_key && channel->private_keys) {
69 /* Use just some private key since we don't know what to use
70 and private keys are set. */
71 silc_dlist_start(channel->private_keys);
72 key = silc_dlist_get(channel->private_keys);
76 /* Use this key as current private key */
77 channel->curr_key = key;
79 /* Use normal channel key generated by the server */
80 cipher = channel->channel_key;
84 /* Use normal channel key generated by the server */
85 cipher = channel->channel_key;
92 block_len = silc_cipher_get_block_len(cipher);
95 iv_len = silc_cipher_get_block_len(cipher);
96 if (channel->iv[0] == '\0')
97 for (i = 0; i < iv_len; i++) channel->iv[i] =
98 silc_rng_get_byte(client->rng);
100 silc_hash_make(client->internal->md5hash, channel->iv, iv_len,
103 /* Encode the channel payload. This also encrypts the message payload. */
104 payload = silc_channel_message_payload_encode(flags, data_len, data, iv_len,
105 channel->iv, cipher, hmac,
108 /* Get data used in packet header encryption, keys and stuff. */
109 cipher = conn->send_key;
110 hmac = conn->hmac_send;
111 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
113 /* Set the packet context pointers. The destination ID is always
114 the Channel ID of the channel. Server and router will handle the
115 distribution of the packet. */
116 data = payload->data;
117 data_len = payload->len;
118 packetdata.flags = 0;
119 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
120 packetdata.src_id = conn->local_id_data;
121 packetdata.src_id_len = silc_id_get_len(conn->local_id, SILC_ID_CLIENT);
122 packetdata.src_id_type = SILC_ID_CLIENT;
123 packetdata.dst_id = id_string;
124 packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
125 packetdata.dst_id_type = SILC_ID_CHANNEL;
126 data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
127 packetdata.src_id_len +
128 packetdata.dst_id_len);
129 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
130 packetdata.src_id_len + packetdata.dst_id_len;
131 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
132 packetdata.src_id_len +
133 packetdata.dst_id_len), block_len);
135 /* Create the outgoing packet */
136 if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
137 data, data_len, (const SilcBuffer)&packet)) {
138 SILC_LOG_ERROR(("Error assembling packet"));
142 /* Encrypt the header and padding of the packet. This is encrypted
143 with normal session key shared with our server. */
144 silc_packet_encrypt(cipher, hmac, conn->psn_send++,
145 (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN +
146 packetdata.src_id_len + packetdata.dst_id_len +
149 SILC_LOG_HEXDUMP(("Packet to channel, len %d", packet.len),
150 packet.data, packet.len);
152 /* Now actually send the packet */
153 silc_client_packet_send_real(client, sock, force_send);
156 silc_buffer_free(payload);
157 silc_free(id_string);
161 SilcChannelMessagePayload payload;
162 SilcChannelID *channel_id;
163 } *SilcChannelClientResolve;
165 static void silc_client_channel_message_cb(SilcClient client,
166 SilcClientConnection conn,
167 SilcClientEntry *clients,
168 SilcUInt32 clients_count,
171 SilcChannelClientResolve res = (SilcChannelClientResolve)context;
173 if (clients_count == 1) {
174 SilcChannelEntry channel;
175 unsigned char *message;
177 channel = silc_client_get_channel_by_id(client, conn, res->channel_id);
181 /* If this client is not on channel, add it there since it clearly
183 if (!silc_client_on_channel(channel, clients[0])) {
184 SilcChannelUser chu = silc_calloc(1, sizeof(*chu));
185 chu->client = clients[0];
186 chu->channel = channel;
187 silc_hash_table_add(channel->user_list, clients[0], chu);
188 silc_hash_table_add(clients[0]->channels, channel, chu);
191 message = silc_channel_message_get_data(res->payload, NULL);
193 /* Pass the message to application */
194 client->internal->ops->channel_message(
195 client, conn, clients[0], channel,
196 silc_channel_message_get_flags(res->payload),
201 silc_channel_message_payload_free(res->payload);
202 silc_free(res->channel_id);
206 /* Process received message to a channel (or from a channel, really). This
207 decrypts the channel message with channel specific key and parses the
208 channel payload. Finally it displays the message on the screen. */
210 void silc_client_channel_message(SilcClient client,
211 SilcSocketConnection sock,
212 SilcPacketContext *packet)
214 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
215 SilcBuffer buffer = packet->buffer;
216 SilcChannelMessagePayload payload = NULL;
217 SilcChannelID *id = NULL;
218 SilcChannelEntry channel;
219 SilcClientEntry client_entry;
220 SilcClientID *client_id = NULL;
221 unsigned char *message;
223 SILC_LOG_DEBUG(("Start"));
226 if (packet->dst_id_type != SILC_ID_CHANNEL)
229 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
233 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
237 /* Find the channel entry from channels on this connection */
238 channel = silc_client_get_channel_by_id(client, conn, id);
242 /* If there is no channel private key then just decrypt the message
243 with the channel key. If private keys are set then just go through
244 all private keys and check what decrypts correctly. */
245 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
246 /* Parse the channel message payload. This also decrypts the payload */
247 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
248 channel->channel_key,
251 /* If decryption failed and we have just performed channel key rekey
252 we will use the old key in decryption. If that fails too then we
253 cannot do more and will drop the packet. */
255 if (!channel->old_channel_key) {
259 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
260 channel->old_channel_key,
266 } else if (channel->private_keys) {
267 SilcChannelPrivateKey entry;
269 silc_dlist_start(channel->private_keys);
270 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
271 /* Parse the channel message payload. This also decrypts the payload */
272 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
278 if (entry == SILC_LIST_END)
284 /* Find client entry */
285 client_entry = silc_client_get_client_by_id(client, conn, client_id);
286 if (!client_entry || !client_entry->nickname) {
287 /* Resolve the client info */
288 SilcChannelClientResolve res = silc_calloc(1, sizeof(*res));
289 res->payload = payload;
290 res->channel_id = id;
291 silc_client_get_client_by_id_resolve(client, conn, client_id,
292 silc_client_channel_message_cb,
299 if (!silc_client_on_channel(channel, client_entry)) {
300 SILC_LOG_WARNING(("Received channel message from client not on channel"));
304 message = silc_channel_message_get_data(payload, NULL);
306 /* Pass the message to application */
307 client->internal->ops->channel_message(
308 client, conn, client_entry, channel,
309 silc_channel_message_get_flags(payload),
314 silc_free(client_id);
316 silc_channel_message_payload_free(payload);
319 /* Timeout callback that is called after a short period of time after the
320 new channel key has been created. This removes the old channel key all
323 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
325 SilcChannelEntry channel = (SilcChannelEntry)context;
327 if (channel->old_channel_key)
328 silc_cipher_free(channel->old_channel_key);
329 if (channel->old_hmac)
330 silc_hmac_free(channel->old_hmac);
331 channel->old_channel_key = NULL;
332 channel->old_hmac = NULL;
333 channel->rekey_task = NULL;
336 /* Saves channel key from encoded `key_payload'. This is used when we
337 receive Channel Key Payload and when we are processing JOIN command
340 void silc_client_save_channel_key(SilcClient client,
341 SilcClientConnection conn,
342 SilcBuffer key_payload,
343 SilcChannelEntry channel)
345 unsigned char *id_string, *key, *cipher, *hmac, hash[32];
348 SilcChannelKeyPayload payload;
350 payload = silc_channel_key_payload_parse(key_payload->data,
355 id_string = silc_channel_key_get_id(payload, &tmp_len);
357 silc_channel_key_payload_free(payload);
361 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
363 silc_channel_key_payload_free(payload);
369 channel = silc_client_get_channel_by_id(client, conn, id);
374 hmac = (channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) :
377 /* Save the old key for a short period of time so that we can decrypt
378 channel message even after the rekey if some client would be sending
379 messages with the old key after the rekey. */
380 if (channel->old_channel_key)
381 silc_cipher_free(channel->old_channel_key);
382 if (channel->old_hmac)
383 silc_hmac_free(channel->old_hmac);
384 if (channel->rekey_task)
385 silc_schedule_task_del(client->schedule, channel->rekey_task);
386 channel->old_channel_key = channel->channel_key;
387 channel->old_hmac = channel->hmac;
388 channel->rekey_task =
389 silc_schedule_task_add(client->schedule, 0,
390 silc_client_save_channel_key_rekey, channel,
391 10, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
393 /* Free the old channel key data */
394 silc_free(channel->key);
397 key = silc_channel_key_get_key(payload, &tmp_len);
398 cipher = silc_channel_key_get_cipher(payload, NULL);
399 channel->key_len = tmp_len * 8;
400 channel->key = silc_memdup(key, tmp_len);
402 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
403 client->internal->ops->say(
405 SILC_CLIENT_MESSAGE_AUDIT,
406 "Cannot talk to channel: unsupported cipher %s",
411 /* Set the cipher key */
412 silc_cipher_set_key(channel->channel_key, key, channel->key_len);
414 /* Generate HMAC key from the channel key data and set it */
415 silc_hmac_alloc(hmac, NULL, &channel->hmac);
416 silc_hash_make(silc_hmac_get_hash(channel->hmac), key, tmp_len, hash);
417 silc_hmac_set_key(channel->hmac, hash,
418 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
419 memset(hash, 0, sizeof(hash));
423 silc_channel_key_payload_free(payload);
426 /* Processes received key for channel. The received key will be used
427 to protect the traffic on the channel for now on. Client must receive
428 the key to the channel before talking on the channel is possible.
429 This is the key that server has generated, this is not the channel
430 private key, it is entirely local setting. */
432 void silc_client_receive_channel_key(SilcClient client,
433 SilcSocketConnection sock,
436 SILC_LOG_DEBUG(("Received key for channel"));
439 silc_client_save_channel_key(client, sock->user_data, packet, NULL);
442 /* Adds private key for channel. This may be set only if the channel's mode
443 mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
444 mode is not set. When channel has private key then the messages are
445 encrypted using that key. All clients on the channel must also know the
446 key in order to decrypt the messages. However, it is possible to have
447 several private keys per one channel. In this case only some of the
448 clients on the channel may know the one key and only some the other key.
450 If `cipher' and/or `hmac' is NULL then default values will be used
451 (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
453 The private key for channel is optional. If it is not set then the
454 channel messages are encrypted using the channel key generated by the
455 server. However, setting the private key (or keys) for the channel
456 significantly adds security. If more than one key is set the library
457 will automatically try all keys at the message decryption phase. Note:
458 setting many keys slows down the decryption phase as all keys has to
459 be tried in order to find the correct decryption key. However, setting
460 a few keys does not have big impact to the decryption performace.
462 NOTE: that this is entirely local setting. The key set using this function
463 is not sent to the network at any phase.
465 NOTE: If the key material was originated by the SKE protocol (using
466 silc_client_send_key_agreement) then the `key' MUST be the
467 key->send_enc_key as this is dictated by the SILC protocol. However,
468 currently it is not expected that the SKE key material would be used
469 as channel private key. However, this API allows it. */
471 int silc_client_add_channel_private_key(SilcClient client,
472 SilcClientConnection conn,
473 SilcChannelEntry channel,
479 SilcChannelPrivateKey entry;
480 unsigned char hash[32];
481 SilcSKEKeyMaterial *keymat;
483 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
487 cipher = SILC_DEFAULT_CIPHER;
489 hmac = SILC_DEFAULT_HMAC;
491 if (!silc_cipher_is_supported(cipher))
494 if (!silc_hmac_is_supported(hmac))
497 /* Produce the key material */
498 keymat = silc_calloc(1, sizeof(*keymat));
499 if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
500 client->internal->md5hash, keymat)
501 != SILC_SKE_STATUS_OK)
504 /* Remove the current key, if it exists. */
505 if (channel->channel_key) {
506 silc_cipher_free(channel->channel_key);
507 memset(channel->key, 0, channel->key_len / 8);
508 silc_free(channel->key);
509 channel->channel_key = NULL;
511 channel->key_len = 0;
514 silc_hmac_free(channel->hmac);
515 channel->hmac = NULL;
518 if (!channel->private_keys)
519 channel->private_keys = silc_dlist_init();
522 entry = silc_calloc(1, sizeof(*entry));
523 entry->key = silc_memdup(keymat->send_enc_key, keymat->enc_key_len / 8);
524 entry->key_len = keymat->enc_key_len / 8;
526 /* Allocate the cipher and set the key*/
527 silc_cipher_alloc(cipher, &entry->cipher);
528 silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
530 /* Generate HMAC key from the channel key data and set it */
531 silc_hmac_alloc(hmac, NULL, &entry->hmac);
532 silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key,
533 entry->key_len, hash);
534 silc_hmac_set_key(entry->hmac, hash,
535 silc_hash_len(silc_hmac_get_hash(entry->hmac)));
536 memset(hash, 0, sizeof(hash));
538 /* Add to the private keys list */
539 silc_dlist_add(channel->private_keys, entry);
541 if (!channel->curr_key)
542 channel->curr_key = entry;
544 /* Free the key material */
545 silc_ske_free_key_material(keymat);
550 /* Removes all private keys from the `channel'. The old channel key is used
551 after calling this to protect the channel messages. Returns FALSE on
552 on error, TRUE otherwise. */
554 int silc_client_del_channel_private_keys(SilcClient client,
555 SilcClientConnection conn,
556 SilcChannelEntry channel)
558 SilcChannelPrivateKey entry;
560 if (!channel->private_keys)
563 silc_dlist_start(channel->private_keys);
564 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
565 silc_dlist_del(channel->private_keys, entry);
566 memset(entry->key, 0, entry->key_len);
567 silc_free(entry->key);
568 silc_cipher_free(entry->cipher);
569 silc_hmac_free(entry->hmac);
573 channel->curr_key = NULL;
575 silc_dlist_uninit(channel->private_keys);
576 channel->private_keys = NULL;
581 /* Removes and frees private key `key' from the channel `channel'. The `key'
582 is retrieved by calling the function silc_client_list_channel_private_keys.
583 The key is not used after this. If the key was last private key then the
584 old channel key is used hereafter to protect the channel messages. This
585 returns FALSE on error, TRUE otherwise. */
587 int silc_client_del_channel_private_key(SilcClient client,
588 SilcClientConnection conn,
589 SilcChannelEntry channel,
590 SilcChannelPrivateKey key)
592 SilcChannelPrivateKey entry;
594 if (!channel->private_keys)
597 silc_dlist_start(channel->private_keys);
598 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
600 if (channel->curr_key == entry)
601 channel->curr_key = NULL;
603 silc_dlist_del(channel->private_keys, entry);
604 memset(entry->key, 0, entry->key_len);
605 silc_free(entry->key);
606 silc_cipher_free(entry->cipher);
607 silc_hmac_free(entry->hmac);
610 if (silc_dlist_count(channel->private_keys) == 0) {
611 silc_dlist_uninit(channel->private_keys);
612 channel->private_keys = NULL;
622 /* Returns array (pointers) of private keys associated to the `channel'.
623 The caller must free the array by calling the function
624 silc_client_free_channel_private_keys. The pointers in the array may be
625 used to delete the specific key by giving the pointer as argument to the
626 function silc_client_del_channel_private_key. */
628 SilcChannelPrivateKey *
629 silc_client_list_channel_private_keys(SilcClient client,
630 SilcClientConnection conn,
631 SilcChannelEntry channel,
632 SilcUInt32 *key_count)
634 SilcChannelPrivateKey *keys = NULL, entry;
635 SilcUInt32 count = 0;
637 if (!channel->private_keys)
640 silc_dlist_start(channel->private_keys);
641 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
642 keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
653 /* Frees the SilcChannelPrivateKey array. */
655 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
656 SilcUInt32 key_count)
661 /* Returns the SilcChannelUser entry if the `client_entry' is joined on the
662 channel indicated by the `channel'. NULL if client is not joined on
665 SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
666 SilcClientEntry client_entry)
670 if (silc_hash_table_find(channel->user_list, client_entry, NULL,