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 SilcIDCacheEntry id_cache = NULL;
174 SilcChannelEntry channel;
175 unsigned char *message;
177 if (!silc_idcache_find_by_id_one(conn->channel_cache, res->channel_id,
181 channel = (SilcChannelEntry)id_cache->context;
182 message = silc_channel_message_get_data(res->payload, NULL);
184 /* Pass the message to application */
185 client->internal->ops->channel_message(
186 client, conn, clients[0], channel,
187 silc_channel_message_get_flags(res->payload),
192 silc_channel_message_payload_free(res->payload);
193 silc_free(res->channel_id);
197 /* Process received message to a channel (or from a channel, really). This
198 decrypts the channel message with channel specific key and parses the
199 channel payload. Finally it displays the message on the screen. */
201 void silc_client_channel_message(SilcClient client,
202 SilcSocketConnection sock,
203 SilcPacketContext *packet)
205 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
206 SilcBuffer buffer = packet->buffer;
207 SilcChannelMessagePayload payload = NULL;
208 SilcChannelID *id = NULL;
209 SilcChannelEntry channel;
211 SilcIDCacheEntry id_cache = NULL;
212 SilcClientID *client_id = NULL;
214 unsigned char *message;
216 SILC_LOG_DEBUG(("Start"));
219 if (packet->dst_id_type != SILC_ID_CHANNEL)
222 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
226 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
230 /* Find the channel entry from channels on this connection */
231 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id, &id_cache))
234 channel = (SilcChannelEntry)id_cache->context;
236 /* If there is no channel private key then just decrypt the message
237 with the channel key. If private keys are set then just go through
238 all private keys and check what decrypts correctly. */
239 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
240 /* Parse the channel message payload. This also decrypts the payload */
241 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
242 channel->channel_key,
245 /* If decryption failed and we have just performed channel key rekey
246 we will use the old key in decryption. If that fails too then we
247 cannot do more and will drop the packet. */
249 if (!channel->old_channel_key)
252 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
253 channel->old_channel_key,
258 } else if (channel->private_keys) {
259 SilcChannelPrivateKey entry;
261 silc_dlist_start(channel->private_keys);
262 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
263 /* Parse the channel message payload. This also decrypts the payload */
264 payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
270 if (entry == SILC_LIST_END)
276 /* Find client entry */
277 silc_list_start(channel->clients);
278 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
279 if (SILC_ID_CLIENT_COMPARE(chu->client->id, client_id) &&
280 chu->client->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 message = silc_channel_message_get_data(payload, NULL);
301 /* Pass the message to application */
302 client->internal->ops->channel_message(
303 client, conn, chu->client, channel,
304 silc_channel_message_get_flags(payload),
311 silc_free(client_id);
313 silc_channel_message_payload_free(payload);
316 /* Timeout callback that is called after a short period of time after the
317 new channel key has been created. This removes the old channel key all
320 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
322 SilcChannelEntry channel = (SilcChannelEntry)context;
324 if (channel->old_channel_key)
325 silc_cipher_free(channel->old_channel_key);
326 if (channel->old_hmac)
327 silc_hmac_free(channel->old_hmac);
328 channel->old_channel_key = NULL;
329 channel->old_hmac = NULL;
330 channel->rekey_task = NULL;
333 /* Saves channel key from encoded `key_payload'. This is used when we
334 receive Channel Key Payload and when we are processing JOIN command
337 void silc_client_save_channel_key(SilcClientConnection conn,
338 SilcBuffer key_payload,
339 SilcChannelEntry channel)
341 unsigned char *id_string, *key, *cipher, *hmac, hash[32];
344 SilcIDCacheEntry id_cache = NULL;
345 SilcChannelKeyPayload payload;
347 payload = silc_channel_key_payload_parse(key_payload->data,
352 id_string = silc_channel_key_get_id(payload, &tmp_len);
354 silc_channel_key_payload_free(payload);
358 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
360 silc_channel_key_payload_free(payload);
366 if (!silc_idcache_find_by_id_one(conn->channel_cache,
367 (void *)id, &id_cache))
370 /* Get channel entry */
371 channel = (SilcChannelEntry)id_cache->context;
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(conn->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(conn->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_calloc(tmp_len, sizeof(*channel->key));
401 memcpy(channel->key, key, tmp_len);
403 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
404 conn->client->internal->ops->say(
406 SILC_CLIENT_MESSAGE_AUDIT,
407 "Cannot talk to channel: unsupported cipher %s",
412 /* Set the cipher key */
413 silc_cipher_set_key(channel->channel_key, key, channel->key_len);
415 /* Generate HMAC key from the channel key data and set it */
416 silc_hmac_alloc(hmac, NULL, &channel->hmac);
417 silc_hash_make(silc_hmac_get_hash(channel->hmac), key, tmp_len, hash);
418 silc_hmac_set_key(channel->hmac, hash,
419 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
420 memset(hash, 0, sizeof(hash));
424 silc_channel_key_payload_free(payload);
427 /* Processes received key for channel. The received key will be used
428 to protect the traffic on the channel for now on. Client must receive
429 the key to the channel before talking on the channel is possible.
430 This is the key that server has generated, this is not the channel
431 private key, it is entirely local setting. */
433 void silc_client_receive_channel_key(SilcClient client,
434 SilcSocketConnection sock,
437 SILC_LOG_DEBUG(("Received key for channel"));
440 silc_client_save_channel_key(sock->user_data, packet, NULL);
443 /* Adds private key for channel. This may be set only if the channel's mode
444 mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
445 mode is not set. When channel has private key then the messages are
446 encrypted using that key. All clients on the channel must also know the
447 key in order to decrypt the messages. However, it is possible to have
448 several private keys per one channel. In this case only some of the
449 clients on the channel may know the one key and only some the other key.
451 If `cipher' and/or `hmac' is NULL then default values will be used
452 (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
454 The private key for channel is optional. If it is not set then the
455 channel messages are encrypted using the channel key generated by the
456 server. However, setting the private key (or keys) for the channel
457 significantly adds security. If more than one key is set the library
458 will automatically try all keys at the message decryption phase. Note:
459 setting many keys slows down the decryption phase as all keys has to
460 be tried in order to find the correct decryption key. However, setting
461 a few keys does not have big impact to the decryption performace.
463 NOTE: that this is entirely local setting. The key set using this function
464 is not sent to the network at any phase.
466 NOTE: If the key material was originated by the SKE protocol (using
467 silc_client_send_key_agreement) then the `key' MUST be the
468 key->send_enc_key as this is dictated by the SILC protocol. However,
469 currently it is not expected that the SKE key material would be used
470 as channel private key. However, this API allows it. */
472 int silc_client_add_channel_private_key(SilcClient client,
473 SilcClientConnection conn,
474 SilcChannelEntry channel,
480 SilcChannelPrivateKey entry;
481 unsigned char hash[32];
482 SilcSKEKeyMaterial *keymat;
484 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
488 cipher = SILC_DEFAULT_CIPHER;
490 hmac = SILC_DEFAULT_HMAC;
492 if (!silc_cipher_is_supported(cipher))
495 if (!silc_hmac_is_supported(hmac))
498 /* Produce the key material */
499 keymat = silc_calloc(1, sizeof(*keymat));
500 if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
501 client->internal->md5hash, keymat)
502 != SILC_SKE_STATUS_OK)
505 /* Remove the current key, if it exists. */
506 if (channel->channel_key) {
507 silc_cipher_free(channel->channel_key);
508 memset(channel->key, 0, channel->key_len / 8);
509 silc_free(channel->key);
510 channel->channel_key = NULL;
512 channel->key_len = 0;
515 silc_hmac_free(channel->hmac);
516 channel->hmac = NULL;
519 if (!channel->private_keys)
520 channel->private_keys = silc_dlist_init();
523 entry = silc_calloc(1, sizeof(*entry));
524 entry->key = silc_calloc(keymat->enc_key_len / 8, sizeof(*entry->key));
525 memcpy(entry->key, keymat->send_enc_key, keymat->enc_key_len / 8);
526 entry->key_len = keymat->enc_key_len / 8;
528 /* Allocate the cipher and set the key*/
529 silc_cipher_alloc(cipher, &entry->cipher);
530 silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
532 /* Generate HMAC key from the channel key data and set it */
533 silc_hmac_alloc(hmac, NULL, &entry->hmac);
534 silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key,
535 entry->key_len, hash);
536 silc_hmac_set_key(entry->hmac, hash,
537 silc_hash_len(silc_hmac_get_hash(entry->hmac)));
538 memset(hash, 0, sizeof(hash));
540 /* Add to the private keys list */
541 silc_dlist_add(channel->private_keys, entry);
543 if (!channel->curr_key)
544 channel->curr_key = entry;
546 /* Free the key material */
547 silc_ske_free_key_material(keymat);
552 /* Removes all private keys from the `channel'. The old channel key is used
553 after calling this to protect the channel messages. Returns FALSE on
554 on error, TRUE otherwise. */
556 int silc_client_del_channel_private_keys(SilcClient client,
557 SilcClientConnection conn,
558 SilcChannelEntry channel)
560 SilcChannelPrivateKey entry;
562 if (!channel->private_keys)
565 silc_dlist_start(channel->private_keys);
566 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
567 silc_dlist_del(channel->private_keys, entry);
568 memset(entry->key, 0, entry->key_len);
569 silc_free(entry->key);
570 silc_cipher_free(entry->cipher);
571 silc_hmac_free(entry->hmac);
575 channel->curr_key = NULL;
577 silc_dlist_uninit(channel->private_keys);
578 channel->private_keys = NULL;
583 /* Removes and frees private key `key' from the channel `channel'. The `key'
584 is retrieved by calling the function silc_client_list_channel_private_keys.
585 The key is not used after this. If the key was last private key then the
586 old channel key is used hereafter to protect the channel messages. This
587 returns FALSE on error, TRUE otherwise. */
589 int silc_client_del_channel_private_key(SilcClient client,
590 SilcClientConnection conn,
591 SilcChannelEntry channel,
592 SilcChannelPrivateKey key)
594 SilcChannelPrivateKey entry;
596 if (!channel->private_keys)
599 silc_dlist_start(channel->private_keys);
600 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
602 if (channel->curr_key == entry)
603 channel->curr_key = NULL;
605 silc_dlist_del(channel->private_keys, entry);
606 memset(entry->key, 0, entry->key_len);
607 silc_free(entry->key);
608 silc_cipher_free(entry->cipher);
609 silc_hmac_free(entry->hmac);
612 if (silc_dlist_count(channel->private_keys) == 0) {
613 silc_dlist_uninit(channel->private_keys);
614 channel->private_keys = NULL;
624 /* Returns array (pointers) of private keys associated to the `channel'.
625 The caller must free the array by calling the function
626 silc_client_free_channel_private_keys. The pointers in the array may be
627 used to delete the specific key by giving the pointer as argument to the
628 function silc_client_del_channel_private_key. */
630 SilcChannelPrivateKey *
631 silc_client_list_channel_private_keys(SilcClient client,
632 SilcClientConnection conn,
633 SilcChannelEntry channel,
636 SilcChannelPrivateKey *keys = NULL, entry;
639 if (!channel->private_keys)
642 silc_dlist_start(channel->private_keys);
643 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
644 keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
655 /* Frees the SilcChannelPrivateKey array. */
657 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,