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 */
63 /* Use key application specified */
66 } else if (channel->curr_key) {
67 /* Use current private key */
68 cipher = channel->curr_key->cipher;
69 hmac = channel->curr_key->hmac;
70 } else if (!channel->curr_key && channel->private_keys) {
71 /* Use just some private key since we don't know what to use
72 and private keys are set. */
73 silc_dlist_start(channel->private_keys);
74 key = silc_dlist_get(channel->private_keys);
78 /* Use this key as current private key */
79 channel->curr_key = key;
81 /* Use normal channel key generated by the server */
82 cipher = channel->channel_key;
87 iv_len = silc_cipher_get_block_len(cipher);
88 if (channel->iv[0] == '\0')
89 for (i = 0; i < iv_len; i++) channel->iv[i] =
90 silc_rng_get_byte(client->rng);
92 silc_hash_make(client->md5hash, channel->iv, iv_len, channel->iv);
94 /* Encode the channel payload. This also encrypts the message payload. */
95 payload = silc_channel_payload_encode(data_len, data, iv_len,
96 channel->iv, cipher, hmac,
99 /* Get data used in packet header encryption, keys and stuff. */
100 cipher = conn->send_key;
102 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
104 /* Set the packet context pointers. The destination ID is always
105 the Channel ID of the channel. Server and router will handle the
106 distribution of the packet. */
107 packetdata.flags = 0;
108 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
109 packetdata.src_id = conn->local_id_data;
110 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
111 packetdata.src_id_type = SILC_ID_CLIENT;
112 packetdata.dst_id = id_string;
113 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
114 packetdata.dst_id_type = SILC_ID_CHANNEL;
115 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
116 packetdata.src_id_len + packetdata.dst_id_len;
117 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
118 packetdata.src_id_len +
119 packetdata.dst_id_len));
121 /* Prepare outgoing data buffer for packet sending */
122 silc_packet_send_prepare(sock,
123 SILC_PACKET_HEADER_LEN +
124 packetdata.src_id_len +
125 packetdata.dst_id_len,
129 packetdata.buffer = sock->outbuf;
131 /* Put the channel message payload to the outgoing data buffer */
132 silc_buffer_put(sock->outbuf, payload->data, payload->len);
134 /* Create the outgoing packet */
135 silc_packet_assemble(&packetdata);
137 /* Encrypt the header and padding of the packet. This is encrypted
138 with normal session key shared with our server. */
139 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
140 packetdata.src_id_len + packetdata.dst_id_len +
143 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
144 sock->outbuf->data, sock->outbuf->len);
146 /* Now actually send the packet */
147 silc_client_packet_send_real(client, sock, force_send);
148 silc_buffer_free(payload);
149 silc_free(id_string);
152 /* Process received message to a channel (or from a channel, really). This
153 decrypts the channel message with channel specific key and parses the
154 channel payload. Finally it displays the message on the screen. */
156 void silc_client_channel_message(SilcClient client,
157 SilcSocketConnection sock,
158 SilcPacketContext *packet)
160 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
161 SilcBuffer buffer = packet->buffer;
162 SilcChannelPayload payload = NULL;
163 SilcChannelID *id = NULL;
164 SilcChannelEntry channel;
166 SilcIDCacheEntry id_cache = NULL;
167 SilcClientID *client_id = NULL;
169 unsigned char *message;
171 SILC_LOG_DEBUG(("Start"));
174 if (packet->dst_id_type != SILC_ID_CHANNEL)
177 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
181 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
185 /* Find the channel entry from channels on this connection */
186 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
187 SILC_ID_CHANNEL, &id_cache))
190 channel = (SilcChannelEntry)id_cache->context;
192 /* If there is no channel private key then just decrypt the message
193 with the channel key. If private keys are set then just go through
194 all private keys and check what decrypts correctly. */
195 if (!channel->private_keys) {
196 /* Parse the channel message payload. This also decrypts the payload */
197 payload = silc_channel_payload_parse(buffer, channel->channel_key,
202 SilcChannelPrivateKey entry;
204 silc_dlist_start(channel->private_keys);
205 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
206 /* Parse the channel message payload. This also decrypts the payload */
207 payload = silc_channel_payload_parse(buffer, entry->cipher,
212 if (entry == SILC_LIST_END)
216 message = silc_channel_get_data(payload, NULL);
218 /* Find client entry */
219 silc_list_start(channel->clients);
220 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
221 if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
227 /* Pass the message to application */
228 client->ops->channel_message(client, conn, found ? chu->client : NULL,
235 silc_free(client_id);
237 silc_channel_payload_free(payload);
240 /* Saves channel key from encoded `key_payload'. This is used when we
241 receive Channel Key Payload and when we are processing JOIN command
244 void silc_client_save_channel_key(SilcClientConnection conn,
245 SilcBuffer key_payload,
246 SilcChannelEntry channel)
248 unsigned char *id_string, *key, *cipher, hash[32];
249 unsigned int tmp_len;
251 SilcIDCacheEntry id_cache = NULL;
252 SilcChannelKeyPayload payload;
254 payload = silc_channel_key_payload_parse(key_payload);
258 id_string = silc_channel_key_get_id(payload, &tmp_len);
260 silc_channel_key_payload_free(payload);
264 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
266 silc_channel_key_payload_free(payload);
272 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
273 SILC_ID_CHANNEL, &id_cache))
276 /* Get channel entry */
277 channel = (SilcChannelEntry)id_cache->context;
281 key = silc_channel_key_get_key(payload, &tmp_len);
282 cipher = silc_channel_key_get_cipher(payload, NULL);
283 channel->key_len = tmp_len * 8;
284 channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
285 memcpy(channel->key, key, tmp_len);
287 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
288 conn->client->ops->say(conn->client, conn,
289 "Cannot talk to channel: unsupported cipher %s", cipher);
293 /* Set the cipher key */
294 silc_cipher_set_key(channel->channel_key, key, channel->key_len);
296 /* Generate HMAC key from the channel key data and set it */
298 silc_hmac_alloc("hmac-sha1-96", NULL, &channel->hmac);
299 silc_hash_make(channel->hmac->hash, key, tmp_len, hash);
300 silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash));
301 memset(hash, 0, sizeof(hash));
303 /* Client is now joined to the channel */
304 channel->on_channel = TRUE;
308 silc_channel_key_payload_free(payload);
311 /* Processes received key for channel. The received key will be used
312 to protect the traffic on the channel for now on. Client must receive
313 the key to the channel before talking on the channel is possible.
314 This is the key that server has generated, this is not the channel
315 private key, it is entirely local setting. */
317 void silc_client_receive_channel_key(SilcClient client,
318 SilcSocketConnection sock,
321 SILC_LOG_DEBUG(("Received key for channel"));
324 silc_client_save_channel_key(sock->user_data, packet, NULL);
327 /* Adds private key for channel. This may be set only if the channel's mode
328 mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
329 mode is not set. When channel has private key then the messages are
330 encrypted using that key. All clients on the channel must also know the
331 key in order to decrypt the messages. However, it is possible to have
332 several private keys per one channel. In this case only some of the
333 clients on the channel may know the one key and only some the other key.
335 if `cipher' and/or `hmac' is NULL then default values will be used
336 (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
338 The private key for channel is optional. If it is not set then the
339 channel messages are encrypted using the channel key generated by the
340 server. However, setting the private key (or keys) for the channel
341 significantly adds security. If more than one key is set the library
342 will automatically try all keys at the message decryption phase. Note:
343 setting many keys slows down the decryption phase as all keys has to
344 be tried in order to find the correct decryption key. However, setting
345 a few keys does not have big impact to the decryption performace.
347 NOTE: that this is entirely local setting. The key set using this function
348 is not sent to the network at any phase.
350 NOTE: If the key material was originated by the SKE protocol (using
351 silc_client_send_key_agreement) then the `key' MUST be the
352 key->send_enc_key as this is dictated by the SILC protocol. However,
353 currently it is not expected that the SKE key material would be used
354 as channel private key. However, this API allows it. */
356 int silc_client_add_channel_private_key(SilcClient client,
357 SilcClientConnection conn,
358 SilcChannelEntry channel,
362 unsigned int key_len)
364 SilcChannelPrivateKey entry;
365 unsigned char hash[32];
367 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
371 cipher = "aes-256-cbc";
373 hmac = "hmac-sha1-96";
375 if (!silc_cipher_is_supported(cipher))
378 if (!silc_hmac_is_supported(hmac))
381 /* Remove the current key, if it exists. */
382 if (channel->channel_key) {
383 silc_cipher_free(channel->channel_key);
384 memset(channel->key, 0, channel->key_len / 8);
385 silc_free(channel->key);
386 channel->channel_key = NULL;
388 channel->key_len = 0;
391 silc_hmac_free(channel->hmac);
393 if (!channel->private_keys)
394 channel->private_keys = silc_dlist_init();
397 entry = silc_calloc(1, sizeof(*entry));
398 entry->key = silc_calloc(key_len, sizeof(*entry->key));
399 memcpy(entry->key, key, key_len);
400 entry->key_len = key_len;
402 /* Allocate the cipher and set the key*/
403 silc_cipher_alloc(cipher, &entry->cipher);
404 silc_cipher_set_key(entry->cipher, key, key_len * 8);
406 /* Generate HMAC key from the channel key data and set it */
407 silc_hmac_alloc(hmac, NULL, &entry->hmac);
408 silc_hash_make(entry->hmac->hash, key, key_len, hash);
409 silc_hmac_set_key(entry->hmac, hash, silc_hash_len(entry->hmac->hash));
410 memset(hash, 0, sizeof(hash));
412 /* Add to the private keys list */
413 silc_dlist_add(channel->private_keys, entry);
415 if (!channel->curr_key)
416 channel->curr_key = entry;
421 /* Removes all private keys from the `channel'. The old channel key is used
422 after calling this to protect the channel messages. Returns FALSE on
423 on error, TRUE otherwise. */
425 int silc_client_del_channel_private_keys(SilcClient client,
426 SilcClientConnection conn,
427 SilcChannelEntry channel)
429 SilcChannelPrivateKey entry;
431 if (!channel->private_keys)
434 silc_dlist_start(channel->private_keys);
435 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
436 silc_dlist_del(channel->private_keys, entry);
437 memset(entry->key, 0, entry->key_len);
438 silc_free(entry->key);
439 silc_cipher_free(entry->cipher);
440 silc_hmac_free(entry->hmac);
444 channel->curr_key = NULL;
446 silc_dlist_uninit(channel->private_keys);
447 channel->private_keys = NULL;
452 /* Removes and frees private key `key' from the channel `channel'. The `key'
453 is retrieved by calling the function silc_client_list_channel_private_keys.
454 The key is not used after this. If the key was last private key then the
455 old channel key is used hereafter to protect the channel messages. This
456 returns FALSE on error, TRUE otherwise. */
458 int silc_client_del_channel_private_key(SilcClient client,
459 SilcClientConnection conn,
460 SilcChannelEntry channel,
461 SilcChannelPrivateKey key)
463 SilcChannelPrivateKey entry;
465 if (!channel->private_keys)
468 silc_dlist_start(channel->private_keys);
469 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
471 if (channel->curr_key == entry)
472 channel->curr_key = NULL;
474 silc_dlist_del(channel->private_keys, entry);
475 memset(entry->key, 0, entry->key_len);
476 silc_free(entry->key);
477 silc_cipher_free(entry->cipher);
478 silc_hmac_free(entry->hmac);
481 if (silc_dlist_count(channel->private_keys) == 0) {
482 silc_dlist_uninit(channel->private_keys);
483 channel->private_keys = NULL;
493 /* Returns array (pointers) of private keys associated to the `channel'.
494 The caller must free the array by calling the function
495 silc_client_free_channel_private_keys. The pointers in the array may be
496 used to delete the specific key by giving the pointer as argument to the
497 function silc_client_del_channel_private_key. */
499 SilcChannelPrivateKey *
500 silc_client_list_channel_private_keys(SilcClient client,
501 SilcClientConnection conn,
502 SilcChannelEntry channel,
503 unsigned int *key_count)
505 SilcChannelPrivateKey *keys = NULL, entry;
506 unsigned int count = 0;
508 if (!channel->private_keys)
511 silc_dlist_start(channel->private_keys);
512 while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
513 keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
524 /* Frees the SilcChannelPrivateKey array. */
526 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
527 unsigned int key_count)