Added support for SID with IV Included flag. Added
[silc.git] / lib / silccore / silcpacket.c
1 /*
2
3   silcpacket.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2006 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; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /*
20  * Created: Fri Jul 25 18:52:14 1997
21  */
22 /* $Id$ */
23
24 #include "silc.h"
25
26 /************************** Types and definitions ***************************/
27
28 /* Packet engine */
29 struct SilcPacketEngineStruct {
30   SilcRng rng;                           /* RNG for engine */
31   SilcPacketCallbacks *callbacks;        /* Packet callbacks */
32   void *callback_context;                /* Context for callbacks */
33   SilcList streams;                      /* All streams in engine */
34   SilcList packet_pool;                  /* Free list for received packets */
35   SilcMutex lock;                        /* Engine lock */
36   SilcBool local_is_router;
37 };
38
39 /* Packet procesor context */
40 typedef struct SilcPacketProcessStruct {
41   SilcInt32 priority;                    /* Priority */
42   SilcPacketType *types;                 /* Packets to process */
43   SilcPacketCallbacks *callbacks;        /* Callbacks or NULL */
44   void *callback_context;
45 } *SilcPacketProcess;
46
47 /* Packet stream */
48 struct SilcPacketStreamStruct {
49   struct SilcPacketStreamStruct *next;
50   SilcAtomic refcnt;                     /* Reference counter */
51   SilcPacketEngine engine;               /* Packet engine */
52   SilcStream stream;                     /* Underlaying stream */
53   SilcMutex lock;                        /* Stream lock */
54   SilcDList process;                     /* Packet processors, it set */
55   void *stream_context;                  /* Stream context */
56   SilcBufferStruct inbuf;                /* In buffer */
57   SilcBufferStruct outbuf;               /* Out buffer */
58   SilcUInt32 send_psn;                   /* Sending sequence */
59   SilcCipher send_key[2];                /* Sending key */
60   SilcHmac send_hmac[2];                 /* Sending HMAC */
61   SilcUInt32 receive_psn;                /* Receiving sequence */
62   SilcCipher receive_key[2];             /* Receiving key */
63   SilcHmac receive_hmac[2];              /* Receiving HMAC */
64   unsigned char *src_id;                 /* Source ID */
65   unsigned char *dst_id;                 /* Destination ID */
66   unsigned int src_id_len  : 6;
67   unsigned int src_id_type : 2;
68   unsigned int dst_id_len  : 6;
69   unsigned int dst_id_type : 2;
70   unsigned int is_router   : 1;          /* Set if router stream */
71   unsigned int destroyed   : 1;          /* Set if destroyed */
72   unsigned int iv_included : 1;          /* Set if IV included */
73   SilcUInt8 sid;                         /* Security ID, set if IV included */
74 };
75
76 /* Initial size of stream buffers */
77 #define SILC_PACKET_DEFAULT_SIZE  1024
78
79 /* Header length without source and destination ID's. */
80 #define SILC_PACKET_HEADER_LEN 10
81
82 /* Minimum length of SILC Packet Header. */
83 #define SILC_PACKET_MIN_HEADER_LEN 16
84 #define SILC_PACKET_MIN_HEADER_LEN_IV 32 + 1
85
86 /* Maximum padding length */
87 #define SILC_PACKET_MAX_PADLEN 128
88
89 /* Default padding length */
90 #define SILC_PACKET_DEFAULT_PADLEN 16
91
92 /* Minimum packet length */
93 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
94
95 /* Returns true length of the packet. */
96 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
97 do {                                                                     \
98   SILC_GET16_MSB((__ret_truelen), (__packetdata));                       \
99   (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4];    \
100 } while(0)
101
102 /* Calculates the data length with given header length.  This macro
103    can be used to check whether the data_len with header_len exceeds
104    SILC_PACKET_MAX_LEN.  If it does, this returns the new data_len
105    so that the SILC_PACKET_MAX_LEN is not exceeded.  If the data_len
106    plus header_len fits SILC_PACKET_MAX_LEN the returned data length
107    is the data_len given as argument. */
108 #define SILC_PACKET_DATALEN(data_len, header_len)                         \
109   ((data_len + header_len) > SILC_PACKET_MAX_LEN ?                        \
110    data_len - ((data_len + header_len) - SILC_PACKET_MAX_LEN) : data_len)
111
112 /* Calculates the length of the padding in the packet. */
113 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen)               \
114 do {                                                                        \
115   __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) %                  \
116               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN));  \
117   if (__padlen < 8)                                                         \
118     __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
119 } while(0)
120
121 /* Returns the length of the padding up to the maximum length, which
122    is 128 bytes.*/
123 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen)          \
124 do {                                                                       \
125   __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) %                     \
126               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
127 } while(0)
128
129 /* EOS callback */
130 #define SILC_PACKET_CALLBACK_EOS(s)                                     \
131 do {                                                                    \
132   (s)->engine->callbacks->eos((s)->engine, s,                           \
133                               (s)->engine->callback_context,            \
134                               (s)->stream_context);                     \
135 } while(0)
136
137 /* Error callback */
138 #define SILC_PACKET_CALLBACK_ERROR(s, err)                              \
139 do {                                                                    \
140   (s)->engine->callbacks->error((s)->engine, s, err,                    \
141                                 (s)->engine->callback_context,          \
142                                 (s)->stream_context);                   \
143 } while(0)
144
145
146 /************************ Static utility functions **************************/
147
148 static void silc_packet_read_process(SilcPacketStream stream);
149
150 /* Our stream IO notifier callback. */
151
152 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
153                                   void *context)
154 {
155   SilcPacketStream ps = context;
156   int ret;
157
158   silc_mutex_lock(ps->lock);
159
160   if (ps->destroyed) {
161     silc_mutex_unlock(ps->lock);
162     return;
163   }
164
165   switch (status) {
166
167   case SILC_STREAM_CAN_WRITE:
168     if (!silc_buffer_headlen(&ps->outbuf)) {
169       silc_mutex_unlock(ps->lock);
170       return;
171     }
172
173     SILC_LOG_DEBUG(("Writing pending data to stream"));
174
175     /* Write pending data to stream */
176     while (silc_buffer_len(&ps->outbuf) > 0) {
177       ret = silc_stream_write(ps->stream, ps->outbuf.data,
178                               silc_buffer_len(&ps->outbuf));
179       if (ret == 0) {
180         /* EOS */
181         silc_buffer_reset(&ps->outbuf);
182         silc_mutex_unlock(ps->lock);
183         SILC_PACKET_CALLBACK_EOS(ps);
184         return;
185       }
186
187       if (ret == -2) {
188         /* Error */
189         silc_buffer_reset(&ps->outbuf);
190         silc_mutex_unlock(ps->lock);
191         SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
192         return;
193       }
194
195       if (ret == -1) {
196         /* Cannot write now, write later. */
197         silc_mutex_unlock(ps->lock);
198         return;
199       }
200
201       /* Wrote data */
202       silc_buffer_pull(&ps->outbuf, ret);
203     }
204
205     silc_buffer_reset(&ps->outbuf);
206
207     silc_mutex_unlock(ps->lock);
208     break;
209
210   case SILC_STREAM_CAN_READ:
211     SILC_LOG_DEBUG(("Reading data from stream"));
212
213     /* Make sure we have fair amount of free space in inbuf */
214     if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
215       if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
216                                SILC_PACKET_DEFAULT_SIZE * 2)) {
217         silc_mutex_unlock(ps->lock);
218         return;
219       }
220
221     /* Read data from stream */
222     ret = silc_stream_read(ps->stream, ps->inbuf.tail,
223                            silc_buffer_taillen(&ps->inbuf));
224
225     if (ret == 0) {
226       /* EOS */
227       silc_buffer_reset(&ps->inbuf);
228       silc_mutex_unlock(ps->lock);
229       SILC_PACKET_CALLBACK_EOS(ps);
230       return;
231     }
232
233     if (ret == -2) {
234       /* Error */
235       silc_buffer_reset(&ps->inbuf);
236       silc_mutex_unlock(ps->lock);
237       SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
238       return;
239     }
240
241     if (ret == -1) {
242       /* Cannot read now, do it later. */
243       silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
244       silc_mutex_unlock(ps->lock);
245       return;
246     }
247
248     /* Now process the data */
249     silc_buffer_pull_tail(&ps->inbuf, ret);
250     silc_packet_read_process(ps);
251
252     silc_mutex_unlock(ps->lock);
253     break;
254
255   default:
256     silc_mutex_unlock(ps->lock);
257     break;
258   }
259 }
260
261 /* Allocate packet */
262
263 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
264 {
265   SilcPacket packet;
266
267   SILC_LOG_DEBUG(("Packet pool count %d",
268                   silc_list_count(engine->packet_pool)));
269
270   silc_mutex_lock(engine->lock);
271
272   /* Get packet from freelist or allocate new one. */
273   packet = silc_list_get(engine->packet_pool);
274   if (!packet) {
275     void *tmp;
276
277     silc_mutex_unlock(engine->lock);
278
279     packet = silc_calloc(1, sizeof(*packet));
280     if (!packet)
281       return NULL;
282
283     SILC_LOG_DEBUG(("Allocating new packet %p", packet));
284
285     tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
286     if (!tmp) {
287       silc_free(packet);
288       return NULL;
289     }
290     silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
291     silc_buffer_reset(&packet->buffer);
292
293     return packet;
294   }
295
296   SILC_LOG_DEBUG(("Get packet %p", packet));
297
298   /* Delete from freelist */
299   silc_list_del(engine->packet_pool, packet);
300
301   silc_mutex_unlock(engine->lock);
302
303   return packet;
304 }
305
306
307 /******************************** Packet API ********************************/
308
309 /* Allocate new packet engine */
310
311 SilcPacketEngine
312 silc_packet_engine_start(SilcRng rng, SilcBool router,
313                          SilcPacketCallbacks *callbacks,
314                          void *callback_context)
315 {
316   SilcPacketEngine engine;
317   SilcPacket packet;
318   int i;
319   void *tmp;
320
321   SILC_LOG_DEBUG(("Starting new packet engine"));
322
323   if (!callbacks)
324     return NULL;
325   if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
326     return NULL;
327
328   engine = silc_calloc(1, sizeof(*engine));
329   if (!engine)
330     return NULL;
331
332   engine->rng = rng;
333   engine->local_is_router = router;
334   engine->callbacks = callbacks;
335   engine->callback_context = callback_context;
336   silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
337   silc_mutex_alloc(&engine->lock);
338
339   /* Allocate packet free list */
340   silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
341   for (i = 0; i < 5; i++) {
342     packet = silc_calloc(1, sizeof(*packet));
343     if (!packet)
344       return NULL;
345
346     tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
347     if (!tmp)
348       return NULL;
349     silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
350     silc_buffer_reset(&packet->buffer);
351
352     silc_list_add(engine->packet_pool, packet);
353   }
354   silc_list_start(engine->packet_pool);
355
356   return engine;
357 }
358
359 /* Stop packet engine */
360
361 void silc_packet_engine_stop(SilcPacketEngine engine)
362 {
363
364   SILC_LOG_DEBUG(("Stopping packet engine"));
365
366   if (!engine)
367     return;
368
369   /* XXX */
370
371   silc_free(engine);
372 }
373
374 /* Create new packet stream */
375
376 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
377                                            SilcSchedule schedule,
378                                            SilcStream stream)
379 {
380   SilcPacketStream ps;
381   void *tmp;
382
383   SILC_LOG_DEBUG(("Creating new packet stream"));
384
385   if (!engine || !stream)
386     return NULL;
387
388   ps = silc_calloc(1, sizeof(*ps));
389   if (!ps)
390     return NULL;
391
392   ps->engine = engine;
393   ps->stream = stream;
394   silc_atomic_init(&ps->refcnt, 1);
395
396   /* Allocate buffers */
397   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
398   if (!tmp)
399     return NULL;
400   silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
401   silc_buffer_reset(&ps->inbuf);
402   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
403   if (!tmp)
404     return NULL;
405   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
406   silc_buffer_reset(&ps->outbuf);
407
408   /* Initialize packet procesors list */
409   ps->process = silc_dlist_init();
410
411   /* Set IO notifier callback */
412   silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
413
414   silc_mutex_alloc(&ps->lock);
415
416   /* Add to engine */
417   silc_mutex_lock(engine->lock);
418   silc_list_add(engine->streams, ps);
419   silc_mutex_unlock(engine->lock);
420
421   return ps;
422 }
423
424 /* Destroy packet stream */
425
426 void silc_packet_stream_destroy(SilcPacketStream stream)
427 {
428   if (!stream)
429     return;
430
431   if (silc_atomic_get_int(&stream->refcnt) > 1) {
432     stream->destroyed = TRUE;
433     return;
434   }
435
436   SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
437
438   /* Delete from engine */
439   silc_mutex_lock(stream->engine->lock);
440   silc_list_del(stream->engine->streams, stream);
441   silc_mutex_unlock(stream->engine->lock);
442
443   /* Clear and free buffers */
444   silc_buffer_clear(&stream->inbuf);
445   silc_buffer_clear(&stream->outbuf);
446   silc_buffer_purge(&stream->inbuf);
447   silc_buffer_purge(&stream->outbuf);
448
449   /* XXX */
450
451   /* Destroy the underlaying stream */
452   silc_stream_destroy(stream->stream);
453
454   silc_atomic_uninit(&stream->refcnt);
455   silc_dlist_uninit(stream->process);
456   silc_mutex_free(stream->lock);
457   silc_free(stream);
458 }
459
460 /* Marks as router stream */
461
462 void silc_packet_stream_set_router(SilcPacketStream stream)
463 {
464   stream->is_router = TRUE;
465 }
466
467 /* Mark to include IV in ciphertext */
468
469 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
470 {
471   stream->iv_included = TRUE;
472 }
473
474 /* Links `callbacks' to `stream' for specified packet types */
475
476 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
477                                            SilcPacketCallbacks *callbacks,
478                                            void *callback_context,
479                                            int priority, va_list ap)
480 {
481   SilcPacketProcess p, e;
482   SilcInt32 packet_type;
483   int i;
484
485   SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
486
487   if (!callbacks)
488     return FALSE;
489   if (!callbacks->packet_receive)
490     return FALSE;
491
492   p = silc_calloc(1, sizeof(*p));
493   if (!p)
494     return FALSE;
495
496   p->priority = priority;
497   p->callbacks = callbacks;
498   p->callback_context = callback_context;
499
500   silc_mutex_lock(stream->lock);
501
502   if (!stream->process) {
503     stream->process = silc_dlist_init();
504     if (!stream->process) {
505       silc_mutex_unlock(stream->lock);
506       return FALSE;
507     }
508   }
509
510   /* According to priority set the procesor to correct position.  First
511      entry has the highest priority */
512   silc_dlist_start(stream->process);
513   while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
514     if (p->priority > e->priority) {
515       silc_dlist_insert(stream->process, p);
516       break;
517     }
518   }
519   if (!e)
520     silc_dlist_add(stream->process, p);
521
522   /* Get packet types to process */
523   i = 1;
524   while (1) {
525     packet_type = va_arg(ap, SilcInt32);
526
527     if (packet_type == SILC_PACKET_ANY)
528       break;
529
530     if (packet_type == -1)
531       break;
532
533     p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
534     if (!p->types) {
535       silc_mutex_unlock(stream->lock);
536       return FALSE;
537     }
538
539     p->types[i - 1] = (SilcPacketType)packet_type;
540     i++;
541   }
542   if (p->types)
543     p->types[i - 1] = 0;
544
545   silc_mutex_unlock(stream->lock);
546
547   silc_packet_stream_ref(stream);
548
549   return TRUE;
550 }
551
552 /* Links `callbacks' to `stream' for specified packet types */
553
554 SilcBool silc_packet_stream_link(SilcPacketStream stream,
555                                  SilcPacketCallbacks *callbacks,
556                                  void *callback_context,
557                                  int priority, ...)
558 {
559   va_list ap;
560   SilcBool ret;
561
562   va_start(ap, priority);
563   ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
564                                    priority, ap);
565   va_end(ap);
566
567   return ret;
568 }
569
570 /* Unlinks `callbacks' from `stream'. */
571
572 void silc_packet_stream_unlink(SilcPacketStream stream,
573                                SilcPacketCallbacks *callbacks,
574                                void *callback_context)
575 {
576   SilcPacketProcess p;
577
578   SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
579                   callbacks, stream));
580
581   silc_mutex_lock(stream->lock);
582
583   silc_dlist_start(stream->process);
584   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
585     if (p->callbacks == callbacks &&
586         p->callback_context == callback_context) {
587       silc_dlist_del(stream->process, p);
588       silc_free(p);
589       break;
590     }
591
592   if (!silc_dlist_count(stream->process)) {
593     silc_dlist_uninit(stream->process);
594     stream->process = NULL;
595   }
596
597   silc_mutex_unlock(stream->lock);
598
599   silc_packet_stream_unref(stream);
600 }
601
602 /* Reference packet stream */
603
604 void silc_packet_stream_ref(SilcPacketStream stream)
605 {
606   silc_atomic_add_int(&stream->refcnt, 1);
607 }
608
609 /* Unreference packet stream */
610
611 void silc_packet_stream_unref(SilcPacketStream stream)
612 {
613   if (silc_atomic_sub_int(&stream->refcnt, 1) == 0)
614     silc_packet_stream_destroy(stream);
615 }
616
617 /* Return engine */
618
619 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
620 {
621   return stream->engine;
622 }
623
624 /* Set application context for packet stream */
625
626 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
627 {
628   silc_mutex_lock(stream->lock);
629   stream->stream_context = stream_context;
630   silc_mutex_unlock(stream->lock);
631 }
632
633 /* Return application context from packet stream */
634
635 void *silc_packet_get_context(SilcPacketStream stream)
636 {
637   void *context;
638   silc_mutex_lock(stream->lock);
639   context = stream->stream_context;
640   silc_mutex_unlock(stream->lock);
641   return context;
642 }
643
644 /* Return underlaying stream */
645
646 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
647 {
648   return stream->stream;
649 }
650
651 /* Set ciphers for packet stream */
652
653 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
654                              SilcCipher receive)
655 {
656   SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
657
658   silc_mutex_lock(stream->lock);
659
660   /* In case IV Included is set, save the old key */
661   if (stream->iv_included) {
662     if (stream->send_key[1]) {
663       silc_cipher_free(stream->send_key[1]);
664       stream->send_key[1] = stream->send_key[0];
665     }
666     if (stream->receive_key[1]) {
667       silc_cipher_free(stream->receive_key[1]);
668       stream->receive_key[1] = stream->receive_key[0];
669     }
670
671     stream->send_key[0] = send;
672     stream->receive_key[0] = receive;
673   } else {
674     if (stream->send_key[0])
675       silc_cipher_free(stream->send_key[0]);
676     if (stream->send_key[1])
677       silc_cipher_free(stream->receive_key[0]);
678
679     stream->send_key[0] = send;
680     stream->receive_key[0] = receive;
681   }
682
683   silc_mutex_unlock(stream->lock);
684 }
685
686 /* Return current ciphers from packet stream */
687
688 SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
689                                  SilcCipher *receive)
690 {
691   if (!stream->send_key[0] && !stream->receive_key[0])
692     return FALSE;
693
694   silc_mutex_lock(stream->lock);
695
696   if (send)
697     *send = stream->send_key[0];
698   if (receive)
699     *receive = stream->receive_key[0];
700
701   silc_mutex_unlock(stream->lock);
702
703   return TRUE;
704 }
705
706 /* Set HMACs for packet stream */
707
708 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
709                            SilcHmac receive)
710 {
711   SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
712
713   silc_mutex_lock(stream->lock);
714
715   /* In case IV Included is set, save the old HMAC */
716   if (stream->iv_included) {
717     if (stream->send_hmac[1]) {
718       silc_hmac_free(stream->send_hmac[1]);
719       stream->send_hmac[1] = stream->send_hmac[0];
720     }
721     if (stream->receive_hmac[1]) {
722       silc_hmac_free(stream->receive_hmac[1]);
723       stream->receive_hmac[1] = stream->receive_hmac[0];
724     }
725
726     stream->send_hmac[0] = send;
727     stream->receive_hmac[0] = receive;
728   } else {
729     if (stream->send_hmac[0])
730       silc_hmac_free(stream->send_hmac[0]);
731     if (stream->receive_hmac[0])
732       silc_hmac_free(stream->receive_hmac[0]);
733
734     stream->send_hmac[0] = send;
735     stream->receive_hmac[0] = receive;
736   }
737
738   silc_mutex_unlock(stream->lock);
739 }
740
741 /* Return current HMACs from packet stream */
742
743 SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
744                                SilcHmac *receive)
745 {
746   if (!stream->send_hmac[0] && !stream->receive_hmac[0])
747     return FALSE;
748
749   silc_mutex_lock(stream->lock);
750
751   if (send)
752     *send = stream->send_hmac[0];
753   if (receive)
754     *receive = stream->receive_hmac[0];
755
756   silc_mutex_unlock(stream->lock);
757
758   return TRUE;
759 }
760
761 /* Set SILC IDs to packet stream */
762
763 SilcBool silc_packet_set_ids(SilcPacketStream stream,
764                              SilcIdType src_id_type, const void *src_id,
765                              SilcIdType dst_id_type, const void *dst_id)
766 {
767   SilcUInt32 len;
768   unsigned char tmp[32];
769
770   if (!src_id && !dst_id)
771     return FALSE;
772
773   SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
774
775   silc_mutex_lock(stream->lock);
776
777   if (src_id) {
778     silc_free(stream->src_id);
779     if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
780       silc_mutex_unlock(stream->lock);
781       return FALSE;
782     }
783     stream->src_id = silc_memdup(tmp, len);
784     if (!stream->src_id) {
785       silc_mutex_unlock(stream->lock);
786       return FALSE;
787     }
788     stream->src_id_type = src_id_type;
789     stream->src_id_len = len;
790   }
791
792   if (dst_id) {
793     silc_free(stream->dst_id);
794     if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
795       silc_mutex_unlock(stream->lock);
796       return FALSE;
797     }
798     stream->dst_id = silc_memdup(tmp, len);
799     if (!stream->dst_id) {
800       silc_mutex_unlock(stream->lock);
801       return FALSE;
802     }
803     stream->dst_id_type = dst_id_type;
804     stream->dst_id_len = len;
805   }
806
807   silc_mutex_unlock(stream->lock);
808
809   return TRUE;
810 }
811
812 /* Adds Security ID (SID) */
813
814 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
815 {
816   if (!stream->iv_included)
817     return FALSE;
818
819   SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
820
821   stream->sid = sid;
822   return TRUE;
823 }
824
825 /* Free packet */
826
827 void silc_packet_free(SilcPacket packet)
828 {
829   SilcPacketStream stream = packet->stream;
830
831   SILC_LOG_DEBUG(("Freeing packet %p", packet));
832
833 #if defined(SILC_DEBUG)
834   /* Check for double free */
835   assert(packet->stream != NULL);
836 #endif /* SILC_DEBUG */
837
838   silc_mutex_lock(stream->engine->lock);
839
840   packet->stream = NULL;
841   packet->src_id = packet->dst_id = NULL;
842   silc_buffer_reset(&packet->buffer);
843
844   /* Put the packet back to freelist */
845   silc_list_add(stream->engine->packet_pool, packet);
846   if (silc_list_count(stream->engine->packet_pool) == 1)
847     silc_list_start(stream->engine->packet_pool);
848
849   silc_mutex_unlock(stream->engine->lock);
850 }
851
852 /****************************** Packet Sending ******************************/
853
854 /* Prepare outgoing data buffer for packet sending.  Returns the
855    pointer to that buffer into the `packet'. */
856
857 static SilcBool silc_packet_send_prepare(SilcPacketStream stream,
858                                          SilcUInt32 totlen,
859                                          SilcHmac hmac,
860                                          SilcBuffer packet)
861 {
862   unsigned char *oldptr;
863   unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
864
865   totlen += mac_len;
866
867   /* Allocate more space if needed */
868   if (silc_buffer_taillen(&stream->outbuf) < totlen) {
869     if (!silc_buffer_realloc(&stream->outbuf,
870                              silc_buffer_truelen(&stream->outbuf) + totlen))
871       return FALSE;
872   }
873
874   /* Pull data area for the new packet, and return pointer to the start of
875      the data area and save the pointer in to the `packet'.  MAC is pulled
876      later after it's computed. */
877   oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
878   silc_buffer_set(packet, oldptr, totlen);
879   silc_buffer_push_tail(packet, mac_len);
880
881   return TRUE;
882 }
883
884 /* Internal routine to send packet */
885
886 static SilcBool silc_packet_send_raw(SilcPacketStream stream,
887                                      SilcPacketType type,
888                                      SilcPacketFlags flags,
889                                      SilcIdType src_id_type,
890                                      unsigned char *src_id,
891                                      SilcUInt32 src_id_len,
892                                      SilcIdType dst_id_type,
893                                      unsigned char *dst_id,
894                                      SilcUInt32 dst_id_len,
895                                      const unsigned char *data,
896                                      SilcUInt32 data_len,
897                                      SilcCipher cipher,
898                                      SilcHmac hmac)
899 {
900   unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
901   int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
902   int i, enclen, truelen, padlen, ivlen = 0, psnlen = 0;
903   SilcBufferStruct packet;
904
905   SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d,"
906                   "data len %d", silc_get_packet_name(type), stream->send_psn,
907                   flags, src_id_type, dst_id_type, data_len));
908
909   /* Get the true length of the packet. This is saved as payload length
910      into the packet header.  This does not include the length of the
911      padding. */
912   data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
913                                             src_id_len + dst_id_len));
914   enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
915                       src_id_len + dst_id_len);
916
917   /* If IV is included, the SID, IV and sequence number is added to packet */
918   if (stream->iv_included && cipher) {
919     psnlen = sizeof(psn);
920     ivlen = block_len + 1;
921     iv[0] = stream->sid;
922     memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
923   }
924
925   /* We automatically figure out the packet structure from the packet
926      type and flags, and calculate correct length.  Private messages with
927      private keys and channel messages are special packets as their
928      payload is encrypted already. */
929   if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
930        flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
931       type == SILC_PACKET_CHANNEL_MESSAGE) {
932
933     /* Padding is calculated from header + IDs */
934     SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
935                         psnlen), block_len, padlen);
936
937     /* Length to encrypt, header + IDs + padding. */
938     enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
939               padlen + psnlen);
940   } else {
941
942     /* Padding is calculated from true length of the packet */
943     if (flags & SILC_PACKET_FLAG_LONG_PAD)
944       SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
945     else
946       SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
947
948     enclen += padlen + psnlen;
949   }
950
951   /* Remove implementation specific flags */
952   flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
953
954   /* Get random padding */
955   for (i = 0; i < padlen; i++) tmppad[i] =
956                                  silc_rng_get_byte_fast(stream->engine->rng);
957
958   silc_mutex_lock(stream->lock);
959
960   /* Get packet pointer from the outgoing buffer */
961   if (!silc_packet_send_prepare(stream, truelen + padlen + ivlen + psnlen,
962                                 hmac, &packet)) {
963     silc_mutex_unlock(stream->lock);
964     return FALSE;
965   }
966
967   SILC_PUT32_MSB(stream->send_psn, psn);
968
969   /* Create the packet.  This creates the SILC header, adds padding, and
970      the actual packet data. */
971   i = silc_buffer_format(&packet,
972                          SILC_STR_UI_XNSTRING(iv, ivlen),
973                          SILC_STR_UI_XNSTRING(psn, psnlen),
974                          SILC_STR_UI_SHORT(truelen),
975                          SILC_STR_UI_CHAR(flags),
976                          SILC_STR_UI_CHAR(type),
977                          SILC_STR_UI_CHAR(padlen),
978                          SILC_STR_UI_CHAR(0),
979                          SILC_STR_UI_CHAR(src_id_len),
980                          SILC_STR_UI_CHAR(dst_id_len),
981                          SILC_STR_UI_CHAR(src_id_type),
982                          SILC_STR_UI_XNSTRING(src_id, src_id_len),
983                          SILC_STR_UI_CHAR(dst_id_type),
984                          SILC_STR_UI_XNSTRING(dst_id, dst_id_len),
985                          SILC_STR_UI_XNSTRING(tmppad, padlen),
986                          SILC_STR_UI_XNSTRING(data, data_len),
987                          SILC_STR_END);
988   if (i < 0) {
989     silc_mutex_unlock(stream->lock);
990     return FALSE;
991   }
992
993   SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
994                    silc_buffer_data(&packet), silc_buffer_len(&packet));
995
996   /* Encrypt the packet */
997   if (cipher) {
998     SILC_LOG_DEBUG(("Encrypting packet"));
999     if (!silc_cipher_encrypt(cipher, packet.data + ivlen,
1000                              packet.data + ivlen, enclen, NULL)) {
1001       SILC_LOG_ERROR(("Packet encryption failed"));
1002       silc_mutex_unlock(stream->lock);
1003       return FALSE;
1004     }
1005   }
1006
1007   /* Compute HMAC */
1008   if (hmac) {
1009     SilcUInt32 mac_len;
1010
1011     /* MAC is computed from the entire encrypted packet data, and put
1012        to the end of the packet. */
1013     silc_hmac_init(hmac);
1014     silc_hmac_update(hmac, psn, sizeof(psn));
1015     silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1016     silc_hmac_final(hmac, packet.tail, &mac_len);
1017     silc_buffer_pull_tail(&packet, mac_len);
1018     stream->send_psn++;
1019   }
1020
1021   /* Write the packet to the stream */
1022   while (silc_buffer_len(&stream->outbuf) > 0) {
1023     i = silc_stream_write(stream->stream, stream->outbuf.data,
1024                           silc_buffer_len(&stream->outbuf));
1025     if (i == 0) {
1026       /* EOS */
1027       silc_buffer_reset(&stream->outbuf);
1028       silc_mutex_unlock(stream->lock);
1029       SILC_PACKET_CALLBACK_EOS(stream);
1030       return FALSE;
1031     }
1032
1033     if (i == -2) {
1034       /* Error */
1035       silc_buffer_reset(&stream->outbuf);
1036       silc_mutex_unlock(stream->lock);
1037       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_WRITE);
1038       return FALSE;
1039     }
1040
1041     if (i == -1) {
1042       /* Cannot write now, write later. */
1043       silc_mutex_unlock(stream->lock);
1044       return TRUE;
1045     }
1046
1047     /* Wrote data */
1048     silc_buffer_pull(&stream->outbuf, i);
1049   }
1050   silc_buffer_reset(&stream->outbuf);
1051
1052   silc_mutex_unlock(stream->lock);
1053   return TRUE;
1054 }
1055
1056 /* Sends a packet */
1057
1058 SilcBool silc_packet_send(SilcPacketStream stream,
1059                           SilcPacketType type, SilcPacketFlags flags,
1060                           const unsigned char *data, SilcUInt32 data_len)
1061 {
1062   return silc_packet_send_raw(stream, type, flags,
1063                               stream->src_id_type,
1064                               stream->src_id,
1065                               stream->src_id_len,
1066                               stream->dst_id_type,
1067                               stream->dst_id,
1068                               stream->dst_id_len,
1069                               data, data_len,
1070                               stream->send_key[0],
1071                               stream->send_hmac[0]);
1072 }
1073
1074 /* Sends a packet, extended routine */
1075
1076 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1077                               SilcPacketType type, SilcPacketFlags flags,
1078                               SilcIdType src_id_type, void *src_id,
1079                               SilcIdType dst_id_type, void *dst_id,
1080                               const unsigned char *data, SilcUInt32 data_len,
1081                               SilcCipher cipher, SilcHmac hmac)
1082 {
1083   unsigned char src_id_data[32], dst_id_data[32];
1084   SilcUInt32 src_id_len, dst_id_len;
1085
1086   if (src_id)
1087     if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1088                         sizeof(src_id_data), &src_id_len))
1089       return FALSE;
1090   if (dst_id)
1091     if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1092                         sizeof(dst_id_data), &dst_id_len))
1093       return FALSE;
1094
1095   return silc_packet_send_raw(stream, type, flags,
1096                               src_id ? src_id_type : stream->src_id_type,
1097                               src_id ? src_id_data : stream->src_id,
1098                               src_id ? src_id_len : stream->src_id_len,
1099                               dst_id ? dst_id_type : stream->dst_id_type,
1100                               dst_id ? dst_id_data : stream->dst_id,
1101                               dst_id ? dst_id_len : stream->dst_id_len,
1102                               data, data_len,
1103                               cipher ? cipher : stream->send_key[0],
1104                               hmac ? hmac : stream->send_hmac[0]);
1105 }
1106
1107
1108 /***************************** Packet Receiving *****************************/
1109
1110 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1111
1112 static SilcBool silc_packet_check_mac(SilcHmac hmac,
1113                                       const unsigned char *data,
1114                                       SilcUInt32 data_len,
1115                                       const unsigned char *packet_mac,
1116                                       const unsigned char *packet_seq,
1117                                       SilcUInt32 sequence)
1118 {
1119   /* Check MAC */
1120   if (hmac) {
1121     unsigned char mac[32], psn[4];
1122     SilcUInt32 mac_len;
1123
1124     SILC_LOG_DEBUG(("Verifying MAC"));
1125
1126     /* Compute HMAC of packet */
1127     silc_hmac_init(hmac);
1128
1129     if (!packet_seq) {
1130       SILC_PUT32_MSB(sequence, psn);
1131       silc_hmac_update(hmac, psn, 4);
1132     } else
1133       silc_hmac_update(hmac, packet_seq, 4);
1134
1135     silc_hmac_update(hmac, data, data_len);
1136     silc_hmac_final(hmac, mac, &mac_len);
1137
1138     /* Compare the MAC's */
1139     if (memcmp(packet_mac, mac, mac_len)) {
1140       SILC_LOG_DEBUG(("MAC failed"));
1141       return FALSE;
1142     }
1143
1144     SILC_LOG_DEBUG(("MAC is Ok"));
1145   }
1146
1147   return TRUE;
1148 }
1149
1150 /* Decrypts SILC packet.  Handles both normal and special packet decryption.
1151    Return 0 when packet is normal and 1 when it it special, -1 on error. */
1152
1153 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1154                                SilcUInt32 sequence, SilcBuffer buffer,
1155                                SilcBool normal)
1156 {
1157   if (normal == TRUE) {
1158     if (cipher) {
1159       /* Decrypt rest of the packet */
1160       SILC_LOG_DEBUG(("Decrypting the packet"));
1161       if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1162                                silc_buffer_len(buffer), NULL))
1163         return -1;
1164     }
1165     return 0;
1166
1167   } else {
1168     /* Decrypt rest of the header plus padding */
1169     if (cipher) {
1170       SilcUInt16 len;
1171       SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1172
1173       SILC_LOG_DEBUG(("Decrypting the header"));
1174
1175       /* Padding length + src id len + dst id len + header length - 16
1176          bytes already decrypted, gives the rest of the encrypted packet */
1177       silc_buffer_push(buffer, block_len);
1178       len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1179               (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1180              block_len);
1181       silc_buffer_pull(buffer, block_len);
1182
1183       if (len > silc_buffer_len(buffer)) {
1184         SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1185                         "packet dropped"));
1186         return -1;
1187       }
1188       if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1189                                len, NULL))
1190         return -1;
1191     }
1192
1193     return 1;
1194   }
1195 }
1196
1197 /* Parses the packet. This is called when a whole packet is ready to be
1198    parsed. The buffer sent must be already decrypted before calling this
1199    function. */
1200
1201 static SilcBool silc_packet_parse(SilcPacket packet)
1202 {
1203   SilcBuffer buffer = &packet->buffer;
1204   SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1205   SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1206   int len, ret;
1207
1208   SILC_LOG_DEBUG(("Parsing incoming packet"));
1209
1210   /* Parse the buffer.  This parses the SILC header of the packet. */
1211   len = silc_buffer_unformat(buffer,
1212                              SILC_STR_OFFSET(6),
1213                              SILC_STR_UI_CHAR(&src_id_len),
1214                              SILC_STR_UI_CHAR(&dst_id_len),
1215                              SILC_STR_UI_CHAR(&src_id_type),
1216                              SILC_STR_END);
1217   if (len == -1) {
1218     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1219     return FALSE;
1220   }
1221
1222   if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1223       dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1224     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1225                     packet->src_id_len, packet->dst_id_len));
1226     return FALSE;
1227   }
1228
1229   ret = silc_buffer_unformat(buffer,
1230                              SILC_STR_OFFSET(len),
1231                              SILC_STR_UI_XNSTRING(&packet->src_id,
1232                                                   src_id_len),
1233                              SILC_STR_UI_CHAR(&dst_id_type),
1234                              SILC_STR_UI_XNSTRING(&packet->dst_id,
1235                                                   dst_id_len),
1236                              SILC_STR_OFFSET(padlen),
1237                              SILC_STR_END);
1238   if (ret == -1) {
1239     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1240     return FALSE;
1241   }
1242
1243   if (src_id_type > SILC_ID_CHANNEL ||
1244       dst_id_type > SILC_ID_CHANNEL) {
1245     SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1246                     src_id_type, dst_id_type));
1247     return FALSE;
1248   }
1249
1250   packet->src_id_len = src_id_len;
1251   packet->dst_id_len = dst_id_len;
1252   packet->src_id_type = src_id_type;
1253   packet->dst_id_type = dst_id_type;
1254
1255   SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_len(buffer)),
1256                    buffer->data, silc_buffer_len(buffer));
1257
1258   /* Pull SILC header and padding from packet to get the data payload */
1259   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
1260                    packet->src_id_len + packet->dst_id_len + padlen);
1261
1262   SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1263                   silc_get_packet_name(packet->type)));
1264
1265   return TRUE;
1266 }
1267
1268 /* Dispatch packet to application.  Called with stream->lock locked. */
1269
1270 static void silc_packet_dispatch(SilcPacket packet)
1271 {
1272   SilcPacketStream stream = packet->stream;
1273   SilcPacketProcess p;
1274   SilcBool default_sent = FALSE;
1275   SilcPacketType *pt;
1276
1277   /* Parse the packet */
1278   if (!silc_packet_parse(packet)) {
1279     silc_mutex_unlock(packet->stream->lock);
1280     SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1281     silc_mutex_lock(packet->stream->lock);
1282     silc_packet_free(packet);
1283     return;
1284   }
1285
1286   /* Dispatch packet to all packet processors that want it */
1287
1288   if (!stream->process) {
1289     /* Send to default processor as no others exist */
1290     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1291     silc_mutex_unlock(packet->stream->lock);
1292     if (!stream->engine->callbacks->
1293         packet_receive(stream->engine, stream, packet,
1294                        stream->engine->callback_context,
1295                        stream->stream_context))
1296       silc_packet_free(packet);
1297     silc_mutex_lock(packet->stream->lock);
1298     return;
1299   }
1300
1301   silc_dlist_start(stream->process);
1302   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1303
1304     /* If priority is 0 or less, we send to default processor first
1305        because default processor has 0 priority */
1306     if (!default_sent && p->priority <= 0) {
1307       SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1308       default_sent = TRUE;
1309       silc_mutex_unlock(packet->stream->lock);
1310       if (stream->engine->callbacks->
1311           packet_receive(stream->engine, stream, packet,
1312                          stream->engine->callback_context,
1313                          stream->stream_context)) {
1314         silc_mutex_lock(packet->stream->lock);
1315         return;
1316       }
1317       silc_mutex_lock(packet->stream->lock);
1318     }
1319
1320     /* Send to processor */
1321     if (!p->types) {
1322       /* Send all packet types */
1323       SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1324       silc_mutex_unlock(packet->stream->lock);
1325       if (p->callbacks->packet_receive(stream->engine, stream, packet,
1326                                        p->callback_context,
1327                                        stream->stream_context)) {
1328         silc_mutex_lock(packet->stream->lock);
1329         return;
1330       }
1331       silc_mutex_lock(packet->stream->lock);
1332     } else {
1333       /* Send specific types */
1334       for (pt = p->types; *pt; pt++) {
1335         if (*pt != packet->type)
1336           continue;
1337         SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1338         silc_mutex_unlock(packet->stream->lock);
1339         if (p->callbacks->packet_receive(stream->engine, stream, packet,
1340                                          p->callback_context,
1341                                          stream->stream_context)) {
1342           silc_mutex_lock(packet->stream->lock);
1343           return;
1344         }
1345         silc_mutex_lock(packet->stream->lock);
1346         break;
1347       }
1348     }
1349   }
1350
1351   if (!default_sent) {
1352     /* Send to default processor as it has not been sent yet */
1353     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1354     silc_mutex_unlock(packet->stream->lock);
1355     if (stream->engine->callbacks->
1356         packet_receive(stream->engine, stream, packet,
1357                        stream->engine->callback_context,
1358                        stream->stream_context)) {
1359       silc_mutex_lock(packet->stream->lock);
1360       return;
1361     }
1362     silc_mutex_lock(packet->stream->lock);
1363   }
1364
1365   /* If we got here, no one wanted the packet, so drop it */
1366   silc_packet_free(packet);
1367 }
1368
1369 /* Process incoming data and parse packets.  Called with stream->lock
1370    locked. */
1371
1372 static void silc_packet_read_process(SilcPacketStream stream)
1373 {
1374   SilcCipher cipher;
1375   SilcHmac hmac;
1376   SilcPacket packet;
1377   SilcUInt8 sid;
1378   SilcUInt16 packetlen;
1379   SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1380   unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1381   unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1382   SilcBool normal = TRUE;
1383   int ret;
1384
1385   /* Parse the packets from the data */
1386   while (silc_buffer_len(&stream->inbuf) > 0) {
1387     ivlen = psnlen = 0;
1388     cipher = stream->receive_key[0];
1389     hmac = stream->receive_hmac[0];
1390
1391     if (silc_buffer_len(&stream->inbuf) <
1392         stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1393         SILC_PACKET_MIN_HEADER_LEN) {
1394       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1395       return;
1396     }
1397
1398     if (hmac)
1399       mac_len = silc_hmac_len(hmac);
1400     else
1401       mac_len = 0;
1402
1403     /* Decrypt first block of the packet to get the length field out */
1404     if (cipher) {
1405       block_len = silc_cipher_get_block_len(cipher);
1406
1407       if (stream->iv_included) {
1408         /* SID, IV and sequence number is included in the ciphertext */
1409         sid = (SilcUInt8)stream->inbuf.data[0];
1410         memcpy(iv, stream->inbuf.data + 1, block_len);
1411         ivlen = block_len + 1;
1412         psnlen = 4;
1413
1414         /* Check SID, and get correct decryption key */
1415         if (sid != stream->sid) {
1416           /* If SID is recent get the previous key and use it */
1417           if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
1418               stream->receive_key[1] && !stream->receive_hmac[1]) {
1419             cipher = stream->receive_key[1];
1420             hmac = stream->receive_hmac[1];
1421           } else {
1422             /* The SID is unknown, drop rest of the data in buffer */
1423             SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
1424                             sid, stream->sid));
1425             silc_mutex_unlock(stream->lock);
1426             SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
1427             silc_mutex_lock(stream->lock);
1428             silc_buffer_reset(&stream->inbuf);
1429             return;
1430           }
1431         }
1432       } else {
1433         memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1434       }
1435
1436       silc_cipher_decrypt(cipher, stream->inbuf.data + ivlen, tmp,
1437                           block_len, iv);
1438
1439       header = tmp;
1440       if (stream->iv_included) {
1441         /* Take sequence number from packet */
1442         packet_seq = header;
1443         header += 4;
1444       }
1445     } else {
1446       block_len = SILC_PACKET_MIN_HEADER_LEN;
1447       header = stream->inbuf.data;
1448     }
1449
1450     /* Get packet length and full packet length with padding */
1451     SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1452
1453     /* Sanity checks */
1454     if (packetlen < SILC_PACKET_MIN_LEN) {
1455       SILC_LOG_ERROR(("Received too short packet"));
1456       silc_mutex_unlock(stream->lock);
1457       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1458       silc_mutex_lock(stream->lock);
1459       memset(tmp, 0, sizeof(tmp));
1460       silc_buffer_reset(&stream->inbuf);
1461       return;
1462     }
1463
1464     if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
1465       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1466                       "(%d bytes)",
1467                       paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1468       memset(tmp, 0, sizeof(tmp));
1469       return;
1470     }
1471
1472     /* Check MAC of the packet */
1473     if (!silc_packet_check_mac(hmac, stream->inbuf.data,
1474                                paddedlen + ivlen,
1475                                stream->inbuf.data + ivlen + paddedlen,
1476                                packet_seq, stream->receive_psn)) {
1477       silc_mutex_unlock(stream->lock);
1478       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1479       silc_mutex_lock(stream->lock);
1480       memset(tmp, 0, sizeof(tmp));
1481       silc_buffer_reset(&stream->inbuf);
1482       return;
1483     }
1484
1485     /* Get packet */
1486     packet = silc_packet_alloc(stream->engine);
1487     if (!packet) {
1488       silc_mutex_unlock(stream->lock);
1489       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1490       silc_mutex_lock(stream->lock);
1491       memset(tmp, 0, sizeof(tmp));
1492       silc_buffer_reset(&stream->inbuf);
1493       return;
1494     }
1495
1496     /* Allocate more space to packet buffer, if needed */
1497     if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1498       if (!silc_buffer_realloc(&packet->buffer,
1499                                silc_buffer_truelen(&packet->buffer) +
1500                                (paddedlen -
1501                                 silc_buffer_truelen(&packet->buffer)))) {
1502         silc_mutex_unlock(stream->lock);
1503         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1504         silc_mutex_lock(stream->lock);
1505         silc_packet_free(packet);
1506         memset(tmp, 0, sizeof(tmp));
1507         silc_buffer_reset(&stream->inbuf);
1508         return;
1509       }
1510     }
1511
1512     /* Parse packet header */
1513     packet->flags = (SilcPacketFlags)header[2];
1514     packet->type = (SilcPacketType)header[3];
1515
1516     if (stream->engine->local_is_router) {
1517       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1518           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1519         normal = FALSE;
1520       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1521                (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1522                 stream->is_router == TRUE))
1523         normal = TRUE;
1524     } else {
1525       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1526           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1527         normal = FALSE;
1528       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1529         normal = TRUE;
1530     }
1531
1532     SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1533                       stream->receive_psn, paddedlen + ivlen + mac_len),
1534                      stream->inbuf.data, paddedlen + ivlen + mac_len);
1535
1536     /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1537     silc_buffer_pull_tail(&packet->buffer, paddedlen);
1538     silc_buffer_put(&packet->buffer, header, block_len - psnlen);
1539     silc_buffer_pull(&packet->buffer, block_len - psnlen);
1540     silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
1541                                       psnlen + (block_len - psnlen)),
1542                     paddedlen - ivlen - psnlen - (block_len - psnlen));
1543     if (cipher) {
1544       silc_cipher_set_iv(cipher, iv);
1545       ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
1546                                 &packet->buffer, normal);
1547       if (ret < 0) {
1548         silc_mutex_unlock(stream->lock);
1549         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1550         silc_mutex_lock(stream->lock);
1551         silc_packet_free(packet);
1552         memset(tmp, 0, sizeof(tmp));
1553         return;
1554       }
1555
1556       stream->receive_psn++;
1557     }
1558     silc_buffer_push(&packet->buffer, block_len);
1559
1560     /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1561     silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1562
1563     /* Dispatch the packet to application */
1564     packet->stream = stream;
1565     silc_packet_dispatch(packet);
1566   }
1567
1568   silc_buffer_reset(&stream->inbuf);
1569 }
1570
1571
1572 /****************************** Packet Waiting ******************************/
1573
1574 /* Packet wait receive callback */
1575 static SilcBool
1576 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1577                                 SilcPacketStream stream,
1578                                 SilcPacket packet,
1579                                 void *callback_context,
1580                                 void *stream_context);
1581
1582 /* Packet waiting callbacks */
1583 static SilcPacketCallbacks silc_packet_wait_cbs =
1584 {
1585   silc_packet_wait_packet_receive, NULL, NULL
1586 };
1587
1588 /* Packet waiting context */
1589 typedef struct {
1590   SilcMutex wait_lock;
1591   SilcCond wait_cond;
1592   SilcList packet_queue;
1593   unsigned int stopped     : 1;
1594 } *SilcPacketWait;
1595
1596 /* Packet wait receive callback */
1597
1598 static SilcBool
1599 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1600                                 SilcPacketStream stream,
1601                                 SilcPacket packet,
1602                                 void *callback_context,
1603                                 void *stream_context)
1604 {
1605   SilcPacketWait pw = callback_context;
1606
1607   /* Signal the waiting thread for a new packet */
1608   silc_mutex_lock(pw->wait_lock);
1609
1610   if (pw->stopped) {
1611     silc_mutex_unlock(pw->wait_lock);
1612     return FALSE;
1613   }
1614
1615   silc_list_add(pw->packet_queue, packet);
1616   silc_cond_broadcast(pw->wait_cond);
1617
1618   silc_mutex_unlock(pw->wait_lock);
1619
1620   return TRUE;
1621 }
1622
1623 /* Initialize packet waiting */
1624
1625 void *silc_packet_wait_init(SilcPacketStream stream, ...)
1626 {
1627   SilcPacketWait pw;
1628   SilcBool ret;
1629   va_list ap;
1630
1631   pw = silc_calloc(1, sizeof(*pw));
1632   if (!pw)
1633     return NULL;
1634
1635   /* Allocate mutex and conditional variable */
1636   if (!silc_mutex_alloc(&pw->wait_lock)) {
1637     silc_free(pw);
1638     return NULL;
1639   }
1640   if (!silc_cond_alloc(&pw->wait_cond)) {
1641     silc_mutex_free(pw->wait_lock);
1642     silc_free(pw);
1643     return NULL;
1644   }
1645
1646   /* Link to the packet stream for the requested packet types */
1647   va_start(ap, stream);
1648   ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
1649                                    10000000, ap);
1650   va_end(ap);
1651   if (!ret) {
1652     silc_cond_free(pw->wait_cond);
1653     silc_mutex_free(pw->wait_lock);
1654     silc_free(pw);
1655     return NULL;
1656   }
1657
1658   /* Initialize packet queue */
1659   silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
1660
1661   return (void *)pw;
1662 }
1663
1664 /* Uninitialize packet waiting */
1665
1666 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
1667 {
1668   SilcPacketWait pw = waiter;
1669   SilcPacket packet;
1670
1671   /* Signal any threads to stop waiting */
1672   silc_mutex_lock(pw->wait_lock);
1673   pw->stopped = TRUE;
1674   silc_cond_broadcast(pw->wait_cond);
1675   silc_mutex_unlock(pw->wait_lock);
1676
1677   /* Re-acquire lock and free resources */
1678   silc_mutex_lock(pw->wait_lock);
1679   silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
1680
1681   /* Free any remaining packets */
1682   silc_list_start(pw->packet_queue);
1683   while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
1684     silc_packet_free(packet);
1685
1686   silc_mutex_unlock(pw->wait_lock);
1687   silc_cond_free(pw->wait_cond);
1688   silc_mutex_free(pw->wait_lock);
1689   silc_free(pw);
1690 }
1691
1692 /* Blocks thread until a packet has been received. */
1693
1694 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
1695 {
1696   SilcPacketWait pw = waiter;
1697   SilcBool ret = FALSE;
1698
1699   silc_mutex_lock(pw->wait_lock);
1700
1701   /* Wait here until packet has arrived */
1702   while (silc_list_count(pw->packet_queue) == 0) {
1703     if (pw->stopped) {
1704       silc_mutex_unlock(pw->wait_lock);
1705       return -1;
1706     }
1707     ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
1708   }
1709
1710   /* Return packet */
1711   silc_list_start(pw->packet_queue);
1712   *return_packet = silc_list_get(pw->packet_queue);
1713   silc_list_del(pw->packet_queue, *return_packet);
1714
1715   silc_mutex_unlock(pw->wait_lock);
1716
1717   return ret == TRUE ? 1 : 0;
1718 }