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,
40 unsigned int data_len,
44 SilcSocketConnection sock = conn->sock;
46 SilcPacketContext packetdata;
49 unsigned char *id_string;
52 SILC_LOG_DEBUG(("Sending packet to channel"));
54 if (!channel || !channel->hmac ||
55 (!channel->channel_key && !key && !channel->private_keys)) {
56 client->ops->say(client, conn,
57 "Cannot talk to channel: key does not exist");
61 /* Take the key to be used */
62 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
64 /* Use key application specified */
67 } else if (channel->curr_key) {
68 /* Use current private key */
69 cipher = channel->curr_key->cipher;
70 hmac = channel->curr_key->hmac;
71 } else if (!channel->curr_key && channel->private_keys) {
72 /* Use just some private key since we don't know what to use
73 and private keys are set. */
74 silc_dlist_start(channel->private_keys);
75 key = silc_dlist_get(channel->private_keys);
79 /* Use this key as current private key */
80 channel->curr_key = key;
82 /* Use normal channel key generated by the server */
83 cipher = channel->channel_key;
87 /* Use normal channel key generated by the server */
88 cipher = channel->channel_key;
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(0, 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;
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_CLIENT_LEN;
116 packetdata.src_id_type = SILC_ID_CLIENT;
117 packetdata.dst_id = id_string;
118 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
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));
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);
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, sock->outbuf, SILC_PACKET_HEADER_LEN +
145 packetdata.src_id_len + packetdata.dst_id_len +
148 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
149 sock->outbuf->data, sock->outbuf->len);
151 /* Now actually send the packet */
152 silc_client_packet_send_real(client, sock, force_send);
153 silc_buffer_free(payload);
154 silc_free(id_string);
157 /* Process received message to a channel (or from a channel, really). This
158 decrypts the channel message with channel specific key and parses the
159 channel payload. Finally it displays the message on the screen. */
161 void silc_client_channel_message(SilcClient client,
162 SilcSocketConnection sock,
163 SilcPacketContext *packet)
165 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
166 SilcBuffer buffer = packet->buffer;
167 SilcChannelMessagePayload payload = NULL;
168 SilcChannelID *id = NULL;
169 SilcChannelEntry channel;
171 SilcIDCacheEntry id_cache = NULL;
172 SilcClientID *client_id = NULL;
174 unsigned char *message;
176 SILC_LOG_DEBUG(("Start"));
179 if (packet->dst_id_type != SILC_ID_CHANNEL)
182 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
186 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
190 /* Find the channel entry from channels on this connection */
191 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
192 SILC_ID_CHANNEL, &id_cache))
195 channel = (SilcChannelEntry)id_cache->context;
197 /* If there is no channel private key then just decrypt the message
198 with the channel key. If private keys are set then just go through
199 all private keys and check what decrypts correctly. */
200 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
201 /* Parse the channel message payload. This also decrypts the payload */
202 payload = silc_channel_message_payload_parse(buffer, channel->channel_key,
206 } else if (channel->private_keys) {
207 SilcChannelPrivateKey entry;
209 silc_dlist_start(channel->private_keys);
210 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
211 /* Parse the channel message payload. This also decrypts the payload */
212 payload = silc_channel_message_payload_parse(buffer, entry->cipher,
217 if (entry == SILC_LIST_END)
223 message = silc_channel_message_get_data(payload, NULL);
225 /* Find client entry */
226 silc_list_start(channel->clients);
227 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
228 if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
234 /* Pass the message to application */
235 client->ops->channel_message(client, conn, found ? chu->client : NULL,
242 silc_free(client_id);
244 silc_channel_message_payload_free(payload);
247 /* Saves channel key from encoded `key_payload'. This is used when we
248 receive Channel Key Payload and when we are processing JOIN command
251 void silc_client_save_channel_key(SilcClientConnection conn,
252 SilcBuffer key_payload,
253 SilcChannelEntry channel)
255 unsigned char *id_string, *key, *cipher, hash[32];
256 unsigned int tmp_len;
258 SilcIDCacheEntry id_cache = NULL;
259 SilcChannelKeyPayload payload;
261 payload = silc_channel_key_payload_parse(key_payload);
265 id_string = silc_channel_key_get_id(payload, &tmp_len);
267 silc_channel_key_payload_free(payload);
271 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
273 silc_channel_key_payload_free(payload);
279 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
280 SILC_ID_CHANNEL, &id_cache))
283 /* Get channel entry */
284 channel = (SilcChannelEntry)id_cache->context;
288 key = silc_channel_key_get_key(payload, &tmp_len);
289 cipher = silc_channel_key_get_cipher(payload, NULL);
290 channel->key_len = tmp_len * 8;
291 channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
292 memcpy(channel->key, key, tmp_len);
294 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
295 conn->client->ops->say(conn->client, conn,
296 "Cannot talk to channel: unsupported cipher %s", cipher);
300 /* Set the cipher key */
301 silc_cipher_set_key(channel->channel_key, key, channel->key_len);
303 /* Generate HMAC key from the channel key data and set it */
305 silc_hmac_alloc("hmac-sha1-96", NULL, &channel->hmac);
306 silc_hash_make(channel->hmac->hash, key, tmp_len, hash);
307 silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash));
308 memset(hash, 0, sizeof(hash));
310 /* Client is now joined to the channel */
311 channel->on_channel = TRUE;
315 silc_channel_key_payload_free(payload);
318 /* Processes received key for channel. The received key will be used
319 to protect the traffic on the channel for now on. Client must receive
320 the key to the channel before talking on the channel is possible.
321 This is the key that server has generated, this is not the channel
322 private key, it is entirely local setting. */
324 void silc_client_receive_channel_key(SilcClient client,
325 SilcSocketConnection sock,
328 SILC_LOG_DEBUG(("Received key for channel"));
331 silc_client_save_channel_key(sock->user_data, packet, NULL);
334 /* Adds private key for channel. This may be set only if the channel's mode
335 mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
336 mode is not set. When channel has private key then the messages are
337 encrypted using that key. All clients on the channel must also know the
338 key in order to decrypt the messages. However, it is possible to have
339 several private keys per one channel. In this case only some of the
340 clients on the channel may know the one key and only some the other key.
342 if `cipher' and/or `hmac' is NULL then default values will be used
343 (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
345 The private key for channel is optional. If it is not set then the
346 channel messages are encrypted using the channel key generated by the
347 server. However, setting the private key (or keys) for the channel
348 significantly adds security. If more than one key is set the library
349 will automatically try all keys at the message decryption phase. Note:
350 setting many keys slows down the decryption phase as all keys has to
351 be tried in order to find the correct decryption key. However, setting
352 a few keys does not have big impact to the decryption performace.
354 NOTE: that this is entirely local setting. The key set using this function
355 is not sent to the network at any phase.
357 NOTE: If the key material was originated by the SKE protocol (using
358 silc_client_send_key_agreement) then the `key' MUST be the
359 key->send_enc_key as this is dictated by the SILC protocol. However,
360 currently it is not expected that the SKE key material would be used
361 as channel private key. However, this API allows it. */
363 int silc_client_add_channel_private_key(SilcClient client,
364 SilcClientConnection conn,
365 SilcChannelEntry channel,
369 unsigned int key_len)
371 SilcChannelPrivateKey entry;
372 unsigned char hash[32];
374 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
378 cipher = "aes-256-cbc";
380 hmac = "hmac-sha1-96";
382 if (!silc_cipher_is_supported(cipher))
385 if (!silc_hmac_is_supported(hmac))
388 /* Remove the current key, if it exists. */
389 if (channel->channel_key) {
390 silc_cipher_free(channel->channel_key);
391 memset(channel->key, 0, channel->key_len / 8);
392 silc_free(channel->key);
393 channel->channel_key = NULL;
395 channel->key_len = 0;
398 silc_hmac_free(channel->hmac);
400 if (!channel->private_keys)
401 channel->private_keys = silc_dlist_init();
404 entry = silc_calloc(1, sizeof(*entry));
405 entry->key = silc_calloc(key_len, sizeof(*entry->key));
406 memcpy(entry->key, key, key_len);
407 entry->key_len = key_len;
409 /* Allocate the cipher and set the key*/
410 silc_cipher_alloc(cipher, &entry->cipher);
411 silc_cipher_set_key(entry->cipher, key, key_len * 8);
413 /* Generate HMAC key from the channel key data and set it */
414 silc_hmac_alloc(hmac, NULL, &entry->hmac);
415 silc_hash_make(entry->hmac->hash, key, key_len, hash);
416 silc_hmac_set_key(entry->hmac, hash, silc_hash_len(entry->hmac->hash));
417 memset(hash, 0, sizeof(hash));
419 /* Add to the private keys list */
420 silc_dlist_add(channel->private_keys, entry);
422 if (!channel->curr_key)
423 channel->curr_key = entry;
428 /* Removes all private keys from the `channel'. The old channel key is used
429 after calling this to protect the channel messages. Returns FALSE on
430 on error, TRUE otherwise. */
432 int silc_client_del_channel_private_keys(SilcClient client,
433 SilcClientConnection conn,
434 SilcChannelEntry channel)
436 SilcChannelPrivateKey entry;
438 if (!channel->private_keys)
441 silc_dlist_start(channel->private_keys);
442 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
443 silc_dlist_del(channel->private_keys, entry);
444 memset(entry->key, 0, entry->key_len);
445 silc_free(entry->key);
446 silc_cipher_free(entry->cipher);
447 silc_hmac_free(entry->hmac);
451 channel->curr_key = NULL;
453 silc_dlist_uninit(channel->private_keys);
454 channel->private_keys = NULL;
459 /* Removes and frees private key `key' from the channel `channel'. The `key'
460 is retrieved by calling the function silc_client_list_channel_private_keys.
461 The key is not used after this. If the key was last private key then the
462 old channel key is used hereafter to protect the channel messages. This
463 returns FALSE on error, TRUE otherwise. */
465 int silc_client_del_channel_private_key(SilcClient client,
466 SilcClientConnection conn,
467 SilcChannelEntry channel,
468 SilcChannelPrivateKey key)
470 SilcChannelPrivateKey entry;
472 if (!channel->private_keys)
475 silc_dlist_start(channel->private_keys);
476 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
478 if (channel->curr_key == entry)
479 channel->curr_key = NULL;
481 silc_dlist_del(channel->private_keys, entry);
482 memset(entry->key, 0, entry->key_len);
483 silc_free(entry->key);
484 silc_cipher_free(entry->cipher);
485 silc_hmac_free(entry->hmac);
488 if (silc_dlist_count(channel->private_keys) == 0) {
489 silc_dlist_uninit(channel->private_keys);
490 channel->private_keys = NULL;
500 /* Returns array (pointers) of private keys associated to the `channel'.
501 The caller must free the array by calling the function
502 silc_client_free_channel_private_keys. The pointers in the array may be
503 used to delete the specific key by giving the pointer as argument to the
504 function silc_client_del_channel_private_key. */
506 SilcChannelPrivateKey *
507 silc_client_list_channel_private_keys(SilcClient client,
508 SilcClientConnection conn,
509 SilcChannelEntry channel,
510 unsigned int *key_count)
512 SilcChannelPrivateKey *keys = NULL, entry;
513 unsigned int count = 0;
515 if (!channel->private_keys)
518 silc_dlist_start(channel->private_keys);
519 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
520 keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
531 /* Frees the SilcChannelPrivateKey array. */
533 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
534 unsigned int key_count)