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;
51 unsigned char *id_string;
55 SILC_LOG_DEBUG(("Sending packet to channel"));
57 /* Take the key to be used */
58 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
60 /* Use key application specified */
63 } else if (channel->curr_key) {
64 /* Use current private key */
65 cipher = channel->curr_key->cipher;
66 hmac = channel->curr_key->hmac;
67 } else if (!channel->curr_key && channel->private_keys) {
68 /* Use just some private key since we don't know what to use
69 and private keys are set. */
70 silc_dlist_start(channel->private_keys);
71 key = silc_dlist_get(channel->private_keys);
75 /* Use this key as current private key */
76 channel->curr_key = key;
78 /* Use normal channel key generated by the server */
79 cipher = channel->channel_key;
83 /* Use normal channel key generated by the server */
84 cipher = channel->channel_key;
91 block_len = silc_cipher_get_block_len(cipher);
94 iv_len = silc_cipher_get_block_len(cipher);
95 if (channel->iv[0] == '\0')
96 for (i = 0; i < iv_len; i++) channel->iv[i] =
97 silc_rng_get_byte(client->rng);
99 silc_hash_make(client->internal->md5hash, channel->iv, iv_len,
102 /* Encode the channel payload. This also encrypts the message payload. */
103 payload = silc_channel_message_payload_encode(flags, data_len, data, iv_len,
104 channel->iv, cipher, hmac,
107 /* Get data used in packet header encryption, keys and stuff. */
108 cipher = conn->send_key;
109 hmac = conn->hmac_send;
110 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
112 /* Set the packet context pointers. The destination ID is always
113 the Channel ID of the channel. Server and router will handle the
114 distribution of the packet. */
115 data = payload->data;
116 data_len = payload->len;
117 packetdata.flags = 0;
118 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
119 packetdata.src_id = conn->local_id_data;
120 packetdata.src_id_len = silc_id_get_len(conn->local_id, SILC_ID_CLIENT);
121 packetdata.src_id_type = SILC_ID_CLIENT;
122 packetdata.dst_id = id_string;
123 packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
124 packetdata.dst_id_type = SILC_ID_CHANNEL;
125 data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
126 packetdata.src_id_len +
127 packetdata.dst_id_len);
128 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
129 packetdata.src_id_len + packetdata.dst_id_len;
130 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
131 packetdata.src_id_len +
132 packetdata.dst_id_len), block_len);
134 /* Prepare outgoing data buffer for packet sending */
135 silc_packet_send_prepare(sock,
136 SILC_PACKET_HEADER_LEN +
137 packetdata.src_id_len +
138 packetdata.dst_id_len,
142 packetdata.buffer = sock->outbuf;
144 /* Put the channel message payload to the outgoing data buffer */
145 silc_buffer_put(sock->outbuf, data, data_len);
147 /* Create the outgoing packet */
148 silc_packet_assemble(&packetdata, cipher);
150 /* Encrypt the header and padding of the packet. This is encrypted
151 with normal session key shared with our server. */
152 silc_packet_encrypt(cipher, hmac, conn->psn_send++,
153 sock->outbuf, SILC_PACKET_HEADER_LEN +
154 packetdata.src_id_len + packetdata.dst_id_len +
157 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
158 sock->outbuf->data, sock->outbuf->len);
160 /* Now actually send the packet */
161 silc_client_packet_send_real(client, sock, force_send);
162 silc_buffer_free(payload);
163 silc_free(id_string);
167 SilcChannelMessagePayload payload;
168 SilcChannelID *channel_id;
169 } *SilcChannelClientResolve;
171 static void silc_client_channel_message_cb(SilcClient client,
172 SilcClientConnection conn,
173 SilcClientEntry *clients,
174 SilcUInt32 clients_count,
177 SilcChannelClientResolve res = (SilcChannelClientResolve)context;
179 if (clients_count == 1) {
180 SilcChannelEntry channel;
181 unsigned char *message;
183 channel = silc_client_get_channel_by_id(client, conn, res->channel_id);
187 /* If this client is not on channel, add it there since it clearly
189 if (!silc_client_on_channel(channel, clients[0])) {
190 SilcChannelUser chu = silc_calloc(1, sizeof(*chu));
191 chu->client = clients[0];
192 chu->channel = channel;
193 silc_hash_table_add(channel->user_list, clients[0], chu);
194 silc_hash_table_add(clients[0]->channels, channel, chu);
197 message = silc_channel_message_get_data(res->payload, NULL);
199 /* Pass the message to application */
200 client->internal->ops->channel_message(
201 client, conn, clients[0], channel,
202 silc_channel_message_get_flags(res->payload),
207 silc_channel_message_payload_free(res->payload);
208 silc_free(res->channel_id);
212 /* Process received message to a channel (or from a channel, really). This
213 decrypts the channel message with channel specific key and parses the
214 channel payload. Finally it displays the message on the screen. */
216 void silc_client_channel_message(SilcClient client,
217 SilcSocketConnection sock,
218 SilcPacketContext *packet)
220 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
221 SilcBuffer buffer = packet->buffer;
222 SilcChannelMessagePayload payload = NULL;
223 SilcChannelID *id = NULL;
224 SilcChannelEntry channel;
225 SilcClientEntry client_entry;
226 SilcClientID *client_id = NULL;
227 unsigned char *message;
229 SILC_LOG_DEBUG(("Start"));
232 if (packet->dst_id_type != SILC_ID_CHANNEL)
235 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
239 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
243 /* Find the channel entry from channels on this connection */
244 channel = silc_client_get_channel_by_id(client, conn, id);
248 /* If there is no channel private key then just decrypt the message
249 with the channel key. If private keys are set then just go through
250 all private keys and check what decrypts correctly. */
251 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
252 /* Parse the channel message payload. This also decrypts the payload */
253 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
254 channel->channel_key,
257 /* If decryption failed and we have just performed channel key rekey
258 we will use the old key in decryption. If that fails too then we
259 cannot do more and will drop the packet. */
261 if (!channel->old_channel_key) {
265 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
266 channel->old_channel_key,
272 } else if (channel->private_keys) {
273 SilcChannelPrivateKey entry;
275 silc_dlist_start(channel->private_keys);
276 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
277 /* Parse the channel message payload. This also decrypts the payload */
278 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
284 if (entry == SILC_LIST_END)
290 /* Find client entry */
291 client_entry = silc_client_get_client_by_id(client, conn, client_id);
292 if (!client_entry || !client_entry->nickname) {
293 /* Resolve the client info */
294 SilcChannelClientResolve res = silc_calloc(1, sizeof(*res));
295 res->payload = payload;
296 res->channel_id = id;
297 silc_client_get_client_by_id_resolve(client, conn, client_id,
298 silc_client_channel_message_cb,
305 if (!silc_client_on_channel(channel, client_entry)) {
306 SILC_LOG_WARNING(("Received channel message from client not on channel"));
310 message = silc_channel_message_get_data(payload, NULL);
312 /* Pass the message to application */
313 client->internal->ops->channel_message(
314 client, conn, client_entry, channel,
315 silc_channel_message_get_flags(payload),
320 silc_free(client_id);
322 silc_channel_message_payload_free(payload);
325 /* Timeout callback that is called after a short period of time after the
326 new channel key has been created. This removes the old channel key all
329 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
331 SilcChannelEntry channel = (SilcChannelEntry)context;
333 if (channel->old_channel_key)
334 silc_cipher_free(channel->old_channel_key);
335 if (channel->old_hmac)
336 silc_hmac_free(channel->old_hmac);
337 channel->old_channel_key = NULL;
338 channel->old_hmac = NULL;
339 channel->rekey_task = NULL;
342 /* Saves channel key from encoded `key_payload'. This is used when we
343 receive Channel Key Payload and when we are processing JOIN command
346 void silc_client_save_channel_key(SilcClient client,
347 SilcClientConnection conn,
348 SilcBuffer key_payload,
349 SilcChannelEntry channel)
351 unsigned char *id_string, *key, *cipher, *hmac, hash[32];
354 SilcChannelKeyPayload payload;
356 payload = silc_channel_key_payload_parse(key_payload->data,
361 id_string = silc_channel_key_get_id(payload, &tmp_len);
363 silc_channel_key_payload_free(payload);
367 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
369 silc_channel_key_payload_free(payload);
375 channel = silc_client_get_channel_by_id(client, conn, id);
380 hmac = (channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) :
383 /* Save the old key for a short period of time so that we can decrypt
384 channel message even after the rekey if some client would be sending
385 messages with the old key after the rekey. */
386 if (channel->old_channel_key)
387 silc_cipher_free(channel->old_channel_key);
388 if (channel->old_hmac)
389 silc_hmac_free(channel->old_hmac);
390 if (channel->rekey_task)
391 silc_schedule_task_del(client->schedule, channel->rekey_task);
392 channel->old_channel_key = channel->channel_key;
393 channel->old_hmac = channel->hmac;
394 channel->rekey_task =
395 silc_schedule_task_add(client->schedule, 0,
396 silc_client_save_channel_key_rekey, channel,
397 10, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
399 /* Free the old channel key data */
400 silc_free(channel->key);
403 key = silc_channel_key_get_key(payload, &tmp_len);
404 cipher = silc_channel_key_get_cipher(payload, NULL);
405 channel->key_len = tmp_len * 8;
406 channel->key = silc_memdup(key, tmp_len);
408 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
409 client->internal->ops->say(
411 SILC_CLIENT_MESSAGE_AUDIT,
412 "Cannot talk to channel: unsupported cipher %s",
417 /* Set the cipher key */
418 silc_cipher_set_key(channel->channel_key, key, channel->key_len);
420 /* Generate HMAC key from the channel key data and set it */
421 silc_hmac_alloc(hmac, NULL, &channel->hmac);
422 silc_hash_make(silc_hmac_get_hash(channel->hmac), key, tmp_len, hash);
423 silc_hmac_set_key(channel->hmac, hash,
424 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
425 memset(hash, 0, sizeof(hash));
429 silc_channel_key_payload_free(payload);
432 /* Processes received key for channel. The received key will be used
433 to protect the traffic on the channel for now on. Client must receive
434 the key to the channel before talking on the channel is possible.
435 This is the key that server has generated, this is not the channel
436 private key, it is entirely local setting. */
438 void silc_client_receive_channel_key(SilcClient client,
439 SilcSocketConnection sock,
442 SILC_LOG_DEBUG(("Received key for channel"));
445 silc_client_save_channel_key(client, sock->user_data, packet, NULL);
448 /* Adds private key for channel. This may be set only if the channel's mode
449 mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
450 mode is not set. When channel has private key then the messages are
451 encrypted using that key. All clients on the channel must also know the
452 key in order to decrypt the messages. However, it is possible to have
453 several private keys per one channel. In this case only some of the
454 clients on the channel may know the one key and only some the other key.
456 If `cipher' and/or `hmac' is NULL then default values will be used
457 (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
459 The private key for channel is optional. If it is not set then the
460 channel messages are encrypted using the channel key generated by the
461 server. However, setting the private key (or keys) for the channel
462 significantly adds security. If more than one key is set the library
463 will automatically try all keys at the message decryption phase. Note:
464 setting many keys slows down the decryption phase as all keys has to
465 be tried in order to find the correct decryption key. However, setting
466 a few keys does not have big impact to the decryption performace.
468 NOTE: that this is entirely local setting. The key set using this function
469 is not sent to the network at any phase.
471 NOTE: If the key material was originated by the SKE protocol (using
472 silc_client_send_key_agreement) then the `key' MUST be the
473 key->send_enc_key as this is dictated by the SILC protocol. However,
474 currently it is not expected that the SKE key material would be used
475 as channel private key. However, this API allows it. */
477 int silc_client_add_channel_private_key(SilcClient client,
478 SilcClientConnection conn,
479 SilcChannelEntry channel,
485 SilcChannelPrivateKey entry;
486 unsigned char hash[32];
487 SilcSKEKeyMaterial *keymat;
489 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
493 cipher = SILC_DEFAULT_CIPHER;
495 hmac = SILC_DEFAULT_HMAC;
497 if (!silc_cipher_is_supported(cipher))
500 if (!silc_hmac_is_supported(hmac))
503 /* Produce the key material */
504 keymat = silc_calloc(1, sizeof(*keymat));
505 if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
506 client->internal->md5hash, keymat)
507 != SILC_SKE_STATUS_OK)
510 /* Remove the current key, if it exists. */
511 if (channel->channel_key) {
512 silc_cipher_free(channel->channel_key);
513 memset(channel->key, 0, channel->key_len / 8);
514 silc_free(channel->key);
515 channel->channel_key = NULL;
517 channel->key_len = 0;
520 silc_hmac_free(channel->hmac);
521 channel->hmac = NULL;
524 if (!channel->private_keys)
525 channel->private_keys = silc_dlist_init();
528 entry = silc_calloc(1, sizeof(*entry));
529 entry->key = silc_memdup(keymat->send_enc_key, keymat->enc_key_len / 8);
530 entry->key_len = keymat->enc_key_len / 8;
532 /* Allocate the cipher and set the key*/
533 silc_cipher_alloc(cipher, &entry->cipher);
534 silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
536 /* Generate HMAC key from the channel key data and set it */
537 silc_hmac_alloc(hmac, NULL, &entry->hmac);
538 silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key,
539 entry->key_len, hash);
540 silc_hmac_set_key(entry->hmac, hash,
541 silc_hash_len(silc_hmac_get_hash(entry->hmac)));
542 memset(hash, 0, sizeof(hash));
544 /* Add to the private keys list */
545 silc_dlist_add(channel->private_keys, entry);
547 if (!channel->curr_key)
548 channel->curr_key = entry;
550 /* Free the key material */
551 silc_ske_free_key_material(keymat);
556 /* Removes all private keys from the `channel'. The old channel key is used
557 after calling this to protect the channel messages. Returns FALSE on
558 on error, TRUE otherwise. */
560 int silc_client_del_channel_private_keys(SilcClient client,
561 SilcClientConnection conn,
562 SilcChannelEntry channel)
564 SilcChannelPrivateKey entry;
566 if (!channel->private_keys)
569 silc_dlist_start(channel->private_keys);
570 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
571 silc_dlist_del(channel->private_keys, entry);
572 memset(entry->key, 0, entry->key_len);
573 silc_free(entry->key);
574 silc_cipher_free(entry->cipher);
575 silc_hmac_free(entry->hmac);
579 channel->curr_key = NULL;
581 silc_dlist_uninit(channel->private_keys);
582 channel->private_keys = NULL;
587 /* Removes and frees private key `key' from the channel `channel'. The `key'
588 is retrieved by calling the function silc_client_list_channel_private_keys.
589 The key is not used after this. If the key was last private key then the
590 old channel key is used hereafter to protect the channel messages. This
591 returns FALSE on error, TRUE otherwise. */
593 int silc_client_del_channel_private_key(SilcClient client,
594 SilcClientConnection conn,
595 SilcChannelEntry channel,
596 SilcChannelPrivateKey key)
598 SilcChannelPrivateKey entry;
600 if (!channel->private_keys)
603 silc_dlist_start(channel->private_keys);
604 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
606 if (channel->curr_key == entry)
607 channel->curr_key = NULL;
609 silc_dlist_del(channel->private_keys, entry);
610 memset(entry->key, 0, entry->key_len);
611 silc_free(entry->key);
612 silc_cipher_free(entry->cipher);
613 silc_hmac_free(entry->hmac);
616 if (silc_dlist_count(channel->private_keys) == 0) {
617 silc_dlist_uninit(channel->private_keys);
618 channel->private_keys = NULL;
628 /* Returns array (pointers) of private keys associated to the `channel'.
629 The caller must free the array by calling the function
630 silc_client_free_channel_private_keys. The pointers in the array may be
631 used to delete the specific key by giving the pointer as argument to the
632 function silc_client_del_channel_private_key. */
634 SilcChannelPrivateKey *
635 silc_client_list_channel_private_keys(SilcClient client,
636 SilcClientConnection conn,
637 SilcChannelEntry channel,
638 SilcUInt32 *key_count)
640 SilcChannelPrivateKey *keys = NULL, entry;
641 SilcUInt32 count = 0;
643 if (!channel->private_keys)
646 silc_dlist_start(channel->private_keys);
647 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
648 keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
659 /* Frees the SilcChannelPrivateKey array. */
661 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
662 SilcUInt32 key_count)
667 /* Returns the SilcChannelUser entry if the `client_entry' is joined on the
668 channel indicated by the `channel'. NULL if client is not joined on
671 SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
672 SilcClientEntry client_entry)
676 if (silc_hash_table_find(channel->user_list, client_entry, NULL,