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.4 2000/07/10 05:34:22 priikone
26 * Added mp binary encoding as protocols defines.
28 * Revision 1.3 2000/07/07 06:46:43 priikone
29 * Removed ske_verify_public_key function as it is not needed
30 * anymore. Added support to the public key verification as callback
31 * function. Other minor changes and bug fixes.
33 * Revision 1.2 2000/07/05 06:05:15 priikone
34 * Global cosmetic change.
36 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
37 * Imported from internal CVS/Added Log headers.
42 #include "silcincludes.h"
43 #include "payload_internal.h"
45 /* Temporary buffer used in payload decoding */
46 unsigned char buf[16384];
48 /* Encodes Key Exchange Start Payload into a SILC Buffer to be sent
51 SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske,
52 SilcSKEStartPayload *payload,
53 SilcBuffer *return_buffer)
57 SILC_LOG_DEBUG(("Encoding KE Start Payload"));
60 return SILC_SKE_STATUS_ERROR;
62 /* Allocate channel payload buffer. */
63 buf = silc_buffer_alloc(payload->len);
65 silc_buffer_pull_tail(buf, payload->len);
67 /* Encode the payload */
68 silc_buffer_format(buf,
69 SILC_STR_UI_CHAR(0), /* RESERVED field */
70 SILC_STR_UI_CHAR(payload->flags),
71 SILC_STR_UI_SHORT(payload->len),
72 SILC_STR_UI_XNSTRING(payload->cookie,
74 SILC_STR_UI_SHORT(payload->ke_grp_len),
75 SILC_STR_UI_XNSTRING(payload->ke_grp_list,
77 SILC_STR_UI_SHORT(payload->pkcs_alg_len),
78 SILC_STR_UI_XNSTRING(payload->pkcs_alg_list,
79 payload->pkcs_alg_len),
80 SILC_STR_UI_SHORT(payload->enc_alg_len),
81 SILC_STR_UI_XNSTRING(payload->enc_alg_list,
82 payload->enc_alg_len),
83 SILC_STR_UI_SHORT(payload->hash_alg_len),
84 SILC_STR_UI_XNSTRING(payload->hash_alg_list,
85 payload->hash_alg_len),
86 SILC_STR_UI_SHORT(payload->comp_alg_len),
87 SILC_STR_UI_XNSTRING(payload->comp_alg_list,
88 payload->comp_alg_len),
91 /* Return the encoded buffer */
94 SILC_LOG_HEXDUMP(("KE Start Payload"), buf->data, buf->len);
96 return SILC_SKE_STATUS_OK;
99 /* Parses the Key Exchange Start Payload. Parsed data is returned
100 to allocated payload structure. */
103 silc_ske_payload_start_decode(SilcSKE ske,
105 SilcSKEStartPayload **return_payload)
107 SilcSKEStartPayload *payload;
108 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
112 SILC_LOG_DEBUG(("Decoding Key Exchange Start Payload"));
114 SILC_LOG_HEXDUMP(("KE Start Payload"), buffer->data, buffer->len);
116 payload = silc_calloc(1, sizeof(*payload));
117 memset(buf, 0, sizeof(buf));
119 /* Parse the entire payload */
120 silc_buffer_unformat(buffer,
121 SILC_STR_UI_CHAR(&tmp), /* RESERVED Field */
122 SILC_STR_UI_CHAR(&payload->flags),
123 SILC_STR_UI_SHORT(&payload->len),
124 SILC_STR_UI_XNSTRING(&buf, SILC_SKE_COOKIE_LEN),
125 SILC_STR_UI_SHORT(&payload->ke_grp_len),
129 SILC_LOG_DEBUG(("Bad reserved field"));
130 status = SILC_SKE_STATUS_BAD_RESERVED_FIELD;
134 if (payload->len != buffer->len) {
135 SILC_LOG_DEBUG(("Bad payload length"));
136 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
140 if (payload->ke_grp_len < 1) {
141 SILC_LOG_DEBUG(("Bad payload length"));
142 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
146 len2 = len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN + 2;
147 silc_buffer_pull(buffer, len);
149 /* Copy cookie from payload */
150 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN,
151 sizeof(unsigned char));
152 payload->cookie_len = SILC_SKE_COOKIE_LEN;
153 memcpy(payload->cookie, buf, SILC_SKE_COOKIE_LEN);
154 memset(buf, 0, sizeof(buf));
156 silc_buffer_unformat(buffer,
157 SILC_STR_UI_XNSTRING(&buf, payload->ke_grp_len),
158 SILC_STR_UI_SHORT(&payload->pkcs_alg_len),
161 if (payload->pkcs_alg_len < 1) {
162 SILC_LOG_DEBUG(("Bad payload length"));
163 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
167 len2 += len = payload->ke_grp_len + 2;
168 silc_buffer_pull(buffer, len);
170 /* Copy KE groups from payload */
171 payload->ke_grp_list = silc_calloc(payload->ke_grp_len + 1,
172 sizeof(unsigned char));
173 memcpy(payload->ke_grp_list, buf, payload->ke_grp_len);
174 memset(buf, 0, sizeof(buf));
176 silc_buffer_unformat(buffer,
177 SILC_STR_UI_XNSTRING(&buf, payload->pkcs_alg_len),
178 SILC_STR_UI_SHORT(&payload->enc_alg_len),
181 if (payload->enc_alg_len < 1) {
182 SILC_LOG_DEBUG(("Bad payload length"));
183 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
187 len2 += len = payload->pkcs_alg_len + 2;
188 silc_buffer_pull(buffer, len);
190 /* Copy PKCS algs from payload */
191 payload->pkcs_alg_list = silc_calloc(payload->pkcs_alg_len + 1,
192 sizeof(unsigned char));
193 memcpy(payload->pkcs_alg_list, buf, payload->pkcs_alg_len);
194 memset(buf, 0, sizeof(buf));
196 silc_buffer_unformat(buffer,
197 SILC_STR_UI_XNSTRING(&buf, payload->enc_alg_len),
198 SILC_STR_UI_SHORT(&payload->hash_alg_len),
201 if (payload->hash_alg_len < 1) {
202 SILC_LOG_DEBUG(("Bad payload length"));
203 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
207 len2 += len = payload->enc_alg_len + 2;
208 silc_buffer_pull(buffer, len);
210 /* Copy encryption algs from payload */
211 payload->enc_alg_list = silc_calloc(payload->enc_alg_len + 1,
212 sizeof(unsigned char));
213 memcpy(payload->enc_alg_list, buf, payload->enc_alg_len);
214 memset(buf, 0, sizeof(buf));
216 silc_buffer_unformat(buffer,
217 SILC_STR_UI_XNSTRING(&buf, payload->hash_alg_len),
218 SILC_STR_UI_SHORT(&payload->comp_alg_len),
221 len2 += len = payload->hash_alg_len + 2;
222 silc_buffer_pull(buffer, len);
224 /* Copy hash algs from payload */
225 payload->hash_alg_list = silc_calloc(payload->hash_alg_len + 1,
226 sizeof(unsigned char));
227 memcpy(payload->hash_alg_list, buf, payload->hash_alg_len);
228 memset(buf, 0, sizeof(buf));
230 if (payload->comp_alg_len) {
231 silc_buffer_unformat(buffer,
232 SILC_STR_UI_XNSTRING(&buf, payload->comp_alg_len),
235 /* Copy compression algs from payload */
236 payload->comp_alg_list = silc_calloc(payload->comp_alg_len + 1,
237 sizeof(unsigned char));
238 memcpy(payload->comp_alg_list, buf, payload->comp_alg_len);
239 memset(buf, 0, sizeof(buf));
242 silc_buffer_push(buffer, len2);
244 /* Return the payload */
245 *return_payload = payload;
247 return SILC_SKE_STATUS_OK;
250 silc_ske_payload_start_free(payload);
255 /* Free's Start Payload */
257 void silc_ske_payload_start_free(SilcSKEStartPayload *payload)
261 silc_free(payload->cookie);
262 if (payload->ke_grp_list)
263 silc_free(payload->ke_grp_list);
264 if (payload->pkcs_alg_list)
265 silc_free(payload->pkcs_alg_list);
266 if (payload->enc_alg_list)
267 silc_free(payload->enc_alg_list);
268 if (payload->hash_alg_list)
269 silc_free(payload->hash_alg_list);
270 if (payload->comp_alg_list)
271 silc_free(payload->comp_alg_list);
276 /* Encodes Key Exchange 1 Payload into a SILC Buffer to be sent
279 SilcSKEStatus silc_ske_payload_one_encode(SilcSKE ske,
280 SilcSKEOnePayload *payload,
281 SilcBuffer *return_buffer)
284 unsigned char *e_str;
287 SILC_LOG_DEBUG(("Encoding KE 1 Payload"));
290 return SILC_SKE_STATUS_ERROR;
292 /* Encode the integer into binary data */
293 e_str = silc_mp_mp2bin(&payload->e, &e_len);
295 /* Allocate channel payload buffer. The length of the buffer
297 buf = silc_buffer_alloc(e_len + 2);
298 silc_buffer_pull_tail(buf, e_len + 2);
300 /* Encode the payload */
301 silc_buffer_format(buf,
302 SILC_STR_UI_SHORT(e_len + 2),
303 SILC_STR_UI_XNSTRING(e_str, e_len),
306 /* Return encoded buffer */
307 *return_buffer = buf;
309 memset(e_str, 'F', e_len);
312 return SILC_SKE_STATUS_OK;
315 /* Parses the Key Exchange 1 Payload. Parsed data is returned
316 to allocated payload structure. */
318 SilcSKEStatus silc_ske_payload_one_decode(SilcSKE ske,
320 SilcSKEOnePayload **return_payload)
322 SilcSKEOnePayload *payload;
323 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
324 unsigned short e_len;
326 SILC_LOG_DEBUG(("Decoding Key Exchange 1 Payload"));
328 SILC_LOG_HEXDUMP(("KE 1 Payload"), buffer->data, buffer->len);
330 payload = silc_calloc(1, sizeof(*payload));
332 memset(buf, 0, sizeof(buf));
334 /* Parse the payload */
335 silc_buffer_unformat(buffer,
336 SILC_STR_UI_SHORT(&e_len),
340 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
344 if (e_len != buffer->len) {
345 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
349 /* Length includes the length field length as well. Remove it. */
352 silc_buffer_unformat(buffer,
353 SILC_STR_UI_SHORT(NULL),
354 SILC_STR_UI_XNSTRING(&buf, e_len),
357 /* Decode the HEX string to integer */
358 silc_mp_init(&payload->e);
359 silc_mp_bin2mp(buf, e_len, &payload->e);
360 memset(buf, 0, sizeof(buf));
362 /* Return the payload */
363 *return_payload = payload;
365 return SILC_SKE_STATUS_OK;
373 /* Free's KE1 Payload */
375 void silc_ske_payload_one_free(SilcSKEOnePayload *payload)
382 /* Encodes Key Exchange 2 Payload into a SILC Buffer to be sent
385 SilcSKEStatus silc_ske_payload_two_encode(SilcSKE ske,
386 SilcSKETwoPayload *payload,
387 SilcBuffer *return_buffer)
390 unsigned char *f_str;
394 SILC_LOG_DEBUG(("Encoding KE 2 Payload"));
397 return SILC_SKE_STATUS_ERROR;
399 /* Encode the integer into HEX string */
400 f_str = silc_mp_mp2bin(&payload->f, &f_len);
402 /* Allocate channel payload buffer. The length of the buffer
403 is 2 + 2 + public key + 2 + f + 2 + signature. */
404 len = payload->pk_len + 2 + 2 + f_len + 2 + payload->sign_len + 2;
405 buf = silc_buffer_alloc(len);
407 silc_buffer_pull_tail(buf, len);
409 /* Encode the payload */
410 silc_buffer_format(buf,
411 SILC_STR_UI_SHORT(payload->pk_len + 4),
412 SILC_STR_UI_SHORT(payload->pk_type),
413 SILC_STR_UI_XNSTRING(payload->pk_data,
415 SILC_STR_UI_SHORT(f_len + 2),
416 SILC_STR_UI_XNSTRING(f_str, f_len),
417 SILC_STR_UI_SHORT(payload->sign_len + 2),
418 SILC_STR_UI_XNSTRING(payload->sign_data,
422 /* Return encoded buffer */
423 *return_buffer = buf;
425 memset(f_str, 'F', f_len);
428 return SILC_SKE_STATUS_OK;
431 /* Parses the Key Exchange 2 Payload. Parsed data is returned
432 to allocated payload structure. */
434 SilcSKEStatus silc_ske_payload_two_decode(SilcSKE ske,
436 SilcSKETwoPayload **return_payload)
438 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
439 SilcSKETwoPayload *payload;
440 unsigned short f_len;
441 unsigned int tot_len = 0, len2;
443 SILC_LOG_DEBUG(("Decoding Key Exchange 2 Payload"));
445 SILC_LOG_HEXDUMP(("KE 2 Payload"), buffer->data, buffer->len);
447 payload = silc_calloc(1, sizeof(*payload));
448 memset(buf, 0, sizeof(buf));
452 /* Parse the payload */
453 silc_buffer_unformat(buffer,
454 SILC_STR_UI_SHORT(&payload->pk_len),
455 SILC_STR_UI_SHORT(&payload->pk_type),
458 if (payload->pk_len < 5) {
459 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
463 tot_len += payload->pk_len;
465 payload->pk_len -= 4;
466 silc_buffer_pull(buffer, 4);
467 silc_buffer_unformat(buffer,
468 SILC_STR_UI_XNSTRING(&buf, payload->pk_len),
469 SILC_STR_UI_SHORT(&f_len),
473 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
479 payload->pk_data = silc_calloc(payload->pk_len + 1,
480 sizeof(unsigned char));
481 memcpy(payload->pk_data, buf, payload->pk_len);
482 memset(buf, 0, sizeof(buf));
485 silc_buffer_pull(buffer, payload->pk_len + 2);
486 silc_buffer_unformat(buffer,
487 SILC_STR_UI_XNSTRING(&buf, f_len),
488 SILC_STR_UI_SHORT(&payload->sign_len),
491 if (payload->sign_len < 3) {
492 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
496 tot_len += payload->sign_len;
498 if (tot_len != len2) {
499 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
503 /* Decode the HEX string to integer */
504 silc_mp_init(&payload->f);
505 silc_mp_bin2mp(buf, f_len, &payload->f);
506 memset(buf, 0, sizeof(buf));
508 payload->sign_len -= 2;
509 silc_buffer_pull(buffer, f_len + 2);
510 silc_buffer_unformat(buffer,
511 SILC_STR_UI_XNSTRING(&buf, payload->sign_len),
514 payload->sign_data = silc_calloc(payload->sign_len + 1,
515 sizeof(unsigned char));
516 memcpy(payload->sign_data, buf, payload->sign_len);
517 memset(buf, 0, sizeof(buf));
519 /* Return the payload */
520 *return_payload = payload;
522 return SILC_SKE_STATUS_OK;
525 if (payload->pk_data)
526 silc_free(payload->pk_data);
527 if (payload->sign_data)
528 silc_free(payload->sign_data);
534 /* Free's KE2 Payload */
536 void silc_ske_payload_two_free(SilcSKETwoPayload *payload)
539 if (payload->pk_data)
540 silc_free(payload->pk_data);
541 if (payload->sign_data)
542 silc_free(payload->sign_data);