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                                       SilcMessageFlags flags,
40                                       unsigned char *data, 
41                                       uint32 data_len, 
42                                       int force_send)
43 {
44   int i;
45   SilcSocketConnection sock = conn->sock;
46   SilcBuffer payload;
47   SilcPacketContext packetdata;
48   SilcCipher cipher;
49   SilcHmac hmac;
50   unsigned char *id_string;
51   uint32 iv_len;
52
53   SILC_LOG_DEBUG(("Sending packet to channel"));
54
55   /* Take the key to be used */
56   if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
57     if (key) {
58       /* Use key application specified */
59       cipher = key->cipher;
60       hmac = key->hmac;
61     } else if (channel->curr_key) {
62       /* Use current private key */
63       cipher = channel->curr_key->cipher;
64       hmac = channel->curr_key->hmac;
65     } else if (!channel->curr_key && channel->private_keys) {
66       /* Use just some private key since we don't know what to use 
67          and private keys are set. */
68       silc_dlist_start(channel->private_keys);
69       key = silc_dlist_get(channel->private_keys);
70       cipher = key->cipher;
71       hmac = key->hmac;
72       
73       /* Use this key as current private key */
74       channel->curr_key = key;
75     } else {
76       /* Use normal channel key generated by the server */
77       cipher = channel->channel_key;
78       hmac = channel->hmac;
79     }
80   } else {
81     /* Use normal channel key generated by the server */
82     cipher = channel->channel_key;
83     hmac = channel->hmac;
84   }
85
86   if (!cipher || !hmac)
87     return;
88
89   /* Generate IV */
90   iv_len = silc_cipher_get_block_len(cipher);
91   if (channel->iv[0] == '\0')
92     for (i = 0; i < iv_len; i++) channel->iv[i] = 
93                                    silc_rng_get_byte(client->rng);
94   else
95     silc_hash_make(client->md5hash, channel->iv, iv_len, channel->iv);
96
97   /* Encode the channel payload. This also encrypts the message payload. */
98   payload = silc_channel_message_payload_encode(flags, data_len, data, iv_len, 
99                                                 channel->iv, cipher, hmac);
100
101   /* Get data used in packet header encryption, keys and stuff. */
102   cipher = conn->send_key;
103   hmac = conn->hmac_send;
104   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
105
106   /* Set the packet context pointers. The destination ID is always
107      the Channel ID of the channel. Server and router will handle the
108      distribution of the packet. */
109   packetdata.flags = 0;
110   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
111   packetdata.src_id = conn->local_id_data;
112   packetdata.src_id_len = silc_id_get_len(conn->local_id, SILC_ID_CLIENT);
113   packetdata.src_id_type = SILC_ID_CLIENT;
114   packetdata.dst_id = id_string;
115   packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
116   packetdata.dst_id_type = SILC_ID_CHANNEL;
117   packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN + 
118     packetdata.src_id_len + packetdata.dst_id_len;
119   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
120                                           packetdata.src_id_len +
121                                           packetdata.dst_id_len));
122
123   /* Prepare outgoing data buffer for packet sending */
124   silc_packet_send_prepare(sock, 
125                            SILC_PACKET_HEADER_LEN +
126                            packetdata.src_id_len + 
127                            packetdata.dst_id_len,
128                            packetdata.padlen,
129                            payload->len);
130
131   packetdata.buffer = sock->outbuf;
132
133   /* Put the channel message payload to the outgoing data buffer */
134   silc_buffer_put(sock->outbuf, payload->data, payload->len);
135
136   /* Create the outgoing packet */
137   silc_packet_assemble(&packetdata);
138
139   /* Encrypt the header and padding of the packet. This is encrypted 
140      with normal session key shared with our server. */
141   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
142                       packetdata.src_id_len + packetdata.dst_id_len +
143                       packetdata.padlen);
144
145   SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
146                    sock->outbuf->data, sock->outbuf->len);
147
148   /* Now actually send the packet */
149   silc_client_packet_send_real(client, sock, force_send, FALSE);
150   silc_buffer_free(payload);
151   silc_free(id_string);
152 }
153
154 /* Process received message to a channel (or from a channel, really). This
155    decrypts the channel message with channel specific key and parses the
156    channel payload. Finally it displays the message on the screen. */
157
158 void silc_client_channel_message(SilcClient client, 
159                                  SilcSocketConnection sock, 
160                                  SilcPacketContext *packet)
161 {
162   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
163   SilcBuffer buffer = packet->buffer;
164   SilcChannelMessagePayload payload = NULL;
165   SilcChannelID *id = NULL;
166   SilcChannelEntry channel;
167   SilcChannelUser chu;
168   SilcIDCacheEntry id_cache = NULL;
169   SilcClientID *client_id = NULL;
170   int found = FALSE;
171   unsigned char *message;
172
173   SILC_LOG_DEBUG(("Start"));
174
175   /* Sanity checks */
176   if (packet->dst_id_type != SILC_ID_CHANNEL)
177     goto out;
178
179   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
180                              SILC_ID_CLIENT);
181   if (!client_id)
182     goto out;
183   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
184   if (!id)
185     goto out;
186
187   /* Find the channel entry from channels on this connection */
188   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
189                                    SILC_ID_CHANNEL, &id_cache))
190     goto out;
191
192   channel = (SilcChannelEntry)id_cache->context;
193
194   /* If there is no channel private key then just decrypt the message 
195      with the channel key. If private keys are set then just go through
196      all private keys and check what decrypts correctly. */
197   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
198     /* Parse the channel message payload. This also decrypts the payload */
199     payload = silc_channel_message_payload_parse(buffer, channel->channel_key,
200                                                  channel->hmac);
201     if (!payload)
202       goto out;
203   } else if (channel->private_keys) {
204     SilcChannelPrivateKey entry;
205
206     silc_dlist_start(channel->private_keys);
207     while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
208       /* Parse the channel message payload. This also decrypts the payload */
209       payload = silc_channel_message_payload_parse(buffer, entry->cipher,
210                                                    entry->hmac);
211       if (payload)
212         break;
213     }
214     if (entry == SILC_LIST_END)
215       goto out;
216   } else {
217     goto out;
218   }
219
220   message = silc_channel_message_get_data(payload, NULL);
221
222   /* Find client entry */
223   silc_list_start(channel->clients);
224   while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
225     if (SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
226       found = TRUE;
227       break;
228     }
229   }
230
231   /* Pass the message to application */
232   client->ops->channel_message(client, conn, found ? chu->client : NULL,
233                                channel, 
234                                silc_channel_message_get_flags(payload),
235                                message);
236
237  out:
238   if (id)
239     silc_free(id);
240   if (client_id)
241     silc_free(client_id);
242   if (payload)
243     silc_channel_message_payload_free(payload);
244 }
245
246 /* Saves channel key from encoded `key_payload'. This is used when we
247    receive Channel Key Payload and when we are processing JOIN command 
248    reply. */
249
250 void silc_client_save_channel_key(SilcClientConnection conn,
251                                   SilcBuffer key_payload, 
252                                   SilcChannelEntry channel)
253 {
254   unsigned char *id_string, *key, *cipher, hash[32];
255   uint32 tmp_len;
256   SilcChannelID *id;
257   SilcIDCacheEntry id_cache = NULL;
258   SilcChannelKeyPayload payload;
259
260   payload = silc_channel_key_payload_parse(key_payload);
261   if (!payload)
262     return;
263
264   id_string = silc_channel_key_get_id(payload, &tmp_len);
265   if (!id_string) {
266     silc_channel_key_payload_free(payload);
267     return;
268   }
269
270   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
271   if (!id) {
272     silc_channel_key_payload_free(payload);
273     return;
274   }
275
276   /* Find channel. */
277   if (!channel) {
278     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
279                                      SILC_ID_CHANNEL, &id_cache))
280       goto out;
281     
282     /* Get channel entry */
283     channel = (SilcChannelEntry)id_cache->context;
284   }
285
286   /* Save the key */
287   key = silc_channel_key_get_key(payload, &tmp_len);
288   cipher = silc_channel_key_get_cipher(payload, NULL);
289   channel->key_len = tmp_len * 8;
290   channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
291   memcpy(channel->key, key, tmp_len);
292
293   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
294     conn->client->ops->say(conn->client, conn,
295                      "Cannot talk to channel: unsupported cipher %s", cipher);
296     goto out;
297   }
298
299   /* Set the cipher key */
300   silc_cipher_set_key(channel->channel_key, key, channel->key_len);
301
302   /* Generate HMAC key from the channel key data and set it */
303   if (!channel->hmac)
304     silc_hmac_alloc("hmac-sha1-96", NULL, &channel->hmac);
305   silc_hash_make(channel->hmac->hash, key, tmp_len, hash);
306   silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash));
307   memset(hash, 0, sizeof(hash));
308
309  out:
310   silc_free(id);
311   silc_channel_key_payload_free(payload);
312 }
313
314 /* Processes received key for channel. The received key will be used
315    to protect the traffic on the channel for now on. Client must receive
316    the key to the channel before talking on the channel is possible. 
317    This is the key that server has generated, this is not the channel
318    private key, it is entirely local setting. */
319
320 void silc_client_receive_channel_key(SilcClient client,
321                                      SilcSocketConnection sock,
322                                      SilcBuffer packet)
323 {
324   SILC_LOG_DEBUG(("Received key for channel"));
325
326   /* Save the key */
327   silc_client_save_channel_key(sock->user_data, packet, NULL);
328 }
329
330 /* Adds private key for channel. This may be set only if the channel's mode
331    mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
332    mode is not set. When channel has private key then the messages are
333    encrypted using that key. All clients on the channel must also know the
334    key in order to decrypt the messages. However, it is possible to have
335    several private keys per one channel. In this case only some of the
336    clients on the channel may know the one key and only some the other key.
337
338    If `cipher' and/or `hmac' is NULL then default values will be used 
339    (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
340
341    The private key for channel is optional. If it is not set then the
342    channel messages are encrypted using the channel key generated by the
343    server. However, setting the private key (or keys) for the channel 
344    significantly adds security. If more than one key is set the library
345    will automatically try all keys at the message decryption phase. Note:
346    setting many keys slows down the decryption phase as all keys has to
347    be tried in order to find the correct decryption key. However, setting
348    a few keys does not have big impact to the decryption performace. 
349
350    NOTE: that this is entirely local setting. The key set using this function
351    is not sent to the network at any phase.
352
353    NOTE: If the key material was originated by the SKE protocol (using
354    silc_client_send_key_agreement) then the `key' MUST be the
355    key->send_enc_key as this is dictated by the SILC protocol. However,
356    currently it is not expected that the SKE key material would be used
357    as channel private key. However, this API allows it. */
358
359 int silc_client_add_channel_private_key(SilcClient client,
360                                         SilcClientConnection conn,
361                                         SilcChannelEntry channel,
362                                         char *cipher,
363                                         char *hmac,
364                                         unsigned char *key,
365                                         uint32 key_len)
366 {
367   SilcChannelPrivateKey entry;
368   unsigned char hash[32];
369   SilcSKEKeyMaterial *keymat;
370
371   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
372     return FALSE;
373
374   if (!cipher)
375     cipher = "aes-256-cbc";
376   if (!hmac)
377     hmac = "hmac-sha1-96";
378
379   if (!silc_cipher_is_supported(cipher))
380     return FALSE;
381
382   if (!silc_hmac_is_supported(hmac))
383     return FALSE;
384
385   /* Produce the key material */
386   keymat = silc_calloc(1, sizeof(*keymat));
387   if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16, 
388                                          client->md5hash, keymat) 
389       != SILC_SKE_STATUS_OK)
390     return FALSE;
391
392   /* Remove the current key, if it exists. */
393   if (channel->channel_key) {
394     silc_cipher_free(channel->channel_key);
395     memset(channel->key, 0, channel->key_len / 8);
396     silc_free(channel->key);
397     channel->channel_key = NULL;
398     channel->key = NULL;
399     channel->key_len = 0;
400   }
401   if (channel->hmac) {
402     silc_hmac_free(channel->hmac);
403     channel->hmac = NULL;
404   }
405
406   if (!channel->private_keys)
407     channel->private_keys = silc_dlist_init();
408
409   /* Save the key */
410   entry = silc_calloc(1, sizeof(*entry));
411   entry->key = silc_calloc(keymat->enc_key_len / 8, sizeof(*entry->key));
412   memcpy(entry->key, keymat->send_enc_key, keymat->enc_key_len / 8);
413   entry->key_len = keymat->enc_key_len / 8;
414
415   /* Allocate the cipher and set the key*/
416   silc_cipher_alloc(cipher, &entry->cipher);
417   silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
418
419   /* Generate HMAC key from the channel key data and set it */
420   silc_hmac_alloc(hmac, NULL, &entry->hmac);
421   silc_hash_make(entry->hmac->hash, entry->key, entry->key_len, hash);
422   silc_hmac_set_key(entry->hmac, hash, silc_hash_len(entry->hmac->hash));
423   memset(hash, 0, sizeof(hash));
424
425   /* Add to the private keys list */
426   silc_dlist_add(channel->private_keys, entry);
427
428   if (!channel->curr_key)
429     channel->curr_key = entry;
430
431   /* Free the key material */
432   silc_ske_free_key_material(keymat);
433
434   return TRUE;
435 }
436
437 /* Removes all private keys from the `channel'. The old channel key is used
438    after calling this to protect the channel messages. Returns FALSE on
439    on error, TRUE otherwise. */
440
441 int silc_client_del_channel_private_keys(SilcClient client,
442                                          SilcClientConnection conn,
443                                          SilcChannelEntry channel)
444 {
445   SilcChannelPrivateKey entry;
446
447   if (!channel->private_keys)
448     return FALSE;
449
450   silc_dlist_start(channel->private_keys);
451   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
452     silc_dlist_del(channel->private_keys, entry);
453     memset(entry->key, 0, entry->key_len);
454     silc_free(entry->key);
455     silc_cipher_free(entry->cipher);
456     silc_hmac_free(entry->hmac);
457     silc_free(entry);
458   }
459
460   channel->curr_key = NULL;
461
462   silc_dlist_uninit(channel->private_keys);
463   channel->private_keys = NULL;
464
465   return TRUE;
466 }
467
468 /* Removes and frees private key `key' from the channel `channel'. The `key'
469    is retrieved by calling the function silc_client_list_channel_private_keys.
470    The key is not used after this. If the key was last private key then the
471    old channel key is used hereafter to protect the channel messages. This
472    returns FALSE on error, TRUE otherwise. */
473
474 int silc_client_del_channel_private_key(SilcClient client,
475                                         SilcClientConnection conn,
476                                         SilcChannelEntry channel,
477                                         SilcChannelPrivateKey key)
478 {
479   SilcChannelPrivateKey entry;
480
481   if (!channel->private_keys)
482     return FALSE;
483
484   silc_dlist_start(channel->private_keys);
485   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
486     if (entry == key) {
487       if (channel->curr_key == entry)
488         channel->curr_key = NULL;
489
490       silc_dlist_del(channel->private_keys, entry);
491       memset(entry->key, 0, entry->key_len);
492       silc_free(entry->key);
493       silc_cipher_free(entry->cipher);
494       silc_hmac_free(entry->hmac);
495       silc_free(entry);
496
497       if (silc_dlist_count(channel->private_keys) == 0) {
498         silc_dlist_uninit(channel->private_keys);
499         channel->private_keys = NULL;
500       }
501
502       return TRUE;
503     }
504   }
505
506   return FALSE;
507 }
508
509 /* Returns array (pointers) of private keys associated to the `channel'.
510    The caller must free the array by calling the function
511    silc_client_free_channel_private_keys. The pointers in the array may be
512    used to delete the specific key by giving the pointer as argument to the
513    function silc_client_del_channel_private_key. */
514
515 SilcChannelPrivateKey *
516 silc_client_list_channel_private_keys(SilcClient client,
517                                       SilcClientConnection conn,
518                                       SilcChannelEntry channel,
519                                       uint32 *key_count)
520 {
521   SilcChannelPrivateKey *keys = NULL, entry;
522   uint32 count = 0;
523
524   if (!channel->private_keys)
525     return NULL;
526
527   silc_dlist_start(channel->private_keys);
528   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
529     keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
530     keys[count] = entry;
531     count++;
532   }
533
534   if (key_count)
535     *key_count = count;
536
537   return keys;
538 }
539
540 /* Frees the SilcChannelPrivateKey array. */
541
542 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
543                                            uint32 key_count)
544 {
545   silc_free(keys);
546 }