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.5 2000/07/19 07:04:37 priikone
26 * Added version detection support to SKE. Minor bugfixes.
28 * Revision 1.4 2000/07/10 05:34:22 priikone
29 * Added mp binary encoding as protocols defines.
31 * Revision 1.3 2000/07/07 06:46:43 priikone
32 * Removed ske_verify_public_key function as it is not needed
33 * anymore. Added support to the public key verification as callback
34 * function. Other minor changes and bug fixes.
36 * Revision 1.2 2000/07/05 06:05:15 priikone
37 * Global cosmetic change.
39 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
40 * Imported from internal CVS/Added Log headers.
45 #include "silcincludes.h"
46 #include "payload_internal.h"
48 /* Temporary buffer used in payload decoding */
49 unsigned char buf[16384];
51 /* Encodes Key Exchange Start Payload into a SILC Buffer to be sent
54 SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske,
55 SilcSKEStartPayload *payload,
56 SilcBuffer *return_buffer)
60 SILC_LOG_DEBUG(("Encoding KE Start Payload"));
63 return SILC_SKE_STATUS_ERROR;
65 /* Allocate channel payload buffer. */
66 buf = silc_buffer_alloc(payload->len);
68 silc_buffer_pull_tail(buf, payload->len);
70 /* Encode the payload */
71 silc_buffer_format(buf,
72 SILC_STR_UI_CHAR(0), /* RESERVED field */
73 SILC_STR_UI_CHAR(payload->flags),
74 SILC_STR_UI_SHORT(payload->len),
75 SILC_STR_UI_XNSTRING(payload->cookie,
77 SILC_STR_UI_SHORT(payload->version_len),
78 SILC_STR_UI_XNSTRING(payload->version,
79 payload->version_len),
80 SILC_STR_UI_SHORT(payload->ke_grp_len),
81 SILC_STR_UI_XNSTRING(payload->ke_grp_list,
83 SILC_STR_UI_SHORT(payload->pkcs_alg_len),
84 SILC_STR_UI_XNSTRING(payload->pkcs_alg_list,
85 payload->pkcs_alg_len),
86 SILC_STR_UI_SHORT(payload->enc_alg_len),
87 SILC_STR_UI_XNSTRING(payload->enc_alg_list,
88 payload->enc_alg_len),
89 SILC_STR_UI_SHORT(payload->hash_alg_len),
90 SILC_STR_UI_XNSTRING(payload->hash_alg_list,
91 payload->hash_alg_len),
92 SILC_STR_UI_SHORT(payload->comp_alg_len),
93 SILC_STR_UI_XNSTRING(payload->comp_alg_list,
94 payload->comp_alg_len),
97 /* Return the encoded buffer */
100 SILC_LOG_HEXDUMP(("KE Start Payload"), buf->data, buf->len);
102 return SILC_SKE_STATUS_OK;
105 /* Parses the Key Exchange Start Payload. Parsed data is returned
106 to allocated payload structure. */
109 silc_ske_payload_start_decode(SilcSKE ske,
111 SilcSKEStartPayload **return_payload)
113 SilcSKEStartPayload *payload;
114 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
118 SILC_LOG_DEBUG(("Decoding Key Exchange Start Payload"));
120 SILC_LOG_HEXDUMP(("KE Start Payload"), buffer->data, buffer->len);
122 payload = silc_calloc(1, sizeof(*payload));
123 memset(buf, 0, sizeof(buf));
125 /* Parse the entire payload */
126 silc_buffer_unformat(buffer,
127 SILC_STR_UI_CHAR(&tmp), /* RESERVED Field */
128 SILC_STR_UI_CHAR(&payload->flags),
129 SILC_STR_UI_SHORT(&payload->len),
130 SILC_STR_UI_XNSTRING(&buf, SILC_SKE_COOKIE_LEN),
131 SILC_STR_UI16_NSTRING_ALLOC(&payload->version,
132 &payload->version_len),
133 SILC_STR_UI_SHORT(&payload->ke_grp_len),
137 SILC_LOG_DEBUG(("Bad reserved field"));
138 status = SILC_SKE_STATUS_BAD_RESERVED_FIELD;
142 if (payload->len != buffer->len) {
143 SILC_LOG_DEBUG(("Bad payload length"));
144 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
148 if (payload->ke_grp_len < 1) {
149 SILC_LOG_DEBUG(("Bad payload length"));
150 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
154 len2 = len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN + 2 + payload->version_len + 2;
155 silc_buffer_pull(buffer, len);
157 /* Copy cookie from payload */
158 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN,
159 sizeof(unsigned char));
160 payload->cookie_len = SILC_SKE_COOKIE_LEN;
161 memcpy(payload->cookie, buf, SILC_SKE_COOKIE_LEN);
162 memset(buf, 0, sizeof(buf));
164 silc_buffer_unformat(buffer,
165 SILC_STR_UI_XNSTRING(&buf, payload->ke_grp_len),
166 SILC_STR_UI_SHORT(&payload->pkcs_alg_len),
169 if (payload->pkcs_alg_len < 1) {
170 SILC_LOG_DEBUG(("Bad payload length"));
171 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
175 len2 += len = payload->ke_grp_len + 2;
176 silc_buffer_pull(buffer, len);
178 /* Copy KE groups from payload */
179 payload->ke_grp_list = silc_calloc(payload->ke_grp_len + 1,
180 sizeof(unsigned char));
181 memcpy(payload->ke_grp_list, buf, payload->ke_grp_len);
182 memset(buf, 0, sizeof(buf));
184 silc_buffer_unformat(buffer,
185 SILC_STR_UI_XNSTRING(&buf, payload->pkcs_alg_len),
186 SILC_STR_UI_SHORT(&payload->enc_alg_len),
189 if (payload->enc_alg_len < 1) {
190 SILC_LOG_DEBUG(("Bad payload length"));
191 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
195 len2 += len = payload->pkcs_alg_len + 2;
196 silc_buffer_pull(buffer, len);
198 /* Copy PKCS algs from payload */
199 payload->pkcs_alg_list = silc_calloc(payload->pkcs_alg_len + 1,
200 sizeof(unsigned char));
201 memcpy(payload->pkcs_alg_list, buf, payload->pkcs_alg_len);
202 memset(buf, 0, sizeof(buf));
204 silc_buffer_unformat(buffer,
205 SILC_STR_UI_XNSTRING(&buf, payload->enc_alg_len),
206 SILC_STR_UI_SHORT(&payload->hash_alg_len),
209 if (payload->hash_alg_len < 1) {
210 SILC_LOG_DEBUG(("Bad payload length"));
211 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
215 len2 += len = payload->enc_alg_len + 2;
216 silc_buffer_pull(buffer, len);
218 /* Copy encryption algs from payload */
219 payload->enc_alg_list = silc_calloc(payload->enc_alg_len + 1,
220 sizeof(unsigned char));
221 memcpy(payload->enc_alg_list, buf, payload->enc_alg_len);
222 memset(buf, 0, sizeof(buf));
224 silc_buffer_unformat(buffer,
225 SILC_STR_UI_XNSTRING(&buf, payload->hash_alg_len),
226 SILC_STR_UI_SHORT(&payload->comp_alg_len),
229 len2 += len = payload->hash_alg_len + 2;
230 silc_buffer_pull(buffer, len);
232 /* Copy hash algs from payload */
233 payload->hash_alg_list = silc_calloc(payload->hash_alg_len + 1,
234 sizeof(unsigned char));
235 memcpy(payload->hash_alg_list, buf, payload->hash_alg_len);
236 memset(buf, 0, sizeof(buf));
238 if (payload->comp_alg_len) {
239 silc_buffer_unformat(buffer,
240 SILC_STR_UI_XNSTRING(&buf, payload->comp_alg_len),
243 /* Copy compression algs from payload */
244 payload->comp_alg_list = silc_calloc(payload->comp_alg_len + 1,
245 sizeof(unsigned char));
246 memcpy(payload->comp_alg_list, buf, payload->comp_alg_len);
247 memset(buf, 0, sizeof(buf));
250 silc_buffer_push(buffer, len2);
252 /* Return the payload */
253 *return_payload = payload;
255 return SILC_SKE_STATUS_OK;
258 silc_ske_payload_start_free(payload);
263 /* Free's Start Payload */
265 void silc_ske_payload_start_free(SilcSKEStartPayload *payload)
269 silc_free(payload->cookie);
270 if (payload->version)
271 silc_free(payload->version);
272 if (payload->ke_grp_list)
273 silc_free(payload->ke_grp_list);
274 if (payload->pkcs_alg_list)
275 silc_free(payload->pkcs_alg_list);
276 if (payload->enc_alg_list)
277 silc_free(payload->enc_alg_list);
278 if (payload->hash_alg_list)
279 silc_free(payload->hash_alg_list);
280 if (payload->comp_alg_list)
281 silc_free(payload->comp_alg_list);
286 /* Encodes Key Exchange 1 Payload into a SILC Buffer to be sent
289 SilcSKEStatus silc_ske_payload_one_encode(SilcSKE ske,
290 SilcSKEOnePayload *payload,
291 SilcBuffer *return_buffer)
294 unsigned char *e_str;
297 SILC_LOG_DEBUG(("Encoding KE 1 Payload"));
300 return SILC_SKE_STATUS_ERROR;
302 /* Encode the integer into binary data */
303 e_str = silc_mp_mp2bin(&payload->e, &e_len);
305 return SILC_SKE_STATUS_ERROR;
307 /* Allocate channel payload buffer. The length of the buffer
309 buf = silc_buffer_alloc(e_len + 2 + payload->pk_len + 2 + 2);
310 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
312 /* Encode the payload */
313 silc_buffer_format(buf,
314 SILC_STR_UI_SHORT(payload->pk_len),
315 SILC_STR_UI_SHORT(payload->pk_type),
316 SILC_STR_UI_XNSTRING(payload->pk_data,
318 SILC_STR_UI_SHORT(e_len),
319 SILC_STR_UI_XNSTRING(e_str, e_len),
322 /* Return encoded buffer */
323 *return_buffer = buf;
325 memset(e_str, 'F', e_len);
328 return SILC_SKE_STATUS_OK;
331 /* Parses the Key Exchange 1 Payload. Parsed data is returned
332 to allocated payload structure. */
334 SilcSKEStatus silc_ske_payload_one_decode(SilcSKE ske,
336 SilcSKEOnePayload **return_payload)
338 SilcSKEOnePayload *payload;
339 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
341 unsigned short e_len;
343 SILC_LOG_DEBUG(("Decoding Key Exchange 1 Payload"));
345 SILC_LOG_HEXDUMP(("KE 1 Payload"), buffer->data, buffer->len);
347 payload = silc_calloc(1, sizeof(*payload));
349 silc_buffer_unformat(buffer,
350 SILC_STR_UI_SHORT(&payload->pk_len),
351 SILC_STR_UI_SHORT(&payload->pk_type),
354 if (payload->pk_len < 5) {
355 status = SILC_SKE_STATUS_BAD_PAYLOAD;
359 silc_buffer_pull(buffer, 2 + 2);
360 silc_buffer_unformat(buffer,
361 SILC_STR_UI_XNSTRING_ALLOC(&payload->pk_data,
363 SILC_STR_UI16_NSTRING_ALLOC(&e, &e_len),
367 status = SILC_SKE_STATUS_BAD_PAYLOAD;
371 silc_buffer_push(buffer, 2 + 2);
373 if (payload->pk_len + 2 + 2 + 2 + e_len != buffer->len) {
374 status = SILC_SKE_STATUS_BAD_PAYLOAD;
378 /* Decode the HEX string to integer */
379 silc_mp_init(&payload->e);
380 silc_mp_bin2mp(e, e_len, &payload->e);
381 memset(e, 0, sizeof(e_len));
384 /* Return the payload */
385 *return_payload = payload;
387 return SILC_SKE_STATUS_OK;
394 /* Free's KE1 Payload */
396 void silc_ske_payload_one_free(SilcSKEOnePayload *payload)
399 if (payload->pk_data)
400 silc_free(payload->pk_data);
405 /* Encodes Key Exchange 2 Payload into a SILC Buffer to be sent
408 SilcSKEStatus silc_ske_payload_two_encode(SilcSKE ske,
409 SilcSKETwoPayload *payload,
410 SilcBuffer *return_buffer)
413 unsigned char *f_str;
417 SILC_LOG_DEBUG(("Encoding KE 2 Payload"));
420 return SILC_SKE_STATUS_ERROR;
422 /* Encode the integer into HEX string */
423 f_str = silc_mp_mp2bin(&payload->f, &f_len);
425 /* Allocate channel payload buffer. The length of the buffer
426 is 2 + 2 + public key + 2 + f + 2 + signature. */
427 len = payload->pk_len + 2 + 2 + f_len + 2 + payload->sign_len + 2;
428 buf = silc_buffer_alloc(len);
430 silc_buffer_pull_tail(buf, len);
432 /* Encode the payload */
433 silc_buffer_format(buf,
434 SILC_STR_UI_SHORT(payload->pk_len),
435 SILC_STR_UI_SHORT(payload->pk_type),
436 SILC_STR_UI_XNSTRING(payload->pk_data,
438 SILC_STR_UI_SHORT(f_len),
439 SILC_STR_UI_XNSTRING(f_str, f_len),
440 SILC_STR_UI_SHORT(payload->sign_len),
441 SILC_STR_UI_XNSTRING(payload->sign_data,
445 /* Return encoded buffer */
446 *return_buffer = buf;
448 memset(f_str, 'F', f_len);
451 return SILC_SKE_STATUS_OK;
454 /* Parses the Key Exchange 2 Payload. Parsed data is returned
455 to allocated payload structure. */
457 SilcSKEStatus silc_ske_payload_two_decode(SilcSKE ske,
459 SilcSKETwoPayload **return_payload)
461 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
462 SilcSKETwoPayload *payload;
464 unsigned short f_len;
465 unsigned int tot_len = 0, len2;
467 SILC_LOG_DEBUG(("Decoding Key Exchange 2 Payload"));
469 SILC_LOG_HEXDUMP(("KE 2 Payload"), buffer->data, buffer->len);
471 payload = silc_calloc(1, sizeof(*payload));
472 memset(buf, 0, sizeof(buf));
476 /* Parse the payload */
477 silc_buffer_unformat(buffer,
478 SILC_STR_UI_SHORT(&payload->pk_len),
479 SILC_STR_UI_SHORT(&payload->pk_type),
482 if (payload->pk_len < 5) {
483 status = SILC_SKE_STATUS_BAD_PAYLOAD;
487 tot_len += payload->pk_len + 4;
489 silc_buffer_pull(buffer, 4);
490 silc_buffer_unformat(buffer,
491 SILC_STR_UI_XNSTRING_ALLOC(&payload->pk_data,
493 SILC_STR_UI16_NSTRING_ALLOC(&f, &f_len),
494 SILC_STR_UI16_NSTRING_ALLOC(&payload->sign_data,
498 tot_len += f_len + 2;
499 tot_len += payload->sign_len + 2;
502 status = SILC_SKE_STATUS_BAD_PAYLOAD;
506 if (payload->sign_len < 3) {
507 status = SILC_SKE_STATUS_BAD_PAYLOAD;
511 if (tot_len != len2) {
512 status = SILC_SKE_STATUS_BAD_PAYLOAD;
516 /* Decode the HEX string to integer */
517 silc_mp_init(&payload->f);
518 silc_mp_bin2mp(f, f_len, &payload->f);
519 memset(f, 0, sizeof(f_len));
522 /* Return the payload */
523 *return_payload = payload;
525 return SILC_SKE_STATUS_OK;
528 if (payload->pk_data)
529 silc_free(payload->pk_data);
530 if (payload->sign_data)
531 silc_free(payload->sign_data);
536 /* Free's KE2 Payload */
538 void silc_ske_payload_two_free(SilcSKETwoPayload *payload)
541 if (payload->pk_data)
542 silc_free(payload->pk_data);
543 if (payload->sign_data)
544 silc_free(payload->sign_data);