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->md5hash, channel->iv, iv_len, channel->iv);
100 /* Encode the channel payload. This also encrypts the message payload. */
101 payload = silc_channel_message_payload_encode(flags, data_len, data, iv_len,
102 channel->iv, cipher, hmac);
104 /* Get data used in packet header encryption, keys and stuff. */
105 cipher = conn->send_key;
106 hmac = conn->hmac_send;
107 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
109 /* Set the packet context pointers. The destination ID is always
110 the Channel ID of the channel. Server and router will handle the
111 distribution of the packet. */
112 packetdata.flags = 0;
113 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
114 packetdata.src_id = conn->local_id_data;
115 packetdata.src_id_len = silc_id_get_len(conn->local_id, SILC_ID_CLIENT);
116 packetdata.src_id_type = SILC_ID_CLIENT;
117 packetdata.dst_id = id_string;
118 packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
119 packetdata.dst_id_type = SILC_ID_CHANNEL;
120 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
121 packetdata.src_id_len + packetdata.dst_id_len;
122 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
123 packetdata.src_id_len +
124 packetdata.dst_id_len), block_len);
126 /* Prepare outgoing data buffer for packet sending */
127 silc_packet_send_prepare(sock,
128 SILC_PACKET_HEADER_LEN +
129 packetdata.src_id_len +
130 packetdata.dst_id_len,
134 packetdata.buffer = sock->outbuf;
136 /* Put the channel message payload to the outgoing data buffer */
137 silc_buffer_put(sock->outbuf, payload->data, payload->len);
139 /* Create the outgoing packet */
140 silc_packet_assemble(&packetdata, cipher);
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 sock->outbuf, SILC_PACKET_HEADER_LEN +
146 packetdata.src_id_len + packetdata.dst_id_len +
149 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
150 sock->outbuf->data, sock->outbuf->len);
152 /* Now actually send the packet */
153 silc_client_packet_send_real(client, sock, force_send);
154 silc_buffer_free(payload);
155 silc_free(id_string);
159 SilcChannelMessagePayload payload;
160 SilcChannelID *channel_id;
161 } *SilcChannelClientResolve;
163 static void silc_client_channel_message_cb(SilcClient client,
164 SilcClientConnection conn,
165 SilcClientEntry *clients,
166 uint32 clients_count,
169 SilcChannelClientResolve res = (SilcChannelClientResolve)context;
171 if (clients_count == 1) {
172 SilcIDCacheEntry id_cache = NULL;
173 SilcChannelEntry channel;
174 unsigned char *message;
176 if (!silc_idcache_find_by_id_one(conn->channel_cache, res->channel_id,
180 channel = (SilcChannelEntry)id_cache->context;
181 message = silc_channel_message_get_data(res->payload, NULL);
183 /* Pass the message to application */
184 client->ops->channel_message(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;
209 SilcIDCacheEntry id_cache = NULL;
210 SilcClientID *client_id = NULL;
212 unsigned char *message;
214 SILC_LOG_DEBUG(("Start"));
217 if (packet->dst_id_type != SILC_ID_CHANNEL)
220 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
224 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
228 /* Find the channel entry from channels on this connection */
229 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id, &id_cache))
232 channel = (SilcChannelEntry)id_cache->context;
234 /* If there is no channel private key then just decrypt the message
235 with the channel key. If private keys are set then just go through
236 all private keys and check what decrypts correctly. */
237 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
238 /* Parse the channel message payload. This also decrypts the payload */
239 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
240 channel->channel_key,
243 /* If decryption failed and we have just performed channel key rekey
244 we will use the old key in decryption. If that fails too then we
245 cannot do more and will drop the packet. */
247 if (!channel->old_channel_key)
250 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
251 channel->old_channel_key,
256 } else if (channel->private_keys) {
257 SilcChannelPrivateKey entry;
259 silc_dlist_start(channel->private_keys);
260 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
261 /* Parse the channel message payload. This also decrypts the payload */
262 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
268 if (entry == SILC_LIST_END)
274 /* Find client entry */
275 silc_list_start(channel->clients);
276 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
277 if (SILC_ID_CLIENT_COMPARE(chu->client->id, client_id) &&
278 chu->client->nickname) {
285 /* Resolve the client info */
286 SilcChannelClientResolve res = silc_calloc(1, sizeof(*res));
287 res->payload = payload;
288 res->channel_id = id;
289 silc_client_get_client_by_id_resolve(client, conn, client_id,
290 silc_client_channel_message_cb,
297 message = silc_channel_message_get_data(payload, NULL);
299 /* Pass the message to application */
300 client->ops->channel_message(client, conn, chu->client, channel,
301 silc_channel_message_get_flags(payload),
308 silc_free(client_id);
310 silc_channel_message_payload_free(payload);
313 /* Timeout callback that is called after a short period of time after the
314 new channel key has been created. This removes the old channel key all
317 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
319 SilcChannelEntry channel = (SilcChannelEntry)context;
321 if (channel->old_channel_key)
322 silc_cipher_free(channel->old_channel_key);
323 if (channel->old_hmac)
324 silc_hmac_free(channel->old_hmac);
325 channel->old_channel_key = NULL;
326 channel->old_hmac = NULL;
327 channel->rekey_task = NULL;
330 /* Saves channel key from encoded `key_payload'. This is used when we
331 receive Channel Key Payload and when we are processing JOIN command
334 void silc_client_save_channel_key(SilcClientConnection conn,
335 SilcBuffer key_payload,
336 SilcChannelEntry channel)
338 unsigned char *id_string, *key, *cipher, *hmac, hash[32];
341 SilcIDCacheEntry id_cache = NULL;
342 SilcChannelKeyPayload payload;
344 payload = silc_channel_key_payload_parse(key_payload->data,
349 id_string = silc_channel_key_get_id(payload, &tmp_len);
351 silc_channel_key_payload_free(payload);
355 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
357 silc_channel_key_payload_free(payload);
363 if (!silc_idcache_find_by_id_one(conn->channel_cache,
364 (void *)id, &id_cache))
367 /* Get channel entry */
368 channel = (SilcChannelEntry)id_cache->context;
371 hmac = (channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) :
374 /* Save the old key for a short period of time so that we can decrypt
375 channel message even after the rekey if some client would be sending
376 messages with the old key after the rekey. */
377 if (channel->old_channel_key)
378 silc_cipher_free(channel->old_channel_key);
379 if (channel->old_hmac)
380 silc_hmac_free(channel->old_hmac);
381 if (channel->rekey_task)
382 silc_schedule_task_del(conn->client->schedule, channel->rekey_task);
383 channel->old_channel_key = channel->channel_key;
384 channel->old_hmac = channel->hmac;
385 channel->rekey_task =
386 silc_schedule_task_add(conn->client->schedule, 0,
387 silc_client_save_channel_key_rekey, channel,
388 10, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
390 /* Free the old channel key data */
391 silc_free(channel->key);
394 key = silc_channel_key_get_key(payload, &tmp_len);
395 cipher = silc_channel_key_get_cipher(payload, NULL);
396 channel->key_len = tmp_len * 8;
397 channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
398 memcpy(channel->key, key, tmp_len);
400 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
401 conn->client->ops->say(conn->client, conn, SILC_CLIENT_MESSAGE_AUDIT,
402 "Cannot talk to channel: unsupported cipher %s",
407 /* Set the cipher key */
408 silc_cipher_set_key(channel->channel_key, key, channel->key_len);
410 /* Generate HMAC key from the channel key data and set it */
411 silc_hmac_alloc(hmac, NULL, &channel->hmac);
412 silc_hash_make(silc_hmac_get_hash(channel->hmac), key, tmp_len, hash);
413 silc_hmac_set_key(channel->hmac, hash,
414 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
415 memset(hash, 0, sizeof(hash));
419 silc_channel_key_payload_free(payload);
422 /* Processes received key for channel. The received key will be used
423 to protect the traffic on the channel for now on. Client must receive
424 the key to the channel before talking on the channel is possible.
425 This is the key that server has generated, this is not the channel
426 private key, it is entirely local setting. */
428 void silc_client_receive_channel_key(SilcClient client,
429 SilcSocketConnection sock,
432 SILC_LOG_DEBUG(("Received key for channel"));
435 silc_client_save_channel_key(sock->user_data, packet, NULL);
438 /* Adds private key for channel. This may be set only if the channel's mode
439 mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
440 mode is not set. When channel has private key then the messages are
441 encrypted using that key. All clients on the channel must also know the
442 key in order to decrypt the messages. However, it is possible to have
443 several private keys per one channel. In this case only some of the
444 clients on the channel may know the one key and only some the other key.
446 If `cipher' and/or `hmac' is NULL then default values will be used
447 (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
449 The private key for channel is optional. If it is not set then the
450 channel messages are encrypted using the channel key generated by the
451 server. However, setting the private key (or keys) for the channel
452 significantly adds security. If more than one key is set the library
453 will automatically try all keys at the message decryption phase. Note:
454 setting many keys slows down the decryption phase as all keys has to
455 be tried in order to find the correct decryption key. However, setting
456 a few keys does not have big impact to the decryption performace.
458 NOTE: that this is entirely local setting. The key set using this function
459 is not sent to the network at any phase.
461 NOTE: If the key material was originated by the SKE protocol (using
462 silc_client_send_key_agreement) then the `key' MUST be the
463 key->send_enc_key as this is dictated by the SILC protocol. However,
464 currently it is not expected that the SKE key material would be used
465 as channel private key. However, this API allows it. */
467 int silc_client_add_channel_private_key(SilcClient client,
468 SilcClientConnection conn,
469 SilcChannelEntry channel,
475 SilcChannelPrivateKey entry;
476 unsigned char hash[32];
477 SilcSKEKeyMaterial *keymat;
479 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
483 cipher = SILC_DEFAULT_CIPHER;
485 hmac = SILC_DEFAULT_HMAC;
487 if (!silc_cipher_is_supported(cipher))
490 if (!silc_hmac_is_supported(hmac))
493 /* Produce the key material */
494 keymat = silc_calloc(1, sizeof(*keymat));
495 if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
496 client->md5hash, keymat)
497 != SILC_SKE_STATUS_OK)
500 /* Remove the current key, if it exists. */
501 if (channel->channel_key) {
502 silc_cipher_free(channel->channel_key);
503 memset(channel->key, 0, channel->key_len / 8);
504 silc_free(channel->key);
505 channel->channel_key = NULL;
507 channel->key_len = 0;
510 silc_hmac_free(channel->hmac);
511 channel->hmac = NULL;
514 if (!channel->private_keys)
515 channel->private_keys = silc_dlist_init();
518 entry = silc_calloc(1, sizeof(*entry));
519 entry->key = silc_calloc(keymat->enc_key_len / 8, sizeof(*entry->key));
520 memcpy(entry->key, keymat->send_enc_key, keymat->enc_key_len / 8);
521 entry->key_len = keymat->enc_key_len / 8;
523 /* Allocate the cipher and set the key*/
524 silc_cipher_alloc(cipher, &entry->cipher);
525 silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
527 /* Generate HMAC key from the channel key data and set it */
528 silc_hmac_alloc(hmac, NULL, &entry->hmac);
529 silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key,
530 entry->key_len, hash);
531 silc_hmac_set_key(entry->hmac, hash,
532 silc_hash_len(silc_hmac_get_hash(entry->hmac)));
533 memset(hash, 0, sizeof(hash));
535 /* Add to the private keys list */
536 silc_dlist_add(channel->private_keys, entry);
538 if (!channel->curr_key)
539 channel->curr_key = entry;
541 /* Free the key material */
542 silc_ske_free_key_material(keymat);
547 /* Removes all private keys from the `channel'. The old channel key is used
548 after calling this to protect the channel messages. Returns FALSE on
549 on error, TRUE otherwise. */
551 int silc_client_del_channel_private_keys(SilcClient client,
552 SilcClientConnection conn,
553 SilcChannelEntry channel)
555 SilcChannelPrivateKey entry;
557 if (!channel->private_keys)
560 silc_dlist_start(channel->private_keys);
561 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
562 silc_dlist_del(channel->private_keys, entry);
563 memset(entry->key, 0, entry->key_len);
564 silc_free(entry->key);
565 silc_cipher_free(entry->cipher);
566 silc_hmac_free(entry->hmac);
570 channel->curr_key = NULL;
572 silc_dlist_uninit(channel->private_keys);
573 channel->private_keys = NULL;
578 /* Removes and frees private key `key' from the channel `channel'. The `key'
579 is retrieved by calling the function silc_client_list_channel_private_keys.
580 The key is not used after this. If the key was last private key then the
581 old channel key is used hereafter to protect the channel messages. This
582 returns FALSE on error, TRUE otherwise. */
584 int silc_client_del_channel_private_key(SilcClient client,
585 SilcClientConnection conn,
586 SilcChannelEntry channel,
587 SilcChannelPrivateKey key)
589 SilcChannelPrivateKey entry;
591 if (!channel->private_keys)
594 silc_dlist_start(channel->private_keys);
595 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
597 if (channel->curr_key == entry)
598 channel->curr_key = NULL;
600 silc_dlist_del(channel->private_keys, entry);
601 memset(entry->key, 0, entry->key_len);
602 silc_free(entry->key);
603 silc_cipher_free(entry->cipher);
604 silc_hmac_free(entry->hmac);
607 if (silc_dlist_count(channel->private_keys) == 0) {
608 silc_dlist_uninit(channel->private_keys);
609 channel->private_keys = NULL;
619 /* Returns array (pointers) of private keys associated to the `channel'.
620 The caller must free the array by calling the function
621 silc_client_free_channel_private_keys. The pointers in the array may be
622 used to delete the specific key by giving the pointer as argument to the
623 function silc_client_del_channel_private_key. */
625 SilcChannelPrivateKey *
626 silc_client_list_channel_private_keys(SilcClient client,
627 SilcClientConnection conn,
628 SilcChannelEntry channel,
631 SilcChannelPrivateKey *keys = NULL, entry;
634 if (!channel->private_keys)
637 silc_dlist_start(channel->private_keys);
638 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
639 keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
650 /* Frees the SilcChannelPrivateKey array. */
652 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,