5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 Pekka Riikonen
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.
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.
21 * Created: Fri Jul 25 18:52:14 1997
26 * Revision 1.2 2000/07/05 06:06:35 priikone
27 * Global cosmetic change.
29 * Revision 1.1.1.1 2000/06/27 11:36:55 priikone
30 * Imported from internal CVS/Added Log headers.
35 #include "silcincludes.h"
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. */
43 int silc_packet_write(int sock, SilcBuffer src)
47 SILC_LOG_DEBUG(("Writing data to socket %d", sock));
50 ret = write(sock, src->data, src->len);
52 if (errno == EAGAIN) {
53 SILC_LOG_DEBUG(("Could not write immediately, will do it later"));
56 SILC_LOG_ERROR(("Cannot write to socket: %s", strerror(errno)));
60 silc_buffer_pull(src, ret);
63 SILC_LOG_DEBUG(("Wrote data %d bytes", ret));
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.
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.
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. */
82 int silc_packet_read(int sock, SilcBuffer dest)
85 unsigned char buf[SILC_PACKET_READ_SIZE];
87 SILC_LOG_DEBUG(("Reading data from socket %d", sock));
89 /* Read the data from the socket. */
90 len = read(sock, buf, sizeof(buf));
92 if (errno == EAGAIN) {
93 SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
96 SILC_LOG_ERROR(("Cannot read from socket: %d", strerror(errno)));
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 */
108 /* If the data doesn't fit we just have to allocate a whole new
110 if (dest->truelen <= len) {
112 /* Free the old buffer */
113 memset(dest->head, 'F', dest->truelen);
114 silc_free(dest->head);
116 /* Allocate new data area */
117 len += SILC_PACKET_DEFAULT_SIZE;
118 dest->data = silc_calloc(len, sizeof(char));
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;
128 silc_buffer_put_tail(dest, buf, len);
129 silc_buffer_pull_tail(dest, len);
132 SILC_LOG_DEBUG(("Read %d bytes", len));
137 /* Encrypts a packet. */
139 void silc_packet_encrypt(SilcCipher cipher, SilcBuffer buffer,
142 SILC_LOG_DEBUG(("Encrypting packet, cipher %s, len %d (%d)",
143 cipher->cipher->name, len, len - 2));
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);
152 /* Decrypts a packet. */
154 void silc_packet_decrypt(SilcCipher cipher, SilcBuffer buffer,
157 SILC_LOG_DEBUG(("Decrypting packet, cipher %s, len %d (%d)",
158 cipher->cipher->name, len, len - 2));
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);
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. */
173 SilcPacketType silc_packet_parse(SilcPacketContext *ctx)
175 SilcBuffer buffer = ctx->buffer;
178 SILC_LOG_DEBUG(("Parsing incoming packet"));
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;
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),
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;
202 /* Calculate length of padding in packet */
203 ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen);
205 silc_buffer_pull(buffer, len);
206 silc_buffer_unformat(buffer,
207 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
209 SILC_STR_UI_CHAR(&ctx->dst_id_type),
210 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
212 SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
214 silc_buffer_push(buffer, len);
216 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
217 ctx->buffer->data, ctx->buffer->len);
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);
223 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
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. */
234 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx)
236 SilcBuffer buffer = ctx->buffer;
239 SILC_LOG_DEBUG(("Parsing incoming packet"));
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;
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),
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;
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);
269 silc_buffer_pull(buffer, len);
270 silc_buffer_unformat(buffer,
271 SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
273 SILC_STR_UI_CHAR(&ctx->dst_id_type),
274 SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
276 SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
278 silc_buffer_push(buffer, len);
280 SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len),
281 ctx->buffer->data, ctx->buffer->len);
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);
287 SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
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.
298 The buffer sent as argument should be something like following:
300 --------------------------------------------
301 | head | data | tail |
302 --------------------------------------------
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:
309 --------------------------------------------
311 --------------------------------------------
313 Start of assembled packet
315 Packet construct is as follows (* = won't be encrypted):
318 2 bytes Payload length (*)
321 1 byte Source ID Type
322 2 bytes Source ID Length
324 1 byte Destination ID Type
325 2 bytes Destination ID Length
326 x bytes Destination ID
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
338 void silc_packet_assemble(SilcPacketContext *ctx)
340 unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
343 SILC_LOG_DEBUG(("Assembling outgoing packet"));
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
349 ctx->truelen = ctx->buffer->len + SILC_PACKET_HEADER_LEN +
350 ctx->src_id_len + ctx->dst_id_len;
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. */
357 ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen);
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);
363 /* Get random padding */
365 for (i = 0; i < ctx->padlen; i++)
366 tmppad[i] = silc_rng_get_byte(ctx->rng);
368 /* XXX: For testing - to be removed */
369 memset(tmppad, 65, sizeof(tmppad));
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),
387 SILC_LOG_HEXDUMP(("Assembled packet, len %d", ctx->buffer->len),
388 ctx->buffer->data, ctx->buffer->len);
390 SILC_LOG_DEBUG(("Outgoing packet assembled"));