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.
20 /* Channel Payload and Channel Key Payload implementations. */
23 #include "silcincludes.h"
24 #include "silcchannel.h"
26 /******************************************************************************
30 ******************************************************************************/
32 /* Channel Payload structure. Contents of this structure is parsed
34 struct SilcChannelPayloadStruct {
35 unsigned short data_len;
37 unsigned short iv_len;
41 /* Parses channel payload returning new channel payload structure */
43 SilcChannelPayload silc_channel_payload_parse(SilcBuffer buffer)
45 SilcChannelPayload new;
47 SILC_LOG_DEBUG(("Parsing channel payload"));
49 new = silc_calloc(1, sizeof(*new));
51 /* Parse the Channel Payload. Ignore padding and IV, we don't need
53 silc_buffer_unformat(buffer,
54 SILC_STR_UI16_NSTRING_ALLOC(&new->data, &new->data_len),
55 SILC_STR_UI16_NSTRING_ALLOC(NULL, NULL),
58 if (new->data_len < 1 || new->data_len > buffer->len) {
59 SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
74 /* Encodes channel payload into a buffer and returns it. This is used
75 to add channel payload into a packet. As the channel payload is
76 encrypted separately from other parts of the packet padding must
77 be applied to the payload. */
79 SilcBuffer silc_channel_payload_encode(unsigned short data_len,
81 unsigned short iv_len,
87 unsigned int len, pad_len;
88 unsigned char pad[SILC_PACKET_MAX_PADLEN];
90 SILC_LOG_DEBUG(("Encoding channel payload"));
92 /* Calculate length of padding. IV is not included into the calculation
93 since it is not encrypted. */
94 len = 2 + data_len + 2;
95 pad_len = SILC_PACKET_PADLEN((len + 2));
97 /* Allocate channel payload buffer */
99 buffer = silc_buffer_alloc(len + iv_len);
101 /* Generate padding */
102 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte(rng);
104 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
106 /* Encode the Channel Payload */
107 silc_buffer_format(buffer,
108 SILC_STR_UI_SHORT(data_len),
109 SILC_STR_UI_XNSTRING(data, data_len),
110 SILC_STR_UI_SHORT(pad_len),
111 SILC_STR_UI_XNSTRING(pad, pad_len),
112 SILC_STR_UI_XNSTRING(iv, iv_len),
115 memset(pad, 0, pad_len);
119 /* Free's Channel Payload */
121 void silc_channel_payload_free(SilcChannelPayload payload)
125 silc_free(payload->data);
127 silc_free(payload->iv);
134 unsigned char *silc_channel_get_data(SilcChannelPayload payload,
135 unsigned int *data_len)
138 *data_len = payload->data_len;
140 return payload->data;
143 /* Return initial vector */
145 unsigned char *silc_channel_get_iv(SilcChannelPayload payload,
146 unsigned int *iv_len)
149 *iv_len = payload->iv_len;
154 /******************************************************************************
158 ******************************************************************************/
160 /* Channel Key Payload structrue. Channel keys are parsed from SILC
161 packets into this structure. */
162 struct SilcChannelKeyPayloadStruct {
163 unsigned short id_len;
165 unsigned short cipher_len;
166 unsigned char *cipher;
167 unsigned short key_len;
171 /* Parses channel key payload returning new channel key payload structure */
173 SilcChannelKeyPayload silc_channel_key_payload_parse(SilcBuffer buffer)
175 SilcChannelKeyPayload new;
177 SILC_LOG_DEBUG(("Parsing channel key payload"));
179 new = silc_calloc(1, sizeof(*new));
181 /* Parse the Channel Key Payload */
182 silc_buffer_unformat(buffer,
183 SILC_STR_UI16_NSTRING_ALLOC(&new->id, &new->id_len),
184 SILC_STR_UI16_NSTRING_ALLOC(&new->cipher,
186 SILC_STR_UI16_NSTRING_ALLOC(&new->key, &new->key_len),
189 if (new->id_len < 1 || new->key_len < 1 || new->cipher_len < 1) {
190 SILC_LOG_ERROR(("Incorrect channel key payload in packet"));
200 silc_free(new->cipher);
207 /* Encodes channel key payload into a buffer and returns it. This is used
208 to add channel key payload into a packet. */
210 SilcBuffer silc_channel_key_payload_encode(unsigned short id_len,
212 unsigned short cipher_len,
213 unsigned char *cipher,
214 unsigned short key_len,
220 SILC_LOG_DEBUG(("Encoding channel key payload"));
223 if (!id_len || !key_len || !id || !key || !cipher_len || !cipher)
226 /* Allocate channel payload buffer. Length is 2 + id + 2 + key +
228 len = 2 + id_len + 2 + key_len + 2 + cipher_len;
229 buffer = silc_buffer_alloc(len);
231 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
233 /* Encode the Channel Payload */
234 silc_buffer_format(buffer,
235 SILC_STR_UI_SHORT(id_len),
236 SILC_STR_UI_XNSTRING(id, id_len),
237 SILC_STR_UI_SHORT(cipher_len),
238 SILC_STR_UI_XNSTRING(cipher, cipher_len),
239 SILC_STR_UI_SHORT(key_len),
240 SILC_STR_UI_XNSTRING(key, key_len),
246 /* Free's Channel Key Payload */
248 void silc_channel_key_payload_free(SilcChannelKeyPayload payload)
252 silc_free(payload->id);
254 silc_free(payload->cipher);
256 memset(payload->key, 0, payload->key_len);
257 silc_free(payload->key);
265 unsigned char *silc_channel_key_get_id(SilcChannelKeyPayload payload,
266 unsigned int *id_len)
269 *id_len = payload->id_len;
274 /* Return cipher name */
276 unsigned char *silc_channel_key_get_cipher(SilcChannelKeyPayload payload,
277 unsigned int *cipher_len)
280 *cipher_len = payload->cipher_len;
282 return payload->cipher;
287 unsigned char *silc_channel_key_get_key(SilcChannelKeyPayload payload,
288 unsigned int *key_len)
291 *key_len = payload->key_len;