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 "clientlibincludes.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 = conn->sock;
47 SilcPacketContext packetdata;
50 unsigned char *id_string;
54 SILC_LOG_DEBUG(("Sending packet to channel"));
56 /* Take the key to be used */
57 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
59 /* Use key application specified */
62 } else if (channel->curr_key) {
63 /* Use current private key */
64 cipher = channel->curr_key->cipher;
65 hmac = channel->curr_key->hmac;
66 } else if (!channel->curr_key && channel->private_keys) {
67 /* Use just some private key since we don't know what to use
68 and private keys are set. */
69 silc_dlist_start(channel->private_keys);
70 key = silc_dlist_get(channel->private_keys);
74 /* Use this key as current private key */
75 channel->curr_key = key;
77 /* Use normal channel key generated by the server */
78 cipher = channel->channel_key;
82 /* Use normal channel key generated by the server */
83 cipher = channel->channel_key;
90 block_len = silc_cipher_get_block_len(cipher);
93 iv_len = silc_cipher_get_block_len(cipher);
94 if (channel->iv[0] == '\0')
95 for (i = 0; i < iv_len; i++) channel->iv[i] =
96 silc_rng_get_byte(client->rng);
98 silc_hash_make(client->internal->md5hash, channel->iv, iv_len,
101 /* Encode the channel payload. This also encrypts the message payload. */
102 payload = silc_channel_message_payload_encode(flags, data_len, data, iv_len,
103 channel->iv, cipher, hmac);
105 /* Get data used in packet header encryption, keys and stuff. */
106 cipher = conn->send_key;
107 hmac = conn->hmac_send;
108 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
110 /* Set the packet context pointers. The destination ID is always
111 the Channel ID of the channel. Server and router will handle the
112 distribution of the packet. */
113 packetdata.flags = 0;
114 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
115 packetdata.src_id = conn->local_id_data;
116 packetdata.src_id_len = silc_id_get_len(conn->local_id, SILC_ID_CLIENT);
117 packetdata.src_id_type = SILC_ID_CLIENT;
118 packetdata.dst_id = id_string;
119 packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
120 packetdata.dst_id_type = SILC_ID_CHANNEL;
121 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
122 packetdata.src_id_len + packetdata.dst_id_len;
123 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
124 packetdata.src_id_len +
125 packetdata.dst_id_len), block_len);
127 /* Prepare outgoing data buffer for packet sending */
128 silc_packet_send_prepare(sock,
129 SILC_PACKET_HEADER_LEN +
130 packetdata.src_id_len +
131 packetdata.dst_id_len,
135 packetdata.buffer = sock->outbuf;
137 /* Put the channel message payload to the outgoing data buffer */
138 silc_buffer_put(sock->outbuf, payload->data, payload->len);
140 /* Create the outgoing packet */
141 silc_packet_assemble(&packetdata, cipher);
143 /* Encrypt the header and padding of the packet. This is encrypted
144 with normal session key shared with our server. */
145 silc_packet_encrypt(cipher, hmac, conn->psn_send++,
146 sock->outbuf, SILC_PACKET_HEADER_LEN +
147 packetdata.src_id_len + packetdata.dst_id_len +
150 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
151 sock->outbuf->data, sock->outbuf->len);
153 /* Now actually send the packet */
154 silc_client_packet_send_real(client, sock, force_send);
155 silc_buffer_free(payload);
156 silc_free(id_string);
160 SilcChannelMessagePayload payload;
161 SilcChannelID *channel_id;
162 } *SilcChannelClientResolve;
164 static void silc_client_channel_message_cb(SilcClient client,
165 SilcClientConnection conn,
166 SilcClientEntry *clients,
167 uint32 clients_count,
170 SilcChannelClientResolve res = (SilcChannelClientResolve)context;
172 if (clients_count == 1) {
173 SilcChannelEntry channel;
174 unsigned char *message;
176 channel = silc_client_get_channel_by_id(client, conn, res->channel_id);
180 /* If this client is not on channel, add it there since it clearly
182 if (!silc_client_on_channel(channel, clients[0])) {
183 SilcChannelUser chu = silc_calloc(1, sizeof(*chu));
184 chu->client = clients[0];
185 chu->channel = channel;
186 silc_hash_table_add(channel->user_list, clients[0], chu);
187 silc_hash_table_add(clients[0]->channels, channel, chu);
190 message = silc_channel_message_get_data(res->payload, NULL);
192 /* Pass the message to application */
193 client->internal->ops->channel_message(
194 client, conn, clients[0], channel,
195 silc_channel_message_get_flags(res->payload),
200 silc_channel_message_payload_free(res->payload);
201 silc_free(res->channel_id);
205 /* Process received message to a channel (or from a channel, really). This
206 decrypts the channel message with channel specific key and parses the
207 channel payload. Finally it displays the message on the screen. */
209 void silc_client_channel_message(SilcClient client,
210 SilcSocketConnection sock,
211 SilcPacketContext *packet)
213 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
214 SilcBuffer buffer = packet->buffer;
215 SilcChannelMessagePayload payload = NULL;
216 SilcChannelID *id = NULL;
217 SilcChannelEntry channel;
218 SilcClientEntry client_entry;
219 SilcClientID *client_id = NULL;
220 unsigned char *message;
222 SILC_LOG_DEBUG(("Start"));
225 if (packet->dst_id_type != SILC_ID_CHANNEL)
228 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
232 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
236 /* Find the channel entry from channels on this connection */
237 channel = silc_client_get_channel_by_id(client, conn, id);
241 /* If there is no channel private key then just decrypt the message
242 with the channel key. If private keys are set then just go through
243 all private keys and check what decrypts correctly. */
244 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
245 /* Parse the channel message payload. This also decrypts the payload */
246 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
247 channel->channel_key,
250 /* If decryption failed and we have just performed channel key rekey
251 we will use the old key in decryption. If that fails too then we
252 cannot do more and will drop the packet. */
254 if (!channel->old_channel_key) {
258 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
259 channel->old_channel_key,
265 } else if (channel->private_keys) {
266 SilcChannelPrivateKey entry;
268 silc_dlist_start(channel->private_keys);
269 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
270 /* Parse the channel message payload. This also decrypts the payload */
271 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
277 if (entry == SILC_LIST_END)
283 /* Find client entry */
284 client_entry = silc_client_get_client_by_id(client, conn, client_id);
285 if (!client_entry || !client_entry->nickname) {
286 /* Resolve the client info */
287 SilcChannelClientResolve res = silc_calloc(1, sizeof(*res));
288 res->payload = payload;
289 res->channel_id = id;
290 silc_client_get_client_by_id_resolve(client, conn, client_id,
291 silc_client_channel_message_cb,
298 if (!silc_client_on_channel(channel, client_entry)) {
299 SILC_LOG_WARNING(("Received channel message from client not on channel"));
303 message = silc_channel_message_get_data(payload, NULL);
305 /* Pass the message to application */
306 client->internal->ops->channel_message(
307 client, conn, client_entry, channel,
308 silc_channel_message_get_flags(payload),
313 silc_free(client_id);
315 silc_channel_message_payload_free(payload);
318 /* Timeout callback that is called after a short period of time after the
319 new channel key has been created. This removes the old channel key all
322 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
324 SilcChannelEntry channel = (SilcChannelEntry)context;
326 if (channel->old_channel_key)
327 silc_cipher_free(channel->old_channel_key);
328 if (channel->old_hmac)
329 silc_hmac_free(channel->old_hmac);
330 channel->old_channel_key = NULL;
331 channel->old_hmac = NULL;
332 channel->rekey_task = NULL;
335 /* Saves channel key from encoded `key_payload'. This is used when we
336 receive Channel Key Payload and when we are processing JOIN command
339 void silc_client_save_channel_key(SilcClient client,
340 SilcClientConnection conn,
341 SilcBuffer key_payload,
342 SilcChannelEntry channel)
344 unsigned char *id_string, *key, *cipher, *hmac, hash[32];
347 SilcChannelKeyPayload payload;
349 payload = silc_channel_key_payload_parse(key_payload->data,
354 id_string = silc_channel_key_get_id(payload, &tmp_len);
356 silc_channel_key_payload_free(payload);
360 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
362 silc_channel_key_payload_free(payload);
368 channel = silc_client_get_channel_by_id(client, conn, id);
373 hmac = (channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) :
376 /* Save the old key for a short period of time so that we can decrypt
377 channel message even after the rekey if some client would be sending
378 messages with the old key after the rekey. */
379 if (channel->old_channel_key)
380 silc_cipher_free(channel->old_channel_key);
381 if (channel->old_hmac)
382 silc_hmac_free(channel->old_hmac);
383 if (channel->rekey_task)
384 silc_schedule_task_del(client->schedule, channel->rekey_task);
385 channel->old_channel_key = channel->channel_key;
386 channel->old_hmac = channel->hmac;
387 channel->rekey_task =
388 silc_schedule_task_add(client->schedule, 0,
389 silc_client_save_channel_key_rekey, channel,
390 10, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
392 /* Free the old channel key data */
393 silc_free(channel->key);
396 key = silc_channel_key_get_key(payload, &tmp_len);
397 cipher = silc_channel_key_get_cipher(payload, NULL);
398 channel->key_len = tmp_len * 8;
399 channel->key = silc_memdup(key, tmp_len);
401 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
402 client->internal->ops->say(
404 SILC_CLIENT_MESSAGE_AUDIT,
405 "Cannot talk to channel: unsupported cipher %s",
410 /* Set the cipher key */
411 silc_cipher_set_key(channel->channel_key, key, channel->key_len);
413 /* Generate HMAC key from the channel key data and set it */
414 silc_hmac_alloc(hmac, NULL, &channel->hmac);
415 silc_hash_make(silc_hmac_get_hash(channel->hmac), key, tmp_len, hash);
416 silc_hmac_set_key(channel->hmac, hash,
417 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
418 memset(hash, 0, sizeof(hash));
422 silc_channel_key_payload_free(payload);
425 /* Processes received key for channel. The received key will be used
426 to protect the traffic on the channel for now on. Client must receive
427 the key to the channel before talking on the channel is possible.
428 This is the key that server has generated, this is not the channel
429 private key, it is entirely local setting. */
431 void silc_client_receive_channel_key(SilcClient client,
432 SilcSocketConnection sock,
435 SILC_LOG_DEBUG(("Received key for channel"));
438 silc_client_save_channel_key(client, sock->user_data, packet, NULL);
441 /* Adds private key for channel. This may be set only if the channel's mode
442 mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
443 mode is not set. When channel has private key then the messages are
444 encrypted using that key. All clients on the channel must also know the
445 key in order to decrypt the messages. However, it is possible to have
446 several private keys per one channel. In this case only some of the
447 clients on the channel may know the one key and only some the other key.
449 If `cipher' and/or `hmac' is NULL then default values will be used
450 (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
452 The private key for channel is optional. If it is not set then the
453 channel messages are encrypted using the channel key generated by the
454 server. However, setting the private key (or keys) for the channel
455 significantly adds security. If more than one key is set the library
456 will automatically try all keys at the message decryption phase. Note:
457 setting many keys slows down the decryption phase as all keys has to
458 be tried in order to find the correct decryption key. However, setting
459 a few keys does not have big impact to the decryption performace.
461 NOTE: that this is entirely local setting. The key set using this function
462 is not sent to the network at any phase.
464 NOTE: If the key material was originated by the SKE protocol (using
465 silc_client_send_key_agreement) then the `key' MUST be the
466 key->send_enc_key as this is dictated by the SILC protocol. However,
467 currently it is not expected that the SKE key material would be used
468 as channel private key. However, this API allows it. */
470 int silc_client_add_channel_private_key(SilcClient client,
471 SilcClientConnection conn,
472 SilcChannelEntry channel,
478 SilcChannelPrivateKey entry;
479 unsigned char hash[32];
480 SilcSKEKeyMaterial *keymat;
482 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
486 cipher = SILC_DEFAULT_CIPHER;
488 hmac = SILC_DEFAULT_HMAC;
490 if (!silc_cipher_is_supported(cipher))
493 if (!silc_hmac_is_supported(hmac))
496 /* Produce the key material */
497 keymat = silc_calloc(1, sizeof(*keymat));
498 if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
499 client->internal->md5hash, keymat)
500 != SILC_SKE_STATUS_OK)
503 /* Remove the current key, if it exists. */
504 if (channel->channel_key) {
505 silc_cipher_free(channel->channel_key);
506 memset(channel->key, 0, channel->key_len / 8);
507 silc_free(channel->key);
508 channel->channel_key = NULL;
510 channel->key_len = 0;
513 silc_hmac_free(channel->hmac);
514 channel->hmac = NULL;
517 if (!channel->private_keys)
518 channel->private_keys = silc_dlist_init();
521 entry = silc_calloc(1, sizeof(*entry));
522 entry->key = silc_memdup(keymat->send_enc_key, keymat->enc_key_len / 8);
523 entry->key_len = keymat->enc_key_len / 8;
525 /* Allocate the cipher and set the key*/
526 silc_cipher_alloc(cipher, &entry->cipher);
527 silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
529 /* Generate HMAC key from the channel key data and set it */
530 silc_hmac_alloc(hmac, NULL, &entry->hmac);
531 silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key,
532 entry->key_len, hash);
533 silc_hmac_set_key(entry->hmac, hash,
534 silc_hash_len(silc_hmac_get_hash(entry->hmac)));
535 memset(hash, 0, sizeof(hash));
537 /* Add to the private keys list */
538 silc_dlist_add(channel->private_keys, entry);
540 if (!channel->curr_key)
541 channel->curr_key = entry;
543 /* Free the key material */
544 silc_ske_free_key_material(keymat);
549 /* Removes all private keys from the `channel'. The old channel key is used
550 after calling this to protect the channel messages. Returns FALSE on
551 on error, TRUE otherwise. */
553 int silc_client_del_channel_private_keys(SilcClient client,
554 SilcClientConnection conn,
555 SilcChannelEntry channel)
557 SilcChannelPrivateKey entry;
559 if (!channel->private_keys)
562 silc_dlist_start(channel->private_keys);
563 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
564 silc_dlist_del(channel->private_keys, entry);
565 memset(entry->key, 0, entry->key_len);
566 silc_free(entry->key);
567 silc_cipher_free(entry->cipher);
568 silc_hmac_free(entry->hmac);
572 channel->curr_key = NULL;
574 silc_dlist_uninit(channel->private_keys);
575 channel->private_keys = NULL;
580 /* Removes and frees private key `key' from the channel `channel'. The `key'
581 is retrieved by calling the function silc_client_list_channel_private_keys.
582 The key is not used after this. If the key was last private key then the
583 old channel key is used hereafter to protect the channel messages. This
584 returns FALSE on error, TRUE otherwise. */
586 int silc_client_del_channel_private_key(SilcClient client,
587 SilcClientConnection conn,
588 SilcChannelEntry channel,
589 SilcChannelPrivateKey key)
591 SilcChannelPrivateKey entry;
593 if (!channel->private_keys)
596 silc_dlist_start(channel->private_keys);
597 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
599 if (channel->curr_key == entry)
600 channel->curr_key = NULL;
602 silc_dlist_del(channel->private_keys, entry);
603 memset(entry->key, 0, entry->key_len);
604 silc_free(entry->key);
605 silc_cipher_free(entry->cipher);
606 silc_hmac_free(entry->hmac);
609 if (silc_dlist_count(channel->private_keys) == 0) {
610 silc_dlist_uninit(channel->private_keys);
611 channel->private_keys = NULL;
621 /* Returns array (pointers) of private keys associated to the `channel'.
622 The caller must free the array by calling the function
623 silc_client_free_channel_private_keys. The pointers in the array may be
624 used to delete the specific key by giving the pointer as argument to the
625 function silc_client_del_channel_private_key. */
627 SilcChannelPrivateKey *
628 silc_client_list_channel_private_keys(SilcClient client,
629 SilcClientConnection conn,
630 SilcChannelEntry channel,
633 SilcChannelPrivateKey *keys = NULL, entry;
636 if (!channel->private_keys)
639 silc_dlist_start(channel->private_keys);
640 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
641 keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
652 /* Frees the SilcChannelPrivateKey array. */
654 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
660 /* Returns the SilcChannelUser entry if the `client_entry' is joined on the
661 channel indicated by the `channel'. NULL if client is not joined on
664 SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
665 SilcClientEntry client_entry)
669 if (silc_hash_table_find(channel->user_list, client_entry, NULL,