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.1.1.1 2000/06/27 11:36:56 priikone
26 * Importet from internal CVS/Added Log headers.
31 #include "silcincludes.h"
32 #include "payload_internal.h"
34 /* Temporary buffer used in payload decoding */
35 unsigned char buf[16384];
37 /* Encodes Key Exchange Start Payload into a SILC Buffer to be sent
40 SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske,
41 SilcSKEStartPayload *payload,
42 SilcBuffer *return_buffer)
46 SILC_LOG_DEBUG(("Encoding KE Start Payload"));
49 return SILC_SKE_STATUS_ERROR;
51 /* Allocate channel payload buffer. */
52 buf = silc_buffer_alloc(payload->len);
54 SILC_LOG_ERROR(("Could not allocate encode buffer"));
55 return SILC_SKE_STATUS_ERROR;
58 silc_buffer_pull_tail(buf, payload->len);
60 /* Encode the payload */
61 silc_buffer_format(buf,
62 SILC_STR_UI_CHAR(0), /* RESERVED field */
63 SILC_STR_UI_CHAR(payload->flags),
64 SILC_STR_UI_SHORT(payload->len),
65 SILC_STR_UI_XNSTRING(payload->cookie,
67 SILC_STR_UI_SHORT(payload->ke_grp_len),
68 SILC_STR_UI_XNSTRING(payload->ke_grp_list,
70 SILC_STR_UI_SHORT(payload->pkcs_alg_len),
71 SILC_STR_UI_XNSTRING(payload->pkcs_alg_list,
72 payload->pkcs_alg_len),
73 SILC_STR_UI_SHORT(payload->enc_alg_len),
74 SILC_STR_UI_XNSTRING(payload->enc_alg_list,
75 payload->enc_alg_len),
76 SILC_STR_UI_SHORT(payload->hash_alg_len),
77 SILC_STR_UI_XNSTRING(payload->hash_alg_list,
78 payload->hash_alg_len),
79 SILC_STR_UI_SHORT(payload->comp_alg_len),
80 SILC_STR_UI_XNSTRING(payload->comp_alg_list,
81 payload->comp_alg_len),
84 /* Return the encoded buffer */
87 SILC_LOG_HEXDUMP(("KE Start Payload"), buf->data, buf->len);
89 return SILC_SKE_STATUS_OK;
92 /* Parses the Key Exchange Start Payload. Parsed data is returned
93 to allocated payload structure. */
96 silc_ske_payload_start_decode(SilcSKE ske,
98 SilcSKEStartPayload **return_payload)
100 SilcSKEStartPayload *payload;
101 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
105 SILC_LOG_DEBUG(("Decoding Key Exchange Start Payload"));
107 SILC_LOG_HEXDUMP(("KE Start Payload"), buffer->data, buffer->len);
109 payload = silc_calloc(1, sizeof(*payload));
110 memset(buf, 0, sizeof(buf));
112 /* Parse the entire payload */
113 silc_buffer_unformat(buffer,
114 SILC_STR_UI_CHAR(&tmp), /* RESERVED Field */
115 SILC_STR_UI_CHAR(&payload->flags),
116 SILC_STR_UI_SHORT(&payload->len),
117 SILC_STR_UI_XNSTRING(&buf, SILC_SKE_COOKIE_LEN),
118 SILC_STR_UI_SHORT(&payload->ke_grp_len),
122 SILC_LOG_DEBUG(("Bad reserved field"));
123 status = SILC_SKE_STATUS_BAD_RESERVED_FIELD;
127 if (payload->len != buffer->len) {
128 SILC_LOG_DEBUG(("Bad payload length"));
129 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
133 if (payload->ke_grp_len < 1) {
134 SILC_LOG_DEBUG(("Bad payload length"));
135 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
139 len2 = len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN + 2;
140 silc_buffer_pull(buffer, len);
142 /* Copy cookie from payload */
143 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN,
144 sizeof(unsigned char));
145 payload->cookie_len = SILC_SKE_COOKIE_LEN;
146 memcpy(payload->cookie, buf, SILC_SKE_COOKIE_LEN);
147 memset(buf, 0, sizeof(buf));
149 silc_buffer_unformat(buffer,
150 SILC_STR_UI_XNSTRING(&buf, payload->ke_grp_len),
151 SILC_STR_UI_SHORT(&payload->pkcs_alg_len),
154 if (payload->pkcs_alg_len < 1) {
155 SILC_LOG_DEBUG(("Bad payload length"));
156 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
160 len2 += len = payload->ke_grp_len + 2;
161 silc_buffer_pull(buffer, len);
163 /* Copy KE groups from payload */
164 payload->ke_grp_list = silc_calloc(payload->ke_grp_len + 1,
165 sizeof(unsigned char));
166 memcpy(payload->ke_grp_list, buf, payload->ke_grp_len);
167 memset(buf, 0, sizeof(buf));
169 silc_buffer_unformat(buffer,
170 SILC_STR_UI_XNSTRING(&buf, payload->pkcs_alg_len),
171 SILC_STR_UI_SHORT(&payload->enc_alg_len),
174 if (payload->enc_alg_len < 1) {
175 SILC_LOG_DEBUG(("Bad payload length"));
176 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
180 len2 += len = payload->pkcs_alg_len + 2;
181 silc_buffer_pull(buffer, len);
183 /* Copy PKCS algs from payload */
184 payload->pkcs_alg_list = silc_calloc(payload->pkcs_alg_len + 1,
185 sizeof(unsigned char));
186 memcpy(payload->pkcs_alg_list, buf, payload->pkcs_alg_len);
187 memset(buf, 0, sizeof(buf));
189 silc_buffer_unformat(buffer,
190 SILC_STR_UI_XNSTRING(&buf, payload->enc_alg_len),
191 SILC_STR_UI_SHORT(&payload->hash_alg_len),
194 if (payload->hash_alg_len < 1) {
195 SILC_LOG_DEBUG(("Bad payload length"));
196 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
200 len2 += len = payload->enc_alg_len + 2;
201 silc_buffer_pull(buffer, len);
203 /* Copy encryption algs from payload */
204 payload->enc_alg_list = silc_calloc(payload->enc_alg_len + 1,
205 sizeof(unsigned char));
206 memcpy(payload->enc_alg_list, buf, payload->enc_alg_len);
207 memset(buf, 0, sizeof(buf));
209 silc_buffer_unformat(buffer,
210 SILC_STR_UI_XNSTRING(&buf, payload->hash_alg_len),
211 SILC_STR_UI_SHORT(&payload->comp_alg_len),
214 len2 += len = payload->hash_alg_len + 2;
215 silc_buffer_pull(buffer, len);
217 /* Copy hash algs from payload */
218 payload->hash_alg_list = silc_calloc(payload->hash_alg_len + 1,
219 sizeof(unsigned char));
220 memcpy(payload->hash_alg_list, buf, payload->hash_alg_len);
221 memset(buf, 0, sizeof(buf));
223 if (payload->comp_alg_len) {
224 silc_buffer_unformat(buffer,
225 SILC_STR_UI_XNSTRING(&buf, payload->comp_alg_len),
228 /* Copy compression algs from payload */
229 payload->comp_alg_list = silc_calloc(payload->comp_alg_len + 1,
230 sizeof(unsigned char));
231 memcpy(payload->comp_alg_list, buf, payload->comp_alg_len);
232 memset(buf, 0, sizeof(buf));
235 silc_buffer_push(buffer, len2);
237 /* Return the payload */
238 *return_payload = payload;
240 return SILC_SKE_STATUS_OK;
243 silc_ske_payload_start_free(payload);
248 /* Free's Start Payload */
250 void silc_ske_payload_start_free(SilcSKEStartPayload *payload)
254 silc_free(payload->cookie);
255 if (payload->ke_grp_list)
256 silc_free(payload->ke_grp_list);
257 if (payload->pkcs_alg_list)
258 silc_free(payload->pkcs_alg_list);
259 if (payload->enc_alg_list)
260 silc_free(payload->enc_alg_list);
261 if (payload->hash_alg_list)
262 silc_free(payload->hash_alg_list);
263 if (payload->comp_alg_list)
264 silc_free(payload->comp_alg_list);
269 /* Encodes Key Exchange 1 Payload into a SILC Buffer to be sent
272 SilcSKEStatus silc_ske_payload_one_encode(SilcSKE ske,
273 SilcSKEOnePayload *payload,
274 SilcBuffer *return_buffer)
277 unsigned char *e_str;
278 unsigned short e_len;
280 SILC_LOG_DEBUG(("Encoding KE 1 Payload"));
283 return SILC_SKE_STATUS_ERROR;
285 /* Encode the integer into HEX string */
286 e_len = silc_mp_sizeinbase(&payload->e, 16);
287 e_str = silc_calloc(e_len + 1, sizeof(unsigned char));
288 silc_mp_get_str(e_str, 16, &payload->e);
290 /* Allocate channel payload buffer. The length of the buffer
292 buf = silc_buffer_alloc(e_len + 2);
294 SILC_LOG_ERROR(("Could not allocate encode buffer"));
295 return SILC_SKE_STATUS_ERROR;
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_set_str(&payload->e, buf, 16);
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)
378 silc_mp_clear(&payload->e);
383 /* Encodes Key Exchange 2 Payload into a SILC Buffer to be sent
386 SilcSKEStatus silc_ske_payload_two_encode(SilcSKE ske,
387 SilcSKETwoPayload *payload,
388 SilcBuffer *return_buffer)
391 unsigned char *f_str;
395 SILC_LOG_DEBUG(("Encoding KE 2 Payload"));
398 return SILC_SKE_STATUS_ERROR;
400 /* Encode the integer into HEX string */
401 f_len = silc_mp_sizeinbase(&payload->f, 16);
402 f_str = silc_calloc(f_len + 1, sizeof(unsigned char));
403 silc_mp_get_str(f_str, 16, &payload->f);
405 /* Allocate channel payload buffer. The length of the buffer
406 is 2 + 2 + public key + 2 + f + 2 + signature. */
407 len = payload->pk_len + 2 + 2 + f_len + 2 + payload->sign_len + 2;
408 buf = silc_buffer_alloc(len);
410 SILC_LOG_ERROR(("Could not allocate encode buffer"));
411 return SILC_SKE_STATUS_ERROR;
414 silc_buffer_pull_tail(buf, len);
416 /* Encode the payload */
417 silc_buffer_format(buf,
418 SILC_STR_UI_SHORT(payload->pk_len + 4),
419 SILC_STR_UI_SHORT(payload->pk_type),
420 SILC_STR_UI_XNSTRING(payload->pk_data,
422 SILC_STR_UI_SHORT(f_len + 2),
423 SILC_STR_UI_XNSTRING(f_str, f_len),
424 SILC_STR_UI_SHORT(payload->sign_len + 2),
425 SILC_STR_UI_XNSTRING(payload->sign_data,
429 /* Return encoded buffer */
430 *return_buffer = buf;
432 memset(f_str, 'F', f_len);
435 return SILC_SKE_STATUS_OK;
438 /* Parses the Key Exchange 2 Payload. Parsed data is returned
439 to allocated payload structure. */
441 SilcSKEStatus silc_ske_payload_two_decode(SilcSKE ske,
443 SilcSKETwoPayload **return_payload)
445 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
446 SilcSKETwoPayload *payload;
447 unsigned short f_len;
448 unsigned int tot_len = 0, len2;
450 SILC_LOG_DEBUG(("Decoding Key Exchange 2 Payload"));
452 SILC_LOG_HEXDUMP(("KE 2 Payload"), buffer->data, buffer->len);
454 payload = silc_calloc(1, sizeof(*payload));
455 memset(buf, 0, sizeof(buf));
459 /* Parse the payload */
460 silc_buffer_unformat(buffer,
461 SILC_STR_UI_SHORT(&payload->pk_len),
462 SILC_STR_UI_SHORT(&payload->pk_type),
465 if (payload->pk_len < 5) {
466 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
470 tot_len += payload->pk_len;
472 payload->pk_len -= 4;
473 silc_buffer_pull(buffer, 4);
474 silc_buffer_unformat(buffer,
475 SILC_STR_UI_XNSTRING(&buf, payload->pk_len),
476 SILC_STR_UI_SHORT(&f_len),
480 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
486 payload->pk_data = silc_calloc(payload->pk_len + 1,
487 sizeof(unsigned char));
488 memcpy(payload->pk_data, buf, payload->pk_len);
489 memset(buf, 0, sizeof(buf));
492 silc_buffer_pull(buffer, payload->pk_len + 2);
493 silc_buffer_unformat(buffer,
494 SILC_STR_UI_XNSTRING(&buf, f_len),
495 SILC_STR_UI_SHORT(&payload->sign_len),
498 if (payload->sign_len < 3) {
499 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
503 tot_len += payload->sign_len;
505 if (tot_len != len2) {
506 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
510 /* Decode the HEX string to integer */
511 silc_mp_init(&payload->f);
512 silc_mp_set_str(&payload->f, buf, 16);
513 memset(buf, 0, sizeof(buf));
515 payload->sign_len -= 2;
516 silc_buffer_pull(buffer, f_len + 2);
517 silc_buffer_unformat(buffer,
518 SILC_STR_UI_XNSTRING(&buf, payload->sign_len),
521 payload->sign_data = silc_calloc(payload->sign_len + 1,
522 sizeof(unsigned char));
523 memcpy(payload->sign_data, buf, payload->sign_len);
524 memset(buf, 0, sizeof(buf));
526 /* Return the payload */
527 *return_payload = payload;
529 return SILC_SKE_STATUS_OK;
532 if (payload->pk_data)
533 silc_free(payload->pk_data);
534 if (payload->sign_data)
535 silc_free(payload->sign_data);
541 /* Free's KE2 Payload */
543 void silc_ske_payload_two_free(SilcSKETwoPayload *payload)
546 if (payload->pk_data)
547 silc_free(payload->pk_data);
548 if (payload->sign_data)
549 silc_free(payload->sign_data);
550 silc_mp_clear(&payload->f);