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.6 2000/10/31 19:48:31 priikone
26 * A LOT updates. Cannot separate. :)
28 * Revision 1.5 2000/07/19 07:04:37 priikone
29 * Added version detection support to SKE. Minor bugfixes.
31 * Revision 1.4 2000/07/10 05:34:22 priikone
32 * Added mp binary encoding as protocols defines.
34 * Revision 1.3 2000/07/07 06:46:43 priikone
35 * Removed ske_verify_public_key function as it is not needed
36 * anymore. Added support to the public key verification as callback
37 * function. Other minor changes and bug fixes.
39 * Revision 1.2 2000/07/05 06:05:15 priikone
40 * Global cosmetic change.
42 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
43 * Imported from internal CVS/Added Log headers.
48 #include "silcincludes.h"
49 #include "payload_internal.h"
51 /* Temporary buffer used in payload decoding */
52 unsigned char buf[16384];
54 /* Encodes Key Exchange Start Payload into a SILC Buffer to be sent
57 SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske,
58 SilcSKEStartPayload *payload,
59 SilcBuffer *return_buffer)
63 SILC_LOG_DEBUG(("Encoding KE Start Payload"));
66 return SILC_SKE_STATUS_ERROR;
68 /* Allocate channel payload buffer. */
69 buf = silc_buffer_alloc(payload->len);
71 silc_buffer_pull_tail(buf, payload->len);
73 /* Encode the payload */
74 silc_buffer_format(buf,
75 SILC_STR_UI_CHAR(0), /* RESERVED field */
76 SILC_STR_UI_CHAR(payload->flags),
77 SILC_STR_UI_SHORT(payload->len),
78 SILC_STR_UI_XNSTRING(payload->cookie,
80 SILC_STR_UI_SHORT(payload->version_len),
81 SILC_STR_UI_XNSTRING(payload->version,
82 payload->version_len),
83 SILC_STR_UI_SHORT(payload->ke_grp_len),
84 SILC_STR_UI_XNSTRING(payload->ke_grp_list,
86 SILC_STR_UI_SHORT(payload->pkcs_alg_len),
87 SILC_STR_UI_XNSTRING(payload->pkcs_alg_list,
88 payload->pkcs_alg_len),
89 SILC_STR_UI_SHORT(payload->enc_alg_len),
90 SILC_STR_UI_XNSTRING(payload->enc_alg_list,
91 payload->enc_alg_len),
92 SILC_STR_UI_SHORT(payload->hash_alg_len),
93 SILC_STR_UI_XNSTRING(payload->hash_alg_list,
94 payload->hash_alg_len),
95 SILC_STR_UI_SHORT(payload->comp_alg_len),
96 SILC_STR_UI_XNSTRING(payload->comp_alg_list,
97 payload->comp_alg_len),
100 /* Return the encoded buffer */
101 *return_buffer = buf;
103 SILC_LOG_HEXDUMP(("KE Start Payload"), buf->data, buf->len);
105 return SILC_SKE_STATUS_OK;
108 /* Parses the Key Exchange Start Payload. Parsed data is returned
109 to allocated payload structure. */
112 silc_ske_payload_start_decode(SilcSKE ske,
114 SilcSKEStartPayload **return_payload)
116 SilcSKEStartPayload *payload;
117 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
121 SILC_LOG_DEBUG(("Decoding Key Exchange Start Payload"));
123 SILC_LOG_HEXDUMP(("KE Start Payload"), buffer->data, buffer->len);
125 payload = silc_calloc(1, sizeof(*payload));
126 memset(buf, 0, sizeof(buf));
128 /* Parse the entire payload */
129 silc_buffer_unformat(buffer,
130 SILC_STR_UI_CHAR(&tmp), /* RESERVED Field */
131 SILC_STR_UI_CHAR(&payload->flags),
132 SILC_STR_UI_SHORT(&payload->len),
133 SILC_STR_UI_XNSTRING(&buf, SILC_SKE_COOKIE_LEN),
134 SILC_STR_UI16_NSTRING_ALLOC(&payload->version,
135 &payload->version_len),
136 SILC_STR_UI_SHORT(&payload->ke_grp_len),
140 SILC_LOG_DEBUG(("Bad reserved field"));
141 status = SILC_SKE_STATUS_BAD_RESERVED_FIELD;
145 if (payload->len != buffer->len) {
146 SILC_LOG_DEBUG(("Bad payload length"));
147 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
151 if (payload->ke_grp_len < 1) {
152 SILC_LOG_DEBUG(("Bad payload length"));
153 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
157 len2 = len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN + 2 + payload->version_len + 2;
158 silc_buffer_pull(buffer, len);
160 /* Copy cookie from payload */
161 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN,
162 sizeof(unsigned char));
163 payload->cookie_len = SILC_SKE_COOKIE_LEN;
164 memcpy(payload->cookie, buf, SILC_SKE_COOKIE_LEN);
165 memset(buf, 0, sizeof(buf));
167 silc_buffer_unformat(buffer,
168 SILC_STR_UI_XNSTRING(&buf, payload->ke_grp_len),
169 SILC_STR_UI_SHORT(&payload->pkcs_alg_len),
172 if (payload->pkcs_alg_len < 1) {
173 SILC_LOG_DEBUG(("Bad payload length"));
174 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
178 len2 += len = payload->ke_grp_len + 2;
179 silc_buffer_pull(buffer, len);
181 /* Copy KE groups from payload */
182 payload->ke_grp_list = silc_calloc(payload->ke_grp_len + 1,
183 sizeof(unsigned char));
184 memcpy(payload->ke_grp_list, buf, payload->ke_grp_len);
185 memset(buf, 0, sizeof(buf));
187 silc_buffer_unformat(buffer,
188 SILC_STR_UI_XNSTRING(&buf, payload->pkcs_alg_len),
189 SILC_STR_UI_SHORT(&payload->enc_alg_len),
192 if (payload->enc_alg_len < 1) {
193 SILC_LOG_DEBUG(("Bad payload length"));
194 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
198 len2 += len = payload->pkcs_alg_len + 2;
199 silc_buffer_pull(buffer, len);
201 /* Copy PKCS algs from payload */
202 payload->pkcs_alg_list = silc_calloc(payload->pkcs_alg_len + 1,
203 sizeof(unsigned char));
204 memcpy(payload->pkcs_alg_list, buf, payload->pkcs_alg_len);
205 memset(buf, 0, sizeof(buf));
207 silc_buffer_unformat(buffer,
208 SILC_STR_UI_XNSTRING(&buf, payload->enc_alg_len),
209 SILC_STR_UI_SHORT(&payload->hash_alg_len),
212 if (payload->hash_alg_len < 1) {
213 SILC_LOG_DEBUG(("Bad payload length"));
214 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
218 len2 += len = payload->enc_alg_len + 2;
219 silc_buffer_pull(buffer, len);
221 /* Copy encryption algs from payload */
222 payload->enc_alg_list = silc_calloc(payload->enc_alg_len + 1,
223 sizeof(unsigned char));
224 memcpy(payload->enc_alg_list, buf, payload->enc_alg_len);
225 memset(buf, 0, sizeof(buf));
227 silc_buffer_unformat(buffer,
228 SILC_STR_UI_XNSTRING(&buf, payload->hash_alg_len),
229 SILC_STR_UI_SHORT(&payload->comp_alg_len),
232 len2 += len = payload->hash_alg_len + 2;
233 silc_buffer_pull(buffer, len);
235 /* Copy hash algs from payload */
236 payload->hash_alg_list = silc_calloc(payload->hash_alg_len + 1,
237 sizeof(unsigned char));
238 memcpy(payload->hash_alg_list, buf, payload->hash_alg_len);
239 memset(buf, 0, sizeof(buf));
241 if (payload->comp_alg_len) {
242 silc_buffer_unformat(buffer,
243 SILC_STR_UI_XNSTRING(&buf, payload->comp_alg_len),
246 /* Copy compression algs from payload */
247 payload->comp_alg_list = silc_calloc(payload->comp_alg_len + 1,
248 sizeof(unsigned char));
249 memcpy(payload->comp_alg_list, buf, payload->comp_alg_len);
250 memset(buf, 0, sizeof(buf));
253 silc_buffer_push(buffer, len2);
255 /* Return the payload */
256 *return_payload = payload;
258 return SILC_SKE_STATUS_OK;
261 silc_ske_payload_start_free(payload);
263 ske->status = status;
267 /* Free's Start Payload */
269 void silc_ske_payload_start_free(SilcSKEStartPayload *payload)
273 silc_free(payload->cookie);
274 if (payload->version)
275 silc_free(payload->version);
276 if (payload->ke_grp_list)
277 silc_free(payload->ke_grp_list);
278 if (payload->pkcs_alg_list)
279 silc_free(payload->pkcs_alg_list);
280 if (payload->enc_alg_list)
281 silc_free(payload->enc_alg_list);
282 if (payload->hash_alg_list)
283 silc_free(payload->hash_alg_list);
284 if (payload->comp_alg_list)
285 silc_free(payload->comp_alg_list);
290 /* Encodes Key Exchange 1 Payload into a SILC Buffer to be sent
293 SilcSKEStatus silc_ske_payload_one_encode(SilcSKE ske,
294 SilcSKEOnePayload *payload,
295 SilcBuffer *return_buffer)
298 unsigned char *e_str;
301 SILC_LOG_DEBUG(("Encoding KE 1 Payload"));
304 return SILC_SKE_STATUS_ERROR;
306 /* Encode the integer into binary data */
307 e_str = silc_mp_mp2bin(&payload->e, &e_len);
309 return SILC_SKE_STATUS_ERROR;
311 /* Allocate channel payload buffer. The length of the buffer
313 buf = silc_buffer_alloc(e_len + 2 + payload->pk_len + 2 + 2);
314 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
316 /* Encode the payload */
317 silc_buffer_format(buf,
318 SILC_STR_UI_SHORT(payload->pk_len),
319 SILC_STR_UI_SHORT(payload->pk_type),
320 SILC_STR_UI_XNSTRING(payload->pk_data,
322 SILC_STR_UI_SHORT(e_len),
323 SILC_STR_UI_XNSTRING(e_str, e_len),
326 /* Return encoded buffer */
327 *return_buffer = buf;
329 memset(e_str, 'F', e_len);
332 return SILC_SKE_STATUS_OK;
335 /* Parses the Key Exchange 1 Payload. Parsed data is returned
336 to allocated payload structure. */
338 SilcSKEStatus silc_ske_payload_one_decode(SilcSKE ske,
340 SilcSKEOnePayload **return_payload)
342 SilcSKEOnePayload *payload;
343 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
345 unsigned short e_len;
347 SILC_LOG_DEBUG(("Decoding Key Exchange 1 Payload"));
349 SILC_LOG_HEXDUMP(("KE 1 Payload"), buffer->data, buffer->len);
351 payload = silc_calloc(1, sizeof(*payload));
353 silc_buffer_unformat(buffer,
354 SILC_STR_UI_SHORT(&payload->pk_len),
355 SILC_STR_UI_SHORT(&payload->pk_type),
358 if (payload->pk_len < 5) {
359 status = SILC_SKE_STATUS_BAD_PAYLOAD;
363 silc_buffer_pull(buffer, 2 + 2);
364 silc_buffer_unformat(buffer,
365 SILC_STR_UI_XNSTRING_ALLOC(&payload->pk_data,
367 SILC_STR_UI16_NSTRING_ALLOC(&e, &e_len),
371 status = SILC_SKE_STATUS_BAD_PAYLOAD;
375 silc_buffer_push(buffer, 2 + 2);
377 if (payload->pk_len + 2 + 2 + 2 + e_len != buffer->len) {
378 status = SILC_SKE_STATUS_BAD_PAYLOAD;
382 /* Decode the HEX string to integer */
383 silc_mp_init(&payload->e);
384 silc_mp_bin2mp(e, e_len, &payload->e);
385 memset(e, 0, sizeof(e_len));
388 /* Return the payload */
389 *return_payload = payload;
391 return SILC_SKE_STATUS_OK;
395 ske->status = status;
399 /* Free's KE1 Payload */
401 void silc_ske_payload_one_free(SilcSKEOnePayload *payload)
404 if (payload->pk_data)
405 silc_free(payload->pk_data);
410 /* Encodes Key Exchange 2 Payload into a SILC Buffer to be sent
413 SilcSKEStatus silc_ske_payload_two_encode(SilcSKE ske,
414 SilcSKETwoPayload *payload,
415 SilcBuffer *return_buffer)
418 unsigned char *f_str;
422 SILC_LOG_DEBUG(("Encoding KE 2 Payload"));
425 return SILC_SKE_STATUS_ERROR;
427 /* Encode the integer into HEX string */
428 f_str = silc_mp_mp2bin(&payload->f, &f_len);
430 /* Allocate channel payload buffer. The length of the buffer
431 is 2 + 2 + public key + 2 + f + 2 + signature. */
432 len = payload->pk_len + 2 + 2 + f_len + 2 + payload->sign_len + 2;
433 buf = silc_buffer_alloc(len);
435 silc_buffer_pull_tail(buf, len);
437 /* Encode the payload */
438 silc_buffer_format(buf,
439 SILC_STR_UI_SHORT(payload->pk_len),
440 SILC_STR_UI_SHORT(payload->pk_type),
441 SILC_STR_UI_XNSTRING(payload->pk_data,
443 SILC_STR_UI_SHORT(f_len),
444 SILC_STR_UI_XNSTRING(f_str, f_len),
445 SILC_STR_UI_SHORT(payload->sign_len),
446 SILC_STR_UI_XNSTRING(payload->sign_data,
450 /* Return encoded buffer */
451 *return_buffer = buf;
453 memset(f_str, 'F', f_len);
456 return SILC_SKE_STATUS_OK;
459 /* Parses the Key Exchange 2 Payload. Parsed data is returned
460 to allocated payload structure. */
462 SilcSKEStatus silc_ske_payload_two_decode(SilcSKE ske,
464 SilcSKETwoPayload **return_payload)
466 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
467 SilcSKETwoPayload *payload;
469 unsigned short f_len;
470 unsigned int tot_len = 0, len2;
472 SILC_LOG_DEBUG(("Decoding Key Exchange 2 Payload"));
474 SILC_LOG_HEXDUMP(("KE 2 Payload"), buffer->data, buffer->len);
476 payload = silc_calloc(1, sizeof(*payload));
477 memset(buf, 0, sizeof(buf));
481 /* Parse the payload */
482 silc_buffer_unformat(buffer,
483 SILC_STR_UI_SHORT(&payload->pk_len),
484 SILC_STR_UI_SHORT(&payload->pk_type),
487 if (payload->pk_len < 5) {
488 status = SILC_SKE_STATUS_BAD_PAYLOAD;
492 tot_len += payload->pk_len + 4;
494 silc_buffer_pull(buffer, 4);
495 silc_buffer_unformat(buffer,
496 SILC_STR_UI_XNSTRING_ALLOC(&payload->pk_data,
498 SILC_STR_UI16_NSTRING_ALLOC(&f, &f_len),
499 SILC_STR_UI16_NSTRING_ALLOC(&payload->sign_data,
503 tot_len += f_len + 2;
504 tot_len += payload->sign_len + 2;
507 status = SILC_SKE_STATUS_BAD_PAYLOAD;
511 if (payload->sign_len < 3) {
512 status = SILC_SKE_STATUS_BAD_PAYLOAD;
516 if (tot_len != len2) {
517 status = SILC_SKE_STATUS_BAD_PAYLOAD;
521 /* Decode the HEX string to integer */
522 silc_mp_init(&payload->f);
523 silc_mp_bin2mp(f, f_len, &payload->f);
524 memset(f, 0, sizeof(f_len));
527 /* Return the payload */
528 *return_payload = payload;
530 return SILC_SKE_STATUS_OK;
533 if (payload->pk_data)
534 silc_free(payload->pk_data);
535 if (payload->sign_data)
536 silc_free(payload->sign_data);
538 ske->status = status;
542 /* Free's KE2 Payload */
544 void silc_ske_payload_two_free(SilcSKETwoPayload *payload)
547 if (payload->pk_data)
548 silc_free(payload->pk_data);
549 if (payload->sign_data)
550 silc_free(payload->sign_data);