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.3 2000/07/07 06:46:43 priikone
26 * Removed ske_verify_public_key function as it is not needed
27 * anymore. Added support to the public key verification as callback
28 * function. Other minor changes and bug fixes.
30 * Revision 1.2 2000/07/05 06:05:15 priikone
31 * Global cosmetic change.
33 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
34 * Imported from internal CVS/Added Log headers.
39 #include "silcincludes.h"
40 #include "payload_internal.h"
42 /* Temporary buffer used in payload decoding */
43 unsigned char buf[16384];
45 /* Encodes Key Exchange Start Payload into a SILC Buffer to be sent
48 SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske,
49 SilcSKEStartPayload *payload,
50 SilcBuffer *return_buffer)
54 SILC_LOG_DEBUG(("Encoding KE Start Payload"));
57 return SILC_SKE_STATUS_ERROR;
59 /* Allocate channel payload buffer. */
60 buf = silc_buffer_alloc(payload->len);
62 silc_buffer_pull_tail(buf, payload->len);
64 /* Encode the payload */
65 silc_buffer_format(buf,
66 SILC_STR_UI_CHAR(0), /* RESERVED field */
67 SILC_STR_UI_CHAR(payload->flags),
68 SILC_STR_UI_SHORT(payload->len),
69 SILC_STR_UI_XNSTRING(payload->cookie,
71 SILC_STR_UI_SHORT(payload->ke_grp_len),
72 SILC_STR_UI_XNSTRING(payload->ke_grp_list,
74 SILC_STR_UI_SHORT(payload->pkcs_alg_len),
75 SILC_STR_UI_XNSTRING(payload->pkcs_alg_list,
76 payload->pkcs_alg_len),
77 SILC_STR_UI_SHORT(payload->enc_alg_len),
78 SILC_STR_UI_XNSTRING(payload->enc_alg_list,
79 payload->enc_alg_len),
80 SILC_STR_UI_SHORT(payload->hash_alg_len),
81 SILC_STR_UI_XNSTRING(payload->hash_alg_list,
82 payload->hash_alg_len),
83 SILC_STR_UI_SHORT(payload->comp_alg_len),
84 SILC_STR_UI_XNSTRING(payload->comp_alg_list,
85 payload->comp_alg_len),
88 /* Return the encoded buffer */
91 SILC_LOG_HEXDUMP(("KE Start Payload"), buf->data, buf->len);
93 return SILC_SKE_STATUS_OK;
96 /* Parses the Key Exchange Start Payload. Parsed data is returned
97 to allocated payload structure. */
100 silc_ske_payload_start_decode(SilcSKE ske,
102 SilcSKEStartPayload **return_payload)
104 SilcSKEStartPayload *payload;
105 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
109 SILC_LOG_DEBUG(("Decoding Key Exchange Start Payload"));
111 SILC_LOG_HEXDUMP(("KE Start Payload"), buffer->data, buffer->len);
113 payload = silc_calloc(1, sizeof(*payload));
114 memset(buf, 0, sizeof(buf));
116 /* Parse the entire payload */
117 silc_buffer_unformat(buffer,
118 SILC_STR_UI_CHAR(&tmp), /* RESERVED Field */
119 SILC_STR_UI_CHAR(&payload->flags),
120 SILC_STR_UI_SHORT(&payload->len),
121 SILC_STR_UI_XNSTRING(&buf, SILC_SKE_COOKIE_LEN),
122 SILC_STR_UI_SHORT(&payload->ke_grp_len),
126 SILC_LOG_DEBUG(("Bad reserved field"));
127 status = SILC_SKE_STATUS_BAD_RESERVED_FIELD;
131 if (payload->len != buffer->len) {
132 SILC_LOG_DEBUG(("Bad payload length"));
133 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
137 if (payload->ke_grp_len < 1) {
138 SILC_LOG_DEBUG(("Bad payload length"));
139 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
143 len2 = len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN + 2;
144 silc_buffer_pull(buffer, len);
146 /* Copy cookie from payload */
147 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN,
148 sizeof(unsigned char));
149 payload->cookie_len = SILC_SKE_COOKIE_LEN;
150 memcpy(payload->cookie, buf, SILC_SKE_COOKIE_LEN);
151 memset(buf, 0, sizeof(buf));
153 silc_buffer_unformat(buffer,
154 SILC_STR_UI_XNSTRING(&buf, payload->ke_grp_len),
155 SILC_STR_UI_SHORT(&payload->pkcs_alg_len),
158 if (payload->pkcs_alg_len < 1) {
159 SILC_LOG_DEBUG(("Bad payload length"));
160 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
164 len2 += len = payload->ke_grp_len + 2;
165 silc_buffer_pull(buffer, len);
167 /* Copy KE groups from payload */
168 payload->ke_grp_list = silc_calloc(payload->ke_grp_len + 1,
169 sizeof(unsigned char));
170 memcpy(payload->ke_grp_list, buf, payload->ke_grp_len);
171 memset(buf, 0, sizeof(buf));
173 silc_buffer_unformat(buffer,
174 SILC_STR_UI_XNSTRING(&buf, payload->pkcs_alg_len),
175 SILC_STR_UI_SHORT(&payload->enc_alg_len),
178 if (payload->enc_alg_len < 1) {
179 SILC_LOG_DEBUG(("Bad payload length"));
180 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
184 len2 += len = payload->pkcs_alg_len + 2;
185 silc_buffer_pull(buffer, len);
187 /* Copy PKCS algs from payload */
188 payload->pkcs_alg_list = silc_calloc(payload->pkcs_alg_len + 1,
189 sizeof(unsigned char));
190 memcpy(payload->pkcs_alg_list, buf, payload->pkcs_alg_len);
191 memset(buf, 0, sizeof(buf));
193 silc_buffer_unformat(buffer,
194 SILC_STR_UI_XNSTRING(&buf, payload->enc_alg_len),
195 SILC_STR_UI_SHORT(&payload->hash_alg_len),
198 if (payload->hash_alg_len < 1) {
199 SILC_LOG_DEBUG(("Bad payload length"));
200 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
204 len2 += len = payload->enc_alg_len + 2;
205 silc_buffer_pull(buffer, len);
207 /* Copy encryption algs from payload */
208 payload->enc_alg_list = silc_calloc(payload->enc_alg_len + 1,
209 sizeof(unsigned char));
210 memcpy(payload->enc_alg_list, buf, payload->enc_alg_len);
211 memset(buf, 0, sizeof(buf));
213 silc_buffer_unformat(buffer,
214 SILC_STR_UI_XNSTRING(&buf, payload->hash_alg_len),
215 SILC_STR_UI_SHORT(&payload->comp_alg_len),
218 len2 += len = payload->hash_alg_len + 2;
219 silc_buffer_pull(buffer, len);
221 /* Copy hash algs from payload */
222 payload->hash_alg_list = silc_calloc(payload->hash_alg_len + 1,
223 sizeof(unsigned char));
224 memcpy(payload->hash_alg_list, buf, payload->hash_alg_len);
225 memset(buf, 0, sizeof(buf));
227 if (payload->comp_alg_len) {
228 silc_buffer_unformat(buffer,
229 SILC_STR_UI_XNSTRING(&buf, payload->comp_alg_len),
232 /* Copy compression algs from payload */
233 payload->comp_alg_list = silc_calloc(payload->comp_alg_len + 1,
234 sizeof(unsigned char));
235 memcpy(payload->comp_alg_list, buf, payload->comp_alg_len);
236 memset(buf, 0, sizeof(buf));
239 silc_buffer_push(buffer, len2);
241 /* Return the payload */
242 *return_payload = payload;
244 return SILC_SKE_STATUS_OK;
247 silc_ske_payload_start_free(payload);
252 /* Free's Start Payload */
254 void silc_ske_payload_start_free(SilcSKEStartPayload *payload)
258 silc_free(payload->cookie);
259 if (payload->ke_grp_list)
260 silc_free(payload->ke_grp_list);
261 if (payload->pkcs_alg_list)
262 silc_free(payload->pkcs_alg_list);
263 if (payload->enc_alg_list)
264 silc_free(payload->enc_alg_list);
265 if (payload->hash_alg_list)
266 silc_free(payload->hash_alg_list);
267 if (payload->comp_alg_list)
268 silc_free(payload->comp_alg_list);
273 /* Encodes Key Exchange 1 Payload into a SILC Buffer to be sent
276 SilcSKEStatus silc_ske_payload_one_encode(SilcSKE ske,
277 SilcSKEOnePayload *payload,
278 SilcBuffer *return_buffer)
281 unsigned char *e_str;
282 unsigned short e_len;
284 SILC_LOG_DEBUG(("Encoding KE 1 Payload"));
287 return SILC_SKE_STATUS_ERROR;
289 /* Encode the integer into HEX string */
290 e_len = silc_mp_sizeinbase(&payload->e, 16);
291 e_str = silc_calloc(e_len + 1, sizeof(unsigned char));
292 silc_mp_get_str(e_str, 16, &payload->e);
294 /* Allocate channel payload buffer. The length of the buffer
296 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_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)
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_len = silc_mp_sizeinbase(&payload->f, 16);
401 f_str = silc_calloc(f_len + 1, sizeof(unsigned char));
402 silc_mp_get_str(f_str, 16, &payload->f);
404 /* Allocate channel payload buffer. The length of the buffer
405 is 2 + 2 + public key + 2 + f + 2 + signature. */
406 len = payload->pk_len + 2 + 2 + f_len + 2 + payload->sign_len + 2;
407 buf = silc_buffer_alloc(len);
409 silc_buffer_pull_tail(buf, len);
411 /* Encode the payload */
412 silc_buffer_format(buf,
413 SILC_STR_UI_SHORT(payload->pk_len + 4),
414 SILC_STR_UI_SHORT(payload->pk_type),
415 SILC_STR_UI_XNSTRING(payload->pk_data,
417 SILC_STR_UI_SHORT(f_len + 2),
418 SILC_STR_UI_XNSTRING(f_str, f_len),
419 SILC_STR_UI_SHORT(payload->sign_len + 2),
420 SILC_STR_UI_XNSTRING(payload->sign_data,
424 /* Return encoded buffer */
425 *return_buffer = buf;
427 memset(f_str, 'F', f_len);
430 return SILC_SKE_STATUS_OK;
433 /* Parses the Key Exchange 2 Payload. Parsed data is returned
434 to allocated payload structure. */
436 SilcSKEStatus silc_ske_payload_two_decode(SilcSKE ske,
438 SilcSKETwoPayload **return_payload)
440 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
441 SilcSKETwoPayload *payload;
442 unsigned short f_len;
443 unsigned int tot_len = 0, len2;
445 SILC_LOG_DEBUG(("Decoding Key Exchange 2 Payload"));
447 SILC_LOG_HEXDUMP(("KE 2 Payload"), buffer->data, buffer->len);
449 payload = silc_calloc(1, sizeof(*payload));
450 memset(buf, 0, sizeof(buf));
454 /* Parse the payload */
455 silc_buffer_unformat(buffer,
456 SILC_STR_UI_SHORT(&payload->pk_len),
457 SILC_STR_UI_SHORT(&payload->pk_type),
460 if (payload->pk_len < 5) {
461 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
465 tot_len += payload->pk_len;
467 payload->pk_len -= 4;
468 silc_buffer_pull(buffer, 4);
469 silc_buffer_unformat(buffer,
470 SILC_STR_UI_XNSTRING(&buf, payload->pk_len),
471 SILC_STR_UI_SHORT(&f_len),
475 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
481 payload->pk_data = silc_calloc(payload->pk_len + 1,
482 sizeof(unsigned char));
483 memcpy(payload->pk_data, buf, payload->pk_len);
484 memset(buf, 0, sizeof(buf));
487 silc_buffer_pull(buffer, payload->pk_len + 2);
488 silc_buffer_unformat(buffer,
489 SILC_STR_UI_XNSTRING(&buf, f_len),
490 SILC_STR_UI_SHORT(&payload->sign_len),
493 if (payload->sign_len < 3) {
494 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
498 tot_len += payload->sign_len;
500 if (tot_len != len2) {
501 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
505 /* Decode the HEX string to integer */
506 silc_mp_init(&payload->f);
507 silc_mp_set_str(&payload->f, buf, 16);
508 memset(buf, 0, sizeof(buf));
510 payload->sign_len -= 2;
511 silc_buffer_pull(buffer, f_len + 2);
512 silc_buffer_unformat(buffer,
513 SILC_STR_UI_XNSTRING(&buf, payload->sign_len),
516 payload->sign_data = silc_calloc(payload->sign_len + 1,
517 sizeof(unsigned char));
518 memcpy(payload->sign_data, buf, payload->sign_len);
519 memset(buf, 0, sizeof(buf));
521 /* Return the payload */
522 *return_payload = payload;
524 return SILC_SKE_STATUS_OK;
527 if (payload->pk_data)
528 silc_free(payload->pk_data);
529 if (payload->sign_data)
530 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);