5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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.
20 /* Includes the Private Message Payload implementation */
23 #include "silcincludes.h"
24 #include "silcprivate.h"
26 /******************************************************************************
28 Private Message Payload
30 ******************************************************************************/
32 /* Calculates padding length for message payload */
33 #define SILC_PRIVATE_MESSAGE_PAD(__payloadlen) (16 - ((__payloadlen) % 16))
35 /* Header length plus maximum padding length */
36 #define SILC_PRIVATE_MESSAGE_HLEN 4 + 16
38 /* Returns the data length that fits to the packet. If data length is too
39 big it will be truncated to fit to the payload. */
40 #define SILC_PRIVATE_MESSAGE_DATALEN(data_len) \
41 ((data_len + SILC_PRIVATE_MESSAGE_HLEN) > SILC_PACKET_MAX_LEN ? \
42 data_len - ((data_len + SILC_PRIVATE_MESSAGE_HLEN) - \
43 SILC_PACKET_MAX_LEN) : data_len)
45 /* Private Message Payload structure. Contents of this structure is parsed
47 struct SilcPrivateMessagePayloadStruct {
49 SilcUInt16 message_len;
50 unsigned char *message;
53 /* Parses private message payload returning new private mesage payload
54 structure. This also decrypts the message if the `cipher' is provided. */
56 SilcPrivateMessagePayload
57 silc_private_message_payload_parse(unsigned char *payload,
58 SilcUInt32 payload_len,
61 SilcBufferStruct buffer;
62 SilcPrivateMessagePayload newp;
65 SILC_LOG_DEBUG(("Parsing private message payload"));
67 silc_buffer_set(&buffer, payload, payload_len);
69 /* Decrypt the payload */
71 silc_cipher_decrypt(cipher, buffer.data, buffer.data,
72 buffer.len, silc_cipher_get_iv(cipher));
74 newp = silc_calloc(1, sizeof(*newp));
78 /* Parse the Private Message Payload. Ignore the padding. */
79 ret = silc_buffer_unformat(&buffer,
80 SILC_STR_UI_SHORT(&newp->flags),
81 SILC_STR_UI16_NSTRING_ALLOC(&newp->message,
85 SILC_LOG_DEBUG(("Incorrect private message payload"));
89 if ((newp->message_len < 1 || newp->message_len > buffer.len - 4)) {
90 SILC_LOG_DEBUG(("Incorrect private message payload in packet, "
98 silc_private_message_payload_free(newp);
102 /* Encodes private message payload into a buffer and returns it. If
103 the cipher is provided the packet is also encrypted here. It is provided
104 if the private message private keys are used. */
106 SilcBuffer silc_private_message_payload_encode(SilcUInt16 flags,
108 const unsigned char *data,
114 SilcUInt32 len, pad_len = 0;
115 unsigned char pad[16];
117 SILC_LOG_DEBUG(("Encoding private message payload"));
119 data_len = SILC_PRIVATE_MESSAGE_DATALEN(data_len);
123 /* Calculate length of padding. */
124 pad_len = SILC_PRIVATE_MESSAGE_PAD(len);
127 /* Generate padding */
128 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte();
131 /* Allocate private message payload buffer */
132 buffer = silc_buffer_alloc_size(len);
136 /* Encode the Channel Message Payload */
137 silc_buffer_format(buffer,
138 SILC_STR_UI_SHORT(flags),
139 SILC_STR_UI_SHORT(data_len),
140 SILC_STR_UI_XNSTRING(data, data_len),
141 SILC_STR_UI_XNSTRING(pad, pad_len),
145 /* Encrypt payload of the packet. */
146 silc_cipher_encrypt(cipher, buffer->data, buffer->data,
147 buffer->len, silc_cipher_get_iv(cipher));
148 memset(pad, 0, sizeof(pad));
154 /* Frees Private Message Payload */
156 void silc_private_message_payload_free(SilcPrivateMessagePayload payload)
158 if (payload->message) {
159 memset(payload->message, 0, payload->message_len);
160 silc_free(payload->message);
168 silc_private_message_get_flags(SilcPrivateMessagePayload payload)
170 return payload->flags;
176 silc_private_message_get_message(SilcPrivateMessagePayload payload,
177 SilcUInt32 *message_len)
180 *message_len = payload->message_len;
182 return payload->message;