Added checking for maximum packet length.
[silc.git] / lib / silccore / silcchannel.c
1 /*
2
3   silcchannel.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 /* Channel Payload, Channel Message Payload and Channel Key Payload 
21    implementations. */
22 /* $Id$ */
23
24 #include "silcincludes.h"
25 #include "silcchannel.h"
26
27 /******************************************************************************
28
29                               Channel Payload
30
31 ******************************************************************************/
32
33 /* Channel Message Payload structure. Contents of this structure is parsed
34    from SILC packets. */
35 struct SilcChannelPayloadStruct {
36   SilcUInt16 name_len;
37   unsigned char *channel_name;
38   SilcUInt16 id_len;
39   unsigned char *channel_id;
40   SilcUInt32 mode;
41 };
42
43 /* Parses channel payload returning new channel payload structure. */
44
45 SilcChannelPayload silc_channel_payload_parse(const unsigned char *payload,
46                                               SilcUInt32 payload_len)
47 {
48   SilcBufferStruct buffer;
49   SilcChannelPayload newp;
50   int ret;
51
52   SILC_LOG_DEBUG(("Parsing channel payload"));
53
54   silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
55   newp = silc_calloc(1, sizeof(*newp));
56   if (!newp)
57     return NULL;
58
59   /* Parse the Channel Payload. Ignore the padding. */
60   ret = silc_buffer_unformat(&buffer,
61                              SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_name, 
62                                                          &newp->name_len),
63                              SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_id, 
64                                                          &newp->id_len),
65                              SILC_STR_UI_INT(&newp->mode),
66                              SILC_STR_END);
67   if (ret == -1)
68     goto err;
69
70   if ((newp->name_len < 1 || newp->name_len > buffer.len) ||
71       (newp->id_len < 1 || newp->id_len > buffer.len)) {
72     SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
73     goto err;
74   }
75
76   return newp;
77
78  err:
79   silc_channel_payload_free(newp);
80   return NULL;
81 }
82
83 /* Parses list of channel payloads returning list of payloads. */
84
85 SilcDList silc_channel_payload_parse_list(const unsigned char *payload,
86                                           SilcUInt32 payload_len)
87 {
88   SilcBufferStruct buffer;
89   SilcDList list;
90   SilcChannelPayload newp;
91   int len, ret;
92
93   SILC_LOG_DEBUG(("Parsing channel payload list"));
94
95   silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
96   list = silc_dlist_init();
97
98   while (buffer.len) {
99     newp = silc_calloc(1, sizeof(*newp));
100     if (!newp)
101       goto err;
102     ret = silc_buffer_unformat(&buffer,
103                                SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_name, 
104                                                            &newp->name_len),
105                                SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_id, 
106                                                            &newp->id_len),
107                                SILC_STR_UI_INT(&newp->mode),
108                                SILC_STR_END);
109     if (ret == -1)
110       goto err;
111
112     if ((newp->name_len < 1 || newp->name_len > buffer.len) ||
113         (newp->id_len < 1 || newp->id_len > buffer.len)) {
114       SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
115       goto err;
116     }
117
118     len = 2 + newp->name_len + 2 + newp->id_len + 4;
119     if (buffer.len < len)
120       break;
121     silc_buffer_pull(&buffer, len);
122
123     silc_dlist_add(list, newp);
124   }
125   
126   return list;
127
128  err:
129   silc_channel_payload_list_free(list);
130   return NULL;
131 }
132
133 /* Encode new channel payload and returns it as buffer. */
134
135 SilcBuffer silc_channel_payload_encode(const unsigned char *channel_name,
136                                        SilcUInt16 channel_name_len,
137                                        const unsigned char *channel_id,
138                                        SilcUInt32 channel_id_len,
139                                        SilcUInt32 mode)
140 {
141   SilcBuffer buffer;
142
143   SILC_LOG_DEBUG(("Encoding message payload"));
144
145   buffer = silc_buffer_alloc_size(2 + channel_name_len + 2 + 
146                                   channel_id_len + 4);
147   if (!buffer)
148     return NULL;
149
150   /* Encode the Channel Payload */
151   silc_buffer_format(buffer, 
152                      SILC_STR_UI_SHORT(channel_name_len),
153                      SILC_STR_UI_XNSTRING(channel_name, channel_name_len),
154                      SILC_STR_UI_SHORT(channel_id_len),
155                      SILC_STR_UI_XNSTRING(channel_id, channel_id_len),
156                      SILC_STR_UI_INT(mode),
157                      SILC_STR_END);
158
159   return buffer;
160 }
161
162 /* Frees Channel Payload */
163
164 void silc_channel_payload_free(SilcChannelPayload payload)
165 {
166   silc_free(payload->channel_name);
167   silc_free(payload->channel_id);
168   silc_free(payload);
169 }
170
171 /* Free's list of Channel Payloads */
172
173 void silc_channel_payload_list_free(SilcDList list)
174 {
175   SilcChannelPayload entry;
176
177   silc_dlist_start(list);
178   while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
179     silc_free(entry->channel_name);
180     silc_free(entry->channel_id);
181     silc_dlist_del(list, entry);
182     silc_free(entry);
183   }
184
185   silc_dlist_uninit(list);
186 }
187
188 /* Return the channel name */
189
190 unsigned char *silc_channel_get_name(SilcChannelPayload payload,
191                                      SilcUInt32 *channel_name_len)
192 {
193   if (channel_name_len)
194     *channel_name_len = payload->name_len;
195
196   return payload->channel_name;
197 }
198
199 /* Return the channel ID */
200
201 unsigned char *silc_channel_get_id(SilcChannelPayload payload,
202                                    SilcUInt32 *channel_id_len)
203 {
204   if (channel_id_len)
205     *channel_id_len = payload->id_len;
206
207   return payload->channel_id;
208 }
209
210 /* Return the channel ID as parsed ID. */
211
212 SilcChannelID *silc_channel_get_id_parse(SilcChannelPayload payload)
213 {
214   return silc_id_str2id(payload->channel_id, payload->id_len,
215                         SILC_ID_CHANNEL);
216 }
217
218 /* Return the mode. The mode is arbitrary. It can be the mode of the
219    channel or perhaps the mode of the client on the channel.  The protocol
220    dictates what the usage of the mode is in different circumstances. */
221
222 SilcUInt32 silc_channel_get_mode(SilcChannelPayload payload)
223 {
224   return payload->mode;
225 }
226
227 /******************************************************************************
228
229                           Channel Message Payload
230
231 ******************************************************************************/
232
233 /* Calculates padding length for message payload */
234 #define SILC_CHANNEL_MESSAGE_PAD(__payloadlen) (16 - (__payloadlen) % 16)
235
236 /* Header length plus maximum padding length */
237 #define SILC_CHANNEL_MESSAGE_HLEN 6 + 16
238
239 /* Returns the data length that fits to the packet.  If data length is too
240    big it will be truncated to fit to the payload. */
241 #define SILC_CHANNEL_MESSAGE_DATALEN(data_len, header_len)              \
242   ((data_len + SILC_CHANNEL_MESSAGE_HLEN + header_len) >                \
243    SILC_PACKET_MAX_LEN ?                                                \
244    data_len - ((data_len + SILC_CHANNEL_MESSAGE_HLEN + header_len) -    \
245                SILC_PACKET_MAX_LEN) : data_len)
246
247 /* Channel Message Payload structure. Contents of this structure is parsed
248    from SILC packets. */
249 struct SilcChannelMessagePayloadStruct {
250   SilcMessageFlags flags;
251   SilcUInt16 data_len;
252   unsigned char *data;
253   unsigned char *mac;
254   unsigned char *iv;
255 };
256
257 /* Decrypts the channel message payload. First push the IV out of the
258    packet. The IV is used in the decryption process. Then decrypt the
259    message. After decyprtion, take the MAC from the decrypted packet, 
260    compute MAC and compare the MACs.  If they match, the decryption was
261    successful and we have the channel message ready to be displayed. */
262
263 bool silc_channel_message_payload_decrypt(unsigned char *data,
264                                           size_t data_len,
265                                           SilcCipher cipher,
266                                           SilcHmac hmac)
267 {
268   SilcUInt32 iv_len, mac_len;
269   unsigned char *end, *mac, mac2[32];
270   unsigned char *dst, iv[SILC_CIPHER_MAX_IV_SIZE];
271
272   /* Push the IV out of the packet, and copy the IV since we do not want
273      to modify the original data buffer. */
274   end = data + data_len;
275   iv_len = silc_cipher_get_block_len(cipher);
276   memcpy(iv, end - iv_len, iv_len);
277
278   /* Allocate destination decryption buffer since we do not want to modify
279      the original data buffer, since we might want to call this function 
280      many times for same payload. */
281   if (hmac) {
282     dst = silc_calloc(data_len - iv_len, sizeof(*dst));
283     if (!dst)
284       return FALSE;
285   } else {
286     dst = data;
287   }
288
289   /* Decrypt the channel message */
290   silc_cipher_decrypt(cipher, data, dst, data_len - iv_len, iv);
291
292   if (hmac) {
293     /* Take the MAC */
294     end = dst + (data_len - iv_len);
295     mac_len = silc_hmac_len(hmac);
296     mac = (end - mac_len);
297
298     /* Check the MAC of the message */
299     SILC_LOG_DEBUG(("Checking channel message MACs"));
300     silc_hmac_make(hmac, dst, (data_len - iv_len - mac_len), mac2, &mac_len);
301     if (memcmp(mac, mac2, mac_len)) {
302       SILC_LOG_DEBUG(("Channel message MACs does not match"));
303       silc_free(dst);
304       return FALSE;
305     }
306     SILC_LOG_DEBUG(("MAC is Ok"));
307
308     /* Now copy the decrypted data into the buffer since it is verified
309        it decrypted correctly. */
310     memcpy(data, dst, data_len - iv_len);
311     memset(dst, 0, data_len - iv_len);
312     silc_free(dst);
313   }
314
315   return TRUE;
316 }
317
318 /* Parses channel message payload returning new channel payload structure.
319    This also decrypts it and checks the MAC. */
320
321 SilcChannelMessagePayload 
322 silc_channel_message_payload_parse(unsigned char *payload,
323                                    SilcUInt32 payload_len,
324                                    SilcCipher cipher,
325                                    SilcHmac hmac)
326 {
327   SilcBufferStruct buffer;
328   SilcChannelMessagePayload newp;
329   int ret;
330   SilcUInt32 iv_len, mac_len;
331
332   SILC_LOG_DEBUG(("Parsing channel message payload"));
333
334   silc_buffer_set(&buffer, payload, payload_len);
335
336   /* Decrypt the payload */
337   ret = silc_channel_message_payload_decrypt(buffer.data, buffer.len,
338                                              cipher, hmac);
339   if (ret == FALSE)
340     return NULL;
341
342   iv_len = silc_cipher_get_block_len(cipher);
343   mac_len = silc_hmac_len(hmac);
344
345   newp = silc_calloc(1, sizeof(*newp));
346   if (!newp)
347     return NULL;
348
349   /* Parse the Channel Message Payload. Ignore the padding. */
350   ret = silc_buffer_unformat(&buffer,
351                              SILC_STR_UI_SHORT(&newp->flags),
352                              SILC_STR_UI16_NSTRING_ALLOC(&newp->data, 
353                                                          &newp->data_len),
354                              SILC_STR_UI16_NSTRING(NULL, NULL),
355                              SILC_STR_UI_XNSTRING(&newp->mac, mac_len),
356                              SILC_STR_UI_XNSTRING(&newp->iv, iv_len),
357                              SILC_STR_END);
358   if (ret == -1)
359     goto err;
360
361   if (newp->data_len > buffer.len) {
362     SILC_LOG_ERROR(("Incorrect channel message payload in packet, "
363                     "packet dropped"));
364     goto err;
365   }
366
367   return newp;
368
369  err:
370   silc_channel_message_payload_free(newp);
371   return NULL;
372 }
373
374 /* Encodes channel message payload into a buffer and returns it. This is used 
375    to add channel message payload into a packet. As the channel payload is
376    encrypted separately from other parts of the packet padding must
377    be applied to the payload. */
378
379 SilcBuffer silc_channel_message_payload_encode(SilcUInt16 flags,
380                                                SilcUInt16 data_len,
381                                                const unsigned char *data,
382                                                SilcUInt16 iv_len,
383                                                unsigned char *iv,
384                                                SilcCipher cipher,
385                                                SilcHmac hmac,
386                                                SilcRng rng)
387 {
388   int i;
389   SilcBuffer buffer;
390   SilcUInt32 len, pad_len, mac_len;
391   unsigned char pad[16];
392   unsigned char mac[32];
393
394   SILC_LOG_DEBUG(("Encoding channel message payload"));
395
396   /* Calculate length of padding. IV is not included into the calculation
397      since it is not encrypted. */
398   mac_len = silc_hmac_len(hmac);
399   data_len = SILC_CHANNEL_MESSAGE_DATALEN(data_len, mac_len + iv_len);
400   len = 6 + data_len + mac_len;
401   pad_len = SILC_CHANNEL_MESSAGE_PAD(len);
402
403   /* Allocate channel payload buffer */
404   len += pad_len + iv_len;
405   buffer = silc_buffer_alloc(len);
406   if (!buffer)
407     return NULL;
408
409   /* Generate padding */
410   if (rng) {
411     for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte(rng);
412   } else {
413     for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte();
414   }
415
416   /* Encode the Channel Message Payload */
417   silc_buffer_pull_tail(buffer, 6 + data_len + pad_len);
418   silc_buffer_format(buffer, 
419                      SILC_STR_UI_SHORT(flags),
420                      SILC_STR_UI_SHORT(data_len),
421                      SILC_STR_UI_XNSTRING(data, data_len),
422                      SILC_STR_UI_SHORT(pad_len),
423                      SILC_STR_UI_XNSTRING(pad, pad_len),
424                      SILC_STR_END);
425
426   /* Compute the MAC of the channel message data */
427   silc_hmac_make(hmac, buffer->data, buffer->len, mac, &mac_len);
428
429   /* Put rest of the data to the payload */
430   silc_buffer_pull_tail(buffer, mac_len + iv_len);
431   silc_buffer_pull(buffer, 6 + data_len + pad_len);
432   silc_buffer_format(buffer, 
433                      SILC_STR_UI_XNSTRING(mac, mac_len),
434                      SILC_STR_UI_XNSTRING(iv, iv_len),
435                      SILC_STR_END);
436   silc_buffer_push(buffer, 6 + data_len + pad_len);
437
438   /* Encrypt payload of the packet. This is encrypted with the channel key. */
439   silc_cipher_encrypt(cipher, buffer->data, buffer->data, 
440                       buffer->len - iv_len, iv);
441
442   memset(pad, 0, sizeof(pad));
443   memset(mac, 0, sizeof(mac));
444
445   return buffer;
446 }
447
448 /* Free's Channel Message Payload */
449
450 void silc_channel_message_payload_free(SilcChannelMessagePayload payload)
451 {
452   if (payload->data) {
453     memset(payload->data, 0, payload->data_len);
454     silc_free(payload->data);
455   }
456   silc_free(payload);
457 }
458
459 /* Return flags */
460
461 SilcMessageFlags
462 silc_channel_message_get_flags(SilcChannelMessagePayload payload)
463 {
464   return payload->flags;
465 }
466
467 /* Return data */
468
469 unsigned char *silc_channel_message_get_data(SilcChannelMessagePayload payload,
470                                              SilcUInt32 *data_len)
471 {
472   if (data_len)
473     *data_len = payload->data_len;
474
475   return payload->data;
476 }
477
478 /* Return MAC. The caller knows the length of the MAC */
479
480 unsigned char *silc_channel_message_get_mac(SilcChannelMessagePayload payload)
481 {
482   return payload->mac;
483 }
484
485 /* Return IV. The caller knows the length of the IV */
486
487 unsigned char *silc_channel_message_get_iv(SilcChannelMessagePayload payload)
488 {
489   return payload->iv;
490 }
491
492 /******************************************************************************
493
494                              Channel Key Payload
495
496 ******************************************************************************/
497
498 /* Channel Key Payload structrue. Channel keys are parsed from SILC
499    packets into this structure. */
500 struct SilcChannelKeyPayloadStruct {
501   SilcUInt16 id_len;
502   unsigned char *id;
503   SilcUInt16 cipher_len;
504   unsigned char *cipher;
505   SilcUInt16 key_len;
506   unsigned char *key;
507 };
508
509 /* Parses channel key payload returning new channel key payload structure */
510
511 SilcChannelKeyPayload 
512 silc_channel_key_payload_parse(const unsigned char *payload,
513                                SilcUInt32 payload_len)
514 {
515   SilcBufferStruct buffer;
516   SilcChannelKeyPayload newp;
517   int ret;
518
519   SILC_LOG_DEBUG(("Parsing channel key payload"));
520
521   silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
522   newp = silc_calloc(1, sizeof(*newp));
523   if (!newp)
524     return NULL;
525
526   /* Parse the Channel Key Payload */
527   ret =
528     silc_buffer_unformat(&buffer,
529                          SILC_STR_UI16_NSTRING_ALLOC(&newp->id, &newp->id_len),
530                          SILC_STR_UI16_NSTRING_ALLOC(&newp->cipher, 
531                                                      &newp->cipher_len),
532                          SILC_STR_UI16_NSTRING_ALLOC(&newp->key, 
533                                                      &newp->key_len),
534                          SILC_STR_END);
535   if (ret == -1)
536     goto err;
537
538   if (newp->id_len < 1 || newp->key_len < 1 || newp->cipher_len < 1) {
539     SILC_LOG_ERROR(("Incorrect channel key payload in packet"));
540     goto err;
541   }
542
543   return newp;
544
545  err:
546   if (newp->id)
547     silc_free(newp->id);
548   if (newp->cipher)
549     silc_free(newp->cipher);
550   if (newp->key)
551     silc_free(newp->key);
552   silc_free(newp);
553   return NULL;
554 }
555
556 /* Encodes channel key payload into a buffer and returns it. This is used 
557    to add channel key payload into a packet. */
558
559 SilcBuffer silc_channel_key_payload_encode(SilcUInt16 id_len,
560                                            const unsigned char *id,
561                                            SilcUInt16 cipher_len,
562                                            const unsigned char *cipher,
563                                            SilcUInt16 key_len,
564                                            const unsigned char *key)
565 {
566   SilcBuffer buffer;
567   SilcUInt32 len;
568
569   SILC_LOG_DEBUG(("Encoding channel key payload"));
570
571   /* Allocate channel payload buffer. Length is 2 + id + 2 + key + 
572      2 + cipher */
573   len = 2 + id_len + 2 + key_len + 2 + cipher_len;
574   buffer = silc_buffer_alloc_size(len);
575   if (!buffer)
576     return NULL;
577
578   /* Encode the Channel Payload */
579   silc_buffer_format(buffer, 
580                      SILC_STR_UI_SHORT(id_len),
581                      SILC_STR_UI_XNSTRING(id, id_len),
582                      SILC_STR_UI_SHORT(cipher_len),
583                      SILC_STR_UI_XNSTRING(cipher, cipher_len),
584                      SILC_STR_UI_SHORT(key_len),
585                      SILC_STR_UI_XNSTRING(key, key_len),
586                      SILC_STR_END);
587
588   return buffer;
589 }
590
591 /* Frees Channel Key Payload */
592
593 void silc_channel_key_payload_free(SilcChannelKeyPayload payload)
594 {
595   if (payload) {
596     silc_free(payload->id);
597     silc_free(payload->cipher);
598     if (payload->key) {
599       memset(payload->key, 0, payload->key_len);
600       silc_free(payload->key);
601     }
602     silc_free(payload);
603   }
604 }
605
606 /* Return ID */
607
608 unsigned char *silc_channel_key_get_id(SilcChannelKeyPayload payload, 
609                                        SilcUInt32 *id_len)
610 {
611   if (id_len)
612     *id_len = payload->id_len;
613
614   return payload->id;
615 }
616
617 /* Return cipher name */
618
619 unsigned char *silc_channel_key_get_cipher(SilcChannelKeyPayload payload,
620                                            SilcUInt32 *cipher_len)
621 {
622   if (cipher_len)
623     *cipher_len = payload->cipher_len;
624
625   return payload->cipher;
626 }
627
628 /* Return key */
629
630 unsigned char *silc_channel_key_get_key(SilcChannelKeyPayload payload,
631                                         SilcUInt32 *key_len)
632 {
633   if (key_len)
634     *key_len = payload->key_len;
635
636   return payload->key;
637 }