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 message = silc_channel_message_get_data(res->payload, NULL);
182 /* Pass the message to application */
183 client->internal->ops->channel_message(
184 client, conn, clients[0], channel,
185 silc_channel_message_get_flags(res->payload),
190 silc_channel_message_payload_free(res->payload);
191 silc_free(res->channel_id);
195 /* Process received message to a channel (or from a channel, really). This
196 decrypts the channel message with channel specific key and parses the
197 channel payload. Finally it displays the message on the screen. */
199 void silc_client_channel_message(SilcClient client,
200 SilcSocketConnection sock,
201 SilcPacketContext *packet)
203 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
204 SilcBuffer buffer = packet->buffer;
205 SilcChannelMessagePayload payload = NULL;
206 SilcChannelID *id = NULL;
207 SilcChannelEntry channel;
208 SilcClientEntry client_entry;
209 SilcClientID *client_id = NULL;
210 unsigned char *message;
212 SILC_LOG_DEBUG(("Start"));
215 if (packet->dst_id_type != SILC_ID_CHANNEL)
218 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
222 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
226 /* Find the channel entry from channels on this connection */
227 channel = silc_client_get_channel_by_id(client, conn, id);
231 /* If there is no channel private key then just decrypt the message
232 with the channel key. If private keys are set then just go through
233 all private keys and check what decrypts correctly. */
234 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
235 /* Parse the channel message payload. This also decrypts the payload */
236 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
237 channel->channel_key,
240 /* If decryption failed and we have just performed channel key rekey
241 we will use the old key in decryption. If that fails too then we
242 cannot do more and will drop the packet. */
244 if (!channel->old_channel_key) {
248 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
249 channel->old_channel_key,
255 } else if (channel->private_keys) {
256 SilcChannelPrivateKey entry;
258 silc_dlist_start(channel->private_keys);
259 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
260 /* Parse the channel message payload. This also decrypts the payload */
261 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
267 if (entry == SILC_LIST_END)
273 /* Find client entry */
274 client_entry = silc_client_get_client_by_id(client, conn, client_id);
275 if (!client_entry || !client_entry->nickname) {
276 /* Resolve the client info */
277 SilcChannelClientResolve res = silc_calloc(1, sizeof(*res));
278 res->payload = payload;
279 res->channel_id = id;
280 silc_client_get_client_by_id_resolve(client, conn, client_id,
281 silc_client_channel_message_cb,
288 if (!silc_client_on_channel(channel, client_entry)) {
289 SILC_LOG_WARNING(("Received channel message from client not on channel"));
293 message = silc_channel_message_get_data(payload, NULL);
295 /* Pass the message to application */
296 client->internal->ops->channel_message(
297 client, conn, client_entry, channel,
298 silc_channel_message_get_flags(payload),
303 silc_free(client_id);
305 silc_channel_message_payload_free(payload);
308 /* Timeout callback that is called after a short period of time after the
309 new channel key has been created. This removes the old channel key all
312 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
314 SilcChannelEntry channel = (SilcChannelEntry)context;
316 if (channel->old_channel_key)
317 silc_cipher_free(channel->old_channel_key);
318 if (channel->old_hmac)
319 silc_hmac_free(channel->old_hmac);
320 channel->old_channel_key = NULL;
321 channel->old_hmac = NULL;
322 channel->rekey_task = NULL;
325 /* Saves channel key from encoded `key_payload'. This is used when we
326 receive Channel Key Payload and when we are processing JOIN command
329 void silc_client_save_channel_key(SilcClient client,
330 SilcClientConnection conn,
331 SilcBuffer key_payload,
332 SilcChannelEntry channel)
334 unsigned char *id_string, *key, *cipher, *hmac, hash[32];
337 SilcChannelKeyPayload payload;
339 payload = silc_channel_key_payload_parse(key_payload->data,
344 id_string = silc_channel_key_get_id(payload, &tmp_len);
346 silc_channel_key_payload_free(payload);
350 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
352 silc_channel_key_payload_free(payload);
358 channel = silc_client_get_channel_by_id(client, conn, id);
363 hmac = (channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) :
366 /* Save the old key for a short period of time so that we can decrypt
367 channel message even after the rekey if some client would be sending
368 messages with the old key after the rekey. */
369 if (channel->old_channel_key)
370 silc_cipher_free(channel->old_channel_key);
371 if (channel->old_hmac)
372 silc_hmac_free(channel->old_hmac);
373 if (channel->rekey_task)
374 silc_schedule_task_del(client->schedule, channel->rekey_task);
375 channel->old_channel_key = channel->channel_key;
376 channel->old_hmac = channel->hmac;
377 channel->rekey_task =
378 silc_schedule_task_add(client->schedule, 0,
379 silc_client_save_channel_key_rekey, channel,
380 10, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
382 /* Free the old channel key data */
383 silc_free(channel->key);
386 key = silc_channel_key_get_key(payload, &tmp_len);
387 cipher = silc_channel_key_get_cipher(payload, NULL);
388 channel->key_len = tmp_len * 8;
389 channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
390 memcpy(channel->key, key, tmp_len);
392 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
393 client->internal->ops->say(
395 SILC_CLIENT_MESSAGE_AUDIT,
396 "Cannot talk to channel: unsupported cipher %s",
401 /* Set the cipher key */
402 silc_cipher_set_key(channel->channel_key, key, channel->key_len);
404 /* Generate HMAC key from the channel key data and set it */
405 silc_hmac_alloc(hmac, NULL, &channel->hmac);
406 silc_hash_make(silc_hmac_get_hash(channel->hmac), key, tmp_len, hash);
407 silc_hmac_set_key(channel->hmac, hash,
408 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
409 memset(hash, 0, sizeof(hash));
413 silc_channel_key_payload_free(payload);
416 /* Processes received key for channel. The received key will be used
417 to protect the traffic on the channel for now on. Client must receive
418 the key to the channel before talking on the channel is possible.
419 This is the key that server has generated, this is not the channel
420 private key, it is entirely local setting. */
422 void silc_client_receive_channel_key(SilcClient client,
423 SilcSocketConnection sock,
426 SILC_LOG_DEBUG(("Received key for channel"));
429 silc_client_save_channel_key(client, sock->user_data, packet, NULL);
432 /* Adds private key for channel. This may be set only if the channel's mode
433 mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
434 mode is not set. When channel has private key then the messages are
435 encrypted using that key. All clients on the channel must also know the
436 key in order to decrypt the messages. However, it is possible to have
437 several private keys per one channel. In this case only some of the
438 clients on the channel may know the one key and only some the other key.
440 If `cipher' and/or `hmac' is NULL then default values will be used
441 (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
443 The private key for channel is optional. If it is not set then the
444 channel messages are encrypted using the channel key generated by the
445 server. However, setting the private key (or keys) for the channel
446 significantly adds security. If more than one key is set the library
447 will automatically try all keys at the message decryption phase. Note:
448 setting many keys slows down the decryption phase as all keys has to
449 be tried in order to find the correct decryption key. However, setting
450 a few keys does not have big impact to the decryption performace.
452 NOTE: that this is entirely local setting. The key set using this function
453 is not sent to the network at any phase.
455 NOTE: If the key material was originated by the SKE protocol (using
456 silc_client_send_key_agreement) then the `key' MUST be the
457 key->send_enc_key as this is dictated by the SILC protocol. However,
458 currently it is not expected that the SKE key material would be used
459 as channel private key. However, this API allows it. */
461 int silc_client_add_channel_private_key(SilcClient client,
462 SilcClientConnection conn,
463 SilcChannelEntry channel,
469 SilcChannelPrivateKey entry;
470 unsigned char hash[32];
471 SilcSKEKeyMaterial *keymat;
473 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
477 cipher = SILC_DEFAULT_CIPHER;
479 hmac = SILC_DEFAULT_HMAC;
481 if (!silc_cipher_is_supported(cipher))
484 if (!silc_hmac_is_supported(hmac))
487 /* Produce the key material */
488 keymat = silc_calloc(1, sizeof(*keymat));
489 if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
490 client->internal->md5hash, keymat)
491 != SILC_SKE_STATUS_OK)
494 /* Remove the current key, if it exists. */
495 if (channel->channel_key) {
496 silc_cipher_free(channel->channel_key);
497 memset(channel->key, 0, channel->key_len / 8);
498 silc_free(channel->key);
499 channel->channel_key = NULL;
501 channel->key_len = 0;
504 silc_hmac_free(channel->hmac);
505 channel->hmac = NULL;
508 if (!channel->private_keys)
509 channel->private_keys = silc_dlist_init();
512 entry = silc_calloc(1, sizeof(*entry));
513 entry->key = silc_calloc(keymat->enc_key_len / 8, sizeof(*entry->key));
514 memcpy(entry->key, keymat->send_enc_key, keymat->enc_key_len / 8);
515 entry->key_len = keymat->enc_key_len / 8;
517 /* Allocate the cipher and set the key*/
518 silc_cipher_alloc(cipher, &entry->cipher);
519 silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
521 /* Generate HMAC key from the channel key data and set it */
522 silc_hmac_alloc(hmac, NULL, &entry->hmac);
523 silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key,
524 entry->key_len, hash);
525 silc_hmac_set_key(entry->hmac, hash,
526 silc_hash_len(silc_hmac_get_hash(entry->hmac)));
527 memset(hash, 0, sizeof(hash));
529 /* Add to the private keys list */
530 silc_dlist_add(channel->private_keys, entry);
532 if (!channel->curr_key)
533 channel->curr_key = entry;
535 /* Free the key material */
536 silc_ske_free_key_material(keymat);
541 /* Removes all private keys from the `channel'. The old channel key is used
542 after calling this to protect the channel messages. Returns FALSE on
543 on error, TRUE otherwise. */
545 int silc_client_del_channel_private_keys(SilcClient client,
546 SilcClientConnection conn,
547 SilcChannelEntry channel)
549 SilcChannelPrivateKey entry;
551 if (!channel->private_keys)
554 silc_dlist_start(channel->private_keys);
555 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
556 silc_dlist_del(channel->private_keys, entry);
557 memset(entry->key, 0, entry->key_len);
558 silc_free(entry->key);
559 silc_cipher_free(entry->cipher);
560 silc_hmac_free(entry->hmac);
564 channel->curr_key = NULL;
566 silc_dlist_uninit(channel->private_keys);
567 channel->private_keys = NULL;
572 /* Removes and frees private key `key' from the channel `channel'. The `key'
573 is retrieved by calling the function silc_client_list_channel_private_keys.
574 The key is not used after this. If the key was last private key then the
575 old channel key is used hereafter to protect the channel messages. This
576 returns FALSE on error, TRUE otherwise. */
578 int silc_client_del_channel_private_key(SilcClient client,
579 SilcClientConnection conn,
580 SilcChannelEntry channel,
581 SilcChannelPrivateKey key)
583 SilcChannelPrivateKey entry;
585 if (!channel->private_keys)
588 silc_dlist_start(channel->private_keys);
589 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
591 if (channel->curr_key == entry)
592 channel->curr_key = NULL;
594 silc_dlist_del(channel->private_keys, entry);
595 memset(entry->key, 0, entry->key_len);
596 silc_free(entry->key);
597 silc_cipher_free(entry->cipher);
598 silc_hmac_free(entry->hmac);
601 if (silc_dlist_count(channel->private_keys) == 0) {
602 silc_dlist_uninit(channel->private_keys);
603 channel->private_keys = NULL;
613 /* Returns array (pointers) of private keys associated to the `channel'.
614 The caller must free the array by calling the function
615 silc_client_free_channel_private_keys. The pointers in the array may be
616 used to delete the specific key by giving the pointer as argument to the
617 function silc_client_del_channel_private_key. */
619 SilcChannelPrivateKey *
620 silc_client_list_channel_private_keys(SilcClient client,
621 SilcClientConnection conn,
622 SilcChannelEntry channel,
625 SilcChannelPrivateKey *keys = NULL, entry;
628 if (!channel->private_keys)
631 silc_dlist_start(channel->private_keys);
632 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
633 keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
644 /* Frees the SilcChannelPrivateKey array. */
646 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
652 /* Returns the SilcChannelUser entry if the `client_entry' is joined on the
653 channel indicated by the `channel'. NULL if client is not joined on
656 SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
657 SilcClientEntry client_entry)
661 if (silc_hash_table_find(channel->user_list, client_entry, NULL,