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++)
103 pad[i] = silc_rng_get_byte(rng);
105 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
107 /* Encode the Channel Payload */
108 silc_buffer_format(buffer,
109 SILC_STR_UI_SHORT(data_len),
110 SILC_STR_UI_XNSTRING(data, data_len),
111 SILC_STR_UI_SHORT(pad_len),
112 SILC_STR_UI_XNSTRING(pad, pad_len),
113 SILC_STR_UI_XNSTRING(iv, iv_len),
116 memset(pad, 0, pad_len);
120 /* Free's Channel Payload */
122 void silc_channel_payload_free(SilcChannelPayload payload)
126 silc_free(payload->data);
128 silc_free(payload->iv);
135 unsigned char *silc_channel_get_data(SilcChannelPayload payload,
136 unsigned int *data_len)
139 *data_len = payload->data_len;
141 return payload->data;
144 /* Return initial vector */
146 unsigned char *silc_channel_get_iv(SilcChannelPayload payload,
147 unsigned int *iv_len)
150 *iv_len = payload->iv_len;
155 /******************************************************************************
159 ******************************************************************************/
161 /* Channel Key Payload structrue. Channel keys are parsed from SILC
162 packets into this structure. */
163 struct SilcChannelKeyPayloadStruct {
164 unsigned short id_len;
166 unsigned short cipher_len;
167 unsigned char *cipher;
168 unsigned short key_len;
172 /* Parses channel key payload returning new channel key payload structure */
174 SilcChannelKeyPayload silc_channel_key_payload_parse(SilcBuffer buffer)
176 SilcChannelKeyPayload new;
178 SILC_LOG_DEBUG(("Parsing channel key payload"));
180 new = silc_calloc(1, sizeof(*new));
182 /* Parse the Channel Key Payload */
183 silc_buffer_unformat(buffer,
184 SILC_STR_UI16_NSTRING_ALLOC(&new->id, &new->id_len),
185 SILC_STR_UI16_NSTRING_ALLOC(&new->cipher,
187 SILC_STR_UI16_NSTRING_ALLOC(&new->key, &new->key_len),
190 if (new->id_len < 1 || new->key_len < 1 || new->cipher_len < 1) {
191 SILC_LOG_ERROR(("Incorrect channel key payload in packet"));
201 silc_free(new->cipher);
208 /* Encodes channel key payload into a buffer and returns it. This is used
209 to add channel key payload into a packet. */
211 SilcBuffer silc_channel_key_payload_encode(unsigned short id_len,
213 unsigned short cipher_len,
214 unsigned char *cipher,
215 unsigned short key_len,
221 SILC_LOG_DEBUG(("Encoding channel key payload"));
224 if (!id_len || !key_len || !id || !key || !cipher_len || !cipher)
227 /* Allocate channel payload buffer. Length is 2 + id + 2 + key +
229 len = 2 + id_len + 2 + key_len + 2 + cipher_len;
230 buffer = silc_buffer_alloc(len);
232 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
234 /* Encode the Channel Payload */
235 silc_buffer_format(buffer,
236 SILC_STR_UI_SHORT(id_len),
237 SILC_STR_UI_XNSTRING(id, id_len),
238 SILC_STR_UI_SHORT(cipher_len),
239 SILC_STR_UI_XNSTRING(cipher, cipher_len),
240 SILC_STR_UI_SHORT(key_len),
241 SILC_STR_UI_XNSTRING(key, key_len),
247 /* Free's Channel Key Payload */
249 void silc_channel_key_payload_free(SilcChannelKeyPayload payload)
253 silc_free(payload->id);
255 silc_free(payload->cipher);
257 memset(payload->key, 0, payload->key_len);
258 silc_free(payload->key);
266 unsigned char *silc_channel_key_get_id(SilcChannelKeyPayload payload,
267 unsigned int *id_len)
270 *id_len = payload->id_len;
275 /* Return cipher name */
277 unsigned char *silc_channel_key_get_cipher(SilcChannelKeyPayload payload,
278 unsigned int *cipher_len)
281 *cipher_len = payload->cipher_len;
283 return payload->cipher;
288 unsigned char *silc_channel_key_get_key(SilcChannelKeyPayload payload,
289 unsigned int *key_len)
292 *key_len = payload->key_len;