5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2000 - 2005 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "silcincludes.h"
23 /* Encodes Key Exchange Start Payload into a SILC Buffer to be sent
26 SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske,
27 SilcSKEStartPayload payload,
28 SilcBuffer *return_buffer)
33 SILC_LOG_DEBUG(("Encoding KE Start Payload"));
36 return SILC_SKE_STATUS_ERROR;
38 buf = silc_buffer_alloc_size(payload->len);
40 return SILC_SKE_STATUS_OUT_OF_MEMORY;
42 /* Encode the payload */
43 ret = silc_buffer_format(buf,
44 SILC_STR_UI_CHAR(0), /* RESERVED field */
45 SILC_STR_UI_CHAR(payload->flags),
46 SILC_STR_UI_SHORT(payload->len),
47 SILC_STR_UI_XNSTRING(payload->cookie,
49 SILC_STR_UI_SHORT(payload->version_len),
50 SILC_STR_UI_XNSTRING(payload->version,
51 payload->version_len),
52 SILC_STR_UI_SHORT(payload->ke_grp_len),
53 SILC_STR_UI_XNSTRING(payload->ke_grp_list,
55 SILC_STR_UI_SHORT(payload->pkcs_alg_len),
56 SILC_STR_UI_XNSTRING(payload->pkcs_alg_list,
57 payload->pkcs_alg_len),
58 SILC_STR_UI_SHORT(payload->enc_alg_len),
59 SILC_STR_UI_XNSTRING(payload->enc_alg_list,
60 payload->enc_alg_len),
61 SILC_STR_UI_SHORT(payload->hash_alg_len),
62 SILC_STR_UI_XNSTRING(payload->hash_alg_list,
63 payload->hash_alg_len),
64 SILC_STR_UI_SHORT(payload->hmac_alg_len),
65 SILC_STR_UI_XNSTRING(payload->hmac_alg_list,
66 payload->hmac_alg_len),
67 SILC_STR_UI_SHORT(payload->comp_alg_len),
68 SILC_STR_UI_XNSTRING(payload->comp_alg_list,
69 payload->comp_alg_len),
72 silc_buffer_free(buf);
73 return SILC_SKE_STATUS_ERROR;
76 /* Return the encoded buffer */
79 SILC_LOG_HEXDUMP(("KE Start Payload"), buf->data, silc_buffer_len(buf));
81 return SILC_SKE_STATUS_OK;
84 /* Parses the Key Exchange Start Payload. Parsed data is returned
85 to allocated payload structure. */
88 silc_ske_payload_start_decode(SilcSKE ske,
90 SilcSKEStartPayload *return_payload)
92 SilcSKEStartPayload payload;
93 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
97 SILC_LOG_DEBUG(("Decoding Key Exchange Start Payload"));
99 SILC_LOG_HEXDUMP(("KE Start Payload"), buffer->data,
100 silc_buffer_len(buffer));
102 payload = silc_calloc(1, sizeof(*payload));
104 return SILC_SKE_STATUS_OUT_OF_MEMORY;
105 payload->cookie_len = SILC_SKE_COOKIE_LEN;
107 /* Parse start of the payload */
109 silc_buffer_unformat(buffer,
110 SILC_STR_UI_CHAR(&tmp), /* RESERVED Field */
111 SILC_STR_UI_CHAR(&payload->flags),
112 SILC_STR_UI_SHORT(&payload->len),
113 SILC_STR_UI_XNSTRING_ALLOC(&payload->cookie,
114 payload->cookie_len),
115 SILC_STR_UI16_NSTRING_ALLOC(&payload->version,
116 &payload->version_len),
117 SILC_STR_UI16_NSTRING_ALLOC(&payload->ke_grp_list,
118 &payload->ke_grp_len),
119 SILC_STR_UI16_NSTRING_ALLOC(&payload->pkcs_alg_list,
120 &payload->pkcs_alg_len),
121 SILC_STR_UI16_NSTRING_ALLOC(&payload->enc_alg_list,
122 &payload->enc_alg_len),
123 SILC_STR_UI16_NSTRING_ALLOC(&payload->hash_alg_list,
124 &payload->hash_alg_len),
125 SILC_STR_UI16_NSTRING_ALLOC(&payload->hmac_alg_list,
126 &payload->hmac_alg_len),
127 SILC_STR_UI16_NSTRING_ALLOC(&payload->comp_alg_list,
128 &payload->comp_alg_len),
131 SILC_LOG_ERROR(("Malformed KE Start Payload"));
132 status = SILC_SKE_STATUS_BAD_PAYLOAD;
137 SILC_LOG_ERROR(("Bad RESERVED field in KE Start Payload"));
138 status = SILC_SKE_STATUS_BAD_RESERVED_FIELD;
142 if (payload->len != silc_buffer_len(buffer)) {
143 SILC_LOG_ERROR(("Garbage after KE Start Payload"));
144 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
148 /* Check for mandatory fields */
149 if (!payload->cookie || !payload->version_len ||
150 !payload->ke_grp_len || !payload->pkcs_alg_len ||
151 !payload->enc_alg_len || !payload->hash_alg_len ||
152 !payload->hmac_alg_len) {
153 SILC_LOG_ERROR(("KE Start Payload is missing mandatory fields"));
154 status = SILC_SKE_STATUS_BAD_PAYLOAD;
158 /* Return the payload */
159 *return_payload = payload;
161 return SILC_SKE_STATUS_OK;
164 silc_ske_payload_start_free(payload);
166 ske->status = status;
170 /* Free's Start Payload */
172 void silc_ske_payload_start_free(SilcSKEStartPayload payload)
175 silc_free(payload->cookie);
176 silc_free(payload->version);
177 silc_free(payload->ke_grp_list);
178 silc_free(payload->pkcs_alg_list);
179 silc_free(payload->enc_alg_list);
180 silc_free(payload->hash_alg_list);
181 silc_free(payload->hmac_alg_list);
182 silc_free(payload->comp_alg_list);
187 /* Encodes Key Exchange Payload into a SILC Buffer to be sent to the other
190 SilcSKEStatus silc_ske_payload_ke_encode(SilcSKE ske,
191 SilcSKEKEPayload payload,
192 SilcBuffer *return_buffer)
195 unsigned char *x_str;
199 SILC_LOG_DEBUG(("Encoding KE Payload"));
202 return SILC_SKE_STATUS_ERROR;
204 if (ske->start_payload &&
205 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL &&
206 !payload->sign_data) {
207 SILC_LOG_DEBUG(("Signature data is missing"));
208 return SILC_SKE_STATUS_ERROR;
211 /* Encode the integer into binary data */
212 x_str = silc_mp_mp2bin(&payload->x, 0, &x_len);
214 /* Allocate channel payload buffer. The length of the buffer
215 is 4 + public key + 2 + x + 2 + signature. */
216 buf = silc_buffer_alloc_size(4 + payload->pk_len + 2 + x_len +
217 2 + payload->sign_len);
219 return SILC_SKE_STATUS_OUT_OF_MEMORY;
221 /* Encode the payload */
222 ret = silc_buffer_format(buf,
223 SILC_STR_UI_SHORT(payload->pk_len),
224 SILC_STR_UI_SHORT(payload->pk_type),
225 SILC_STR_UI_XNSTRING(payload->pk_data,
227 SILC_STR_UI_SHORT(x_len),
228 SILC_STR_UI_XNSTRING(x_str, x_len),
229 SILC_STR_UI_SHORT(payload->sign_len),
230 SILC_STR_UI_XNSTRING(payload->sign_data,
234 memset(x_str, 'F', x_len);
236 silc_buffer_free(buf);
237 return SILC_SKE_STATUS_ERROR;
240 /* Return encoded buffer */
241 *return_buffer = buf;
243 SILC_LOG_HEXDUMP(("KE Payload"), buf->data, silc_buffer_len(buf));
245 memset(x_str, 'F', x_len);
248 return SILC_SKE_STATUS_OK;
251 /* Parses the Key Exchange Payload. Parsed data is returned to allocated
252 payload structure. */
254 SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske,
256 SilcSKEKEPayload *return_payload)
258 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
259 SilcSKEKEPayload payload;
260 unsigned char *x = NULL;
262 SilcUInt32 tot_len = 0, len2;
265 SILC_LOG_DEBUG(("Decoding Key Exchange Payload"));
267 SILC_LOG_HEXDUMP(("KE Payload"), buffer->data, silc_buffer_len(buffer));
269 payload = silc_calloc(1, sizeof(*payload));
271 return SILC_SKE_STATUS_OUT_OF_MEMORY;
273 len2 = silc_buffer_len(buffer);
275 /* Parse start of the payload */
276 ret = silc_buffer_unformat(buffer,
277 SILC_STR_UI_SHORT(&payload->pk_len),
278 SILC_STR_UI_SHORT(&payload->pk_type),
281 SILC_LOG_ERROR(("Cannot decode public key from KE payload"));
282 status = SILC_SKE_STATUS_BAD_PAYLOAD;
286 if (ske->start_payload &&
287 ((payload->pk_type < SILC_SKE_PK_TYPE_SILC ||
288 payload->pk_type > SILC_SKE_PK_TYPE_SPKI) || !payload->pk_len)) {
289 SILC_LOG_ERROR(("Malformed public key in KE payload"));
290 status = SILC_SKE_STATUS_BAD_PAYLOAD;
294 tot_len += payload->pk_len + 4;
296 /* Parse PK data and the signature */
297 silc_buffer_pull(buffer, 4);
298 ret = silc_buffer_unformat(buffer,
299 SILC_STR_UI_XNSTRING_ALLOC(&payload->pk_data,
301 SILC_STR_UI16_NSTRING_ALLOC(&x, &x_len),
302 SILC_STR_UI16_NSTRING_ALLOC(&payload->sign_data,
306 SILC_LOG_ERROR(("Malformed KE Payload"));
307 status = SILC_SKE_STATUS_BAD_PAYLOAD;
311 tot_len += x_len + 2;
312 tot_len += payload->sign_len + 2;
315 SILC_LOG_ERROR(("Too short DH value in KE Payload"));
316 status = SILC_SKE_STATUS_BAD_PAYLOAD;
320 if (ske->start_payload &&
321 (ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) &&
322 (payload->sign_len < 3 || !payload->sign_data)) {
323 SILC_LOG_ERROR(("The signature data is missing - both parties are "
324 "required to do authentication"));
325 status = SILC_SKE_STATUS_BAD_PAYLOAD;
329 if (tot_len != len2) {
330 SILC_LOG_ERROR(("Garbage after KE payload"));
331 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
335 /* Decode the binary data to integer */
336 silc_mp_init(&payload->x);
337 silc_mp_bin2mp(x, x_len, &payload->x);
338 memset(x, 0, sizeof(x_len));
341 /* Return the payload */
342 *return_payload = payload;
344 return SILC_SKE_STATUS_OK;
347 silc_free(payload->pk_data);
348 silc_free(payload->sign_data);
351 ske->status = status;
355 /* Free's KE Payload */
357 void silc_ske_payload_ke_free(SilcSKEKEPayload payload)
360 silc_free(payload->pk_data);
361 silc_mp_uninit(&payload->x);
362 silc_free(payload->sign_data);