-Tue Mar 19 12:32:43 CET 2002 Pekka Riikonen <priikone@silcnet.org>
+Tue Mar 19 16:32:43 CET 2002 Pekka Riikonen <priikone@silcnet.org>
* 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 <priikone@silcnet.org>
* Added macro SILC_PACKET_DATALEN which can be used during
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);
bool force_send)
{
SilcPacketContext packetdata;
+ const SilcBufferStruct packet;
SilcIDListData idata = (SilcIDListData)sock->user_data;
SilcCipher cipher = NULL;
SilcHmac hmac = NULL;
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)
bool force_send)
{
SilcPacketContext packetdata;
+ const SilcBufferStruct packet;
SilcIDListData idata;
SilcCipher cipher = NULL;
SilcHmac hmac = NULL;
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)
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);
SilcPacketContext *packet)
{
SilcBuffer buffer = packet->buffer;
+ const SilcBufferStruct p;
SilcIDListData idata;
SILC_LOG_DEBUG(("Routing received packet"));
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);
bool force_send)
{
int block_len;
+ const SilcBufferStruct p;
if (!sock)
return;
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);
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 */
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 */
SilcServerEntry backup;
SilcSocketConnection sock;
SilcBuffer buffer;
+ const SilcBufferStruct p;
SilcIDListData idata;
int i;
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);
int force_send)
{
SilcPacketContext packetdata;
+ const SilcBufferStruct packet;
int block_len;
SilcUInt32 sequence = 0;
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);
SilcSocketConnection sock = conn->sock;
SilcBuffer payload;
SilcPacketContext packetdata;
+ const SilcBufferStruct packet;
SilcCipher cipher;
SilcHmac hmac;
unsigned char *id_string;
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);
}
SilcSocketConnection sock = conn->sock;
SilcBuffer buffer;
SilcPacketContext packetdata;
+ const SilcBufferStruct packet;
SilcCipher cipher;
SilcHmac hmac;
int block_len;
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);
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;
}
/******************************************************************************
*
* 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
*