From: Pekka Riikonen Date: Tue, 19 Mar 2002 14:24:01 +0000 (+0000) Subject: Changed packet assembling interfaces. X-Git-Tag: silc.toolkit.0.8.1~8 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=a139a25daf7ccfd8acb3c33746df6c12ea71b0ea Changed packet assembling interfaces. --- diff --git a/CHANGES b/CHANGES index 7667f232..451cced5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,8 +1,20 @@ -Tue Mar 19 12:32:43 CET 2002 Pekka Riikonen +Tue Mar 19 16:32:43 CET 2002 Pekka Riikonen * Added silc_rng_get_byte_fast function in to the lib/silccrypt/silcrng.[ch]. + * Changed the interface of silc_packet_assemble and the + silc_packet_send_prepare. If silc_packet_assmble is now + called the application does not call silc_packet_send_prepare + because the library will call it automatically. These + interfaces now also return a reference to the outgoing buffer + which includes the assembled packet, which the application can + use to encrypt the packet. + + Affected files are lib/silccore/silcpacket.[ch], + lib/silcclient/client.c, client_channel.c client_prvmsg.c, + silcd/packet_send.c, server_backup.c and packet_receive.c. + Mon Mar 18 21:00:41 EET 2002 Pekka Riikonen * Added macro SILC_PACKET_DATALEN which can be used during diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index d3191d01..61b3e4fa 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -1379,19 +1379,23 @@ void silc_server_command_reply(SilcServer server, if (packet->dst_id_type == SILC_ID_CLIENT && client && id) { /* Relay the packet to the client */ + const SilcBufferStruct p; dst_sock = (SilcSocketConnection)client->connection; + idata = (SilcIDListData)client; + silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len + packet->dst_id_len + packet->padlen); - - silc_packet_send_prepare(dst_sock, 0, 0, buffer->len); - silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len); - - idata = (SilcIDListData)client; + if (!silc_packet_send_prepare(dst_sock, 0, 0, buffer->len, + idata->hmac_send, (const SilcBuffer)&p)) { + SILC_LOG_ERROR(("Cannot send packet")); + return; + } + silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len); /* Encrypt packet */ silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++, - dst_sock->outbuf, buffer->len); + (SilcBuffer)&p, buffer->len); /* Send the packet */ silc_server_packet_send_real(server, dst_sock, TRUE); diff --git a/apps/silcd/packet_send.c b/apps/silcd/packet_send.c index e9d70fbb..3cda68b0 100644 --- a/apps/silcd/packet_send.c +++ b/apps/silcd/packet_send.c @@ -137,6 +137,7 @@ void silc_server_packet_send_dest(SilcServer server, bool force_send) { SilcPacketContext packetdata; + const SilcBufferStruct packet; SilcIDListData idata = (SilcIDListData)sock->user_data; SilcCipher cipher = NULL; SilcHmac hmac = NULL; @@ -183,35 +184,23 @@ void silc_server_packet_send_dest(SilcServer server, packetdata.src_id_len + dst_id_len; packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len); - /* Prepare outgoing data buffer for packet sending */ - silc_packet_send_prepare(sock, - SILC_PACKET_HEADER_LEN + - packetdata.src_id_len + - packetdata.dst_id_len, - packetdata.padlen, - data_len); - - SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len)); - - packetdata.buffer = sock->outbuf; - - /* Put the data to the buffer */ - if (data && data_len) - silc_buffer_put(sock->outbuf, data, data_len); - /* Create the outgoing packet */ - silc_packet_assemble(&packetdata, cipher); + if (!silc_packet_assemble(&packetdata, NULL, cipher, hmac, sock, + data, data_len, (const SilcBuffer)&packet)) { + SILC_LOG_ERROR(("Cannot assemble packet")); + goto out; + } /* Encrypt the packet */ - silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, sock->outbuf->len); + silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet, packet.len); - SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, - sock->outbuf->len), - sock->outbuf->data, sock->outbuf->len); + SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, packet.len), + packet.data, packet.len); /* Now actually send the packet */ silc_server_packet_send_real(server, sock, force_send); + out: if (packetdata.src_id) silc_free(packetdata.src_id); if (packetdata.dst_id) @@ -239,6 +228,7 @@ void silc_server_packet_send_srcdest(SilcServer server, bool force_send) { SilcPacketContext packetdata; + const SilcBufferStruct packet; SilcIDListData idata; SilcCipher cipher = NULL; SilcHmac hmac = NULL; @@ -287,35 +277,23 @@ void silc_server_packet_send_srcdest(SilcServer server, packetdata.src_id_len + dst_id_len; packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len); - /* Prepare outgoing data buffer for packet sending */ - silc_packet_send_prepare(sock, - SILC_PACKET_HEADER_LEN + - packetdata.src_id_len + - packetdata.dst_id_len, - packetdata.padlen, - data_len); - - SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len)); - - packetdata.buffer = sock->outbuf; - - /* Put the data to the buffer */ - if (data && data_len) - silc_buffer_put(sock->outbuf, data, data_len); - /* Create the outgoing packet */ - silc_packet_assemble(&packetdata, cipher); + if (!silc_packet_assemble(&packetdata, NULL, cipher, hmac, sock, data, + data_len, (const SilcBuffer)&packet)) { + SILC_LOG_ERROR(("Cannot assemble packe")); + goto out; + } /* Encrypt the packet */ - silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, sock->outbuf->len); + silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet, packet.len); - SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, - sock->outbuf->len), - sock->outbuf->data, sock->outbuf->len); + SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, packet.len), + packet.data, packet.len); /* Now actually send the packet */ silc_server_packet_send_real(server, sock, force_send); + out: if (packetdata.src_id) silc_free(packetdata.src_id); if (packetdata.dst_id) @@ -341,17 +319,23 @@ void silc_server_packet_broadcast(SilcServer server, not allowed to send the packet. */ id = silc_id_str2id(packet->src_id, packet->src_id_len, packet->src_id_type); if (id && !SILC_ID_SERVER_COMPARE(id, server->router->id)) { + const SilcBufferStruct p; + idata = (SilcIDListData)sock->user_data; silc_buffer_push(buffer, buffer->data - buffer->head); - silc_packet_send_prepare(sock, 0, 0, buffer->len); - silc_buffer_put(sock->outbuf, buffer->data, buffer->len); + if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send, + (const SilcBuffer)&p)) { + SILC_LOG_ERROR(("Cannot send packet")); + silc_free(id); + return; + } + silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len); silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++, - sock->outbuf, sock->outbuf->len); + (SilcBuffer)&p, p.len); SILC_LOG_HEXDUMP(("Broadcasted packet (%d), len %d", idata->psn_send - 1, - sock->outbuf->len), - sock->outbuf->data, sock->outbuf->len); + p.len), p.data, p.len); /* Now actually send the packet */ silc_server_packet_send_real(server, sock, TRUE); @@ -372,6 +356,7 @@ void silc_server_packet_route(SilcServer server, SilcPacketContext *packet) { SilcBuffer buffer = packet->buffer; + const SilcBufferStruct p; SilcIDListData idata; SILC_LOG_DEBUG(("Routing received packet")); @@ -379,14 +364,17 @@ void silc_server_packet_route(SilcServer server, idata = (SilcIDListData)sock->user_data; silc_buffer_push(buffer, buffer->data - buffer->head); - silc_packet_send_prepare(sock, 0, 0, buffer->len); - silc_buffer_put(sock->outbuf, buffer->data, buffer->len); + if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send, + (const SilcBuffer)&p)) { + SILC_LOG_ERROR(("Cannot send packet")); + return; + } + silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len); silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++, - sock->outbuf, sock->outbuf->len); + (SilcBuffer)&p, p.len); SILC_LOG_HEXDUMP(("Routed packet (%d), len %d", idata->psn_send - 1, - sock->outbuf->len), - sock->outbuf->data, sock->outbuf->len); + p.len), p.data, p.len); /* Now actually send the packet */ silc_server_packet_send_real(server, sock, TRUE); @@ -482,6 +470,7 @@ silc_server_packet_send_to_channel_real(SilcServer server, bool force_send) { int block_len; + const SilcBufferStruct p; if (!sock) return; @@ -500,32 +489,24 @@ silc_server_packet_send_to_channel_real(SilcServer server, else packet->padlen = SILC_PACKET_PADLEN(packet->truelen, block_len); - /* Prepare outgoing data buffer for packet sending */ - silc_packet_send_prepare(sock, - SILC_PACKET_HEADER_LEN + - packet->src_id_len + - packet->dst_id_len, - packet->padlen, - data_len); - - packet->buffer = sock->outbuf; - /* Put the data to buffer, assemble and encrypt the packet. The packet is encrypted with normal session key shared with the client, unless the `channel_message' is TRUE. */ - silc_buffer_put(sock->outbuf, data, data_len); - silc_packet_assemble(packet, cipher); + if (!silc_packet_assemble(packet, NULL, cipher, hmac, sock, data, + data_len, (const SilcBuffer)&p)) { + SILC_LOG_ERROR(("Cannot assemble packet")); + return; + } + if (channel_message) - silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, + silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, SILC_PACKET_HEADER_LEN + packet->src_id_len + packet->dst_id_len + packet->padlen); else - silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, - sock->outbuf->len); + silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, p.len); - SILC_LOG_HEXDUMP(("Channel packet (%d), len %d", sequence, - sock->outbuf->len), - sock->outbuf->data, sock->outbuf->len); + SILC_LOG_HEXDUMP(("Channel packet (%d), len %d", sequence, p.len), + p.data, p.len); /* Now actually send the packet */ silc_server_packet_send_real(server, sock, force_send); @@ -1008,35 +989,30 @@ void silc_server_send_private_message(SilcServer server, SilcPacketContext *packet) { SilcBuffer buffer = packet->buffer; + const SilcBufferStruct p; + + silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len + + packet->dst_id_len + packet->padlen); + if (!silc_packet_send_prepare(dst_sock, 0, 0, buffer->len, hmac, + (const SilcBuffer)&p)) { + SILC_LOG_ERROR(("Cannot send packet")); + return; + } + silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len); /* Re-encrypt and send if private messge key does not exist */ if (!(packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY)) { - - silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len - + packet->dst_id_len + packet->padlen); - silc_packet_send_prepare(dst_sock, 0, 0, buffer->len); - silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len); - /* Re-encrypt packet */ - silc_packet_encrypt(cipher, hmac, sequence, dst_sock->outbuf, buffer->len); - - /* Send the packet */ - silc_server_packet_send_real(server, dst_sock, FALSE); - + silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, buffer->len); } else { /* Key exist so encrypt just header and send it */ - silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len - + packet->dst_id_len + packet->padlen); - silc_packet_send_prepare(dst_sock, 0, 0, buffer->len); - silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len); - - /* Encrypt header */ - silc_packet_encrypt(cipher, hmac, sequence, dst_sock->outbuf, + silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, SILC_PACKET_HEADER_LEN + packet->src_id_len + packet->dst_id_len + packet->padlen); - - silc_server_packet_send_real(server, dst_sock, FALSE); } + + /* Send the packet */ + silc_server_packet_send_real(server, dst_sock, FALSE); } /* Sends current motd to client */ @@ -1841,14 +1817,19 @@ void silc_server_relay_packet(SilcServer server, SilcPacketContext *packet, bool force_send) { + const SilcBufferStruct p; + silc_buffer_push(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len + packet->dst_id_len + packet->padlen); - - silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len); - silc_buffer_put(dst_sock->outbuf, packet->buffer->data, packet->buffer->len); + if (!silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len, hmac, + (const SilcBuffer)&p)) { + SILC_LOG_ERROR(("Cannot send packet")); + return; + } + silc_buffer_put((SilcBuffer)&p, packet->buffer->data, packet->buffer->len); /* Re-encrypt packet */ - silc_packet_encrypt(cipher, hmac, sequence, dst_sock->outbuf, + silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, packet->buffer->len); /* Send the packet */ diff --git a/apps/silcd/server_backup.c b/apps/silcd/server_backup.c index 5888909c..b1995e69 100644 --- a/apps/silcd/server_backup.c +++ b/apps/silcd/server_backup.c @@ -270,6 +270,7 @@ void silc_server_backup_broadcast(SilcServer server, SilcServerEntry backup; SilcSocketConnection sock; SilcBuffer buffer; + const SilcBufferStruct p; SilcIDListData idata; int i; @@ -291,13 +292,16 @@ void silc_server_backup_broadcast(SilcServer server, idata = (SilcIDListData)backup; sock = backup->connection; - silc_packet_send_prepare(sock, 0, 0, buffer->len); - silc_buffer_put(sock->outbuf, buffer->data, buffer->len); + if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send, + (const SilcBuffer)&p)) { + SILC_LOG_ERROR(("Cannot send packet")); + return; + } + silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len); silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++, - sock->outbuf, sock->outbuf->len); + (SilcBuffer)&p, p.len); - SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", sock->outbuf->len), - sock->outbuf->data, sock->outbuf->len); + SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", p.len), p.data, p.len); /* Now actually send the packet */ silc_server_packet_send_real(server, sock, FALSE); diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index 5cbfc588..3e33cd93 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -1184,6 +1184,7 @@ void silc_client_packet_send(SilcClient client, int force_send) { SilcPacketContext packetdata; + const SilcBufferStruct packet; int block_len; SilcUInt32 sequence = 0; @@ -1241,32 +1242,20 @@ void silc_client_packet_send(SilcClient client, packetdata.src_id_len + packetdata.dst_id_len; packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len); - /* Prepare outgoing data buffer for packet sending */ - silc_packet_send_prepare(sock, - SILC_PACKET_HEADER_LEN + - packetdata.src_id_len + - packetdata.dst_id_len, - packetdata.padlen, - data_len); - - SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len)); - - packetdata.buffer = sock->outbuf; - - /* Put the data to the buffer */ - if (data && data_len) - silc_buffer_put(sock->outbuf, data, data_len); - /* Create the outgoing packet */ - silc_packet_assemble(&packetdata, cipher); + if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock, + data, data_len, (const SilcBuffer)&packet)) { + SILC_LOG_ERROR(("Error assembling packet")); + return; + } /* Encrypt the packet */ if (cipher) - silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, - sock->outbuf->len); + silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet, + packet.len); - SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, sock->outbuf->len), - sock->outbuf->data, sock->outbuf->len); + SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len), + packet.data, packet.len); /* Now actually send the packet */ silc_client_packet_send_real(client, sock, force_send); diff --git a/lib/silcclient/client_channel.c b/lib/silcclient/client_channel.c index dbc60834..485decf0 100644 --- a/lib/silcclient/client_channel.c +++ b/lib/silcclient/client_channel.c @@ -46,6 +46,7 @@ void silc_client_send_channel_message(SilcClient client, SilcSocketConnection sock = conn->sock; SilcBuffer payload; SilcPacketContext packetdata; + const SilcBufferStruct packet; SilcCipher cipher; SilcHmac hmac; unsigned char *id_string; @@ -131,34 +132,27 @@ void silc_client_send_channel_message(SilcClient client, packetdata.src_id_len + packetdata.dst_id_len), block_len); - /* Prepare outgoing data buffer for packet sending */ - silc_packet_send_prepare(sock, - SILC_PACKET_HEADER_LEN + - packetdata.src_id_len + - packetdata.dst_id_len, - packetdata.padlen, - data_len); - - packetdata.buffer = sock->outbuf; - - /* Put the channel message payload to the outgoing data buffer */ - silc_buffer_put(sock->outbuf, data, data_len); - /* Create the outgoing packet */ - silc_packet_assemble(&packetdata, cipher); + if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock, + data, data_len, (const SilcBuffer)&packet)) { + SILC_LOG_ERROR(("Error assembling packet")); + goto out; + } /* Encrypt the header and padding of the packet. This is encrypted with normal session key shared with our server. */ silc_packet_encrypt(cipher, hmac, conn->psn_send++, - sock->outbuf, SILC_PACKET_HEADER_LEN + + (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN + packetdata.src_id_len + packetdata.dst_id_len + packetdata.padlen); - SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len), - sock->outbuf->data, sock->outbuf->len); + SILC_LOG_HEXDUMP(("Packet to channel, len %d", packet.len), + packet.data, packet.len); /* Now actually send the packet */ silc_client_packet_send_real(client, sock, force_send); + + out: silc_buffer_free(payload); silc_free(id_string); } diff --git a/lib/silcclient/client_prvmsg.c b/lib/silcclient/client_prvmsg.c index be4d8b0d..2ef43aec 100644 --- a/lib/silcclient/client_prvmsg.c +++ b/lib/silcclient/client_prvmsg.c @@ -44,6 +44,7 @@ void silc_client_send_private_message(SilcClient client, SilcSocketConnection sock = conn->sock; SilcBuffer buffer; SilcPacketContext packetdata; + const SilcBufferStruct packet; SilcCipher cipher; SilcHmac hmac; int block_len; @@ -94,31 +95,22 @@ void silc_client_send_private_message(SilcClient client, packetdata.src_id_len + packetdata.dst_id_len), block_len); - /* Prepare outgoing data buffer for packet sending */ - silc_packet_send_prepare(sock, - SILC_PACKET_HEADER_LEN + - packetdata.src_id_len + - packetdata.dst_id_len, - packetdata.padlen, - data_len); - - packetdata.buffer = sock->outbuf; - - /* Put the actual encrypted message payload data into the buffer. */ - silc_buffer_put(sock->outbuf, data, data_len); - /* Create the outgoing packet */ - silc_packet_assemble(&packetdata, cipher); + if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock, + data, data_len, (const SilcBuffer)&packet)) { + SILC_LOG_ERROR(("Error assembling packet")); + goto out; + } /* Encrypt the header and padding of the packet. */ cipher = conn->send_key; silc_packet_encrypt(cipher, hmac, conn->psn_send++, - sock->outbuf, SILC_PACKET_HEADER_LEN + + (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN + packetdata.src_id_len + packetdata.dst_id_len + packetdata.padlen); - SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len), - sock->outbuf->data, sock->outbuf->len); + SILC_LOG_HEXDUMP(("Private message packet, len %d", packet.len), + packet.data, packet.len); /* Now actually send the packet */ silc_client_packet_send_real(client, sock, force_send); diff --git a/lib/silccore/silcpacket.c b/lib/silccore/silcpacket.c index dc68a6bb..5c5f6be6 100644 --- a/lib/silccore/silcpacket.c +++ b/lib/silccore/silcpacket.c @@ -110,176 +110,141 @@ void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, SilcUInt32 sequence, silc_buffer_pull_tail(buffer, mac_len); } -/* Assembles a new packet to be ready for send out. The buffer sent as - argument must include the data to be sent and it must not be encrypted. - The packet also must have enough free space so that the SILC header - and padding maybe added to the packet. The packet is encrypted after - this function has returned. - - The buffer sent as argument should be something like following: - - -------------------------------------------- - | head | data | tail | - -------------------------------------------- - ^ ^ - 58 bytes x bytes - - So that the SILC header and 1 - 16 bytes of padding can fit to - the buffer. After assembly the buffer might look like this: - - -------------------------------------------- - | data | | - -------------------------------------------- - ^ ^ - Start of assembled packet - - Packet construct is as follows: - - n bytes SILC Header - 2 bytes Payload length - 1 byte Flags - 1 byte Packet type - 1 byte Padding length - 1 byte RESERVED - 1 bytes Source ID Length - 1 bytes Destination ID Length - 1 byte Source ID Type - n bytes Source ID - 1 byte Destination ID Type - n bytes Destination ID - - 1 - 16 bytes Padding - - n bytes Data payload - - All fields in the packet will be authenticated by MAC. The MAC is - not computed here, it must be computed separately before encrypting - the packet. - -*/ - -void silc_packet_assemble(SilcPacketContext *ctx, SilcCipher cipher) -{ - unsigned char tmppad[SILC_PACKET_MAX_PADLEN]; +/* Assembles a new packet to be ready for send out. */ + +bool silc_packet_assemble(SilcPacketContext *packet, SilcRng rng, + SilcCipher cipher, SilcHmac hmac, + SilcSocketConnection sock, + const unsigned char *data, SilcUInt32 data_len, + const SilcBuffer assembled_packet) +{ + unsigned char tmppad[SILC_PACKET_MAX_PADLEN]; int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0; - int i; + int i, ret; SILC_LOG_DEBUG(("Assembling outgoing packet")); - + + /* Calculate the packet's length and padding length if upper layer + didn't already do it. */ + /* Get the true length of the packet. This is saved as payload length into the packet header. This does not include the length of the padding. */ - if (!ctx->truelen) { - ctx->truelen = ctx->buffer->len + SILC_PACKET_HEADER_LEN + - ctx->src_id_len + ctx->dst_id_len; - if (ctx->truelen > SILC_PACKET_MAX_LEN) { - ctx->truelen -= (ctx->truelen - SILC_PACKET_MAX_LEN); - silc_buffer_push_tail(ctx->buffer, (ctx->truelen - SILC_PACKET_MAX_LEN)); - } + if (!packet->truelen) { + data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN + + packet->src_id_len + packet->dst_id_len); + packet->truelen = data_len + SILC_PACKET_HEADER_LEN + + packet->src_id_len + packet->dst_id_len; } /* Calculate the length of the padding. The padding is calculated from the data that will be encrypted. */ - if (!ctx->padlen) { - if (ctx->long_pad) - ctx->padlen = SILC_PACKET_PADLEN_MAX(ctx->truelen); - else - ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen, block_len); + if (!packet->padlen) { + packet->padlen = (packet->long_pad ? + SILC_PACKET_PADLEN_MAX(packet->truelen) : + SILC_PACKET_PADLEN(packet->truelen, block_len)); } - /* Put the start of the data section to the right place. */ - silc_buffer_push(ctx->buffer, SILC_PACKET_HEADER_LEN + - ctx->src_id_len + ctx->dst_id_len + ctx->padlen); + /* Now prepare the outgoing data buffer for packet sending and start + assembling the packet. */ + + /* Return pointer to the assembled packet */ + if (!silc_packet_send_prepare(sock, packet->truelen - data_len, + packet->padlen, data_len, hmac, + assembled_packet)) + return FALSE; /* Get random padding */ -#if 1 - for (i = 0; i < ctx->padlen; i++) tmppad[i] = - silc_rng_global_get_byte_fast(); -#else - /* XXX: For testing - to be removed */ - memset(tmppad, 65, sizeof(tmppad)); -#endif - - /* Create the packet. This creates the SILC header and adds padding, - rest of the buffer remains as it is. */ - silc_buffer_format(ctx->buffer, - SILC_STR_UI_SHORT(ctx->truelen), - SILC_STR_UI_CHAR(ctx->flags), - SILC_STR_UI_CHAR(ctx->type), - SILC_STR_UI_CHAR(ctx->padlen), - SILC_STR_UI_CHAR(0), - SILC_STR_UI_CHAR(ctx->src_id_len), - SILC_STR_UI_CHAR(ctx->dst_id_len), - SILC_STR_UI_CHAR(ctx->src_id_type), - SILC_STR_UI_XNSTRING(ctx->src_id, ctx->src_id_len), - SILC_STR_UI_CHAR(ctx->dst_id_type), - SILC_STR_UI_XNSTRING(ctx->dst_id, ctx->dst_id_len), - SILC_STR_UI_XNSTRING(tmppad, ctx->padlen), - SILC_STR_END); - - SILC_LOG_HEXDUMP(("Assembled packet, len %d", ctx->buffer->len), - ctx->buffer->data, ctx->buffer->len); + if (rng) + for (i = 0; i < packet->padlen; i++) tmppad[i] = + silc_rng_get_byte_fast(rng); + else + for (i = 0; i < packet->padlen; i++) tmppad[i] = + silc_rng_global_get_byte_fast(); + + /* Create the packet. This creates the SILC header, adds padding, and + the actual packet data. */ + ret = + silc_buffer_format(assembled_packet, + SILC_STR_UI_SHORT(packet->truelen), + SILC_STR_UI_CHAR(packet->flags), + SILC_STR_UI_CHAR(packet->type), + SILC_STR_UI_CHAR(packet->padlen), + SILC_STR_UI_CHAR(0), + SILC_STR_UI_CHAR(packet->src_id_len), + SILC_STR_UI_CHAR(packet->dst_id_len), + SILC_STR_UI_CHAR(packet->src_id_type), + SILC_STR_UI_XNSTRING(packet->src_id, + packet->src_id_len), + SILC_STR_UI_CHAR(packet->dst_id_type), + SILC_STR_UI_XNSTRING(packet->dst_id, + packet->dst_id_len), + SILC_STR_UI_XNSTRING(tmppad, packet->padlen), + SILC_STR_UI_XNSTRING(data, data_len), + SILC_STR_END); + if (ret < 0) + return FALSE; + + SILC_LOG_HEXDUMP(("Assembled packet, len %d", assembled_packet->len), + assembled_packet->data, assembled_packet->len); - SILC_LOG_DEBUG(("Outgoing packet assembled")); + return TRUE; } /* Prepare outgoing data buffer for packet sending. This moves the data area so that new packet may be added into it. If needed this allocates more space to the buffer. This handles directly the connection's - outgoing buffer in SilcSocketConnection object. */ + outgoing buffer in SilcSocketConnection object, and returns the + pointer to that buffer into the `packet'. */ -void silc_packet_send_prepare(SilcSocketConnection sock, - SilcUInt32 header_len, - SilcUInt32 padlen, - SilcUInt32 data_len) -{ - int totlen, oldlen; +bool silc_packet_send_prepare(SilcSocketConnection sock, + SilcUInt32 header_len, + SilcUInt32 pad_len, + SilcUInt32 data_len, + SilcHmac hmac, + const SilcBuffer packet) +{ + int totlen; + unsigned char *oldptr; + int mac_len = hmac ? silc_hmac_len(hmac) : 0; + + if (!packet) + return FALSE; - totlen = header_len + padlen + data_len; + totlen = header_len + pad_len + data_len; /* Prepare the outgoing buffer for packet sending. */ if (!sock->outbuf) { /* Allocate new buffer. This is done only once per connection. */ SILC_LOG_DEBUG(("Allocating outgoing data buffer")); - - if (totlen > SILC_PACKET_DEFAULT_SIZE) - sock->outbuf = silc_buffer_alloc(totlen); - else - sock->outbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE); - silc_buffer_pull_tail(sock->outbuf, totlen); - silc_buffer_pull(sock->outbuf, header_len + padlen); - } else { - if (SILC_IS_OUTBUF_PENDING(sock)) { - /* There is some pending data in the buffer. */ - - /* Allocate more space if needed */ - if ((sock->outbuf->end - sock->outbuf->tail) < - (totlen + 20)) { - SILC_LOG_DEBUG(("Reallocating outgoing data buffer")); - sock->outbuf = silc_buffer_realloc(sock->outbuf, - sock->outbuf->truelen + - (totlen * 2)); - } - oldlen = sock->outbuf->len; - silc_buffer_pull_tail(sock->outbuf, totlen); - silc_buffer_pull(sock->outbuf, header_len + padlen + oldlen); - } else { + sock->outbuf = silc_buffer_alloc(totlen > SILC_PACKET_DEFAULT_SIZE ? + totlen : SILC_PACKET_DEFAULT_SIZE); + if (!sock->outbuf) + return FALSE; + } else { + if (!SILC_IS_OUTBUF_PENDING(sock)) { /* Buffer is free for use */ silc_buffer_clear(sock->outbuf); - - /* Allocate more space if needed */ - if ((sock->outbuf->end - sock->outbuf->tail) < (totlen + 20)) { - SILC_LOG_DEBUG(("Reallocating outgoing data buffer")); - sock->outbuf = silc_buffer_realloc(sock->outbuf, - sock->outbuf->truelen + - (totlen * 2)); - } - - silc_buffer_pull_tail(sock->outbuf, totlen); - silc_buffer_pull(sock->outbuf, header_len + padlen); } } + + /* Allocate more space if needed */ + if ((sock->outbuf->end - sock->outbuf->tail) < (totlen + mac_len)) { + SILC_LOG_DEBUG(("Reallocating outgoing data buffer")); + sock->outbuf = silc_buffer_realloc(sock->outbuf, + sock->outbuf->truelen + (totlen * 2)); + if (!sock->outbuf) + return FALSE; + } + + /* Pull data area for the new packet, and return pointer to the start of + the data area and save the pointer in to the `packet'. */ + oldptr = silc_buffer_pull_tail(sock->outbuf, totlen + mac_len); + silc_buffer_set(packet, oldptr, totlen + mac_len); + silc_buffer_push_tail(packet, mac_len); + + return TRUE; } /****************************************************************************** diff --git a/lib/silccore/silcpacket.h b/lib/silccore/silcpacket.h index a944d332..d4f28ede 100644 --- a/lib/silccore/silcpacket.h +++ b/lib/silccore/silcpacket.h @@ -434,78 +434,62 @@ void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, SilcUInt32 sequence, * * SYNOPSIS * - * void silc_packet_assemble(SilcPacketContext *ctx); + * bool silc_packet_assemble(SilcPacketContext *packet, SilcRng rng, + * SilcCipher cipher, SilcHmac hmac, + * SilcSocketConnection sock, + * const unsigned char *data, SilcUInt32 data_len, + * const SilcBuffer assembled_packet); * * DESCRIPTION * - * Assembles a new packet to be ready for send out. The buffer sent as - * argument must include the data to be sent and it must not be encrypted. - * The packet also must have enough free space so that the SILC header - * and padding maybe added to the packet. The packet is encrypted after - * this function has returned. - * - * The buffer sent as argument should be something like following: - * - * -------------------------------------------- - * | head | data | tail | - * -------------------------------------------- - * ^ ^ - * 58 bytes x bytes - * - * So that the SILC header and 1 - 16 bytes of padding can fit to - * the buffer. After assembly the buffer might look like this: - * - * -------------------------------------------- - * | data | | - * -------------------------------------------- - * ^ ^ - * Start of assembled packet - * - * Packet construct is as follows (* = won't be encrypted): - * - * n bytes SILC Header - * 2 bytes Payload length (*) - * 1 byte Flags - * 1 byte Packet type - * 2 bytes Source ID Length - * 2 bytes Destination ID Length - * 1 byte Source ID Type - * n bytes Source ID - * 1 byte Destination ID Type - * n bytes Destination ID - * - * 1 - 16 bytes Padding - * - * n bytes Data payload - * - * All fields in the packet will be authenticated by MAC. The MAC is - * not computed here, it must be computed separately before encrypting - * the packet. + * Assembles new packet to be ready for encrypting and sending out. + * The `packet' is filled by caller to include the packet header specific + * values. This prepares the socket connection's `sock' outoing buffer + * for sending data, and returns the assembled packet to the + * `assembled_packet' pointer sent by the caller. The `assembled_packet' + * is a reference to the socket connection's outgoing buffer. The + * returned packet can be encrypted, and then sent to network by calling + * silc_packet_send function. * ***/ -void silc_packet_assemble(SilcPacketContext *ctx, SilcCipher cipher); +bool silc_packet_assemble(SilcPacketContext *packet, SilcRng rng, + SilcCipher cipher, SilcHmac hmac, + SilcSocketConnection sock, + const unsigned char *data, SilcUInt32 data_len, + const SilcBuffer assembled_packet); /****f* silccore/SilcPacketAPI/silc_packet_send_prepare * * SYNOPSIS * - * void silc_packet_send_prepare(SilcSocketConnection sock, + * bool silc_packet_send_prepare(SilcSocketConnection sock, * SilcUInt32 header_len, - * SilcUInt32 padlen, - * SilcUInt32 data_len); + * SilcUInt32 pad_len, + * SilcUInt32 data_len, + * SilcHmac hmac, + * const SilcBuffer packet); * * DESCRIPTION * - * Prepare outgoing data buffer for packet sending. This moves the data - * area so that new packet may be added into it. If needed this allocates - * more space to the buffer. This handles directly the connection's - * outgoing buffer in SilcSocketConnection object. + * This function can be used to prepare the outgoing data buffer in + * the socket connection specified by `sock' for packet sending. + * This is used internally by packet sending routines, but application + * may call this if it doesn't call silc_packet_assemble function. + * If that function is called then application must not call this since + * that function calls this internally. + * + * This returns the prepared data area into the `packet' pointer provided + * caller, which can be used then to add data to it, and later encrypt + * it. The `packet' includes reference to the socket connection's + * outgoing buffer. * ***/ -void silc_packet_send_prepare(SilcSocketConnection sock, - SilcUInt32 header_len, - SilcUInt32 padlen, - SilcUInt32 data_len); +bool silc_packet_send_prepare(SilcSocketConnection sock, + SilcUInt32 header_len, + SilcUInt32 pad_len, + SilcUInt32 data_len, + SilcHmac hmac, + const SilcBuffer packet); /****f* silccore/SilcPacketAPI/silc_packet_receive *