Added some asserts and error checks.
[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 "silcincludes.h"
26 #include "silcclient.h"
27 #include "client_internal.h"
28
29 /* Sends packet to the `channel'. Packet to channel is always encrypted
30    differently from "normal" packets. SILC header of the packet is 
31    encrypted with the next receiver's key and the rest of the packet is
32    encrypted with the channel specific key. Padding and HMAC is computed
33    with the next receiver's key. The `data' is the channel message. If
34    the `force_send' is TRUE then the packet is sent immediately. */
35
36 void silc_client_send_channel_message(SilcClient client, 
37                                       SilcClientConnection conn,
38                                       SilcChannelEntry channel,
39                                       SilcChannelPrivateKey key,
40                                       SilcMessageFlags flags,
41                                       unsigned char *data, 
42                                       SilcUInt32 data_len, 
43                                       int force_send)
44 {
45   int i;
46   SilcSocketConnection sock;
47   SilcBuffer payload;
48   SilcPacketContext packetdata;
49   const SilcBufferStruct packet;
50   SilcCipher cipher;
51   SilcHmac hmac;
52   unsigned char *id_string;
53   SilcUInt32 iv_len;
54   int block_len;
55   SilcChannelUser chu;
56
57   assert(client && conn && channel);
58   sock = conn->sock;
59   SILC_LOG_DEBUG(("Sending packet to channel"));
60
61   chu = silc_client_on_channel(channel, conn->local_entry);
62   if (!chu) {
63     SILC_LOG_ERROR(("Cannot send message to channel we are not joined"));
64     return;
65   }
66
67   /* Check if it is allowed to send messages to this channel by us. */
68   if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS && !chu->mode)
69     return;
70   if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS && 
71       chu->mode & SILC_CHANNEL_UMODE_CHANOP &&
72       !(chu->mode & SILC_CHANNEL_UMODE_CHANFO))
73     return;
74   if (chu->mode & SILC_CHANNEL_UMODE_QUIET)
75     return;
76
77   /* Take the key to be used */
78   if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
79     if (key) {
80       /* Use key application specified */
81       cipher = key->cipher;
82       hmac = key->hmac;
83     } else if (channel->curr_key) {
84       /* Use current private key */
85       cipher = channel->curr_key->cipher;
86       hmac = channel->curr_key->hmac;
87     } else if (!channel->curr_key && channel->private_keys) {
88       /* Use just some private key since we don't know what to use 
89          and private keys are set. */
90       silc_dlist_start(channel->private_keys);
91       key = silc_dlist_get(channel->private_keys);
92       cipher = key->cipher;
93       hmac = key->hmac;
94       
95       /* Use this key as current private key */
96       channel->curr_key = key;
97     } else {
98       /* Use normal channel key generated by the server */
99       cipher = channel->channel_key;
100       hmac = channel->hmac;
101     }
102   } else {
103     /* Use normal channel key generated by the server */
104     cipher = channel->channel_key;
105     hmac = channel->hmac;
106   }
107
108   if (!cipher || !hmac)
109     return;
110
111   block_len = silc_cipher_get_block_len(cipher);
112
113   /* Generate IV */
114   iv_len = silc_cipher_get_block_len(cipher);
115   if (channel->iv[0] == '\0')
116     for (i = 0; i < iv_len; i++) channel->iv[i] = 
117                                    silc_rng_get_byte(client->rng);
118   else
119     silc_hash_make(client->md5hash, channel->iv, iv_len, channel->iv);
120
121   /* Encode the channel payload. This also encrypts the message payload. */
122   payload = silc_channel_message_payload_encode(flags, data_len, data, iv_len, 
123                                                 channel->iv, cipher, hmac,
124                                                 client->rng);
125
126   /* Get data used in packet header encryption, keys and stuff. */
127   cipher = conn->internal->send_key;
128   hmac = conn->internal->hmac_send;
129   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
130
131   /* Set the packet context pointers. The destination ID is always
132      the Channel ID of the channel. Server and router will handle the
133      distribution of the packet. */
134   data = payload->data;
135   data_len = payload->len;
136   packetdata.flags = 0;
137   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
138   packetdata.src_id = conn->local_id_data;
139   packetdata.src_id_len = silc_id_get_len(conn->local_id, SILC_ID_CLIENT);
140   packetdata.src_id_type = SILC_ID_CLIENT;
141   packetdata.dst_id = id_string;
142   packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
143   packetdata.dst_id_type = SILC_ID_CHANNEL;
144   data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
145                                  packetdata.src_id_len +
146                                  packetdata.dst_id_len);
147   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
148     packetdata.src_id_len + packetdata.dst_id_len;
149   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
150                                           packetdata.src_id_len +
151                                           packetdata.dst_id_len), block_len);
152
153   /* Create the outgoing packet */
154   if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
155                             data, data_len, (const SilcBuffer)&packet)) {
156     SILC_LOG_ERROR(("Error assembling packet"));
157     goto out;
158   }
159
160   /* Encrypt the header and padding of the packet. This is encrypted 
161      with normal session key shared with our server. */
162   silc_packet_encrypt(cipher, hmac, conn->internal->psn_send++,
163                       (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN + 
164                       packetdata.src_id_len + packetdata.dst_id_len +
165                       packetdata.padlen);
166
167   SILC_LOG_HEXDUMP(("Packet to channel, len %d", packet.len),
168                     packet.data, packet.len);
169
170   /* Now actually send the packet */
171   silc_client_packet_send_real(client, sock, force_send);
172
173  out:
174   silc_buffer_free(payload);
175   silc_free(id_string);
176 }
177
178 typedef struct {
179   SilcChannelMessagePayload payload;
180   SilcChannelID *channel_id;
181 } *SilcChannelClientResolve;
182
183 static void silc_client_channel_message_cb(SilcClient client,
184                                            SilcClientConnection conn,
185                                            SilcClientEntry *clients,
186                                            SilcUInt32 clients_count,
187                                            void *context)
188 {
189   SilcChannelClientResolve res = (SilcChannelClientResolve)context;
190
191   if (clients_count == 1) {
192     SilcChannelEntry channel;
193     unsigned char *message;
194     SilcUInt32 message_len;
195
196     channel = silc_client_get_channel_by_id(client, conn, res->channel_id);
197     if (!channel)
198       goto out;
199
200     /* If this client is not on channel, add it there since it clearly
201        is there. */
202     if (!silc_client_on_channel(channel, clients[0])) {
203       SilcChannelUser chu = silc_calloc(1, sizeof(*chu));
204       chu->client = clients[0];
205       chu->channel = channel;
206       silc_hash_table_add(channel->user_list, clients[0], chu);
207       silc_hash_table_add(clients[0]->channels, channel, chu);
208     }
209
210     message = silc_channel_message_get_data(res->payload, &message_len);
211     
212     /* Pass the message to application */
213     client->internal->ops->channel_message(
214                                client, conn, clients[0], channel,
215                                silc_channel_message_get_flags(res->payload),
216                                message, message_len);
217   }
218
219  out:
220   silc_channel_message_payload_free(res->payload);
221   silc_free(res->channel_id);
222   silc_free(res);
223 }
224
225 /* Process received message to a channel (or from a channel, really). This
226    decrypts the channel message with channel specific key and parses the
227    channel payload. Finally it displays the message on the screen. */
228
229 void silc_client_channel_message(SilcClient client, 
230                                  SilcSocketConnection sock, 
231                                  SilcPacketContext *packet)
232 {
233   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
234   SilcBuffer buffer = packet->buffer;
235   SilcChannelMessagePayload payload = NULL;
236   SilcChannelID *id = NULL;
237   SilcChannelEntry channel;
238   SilcClientEntry client_entry;
239   SilcClientID *client_id = NULL;
240   unsigned char *message;
241   SilcUInt32 message_len;
242
243   SILC_LOG_DEBUG(("Start"));
244
245   /* Sanity checks */
246   if (packet->dst_id_type != SILC_ID_CHANNEL)
247     goto out;
248
249   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
250                              SILC_ID_CLIENT);
251   if (!client_id)
252     goto out;
253   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
254   if (!id)
255     goto out;
256
257   /* Find the channel entry from channels on this connection */
258   channel = silc_client_get_channel_by_id(client, conn, id);
259   if (!channel)
260     goto out;
261
262   /* If there is no channel private key then just decrypt the message 
263      with the channel key. If private keys are set then just go through
264      all private keys and check what decrypts correctly. */
265   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
266     /* Parse the channel message payload. This also decrypts the payload */
267     payload = silc_channel_message_payload_parse(buffer->data, buffer->len, 
268                                                  channel->channel_key,
269                                                  channel->hmac);
270
271     /* If decryption failed and we have just performed channel key rekey
272        we will use the old key in decryption. If that fails too then we
273        cannot do more and will drop the packet. */
274     if (!payload) {
275       if (!channel->old_channel_key) {
276         goto out;
277       }
278
279       payload = silc_channel_message_payload_parse(buffer->data, buffer->len, 
280                                                    channel->old_channel_key,
281                                                    channel->old_hmac);
282       if (!payload) {
283         goto out;
284       }
285     }
286   } else if (channel->private_keys) {
287     SilcChannelPrivateKey entry;
288
289     silc_dlist_start(channel->private_keys);
290     while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
291       /* Parse the channel message payload. This also decrypts the payload */
292       payload = silc_channel_message_payload_parse(buffer->data, buffer->len, 
293                                                    entry->cipher,
294                                                    entry->hmac);
295       if (payload)
296         break;
297     }
298     if (entry == SILC_LIST_END)
299       goto out;
300   } else {
301     goto out;
302   }
303
304   /* Find client entry */
305   client_entry = silc_client_get_client_by_id(client, conn, client_id);
306   if (!client_entry || !client_entry->nickname ||
307       !silc_client_on_channel(channel, client_entry)) {
308     /* Resolve the client info */
309     SilcChannelClientResolve res = silc_calloc(1, sizeof(*res));
310     res->payload = payload;
311     res->channel_id = id;
312     silc_client_get_client_by_id_resolve(client, conn, client_id, NULL,
313                                          silc_client_channel_message_cb,
314                                          res);
315     payload = NULL;
316     id = NULL;
317     goto out;
318   }
319
320   message = silc_channel_message_get_data(payload, &message_len);
321
322   /* Pass the message to application */
323   client->internal->ops->channel_message(
324                                  client, conn, client_entry, channel,
325                                  silc_channel_message_get_flags(payload),
326                                  message, message_len);
327
328  out:
329   silc_free(id);
330   silc_free(client_id);
331   if (payload)
332     silc_channel_message_payload_free(payload);
333 }
334
335 /* Timeout callback that is called after a short period of time after the
336    new channel key has been created. This removes the old channel key all
337    together. */
338
339 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
340 {
341   SilcChannelEntry channel = (SilcChannelEntry)context;
342
343   if (channel->old_channel_key)
344     silc_cipher_free(channel->old_channel_key);
345   if (channel->old_hmac)
346     silc_hmac_free(channel->old_hmac);
347   channel->old_channel_key = NULL;
348   channel->old_hmac = NULL;
349   channel->rekey_task = NULL;
350 }
351
352 /* Saves channel key from encoded `key_payload'. This is used when we
353    receive Channel Key Payload and when we are processing JOIN command 
354    reply. */
355
356 void silc_client_save_channel_key(SilcClient client,
357                                   SilcClientConnection conn,
358                                   SilcBuffer key_payload, 
359                                   SilcChannelEntry channel)
360 {
361   unsigned char *id_string, *key, *cipher, *hmac, hash[32];
362   SilcUInt32 tmp_len;
363   SilcChannelID *id;
364   SilcChannelKeyPayload payload;
365
366   payload = silc_channel_key_payload_parse(key_payload->data,
367                                            key_payload->len);
368   if (!payload)
369     return;
370
371   id_string = silc_channel_key_get_id(payload, &tmp_len);
372   if (!id_string) {
373     silc_channel_key_payload_free(payload);
374     return;
375   }
376
377   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
378   if (!id) {
379     silc_channel_key_payload_free(payload);
380     return;
381   }
382
383   /* Find channel. */
384   if (!channel) {
385     channel = silc_client_get_channel_by_id(client, conn, id);
386     if (!channel)
387       goto out;
388   }
389
390   hmac = (channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) : 
391           SILC_DEFAULT_HMAC);
392
393   /* Save the old key for a short period of time so that we can decrypt
394      channel message even after the rekey if some client would be sending
395      messages with the old key after the rekey. */
396   if (channel->old_channel_key)
397     silc_cipher_free(channel->old_channel_key);
398   if (channel->old_hmac)
399     silc_hmac_free(channel->old_hmac);
400   if (channel->rekey_task)
401     silc_schedule_task_del(client->schedule, channel->rekey_task);
402   channel->old_channel_key = channel->channel_key;
403   channel->old_hmac = channel->hmac;
404   channel->rekey_task = 
405     silc_schedule_task_add(client->schedule, 0,
406                            silc_client_save_channel_key_rekey, channel,
407                            10, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
408
409   /* Free the old channel key data */
410   silc_free(channel->key);
411
412   /* Save the key */
413   key = silc_channel_key_get_key(payload, &tmp_len);
414   cipher = silc_channel_key_get_cipher(payload, NULL);
415   channel->key_len = tmp_len * 8;
416   channel->key = silc_memdup(key, tmp_len);
417
418   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
419     client->internal->ops->say(
420                            conn->client, conn, 
421                            SILC_CLIENT_MESSAGE_AUDIT,
422                            "Cannot talk to channel: unsupported cipher %s", 
423                            cipher);
424     goto out;
425   }
426
427   /* Set the cipher key */
428   silc_cipher_set_key(channel->channel_key, key, channel->key_len);
429
430   /* Generate HMAC key from the channel key data and set it */
431   silc_hmac_alloc(hmac, NULL, &channel->hmac);
432   silc_hash_make(silc_hmac_get_hash(channel->hmac), key, tmp_len, hash);
433   silc_hmac_set_key(channel->hmac, hash, 
434                     silc_hash_len(silc_hmac_get_hash(channel->hmac)));
435   memset(hash, 0, sizeof(hash));
436
437  out:
438   silc_free(id);
439   silc_channel_key_payload_free(payload);
440 }
441
442 /* Processes received key for channel. The received key will be used
443    to protect the traffic on the channel for now on. Client must receive
444    the key to the channel before talking on the channel is possible. 
445    This is the key that server has generated, this is not the channel
446    private key, it is entirely local setting. */
447
448 void silc_client_receive_channel_key(SilcClient client,
449                                      SilcSocketConnection sock,
450                                      SilcBuffer packet)
451 {
452   SILC_LOG_DEBUG(("Received key for channel"));
453
454   /* Save the key */
455   silc_client_save_channel_key(client, sock->user_data, packet, NULL);
456 }
457
458 /* Adds private key for channel. This may be set only if the channel's mode
459    mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
460    mode is not set. When channel has private key then the messages are
461    encrypted using that key. All clients on the channel must also know the
462    key in order to decrypt the messages. However, it is possible to have
463    several private keys per one channel. In this case only some of the
464    clients on the channel may know the one key and only some the other key.
465
466    If `cipher' and/or `hmac' is NULL then default values will be used 
467    (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
468
469    The private key for channel is optional. If it is not set then the
470    channel messages are encrypted using the channel key generated by the
471    server. However, setting the private key (or keys) for the channel 
472    significantly adds security. If more than one key is set the library
473    will automatically try all keys at the message decryption phase. Note:
474    setting many keys slows down the decryption phase as all keys has to
475    be tried in order to find the correct decryption key. However, setting
476    a few keys does not have big impact to the decryption performace. 
477
478    NOTE: that this is entirely local setting. The key set using this function
479    is not sent to the network at any phase.
480
481    NOTE: If the key material was originated by the SKE protocol (using
482    silc_client_send_key_agreement) then the `key' MUST be the
483    key->send_enc_key as this is dictated by the SILC protocol. However,
484    currently it is not expected that the SKE key material would be used
485    as channel private key. However, this API allows it. */
486
487 int silc_client_add_channel_private_key(SilcClient client,
488                                         SilcClientConnection conn,
489                                         SilcChannelEntry channel,
490                                         const char *name,
491                                         char *cipher,
492                                         char *hmac,
493                                         unsigned char *key,
494                                         SilcUInt32 key_len)
495 {
496   SilcChannelPrivateKey entry;
497   unsigned char hash[32];
498   SilcSKEKeyMaterial *keymat;
499
500   assert(client && channel);
501
502   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
503     return FALSE;
504
505   if (!cipher)
506     cipher = SILC_DEFAULT_CIPHER;
507   if (!hmac)
508     hmac = SILC_DEFAULT_HMAC;
509
510   if (!silc_cipher_is_supported(cipher))
511     return FALSE;
512
513   if (!silc_hmac_is_supported(hmac))
514     return FALSE;
515
516   /* Produce the key material */
517   keymat = silc_calloc(1, sizeof(*keymat));
518   if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16, 
519                                          client->md5hash, keymat) 
520       != SILC_SKE_STATUS_OK)
521     return FALSE;
522
523   /* Remove the current key, if it exists. */
524   if (channel->channel_key) {
525     silc_cipher_free(channel->channel_key);
526     memset(channel->key, 0, channel->key_len / 8);
527     silc_free(channel->key);
528     channel->channel_key = NULL;
529     channel->key = NULL;
530     channel->key_len = 0;
531   }
532   if (channel->hmac) {
533     silc_hmac_free(channel->hmac);
534     channel->hmac = NULL;
535   }
536
537   if (!channel->private_keys)
538     channel->private_keys = silc_dlist_init();
539
540   /* Save the key */
541   entry = silc_calloc(1, sizeof(*entry));
542   entry->name = name ? strdup(name) : NULL;
543   entry->key = silc_memdup(keymat->send_enc_key, keymat->enc_key_len / 8);
544   entry->key_len = keymat->enc_key_len / 8;
545
546   /* Allocate the cipher and set the key*/
547   silc_cipher_alloc(cipher, &entry->cipher);
548   silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
549
550   /* Generate HMAC key from the channel key data and set it */
551   silc_hmac_alloc(hmac, NULL, &entry->hmac);
552   silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key, 
553                  entry->key_len, hash);
554   silc_hmac_set_key(entry->hmac, hash, 
555                     silc_hash_len(silc_hmac_get_hash(entry->hmac)));
556   memset(hash, 0, sizeof(hash));
557
558   /* Add to the private keys list */
559   silc_dlist_add(channel->private_keys, entry);
560
561   if (!channel->curr_key)
562     channel->curr_key = entry;
563
564   /* Free the key material */
565   silc_ske_free_key_material(keymat);
566
567   return TRUE;
568 }
569
570 /* Removes all private keys from the `channel'. The old channel key is used
571    after calling this to protect the channel messages. Returns FALSE on
572    on error, TRUE otherwise. */
573
574 int silc_client_del_channel_private_keys(SilcClient client,
575                                          SilcClientConnection conn,
576                                          SilcChannelEntry channel)
577 {
578   SilcChannelPrivateKey entry;
579
580   assert(client && channel);
581
582   if (!channel->private_keys)
583     return FALSE;
584
585   silc_dlist_start(channel->private_keys);
586   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
587     silc_dlist_del(channel->private_keys, entry);
588     memset(entry->key, 0, entry->key_len);
589     silc_free(entry->key);
590     silc_free(entry->name);
591     silc_cipher_free(entry->cipher);
592     silc_hmac_free(entry->hmac);
593     silc_free(entry);
594   }
595
596   channel->curr_key = NULL;
597
598   silc_dlist_uninit(channel->private_keys);
599   channel->private_keys = NULL;
600
601   return TRUE;
602 }
603
604 /* Removes and frees private key `key' from the channel `channel'. The `key'
605    is retrieved by calling the function silc_client_list_channel_private_keys.
606    The key is not used after this. If the key was last private key then the
607    old channel key is used hereafter to protect the channel messages. This
608    returns FALSE on error, TRUE otherwise. */
609
610 int silc_client_del_channel_private_key(SilcClient client,
611                                         SilcClientConnection conn,
612                                         SilcChannelEntry channel,
613                                         SilcChannelPrivateKey key)
614 {
615   SilcChannelPrivateKey entry;
616
617   assert(client && channel);
618
619   if (!channel->private_keys)
620     return FALSE;
621
622   silc_dlist_start(channel->private_keys);
623   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
624     if (entry == key) {
625       if (channel->curr_key == entry)
626         channel->curr_key = NULL;
627
628       silc_dlist_del(channel->private_keys, entry);
629       memset(entry->key, 0, entry->key_len);
630       silc_free(entry->key);
631       silc_free(entry->name);
632       silc_cipher_free(entry->cipher);
633       silc_hmac_free(entry->hmac);
634       silc_free(entry);
635
636       if (silc_dlist_count(channel->private_keys) == 0) {
637         silc_dlist_uninit(channel->private_keys);
638         channel->private_keys = NULL;
639       }
640
641       return TRUE;
642     }
643   }
644
645   return FALSE;
646 }
647
648 /* Returns array (pointers) of private keys associated to the `channel'.
649    The caller must free the array by calling the function
650    silc_client_free_channel_private_keys. The pointers in the array may be
651    used to delete the specific key by giving the pointer as argument to the
652    function silc_client_del_channel_private_key. */
653
654 SilcChannelPrivateKey *
655 silc_client_list_channel_private_keys(SilcClient client,
656                                       SilcClientConnection conn,
657                                       SilcChannelEntry channel,
658                                       SilcUInt32 *key_count)
659 {
660   SilcChannelPrivateKey *keys = NULL, entry;
661   SilcUInt32 count = 0;
662
663   assert(client && channel);
664
665   if (!channel->private_keys)
666     return NULL;
667
668   silc_dlist_start(channel->private_keys);
669   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
670     keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
671     keys[count] = entry;
672     count++;
673   }
674
675   if (key_count)
676     *key_count = count;
677
678   return keys;
679 }
680
681 /* Frees the SilcChannelPrivateKey array. */
682
683 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
684                                            SilcUInt32 key_count)
685 {
686   silc_free(keys);
687 }
688
689 /* Sets the `key' to be used as current channel private key on the
690    `channel'.  Packet sent after calling this function will be secured
691    with `key'. */
692
693 void silc_client_current_channel_private_key(SilcClient client,
694                                              SilcClientConnection conn,
695                                              SilcChannelEntry channel,
696                                              SilcChannelPrivateKey key)
697 {
698   assert(client && channel);
699   channel->curr_key = key;
700 }
701
702 /* Returns the SilcChannelUser entry if the `client_entry' is joined on the 
703    channel indicated by the `channel'. NULL if client is not joined on
704    the channel. */
705
706 SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
707                                        SilcClientEntry client_entry)
708 {
709   SilcChannelUser chu;
710
711   if (silc_hash_table_find(channel->user_list, client_entry, NULL, 
712                            (void *)&chu))
713     return chu;
714
715   return NULL;
716 }