Global cosmetic change.
[silc.git] / lib / silccore / silcpacket.c
1 /*
2
3   silcpacket.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 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 /*
21  * Created: Fri Jul 25 18:52:14 1997
22  */
23 /*
24  * $Id$
25  * $Log$
26  * Revision 1.2  2000/07/05 06:06:35  priikone
27  *      Global cosmetic change.
28  *
29  * Revision 1.1.1.1  2000/06/27 11:36:55  priikone
30  *      Imported from internal CVS/Added Log headers.
31  *
32  *
33  */
34
35 #include "silcincludes.h"
36
37 /* Writes data from encrypted buffer to the socket connection. If the
38    data cannot be written at once, it will be written later with a timeout. 
39    The data is written from the data section of the buffer, not from head
40    or tail section. This automatically pulls the data section towards end
41    after writing the data. */
42
43 int silc_packet_write(int sock, SilcBuffer src)
44 {
45   int ret = 0;
46
47   SILC_LOG_DEBUG(("Writing data to socket %d", sock));
48
49   if (src->len > 0) {
50     ret = write(sock, src->data, src->len);
51     if (ret < 0) {
52       if (errno == EAGAIN) {
53         SILC_LOG_DEBUG(("Could not write immediately, will do it later"));
54         return -2;
55       }
56       SILC_LOG_ERROR(("Cannot write to socket: %s", strerror(errno)));
57       return -1;
58     }
59
60     silc_buffer_pull(src, ret);
61   }
62
63   SILC_LOG_DEBUG(("Wrote data %d bytes", ret));
64
65   return ret;
66 }
67
68 /* Reads data from the socket connection into the incoming data buffer.
69    However, this does not parse the packet, it only reads some amount from
70    the network. If there are more data available that can be read at a time
71    the rest of the data will be read later with a timeout and only after
72    that the packet is ready to be parsed. 
73
74    The destination buffer sent as argument must be initialized before 
75    calling this function, and, the data section and the start of the tail
76    section must be same. Ie. we add the read data to the tail section of
77    the buffer hence the data section is the start of the buffer.
78
79    This returns amount of bytes read or -1 on error or -2 on case where
80    all of the data could not be read at once. */
81
82 int silc_packet_read(int sock, SilcBuffer dest)
83 {
84   int len = 0;
85   unsigned char buf[SILC_PACKET_READ_SIZE];
86
87   SILC_LOG_DEBUG(("Reading data from socket %d", sock));
88
89   /* Read the data from the socket. */
90   len = read(sock, buf, sizeof(buf));
91   if (len < 0) {
92     if (errno == EAGAIN) {
93       SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
94       return -2;
95     }
96     SILC_LOG_ERROR(("Cannot read from socket: %d", strerror(errno)));
97     return -1;
98   }
99
100   if (!len)
101     return 0;
102
103   /* Insert the data to the buffer. If the data doesn't fit to the 
104      buffer space is allocated for the buffer.  
105      XXX: I don't like this. -Pekka */
106   if (dest) {
107
108     /* If the data doesn't fit we just have to allocate a whole new 
109        data area */
110     if (dest->truelen <= len) {
111
112       /* Free the old buffer */
113       memset(dest->head, 'F', dest->truelen);
114       silc_free(dest->head);
115
116       /* Allocate new data area */
117       len += SILC_PACKET_DEFAULT_SIZE;
118       dest->data = silc_calloc(len, sizeof(char));
119       dest->truelen = len;
120       dest->len = 0;
121       dest->head = dest->data;
122       dest->data = dest->data;
123       dest->tail = dest->data;
124       dest->end = dest->data + dest->truelen;
125       len -= SILC_PACKET_DEFAULT_SIZE;
126     }
127
128     silc_buffer_put_tail(dest, buf, len);
129     silc_buffer_pull_tail(dest, len);
130   }
131
132   SILC_LOG_DEBUG(("Read %d bytes", len));
133
134   return len;
135 }
136
137 /* Encrypts a packet. */
138
139 void silc_packet_encrypt(SilcCipher cipher, SilcBuffer buffer,
140                          unsigned int len)
141 {
142   SILC_LOG_DEBUG(("Encrypting packet, cipher %s, len %d (%d)", 
143                   cipher->cipher->name, len, len - 2));
144
145   /* Encrypt the data area of the packet. 3 bytes of the packet
146      are not encrypted. */
147   cipher->cipher->encrypt(cipher->context, buffer->data + 2, 
148                           buffer->data + 2, len - 2, cipher->iv);
149
150 }
151
152 /* Decrypts a packet. */
153
154 void silc_packet_decrypt(SilcCipher cipher, SilcBuffer buffer, 
155                          unsigned int len)
156 {
157   SILC_LOG_DEBUG(("Decrypting packet, cipher %s, len %d (%d)", 
158                   cipher->cipher->name, len, len - 2));
159
160   /* Decrypt the data area of the packet. 2 bytes of the packet
161      are not decrypted (they are not encrypted). */
162   cipher->cipher->decrypt(cipher->context, buffer->data + 2, 
163                           buffer->data + 2, len - 2, cipher->iv);
164
165 }
166
167 /* Parses the packet. This is called when a whole packet is ready to be
168    parsed. The buffer sent must be already decrypted before calling this 
169    function. The len argument must be the true length of the packet. This 
170    function returns the type of the packet. The data section of the 
171    buffer is parsed, not head or tail sections. */
172
173 SilcPacketType silc_packet_parse(SilcPacketContext *ctx)
174 {
175   SilcBuffer buffer = ctx->buffer;
176   int len;
177
178   SILC_LOG_DEBUG(("Parsing incoming packet"));
179
180   /* Check the length of the buffer */
181   if (buffer->len < SILC_PACKET_MIN_LEN) {
182     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
183     return SILC_PACKET_NONE;
184   }
185
186   /* Parse the buffer. This parses the SILC header of the packet. */
187   len = silc_buffer_unformat(buffer, 
188                              SILC_STR_UI_SHORT(&ctx->truelen),
189                              SILC_STR_UI_CHAR(&ctx->flags),
190                              SILC_STR_UI_CHAR(&ctx->type),
191                              SILC_STR_UI_SHORT(&ctx->src_id_len),
192                              SILC_STR_UI_SHORT(&ctx->dst_id_len),
193                              SILC_STR_UI_CHAR(&ctx->src_id_type),
194                              SILC_STR_END);
195
196   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
197       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
198     SILC_LOG_ERROR(("Bad ID lengths in packet"));
199     return SILC_PACKET_NONE;
200   }
201
202   /* Calculate length of padding in packet */
203   ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen);
204
205   silc_buffer_pull(buffer, len);
206   silc_buffer_unformat(buffer, 
207                        SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
208                                                   ctx->src_id_len),
209                        SILC_STR_UI_CHAR(&ctx->dst_id_type),
210                        SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
211                                                   ctx->dst_id_len),
212                        SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
213                        SILC_STR_END);
214   silc_buffer_push(buffer, len);
215
216   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
217                    ctx->buffer->data, ctx->buffer->len);
218
219   /* Pull SILC header and padding from packet */
220   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
221                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
222
223   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
224
225   return ctx->type;
226 }
227
228 /* Perform special SILC Packet header parsing. This is required to some
229    packet types that have the data payload encrypted with different key
230    than the header area plus padding of the packet. Hence, this parses
231    the header in a way that it does not take the data area into account
232    and parses the header and padding area only. */
233
234 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx)
235 {
236   SilcBuffer buffer = ctx->buffer;
237   int len, tmplen;
238
239   SILC_LOG_DEBUG(("Parsing incoming packet"));
240
241   /* Check the length of the buffer */
242   if (buffer->len < SILC_PACKET_MIN_LEN) {
243     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
244     return SILC_PACKET_NONE;
245   }
246
247   /* Parse the buffer. This parses the SILC header of the packet. */
248   len = silc_buffer_unformat(buffer, 
249                              SILC_STR_UI_SHORT(&ctx->truelen),
250                              SILC_STR_UI_CHAR(&ctx->flags),
251                              SILC_STR_UI_CHAR(&ctx->type),
252                              SILC_STR_UI_SHORT(&ctx->src_id_len),
253                              SILC_STR_UI_SHORT(&ctx->dst_id_len),
254                              SILC_STR_UI_CHAR(&ctx->src_id_type),
255                              SILC_STR_END);
256
257   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
258       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
259     SILC_LOG_ERROR(("Bad ID lengths in packet"));
260     return SILC_PACKET_NONE;
261   }
262
263   /* Calculate length of padding in packet. As this is special packet
264      the data area is not used in the padding calculation as it won't
265      be decrypted by the caller. */
266   tmplen = SILC_PACKET_HEADER_LEN + ctx->src_id_len + ctx->dst_id_len;
267   ctx->padlen = SILC_PACKET_PADLEN(tmplen);
268
269   silc_buffer_pull(buffer, len);
270   silc_buffer_unformat(buffer, 
271                        SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
272                                                   ctx->src_id_len),
273                        SILC_STR_UI_CHAR(&ctx->dst_id_type),
274                        SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
275                                                   ctx->dst_id_len),
276                        SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
277                        SILC_STR_END);
278   silc_buffer_push(buffer, len);
279
280   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
281                    ctx->buffer->data, ctx->buffer->len);
282
283   /* Pull SILC header and padding from packet */
284   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
285                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
286
287   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
288
289   return ctx->type;
290 }
291
292 /* Assembles a new packet to be ready for send out. The buffer sent as
293    argument must include the data to be sent and it must not be encrypted. 
294    The packet also must have enough free space so that the SILC header
295    and padding maybe added to the packet. The packet is encrypted after 
296    this function has returned.
297
298    The buffer sent as argument should be something like following:
299
300    --------------------------------------------
301    | head             | data           | tail |
302    --------------------------------------------
303    ^                  ^
304    58 bytes           x bytes
305
306    So that the SILC header and 1 - 16 bytes of padding can fit to
307    the buffer. After assembly the buffer might look like this:
308
309    --------------------------------------------
310    | data                              |      |
311    --------------------------------------------
312    ^                                   ^
313    Start of assembled packet
314
315    Packet construct is as follows (* = won't be encrypted):
316
317    x bytes       SILC Header
318       2 bytes     Payload length  (*)
319       1 byte      Flags           (*)
320       1 byte      Packet type
321       1 byte      Source ID Type
322       2 bytes     Source ID Length
323       x bytes     Source ID
324       1 byte      Destination ID Type
325       2 bytes     Destination ID Length
326       x bytes     Destination ID
327
328    1 - 16 bytes    Padding
329
330    x bytes        Data payload
331
332    All fields in the packet will be authenticated by MAC. The MAC is
333    not computed here, it must be computed differently before encrypting
334    the packet.
335
336 */
337
338 void silc_packet_assemble(SilcPacketContext *ctx)
339 {
340   unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
341   int i;
342
343   SILC_LOG_DEBUG(("Assembling outgoing packet"));
344   
345   /* Get the true length of the packet. This is saved as payload length
346      into the packet header. This does not include the length of the
347      padding. */
348   if (!ctx->truelen)
349     ctx->truelen = ctx->buffer->len + SILC_PACKET_HEADER_LEN + 
350       ctx->src_id_len + ctx->dst_id_len;
351
352   /* Calculate the length of the padding. The padding is calculated from
353      the data that will be encrypted. As protocol states 3 first bytes
354      of the packet are not encrypted they are not included in the
355      padding calculation. */
356   if (!ctx->padlen)
357     ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen);
358
359   /* Put the start of the data section to the right place. */
360   silc_buffer_push(ctx->buffer, SILC_PACKET_HEADER_LEN + 
361                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
362
363   /* Get random padding */
364 #if 1
365   for (i = 0; i < ctx->padlen; i++)
366     tmppad[i] = silc_rng_get_byte(ctx->rng);
367 #else
368   /* XXX: For testing - to be removed */
369   memset(tmppad, 65, sizeof(tmppad));
370 #endif
371
372   /* Create the packet. This creates the SILC header and adds padding,
373      rest of the buffer remains as it is. */
374   silc_buffer_format(ctx->buffer, 
375                      SILC_STR_UI_SHORT(ctx->truelen),
376                      SILC_STR_UI_CHAR(ctx->flags),
377                      SILC_STR_UI_CHAR(ctx->type),
378                      SILC_STR_UI_SHORT(ctx->src_id_len),
379                      SILC_STR_UI_SHORT(ctx->dst_id_len),
380                      SILC_STR_UI_CHAR(ctx->src_id_type),
381                      SILC_STR_UI_XNSTRING(ctx->src_id, ctx->src_id_len),
382                      SILC_STR_UI_CHAR(ctx->dst_id_type),
383                      SILC_STR_UI_XNSTRING(ctx->dst_id, ctx->dst_id_len),
384                      SILC_STR_UI_XNSTRING(tmppad, ctx->padlen),
385                      SILC_STR_END);
386
387   SILC_LOG_HEXDUMP(("Assembled packet, len %d", ctx->buffer->len), 
388                    ctx->buffer->data, ctx->buffer->len);
389
390   SILC_LOG_DEBUG(("Outgoing packet assembled"));
391 }