updates.
[silc.git] / lib / silcclient / client_channel.c
1 /*
2
3   client_channel.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 Pekka Riikonen
8
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.
13   
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.
18
19 */
20 /* $Id$ */
21 /* This file includes channel message sending and receiving routines,
22    channel key receiving and setting, and channel private key handling 
23    routines. */
24
25 #include "clientlibincludes.h"
26 #include "client_internal.h"
27
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. */
34
35 void silc_client_send_channel_message(SilcClient client, 
36                                       SilcClientConnection conn,
37                                       SilcChannelEntry channel,
38                                       SilcChannelPrivateKey key,
39                                       unsigned char *data, 
40                                       unsigned int data_len, 
41                                       int force_send)
42 {
43   int i;
44   SilcSocketConnection sock = conn->sock;
45   SilcBuffer payload;
46   SilcPacketContext packetdata;
47   SilcCipher cipher;
48   SilcHmac hmac;
49   unsigned char *id_string;
50   unsigned int iv_len;
51
52   SILC_LOG_DEBUG(("Sending packet to channel"));
53
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");
58     return;
59   }
60
61   /* Take the key to be used */
62   if (key) {
63     /* Use key application specified */
64     cipher = key->cipher;
65     hmac = key->hmac;
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);
75     cipher = key->cipher;
76     hmac = key->hmac;
77
78     /* Use this key as current private key */
79     channel->curr_key = key;
80   } else {
81     /* Use normal channel key generated by the server */
82     cipher = channel->channel_key;
83     hmac = channel->hmac;
84   }
85
86   /* Generate IV */
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);
91   else
92     silc_hash_make(client->md5hash, channel->iv, iv_len, channel->iv);
93
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,
97                                         client->rng);
98
99   /* Get data used in packet header encryption, keys and stuff. */
100   cipher = conn->send_key;
101   hmac = conn->hmac;
102   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
103
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));
120
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,
126                            packetdata.padlen,
127                            payload->len);
128
129   packetdata.buffer = sock->outbuf;
130
131   /* Put the channel message payload to the outgoing data buffer */
132   silc_buffer_put(sock->outbuf, payload->data, payload->len);
133
134   /* Create the outgoing packet */
135   silc_packet_assemble(&packetdata);
136
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 +
141                       packetdata.padlen);
142
143   SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
144                    sock->outbuf->data, sock->outbuf->len);
145
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);
150 }
151
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. */
155
156 void silc_client_channel_message(SilcClient client, 
157                                  SilcSocketConnection sock, 
158                                  SilcPacketContext *packet)
159 {
160   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
161   SilcBuffer buffer = packet->buffer;
162   SilcChannelPayload payload = NULL;
163   SilcChannelID *id = NULL;
164   SilcChannelEntry channel;
165   SilcChannelUser chu;
166   SilcIDCacheEntry id_cache = NULL;
167   SilcClientID *client_id = NULL;
168   int found = FALSE;
169   unsigned char *message;
170
171   SILC_LOG_DEBUG(("Start"));
172
173   /* Sanity checks */
174   if (packet->dst_id_type != SILC_ID_CHANNEL)
175     goto out;
176
177   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
178                              SILC_ID_CLIENT);
179   if (!client_id)
180     goto out;
181   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
182   if (!id)
183     goto out;
184
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))
188     goto out;
189
190   channel = (SilcChannelEntry)id_cache->context;
191
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,
198                                          channel->hmac);
199     if (!payload)
200       goto out;
201   } else {
202     SilcChannelPrivateKey entry;
203
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,
208                                            entry->hmac);
209       if (payload)
210         break;
211     }
212     if (entry == SILC_LIST_END)
213       goto out;
214   }
215
216   message = silc_channel_get_data(payload, NULL);
217
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)) {
222       found = TRUE;
223       break;
224     }
225   }
226
227   /* Pass the message to application */
228   client->ops->channel_message(client, conn, found ? chu->client : NULL,
229                                channel, message);
230
231  out:
232   if (id)
233     silc_free(id);
234   if (client_id)
235     silc_free(client_id);
236   if (payload)
237     silc_channel_payload_free(payload);
238 }
239
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 
242    reply. */
243
244 void silc_client_save_channel_key(SilcClientConnection conn,
245                                   SilcBuffer key_payload, 
246                                   SilcChannelEntry channel)
247 {
248   unsigned char *id_string, *key, *cipher, hash[32];
249   unsigned int tmp_len;
250   SilcChannelID *id;
251   SilcIDCacheEntry id_cache = NULL;
252   SilcChannelKeyPayload payload;
253
254   payload = silc_channel_key_payload_parse(key_payload);
255   if (!payload)
256     return;
257
258   id_string = silc_channel_key_get_id(payload, &tmp_len);
259   if (!id_string) {
260     silc_channel_key_payload_free(payload);
261     return;
262   }
263
264   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
265   if (!id) {
266     silc_channel_key_payload_free(payload);
267     return;
268   }
269
270   /* Find channel. */
271   if (!channel) {
272     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
273                                      SILC_ID_CHANNEL, &id_cache))
274       goto out;
275     
276     /* Get channel entry */
277     channel = (SilcChannelEntry)id_cache->context;
278   }
279
280   /* Save the key */
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);
286
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);
290     goto out;
291   }
292
293   /* Set the cipher key */
294   silc_cipher_set_key(channel->channel_key, key, channel->key_len);
295
296   /* Generate HMAC key from the channel key data and set it */
297   if (!channel->hmac)
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));
302
303   /* Client is now joined to the channel */
304   channel->on_channel = TRUE;
305
306  out:
307   silc_free(id);
308   silc_channel_key_payload_free(payload);
309 }
310
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. */
316
317 void silc_client_receive_channel_key(SilcClient client,
318                                      SilcSocketConnection sock,
319                                      SilcBuffer packet)
320 {
321   SILC_LOG_DEBUG(("Received key for channel"));
322
323   /* Save the key */
324   silc_client_save_channel_key(sock->user_data, packet, NULL);
325 }
326
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.
334
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).
337
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. 
346
347    NOTE: that this is entirely local setting. The key set using this function
348    is not sent to the network at any phase.
349
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. */
355
356 int silc_client_add_channel_private_key(SilcClient client,
357                                         SilcClientConnection conn,
358                                         SilcChannelEntry channel,
359                                         char *cipher,
360                                         char *hmac,
361                                         unsigned char *key,
362                                         unsigned int key_len)
363 {
364   SilcChannelPrivateKey entry;
365   unsigned char hash[32];
366
367   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
368     return FALSE;
369
370   if (!cipher)
371     cipher = "aes-256-cbc";
372   if (!hmac)
373     hmac = "hmac-sha1-96";
374
375   if (!silc_cipher_is_supported(cipher))
376     return FALSE;
377
378   if (!silc_hmac_is_supported(hmac))
379     return FALSE;
380
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;
387     channel->key = NULL;
388     channel->key_len = 0;
389   }
390   if (channel->hmac)
391     silc_hmac_free(channel->hmac);
392
393   if (!channel->private_keys)
394     channel->private_keys = silc_dlist_init();
395
396   /* Save the key */
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;
401
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);
405
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));
411
412   /* Add to the private keys list */
413   silc_dlist_add(channel->private_keys, entry);
414
415   if (!channel->curr_key)
416     channel->curr_key = entry;
417
418   return TRUE;
419 }
420
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. */
424
425 int silc_client_del_channel_private_keys(SilcClient client,
426                                          SilcClientConnection conn,
427                                          SilcChannelEntry channel)
428 {
429   SilcChannelPrivateKey entry;
430
431   if (!channel->private_keys)
432     return FALSE;
433
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);
441     silc_free(entry);
442   }
443
444   channel->curr_key = NULL;
445
446   silc_dlist_uninit(channel->private_keys);
447   channel->private_keys = NULL;
448
449   return TRUE;
450 }
451
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. */
457
458 int silc_client_del_channel_private_key(SilcClient client,
459                                         SilcClientConnection conn,
460                                         SilcChannelEntry channel,
461                                         SilcChannelPrivateKey key)
462 {
463   SilcChannelPrivateKey entry;
464
465   if (!channel->private_keys)
466     return FALSE;
467
468   silc_dlist_start(channel->private_keys);
469   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
470     if (entry == key) {
471       if (channel->curr_key == entry)
472         channel->curr_key = NULL;
473
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);
479       silc_free(entry);
480
481       if (silc_dlist_count(channel->private_keys) == 0) {
482         silc_dlist_uninit(channel->private_keys);
483         channel->private_keys = NULL;
484       }
485
486       return TRUE;
487     }
488   }
489
490   return FALSE;
491 }
492
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. */
498
499 SilcChannelPrivateKey *
500 silc_client_list_channel_private_keys(SilcClient client,
501                                       SilcClientConnection conn,
502                                       SilcChannelEntry channel,
503                                       unsigned int *key_count)
504 {
505   SilcChannelPrivateKey *keys = NULL, entry;
506   unsigned int count = 0;
507
508   if (!channel->private_keys)
509     return NULL;
510
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));
514     keys[count] = entry;
515     count++;
516   }
517
518   if (key_count)
519     *key_count = count;
520
521   return keys;
522 }
523
524 /* Frees the SilcChannelPrivateKey array. */
525
526 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
527                                            unsigned int key_count)
528 {
529   silc_free(keys);
530 }