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.
23 * Revision 1.2 2000/07/05 06:06:35 priikone
24 * Global cosmetic change.
26 * Revision 1.1.1.1 2000/06/27 11:36:55 priikone
27 * Imported from internal CVS/Added Log headers.
32 #include "silcincludes.h"
33 #include "silcchannel.h"
35 /* Channel Payload structure. Contents of this structure is parsed
37 struct SilcChannelPayloadStruct {
38 unsigned short nick_len;
40 unsigned short data_len;
42 unsigned short iv_len;
46 /* Channel Key Payload structrue. Channel keys are parsed from SILC
47 packets into this structure. */
48 struct SilcChannelKeyPayloadStruct {
49 unsigned short id_len;
51 unsigned short cipher_len;
52 unsigned char *cipher;
53 unsigned short key_len;
57 /* Parses channel payload returning new channel payload structure */
59 SilcChannelPayload silc_channel_parse_payload(SilcBuffer buffer)
61 SilcChannelPayload new;
63 SILC_LOG_DEBUG(("Parsing channel payload"));
65 new = silc_calloc(1, sizeof(*new));
67 /* Parse the Channel Payload. Ignore padding and IV, we don't need
69 silc_buffer_unformat(buffer,
70 SILC_STR_UI16_NSTRING_ALLOC(&new->nick, &new->nick_len),
71 SILC_STR_UI16_NSTRING_ALLOC(&new->data, &new->data_len),
72 SILC_STR_UI16_NSTRING_ALLOC(NULL, NULL),
75 if (new->data_len < 1) {
76 SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
93 /* Encodes channel payload into a buffer and returns it. This is used
94 to add channel payload into a packet. As the channel payload is
95 encrypted separately from other parts of the packet padding must
96 be applied to the payload. */
98 SilcBuffer silc_channel_encode_payload(unsigned short nick_len,
100 unsigned short data_len,
102 unsigned short iv_len,
108 unsigned int len, pad_len;
109 unsigned char pad[SILC_PACKET_MAX_PADLEN];
111 SILC_LOG_DEBUG(("Encoding channel payload"));
113 /* Calculate length of padding. IV is not included into the calculation
114 since it is not encrypted. */
115 len = 2 + nick_len + 2 + data_len + 2;
116 pad_len = SILC_PACKET_PADLEN((len + 2));
118 /* Allocate channel payload buffer */
120 buffer = silc_buffer_alloc(len + iv_len);
122 /* Generate padding */
123 for (i = 0; i < pad_len; i++)
124 pad[i] = silc_rng_get_byte(rng);
126 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
128 /* Encode the Channel Payload */
129 silc_buffer_format(buffer,
130 SILC_STR_UI_SHORT(nick_len),
131 SILC_STR_UI_XNSTRING(nick, nick_len),
132 SILC_STR_UI_SHORT(data_len),
133 SILC_STR_UI_XNSTRING(data, data_len),
134 SILC_STR_UI_SHORT(pad_len),
135 SILC_STR_UI_XNSTRING(pad, pad_len),
136 SILC_STR_UI_XNSTRING(iv, iv_len),
139 memset(pad, 0, pad_len);
143 /* Free's Channel Payload */
145 void silc_channel_free_payload(SilcChannelPayload payload)
149 silc_free(payload->data);
151 silc_free(payload->iv);
156 /* Return nickname */
158 unsigned char *silc_channel_get_nickname(SilcChannelPayload payload,
159 unsigned int *nick_len)
162 *nick_len = payload->nick_len;
164 return payload->nick;
169 unsigned char *silc_channel_get_data(SilcChannelPayload payload,
170 unsigned int *data_len)
173 *data_len = payload->data_len;
175 return payload->data;
178 /* Return initial vector */
180 unsigned char *silc_channel_get_iv(SilcChannelPayload payload,
181 unsigned int *iv_len)
184 *iv_len = payload->iv_len;
189 /* Parses channel key payload returning new channel key payload structure */
191 SilcChannelKeyPayload silc_channel_key_parse_payload(SilcBuffer buffer)
193 SilcChannelKeyPayload new;
195 SILC_LOG_DEBUG(("Parsing channel key payload"));
197 new = silc_calloc(1, sizeof(*new));
199 /* Parse the Channel Key Payload */
200 silc_buffer_unformat(buffer,
201 SILC_STR_UI16_NSTRING_ALLOC(&new->id, &new->id_len),
202 SILC_STR_UI16_NSTRING_ALLOC(&new->cipher,
204 SILC_STR_UI16_NSTRING_ALLOC(&new->key, &new->key_len),
207 if (new->id_len < 1 || new->key_len < 1 || new->cipher_len < 1) {
208 SILC_LOG_ERROR(("Incorrect channel key payload in packet"));
218 silc_free(new->cipher);
225 /* Encodes channel key payload into a buffer and returns it. This is used
226 to add channel key payload into a packet. */
228 SilcBuffer silc_channel_key_encode_payload(unsigned short id_len,
230 unsigned short cipher_len,
231 unsigned char *cipher,
232 unsigned short key_len,
238 SILC_LOG_DEBUG(("Encoding channel key payload"));
241 if (!id_len || !key_len || !id || !key || !cipher_len || !cipher)
244 /* Allocate channel payload buffer. Length is 2 + id + 2 + key +
246 len = 2 + id_len + 2 + key_len + 2 + cipher_len;
247 buffer = silc_buffer_alloc(len);
249 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
251 /* Encode the Channel Payload */
252 silc_buffer_format(buffer,
253 SILC_STR_UI_SHORT(id_len),
254 SILC_STR_UI_XNSTRING(id, id_len),
255 SILC_STR_UI_SHORT(cipher_len),
256 SILC_STR_UI_XNSTRING(cipher, cipher_len),
257 SILC_STR_UI_SHORT(key_len),
258 SILC_STR_UI_XNSTRING(key, key_len),
264 /* Free's Channel Key Payload */
266 void silc_channel_key_free_payload(SilcChannelKeyPayload payload)
270 silc_free(payload->id);
272 silc_free(payload->cipher);
274 memset(payload->key, 0, payload->key_len);
275 silc_free(payload->key);
283 unsigned char *silc_channel_key_get_id(SilcChannelKeyPayload payload,
284 unsigned int *id_len)
287 *id_len = payload->id_len;
292 /* Return cipher name */
294 unsigned char *silc_channel_key_get_cipher(SilcChannelKeyPayload payload,
295 unsigned int *cipher_len)
298 *cipher_len = payload->cipher_len;
300 return payload->cipher;
305 unsigned char *silc_channel_key_get_key(SilcChannelKeyPayload payload,
306 unsigned int *key_len)
309 *key_len = payload->key_len;