5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 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 /* XXX TODO: This is not optimized version and should be optimized!
21 Use *_ALLOC buffer formatting in payload decodings! */
25 * Revision 1.2 2000/07/05 06:05:15 priikone
26 * Global cosmetic change.
28 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
29 * Imported from internal CVS/Added Log headers.
34 #include "silcincludes.h"
35 #include "payload_internal.h"
37 /* Temporary buffer used in payload decoding */
38 unsigned char buf[16384];
40 /* Encodes Key Exchange Start Payload into a SILC Buffer to be sent
43 SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske,
44 SilcSKEStartPayload *payload,
45 SilcBuffer *return_buffer)
49 SILC_LOG_DEBUG(("Encoding KE Start Payload"));
52 return SILC_SKE_STATUS_ERROR;
54 /* Allocate channel payload buffer. */
55 buf = silc_buffer_alloc(payload->len);
57 silc_buffer_pull_tail(buf, payload->len);
59 /* Encode the payload */
60 silc_buffer_format(buf,
61 SILC_STR_UI_CHAR(0), /* RESERVED field */
62 SILC_STR_UI_CHAR(payload->flags),
63 SILC_STR_UI_SHORT(payload->len),
64 SILC_STR_UI_XNSTRING(payload->cookie,
66 SILC_STR_UI_SHORT(payload->ke_grp_len),
67 SILC_STR_UI_XNSTRING(payload->ke_grp_list,
69 SILC_STR_UI_SHORT(payload->pkcs_alg_len),
70 SILC_STR_UI_XNSTRING(payload->pkcs_alg_list,
71 payload->pkcs_alg_len),
72 SILC_STR_UI_SHORT(payload->enc_alg_len),
73 SILC_STR_UI_XNSTRING(payload->enc_alg_list,
74 payload->enc_alg_len),
75 SILC_STR_UI_SHORT(payload->hash_alg_len),
76 SILC_STR_UI_XNSTRING(payload->hash_alg_list,
77 payload->hash_alg_len),
78 SILC_STR_UI_SHORT(payload->comp_alg_len),
79 SILC_STR_UI_XNSTRING(payload->comp_alg_list,
80 payload->comp_alg_len),
83 /* Return the encoded buffer */
86 SILC_LOG_HEXDUMP(("KE Start Payload"), buf->data, buf->len);
88 return SILC_SKE_STATUS_OK;
91 /* Parses the Key Exchange Start Payload. Parsed data is returned
92 to allocated payload structure. */
95 silc_ske_payload_start_decode(SilcSKE ske,
97 SilcSKEStartPayload **return_payload)
99 SilcSKEStartPayload *payload;
100 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
104 SILC_LOG_DEBUG(("Decoding Key Exchange Start Payload"));
106 SILC_LOG_HEXDUMP(("KE Start Payload"), buffer->data, buffer->len);
108 payload = silc_calloc(1, sizeof(*payload));
109 memset(buf, 0, sizeof(buf));
111 /* Parse the entire payload */
112 silc_buffer_unformat(buffer,
113 SILC_STR_UI_CHAR(&tmp), /* RESERVED Field */
114 SILC_STR_UI_CHAR(&payload->flags),
115 SILC_STR_UI_SHORT(&payload->len),
116 SILC_STR_UI_XNSTRING(&buf, SILC_SKE_COOKIE_LEN),
117 SILC_STR_UI_SHORT(&payload->ke_grp_len),
121 SILC_LOG_DEBUG(("Bad reserved field"));
122 status = SILC_SKE_STATUS_BAD_RESERVED_FIELD;
126 if (payload->len != buffer->len) {
127 SILC_LOG_DEBUG(("Bad payload length"));
128 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
132 if (payload->ke_grp_len < 1) {
133 SILC_LOG_DEBUG(("Bad payload length"));
134 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
138 len2 = len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN + 2;
139 silc_buffer_pull(buffer, len);
141 /* Copy cookie from payload */
142 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN,
143 sizeof(unsigned char));
144 payload->cookie_len = SILC_SKE_COOKIE_LEN;
145 memcpy(payload->cookie, buf, SILC_SKE_COOKIE_LEN);
146 memset(buf, 0, sizeof(buf));
148 silc_buffer_unformat(buffer,
149 SILC_STR_UI_XNSTRING(&buf, payload->ke_grp_len),
150 SILC_STR_UI_SHORT(&payload->pkcs_alg_len),
153 if (payload->pkcs_alg_len < 1) {
154 SILC_LOG_DEBUG(("Bad payload length"));
155 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
159 len2 += len = payload->ke_grp_len + 2;
160 silc_buffer_pull(buffer, len);
162 /* Copy KE groups from payload */
163 payload->ke_grp_list = silc_calloc(payload->ke_grp_len + 1,
164 sizeof(unsigned char));
165 memcpy(payload->ke_grp_list, buf, payload->ke_grp_len);
166 memset(buf, 0, sizeof(buf));
168 silc_buffer_unformat(buffer,
169 SILC_STR_UI_XNSTRING(&buf, payload->pkcs_alg_len),
170 SILC_STR_UI_SHORT(&payload->enc_alg_len),
173 if (payload->enc_alg_len < 1) {
174 SILC_LOG_DEBUG(("Bad payload length"));
175 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
179 len2 += len = payload->pkcs_alg_len + 2;
180 silc_buffer_pull(buffer, len);
182 /* Copy PKCS algs from payload */
183 payload->pkcs_alg_list = silc_calloc(payload->pkcs_alg_len + 1,
184 sizeof(unsigned char));
185 memcpy(payload->pkcs_alg_list, buf, payload->pkcs_alg_len);
186 memset(buf, 0, sizeof(buf));
188 silc_buffer_unformat(buffer,
189 SILC_STR_UI_XNSTRING(&buf, payload->enc_alg_len),
190 SILC_STR_UI_SHORT(&payload->hash_alg_len),
193 if (payload->hash_alg_len < 1) {
194 SILC_LOG_DEBUG(("Bad payload length"));
195 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
199 len2 += len = payload->enc_alg_len + 2;
200 silc_buffer_pull(buffer, len);
202 /* Copy encryption algs from payload */
203 payload->enc_alg_list = silc_calloc(payload->enc_alg_len + 1,
204 sizeof(unsigned char));
205 memcpy(payload->enc_alg_list, buf, payload->enc_alg_len);
206 memset(buf, 0, sizeof(buf));
208 silc_buffer_unformat(buffer,
209 SILC_STR_UI_XNSTRING(&buf, payload->hash_alg_len),
210 SILC_STR_UI_SHORT(&payload->comp_alg_len),
213 len2 += len = payload->hash_alg_len + 2;
214 silc_buffer_pull(buffer, len);
216 /* Copy hash algs from payload */
217 payload->hash_alg_list = silc_calloc(payload->hash_alg_len + 1,
218 sizeof(unsigned char));
219 memcpy(payload->hash_alg_list, buf, payload->hash_alg_len);
220 memset(buf, 0, sizeof(buf));
222 if (payload->comp_alg_len) {
223 silc_buffer_unformat(buffer,
224 SILC_STR_UI_XNSTRING(&buf, payload->comp_alg_len),
227 /* Copy compression algs from payload */
228 payload->comp_alg_list = silc_calloc(payload->comp_alg_len + 1,
229 sizeof(unsigned char));
230 memcpy(payload->comp_alg_list, buf, payload->comp_alg_len);
231 memset(buf, 0, sizeof(buf));
234 silc_buffer_push(buffer, len2);
236 /* Return the payload */
237 *return_payload = payload;
239 return SILC_SKE_STATUS_OK;
242 silc_ske_payload_start_free(payload);
247 /* Free's Start Payload */
249 void silc_ske_payload_start_free(SilcSKEStartPayload *payload)
253 silc_free(payload->cookie);
254 if (payload->ke_grp_list)
255 silc_free(payload->ke_grp_list);
256 if (payload->pkcs_alg_list)
257 silc_free(payload->pkcs_alg_list);
258 if (payload->enc_alg_list)
259 silc_free(payload->enc_alg_list);
260 if (payload->hash_alg_list)
261 silc_free(payload->hash_alg_list);
262 if (payload->comp_alg_list)
263 silc_free(payload->comp_alg_list);
268 /* Encodes Key Exchange 1 Payload into a SILC Buffer to be sent
271 SilcSKEStatus silc_ske_payload_one_encode(SilcSKE ske,
272 SilcSKEOnePayload *payload,
273 SilcBuffer *return_buffer)
276 unsigned char *e_str;
277 unsigned short e_len;
279 SILC_LOG_DEBUG(("Encoding KE 1 Payload"));
282 return SILC_SKE_STATUS_ERROR;
284 /* Encode the integer into HEX string */
285 e_len = silc_mp_sizeinbase(&payload->e, 16);
286 e_str = silc_calloc(e_len + 1, sizeof(unsigned char));
287 silc_mp_get_str(e_str, 16, &payload->e);
289 /* Allocate channel payload buffer. The length of the buffer
291 buf = silc_buffer_alloc(e_len + 2);
293 silc_buffer_pull_tail(buf, e_len + 2);
295 /* Encode the payload */
296 silc_buffer_format(buf,
297 SILC_STR_UI_SHORT(e_len + 2),
298 SILC_STR_UI_XNSTRING(e_str, e_len),
301 /* Return encoded buffer */
302 *return_buffer = buf;
304 memset(e_str, 'F', e_len);
307 return SILC_SKE_STATUS_OK;
310 /* Parses the Key Exchange 1 Payload. Parsed data is returned
311 to allocated payload structure. */
313 SilcSKEStatus silc_ske_payload_one_decode(SilcSKE ske,
315 SilcSKEOnePayload **return_payload)
317 SilcSKEOnePayload *payload;
318 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
319 unsigned short e_len;
321 SILC_LOG_DEBUG(("Decoding Key Exchange 1 Payload"));
323 SILC_LOG_HEXDUMP(("KE 1 Payload"), buffer->data, buffer->len);
325 payload = silc_calloc(1, sizeof(*payload));
327 memset(buf, 0, sizeof(buf));
329 /* Parse the payload */
330 silc_buffer_unformat(buffer,
331 SILC_STR_UI_SHORT(&e_len),
335 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
339 if (e_len != buffer->len) {
340 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
344 /* Length includes the length field length as well. Remove it. */
347 silc_buffer_unformat(buffer,
348 SILC_STR_UI_SHORT(NULL),
349 SILC_STR_UI_XNSTRING(&buf, e_len),
352 /* Decode the HEX string to integer */
353 silc_mp_init(&payload->e);
354 silc_mp_set_str(&payload->e, buf, 16);
355 memset(buf, 0, sizeof(buf));
357 /* Return the payload */
358 *return_payload = payload;
360 return SILC_SKE_STATUS_OK;
368 /* Free's KE1 Payload */
370 void silc_ske_payload_one_free(SilcSKEOnePayload *payload)
373 silc_mp_clear(&payload->e);
378 /* Encodes Key Exchange 2 Payload into a SILC Buffer to be sent
381 SilcSKEStatus silc_ske_payload_two_encode(SilcSKE ske,
382 SilcSKETwoPayload *payload,
383 SilcBuffer *return_buffer)
386 unsigned char *f_str;
390 SILC_LOG_DEBUG(("Encoding KE 2 Payload"));
393 return SILC_SKE_STATUS_ERROR;
395 /* Encode the integer into HEX string */
396 f_len = silc_mp_sizeinbase(&payload->f, 16);
397 f_str = silc_calloc(f_len + 1, sizeof(unsigned char));
398 silc_mp_get_str(f_str, 16, &payload->f);
400 /* Allocate channel payload buffer. The length of the buffer
401 is 2 + 2 + public key + 2 + f + 2 + signature. */
402 len = payload->pk_len + 2 + 2 + f_len + 2 + payload->sign_len + 2;
403 buf = silc_buffer_alloc(len);
405 silc_buffer_pull_tail(buf, len);
407 /* Encode the payload */
408 silc_buffer_format(buf,
409 SILC_STR_UI_SHORT(payload->pk_len + 4),
410 SILC_STR_UI_SHORT(payload->pk_type),
411 SILC_STR_UI_XNSTRING(payload->pk_data,
413 SILC_STR_UI_SHORT(f_len + 2),
414 SILC_STR_UI_XNSTRING(f_str, f_len),
415 SILC_STR_UI_SHORT(payload->sign_len + 2),
416 SILC_STR_UI_XNSTRING(payload->sign_data,
420 /* Return encoded buffer */
421 *return_buffer = buf;
423 memset(f_str, 'F', f_len);
426 return SILC_SKE_STATUS_OK;
429 /* Parses the Key Exchange 2 Payload. Parsed data is returned
430 to allocated payload structure. */
432 SilcSKEStatus silc_ske_payload_two_decode(SilcSKE ske,
434 SilcSKETwoPayload **return_payload)
436 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
437 SilcSKETwoPayload *payload;
438 unsigned short f_len;
439 unsigned int tot_len = 0, len2;
441 SILC_LOG_DEBUG(("Decoding Key Exchange 2 Payload"));
443 SILC_LOG_HEXDUMP(("KE 2 Payload"), buffer->data, buffer->len);
445 payload = silc_calloc(1, sizeof(*payload));
446 memset(buf, 0, sizeof(buf));
450 /* Parse the payload */
451 silc_buffer_unformat(buffer,
452 SILC_STR_UI_SHORT(&payload->pk_len),
453 SILC_STR_UI_SHORT(&payload->pk_type),
456 if (payload->pk_len < 5) {
457 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
461 tot_len += payload->pk_len;
463 payload->pk_len -= 4;
464 silc_buffer_pull(buffer, 4);
465 silc_buffer_unformat(buffer,
466 SILC_STR_UI_XNSTRING(&buf, payload->pk_len),
467 SILC_STR_UI_SHORT(&f_len),
471 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
477 payload->pk_data = silc_calloc(payload->pk_len + 1,
478 sizeof(unsigned char));
479 memcpy(payload->pk_data, buf, payload->pk_len);
480 memset(buf, 0, sizeof(buf));
483 silc_buffer_pull(buffer, payload->pk_len + 2);
484 silc_buffer_unformat(buffer,
485 SILC_STR_UI_XNSTRING(&buf, f_len),
486 SILC_STR_UI_SHORT(&payload->sign_len),
489 if (payload->sign_len < 3) {
490 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
494 tot_len += payload->sign_len;
496 if (tot_len != len2) {
497 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
501 /* Decode the HEX string to integer */
502 silc_mp_init(&payload->f);
503 silc_mp_set_str(&payload->f, buf, 16);
504 memset(buf, 0, sizeof(buf));
506 payload->sign_len -= 2;
507 silc_buffer_pull(buffer, f_len + 2);
508 silc_buffer_unformat(buffer,
509 SILC_STR_UI_XNSTRING(&buf, payload->sign_len),
512 payload->sign_data = silc_calloc(payload->sign_len + 1,
513 sizeof(unsigned char));
514 memcpy(payload->sign_data, buf, payload->sign_len);
515 memset(buf, 0, sizeof(buf));
517 /* Return the payload */
518 *return_payload = payload;
520 return SILC_SKE_STATUS_OK;
523 if (payload->pk_data)
524 silc_free(payload->pk_data);
525 if (payload->sign_data)
526 silc_free(payload->sign_data);
532 /* Free's KE2 Payload */
534 void silc_ske_payload_two_free(SilcSKETwoPayload *payload)
537 if (payload->pk_data)
538 silc_free(payload->pk_data);
539 if (payload->sign_data)
540 silc_free(payload->sign_data);
541 silc_mp_clear(&payload->f);