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.
22 #include "silcincludes.h"
23 #include "payload_internal.h"
25 /* Encodes Key Exchange Start Payload into a SILC Buffer to be sent
28 SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske,
29 SilcSKEStartPayload *payload,
30 SilcBuffer *return_buffer)
35 SILC_LOG_DEBUG(("Encoding KE Start Payload"));
38 return SILC_SKE_STATUS_ERROR;
40 buf = silc_buffer_alloc(payload->len);
41 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
43 /* Encode the payload */
44 ret = silc_buffer_format(buf,
45 SILC_STR_UI_CHAR(0), /* RESERVED field */
46 SILC_STR_UI_CHAR(payload->flags),
47 SILC_STR_UI_SHORT(payload->len),
48 SILC_STR_UI_XNSTRING(payload->cookie,
50 SILC_STR_UI_SHORT(payload->version_len),
51 SILC_STR_UI_XNSTRING(payload->version,
52 payload->version_len),
53 SILC_STR_UI_SHORT(payload->ke_grp_len),
54 SILC_STR_UI_XNSTRING(payload->ke_grp_list,
56 SILC_STR_UI_SHORT(payload->pkcs_alg_len),
57 SILC_STR_UI_XNSTRING(payload->pkcs_alg_list,
58 payload->pkcs_alg_len),
59 SILC_STR_UI_SHORT(payload->enc_alg_len),
60 SILC_STR_UI_XNSTRING(payload->enc_alg_list,
61 payload->enc_alg_len),
62 SILC_STR_UI_SHORT(payload->hash_alg_len),
63 SILC_STR_UI_XNSTRING(payload->hash_alg_list,
64 payload->hash_alg_len),
65 SILC_STR_UI_SHORT(payload->comp_alg_len),
66 SILC_STR_UI_XNSTRING(payload->comp_alg_list,
67 payload->comp_alg_len),
70 silc_buffer_free(buf);
71 return SILC_SKE_STATUS_ERROR;
74 /* Return the encoded buffer */
77 SILC_LOG_HEXDUMP(("KE Start Payload"), buf->data, buf->len);
79 return SILC_SKE_STATUS_OK;
82 /* Parses the Key Exchange Start Payload. Parsed data is returned
83 to allocated payload structure. */
86 silc_ske_payload_start_decode(SilcSKE ske,
88 SilcSKEStartPayload **return_payload)
90 SilcSKEStartPayload *payload;
91 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
95 SILC_LOG_DEBUG(("Decoding Key Exchange Start Payload"));
97 SILC_LOG_HEXDUMP(("KE Start Payload"), buffer->data, buffer->len);
99 payload = silc_calloc(1, sizeof(*payload));
100 payload->cookie_len = SILC_SKE_COOKIE_LEN;
102 /* Parse start of the payload */
104 silc_buffer_unformat(buffer,
105 SILC_STR_UI_CHAR(&tmp), /* RESERVED Field */
106 SILC_STR_UI_CHAR(&payload->flags),
107 SILC_STR_UI_SHORT(&payload->len),
108 SILC_STR_UI_XNSTRING_ALLOC(&payload->cookie,
109 payload->cookie_len),
110 SILC_STR_UI16_NSTRING_ALLOC(&payload->version,
111 &payload->version_len),
112 SILC_STR_UI_SHORT(&payload->ke_grp_len),
115 status = SILC_SKE_STATUS_ERROR;
120 SILC_LOG_DEBUG(("Bad reserved field"));
121 status = SILC_SKE_STATUS_BAD_RESERVED_FIELD;
125 if (payload->len != buffer->len) {
126 SILC_LOG_DEBUG(("Bad payload length"));
127 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
131 if (payload->ke_grp_len < 1) {
132 SILC_LOG_DEBUG(("Bad payload length"));
133 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
137 len2 = len = 1 + 1 + 2 + payload->cookie_len + 2 + payload->version_len + 2;
138 silc_buffer_pull(buffer, len);
140 /* Parse group list */
141 ret = silc_buffer_unformat(buffer,
142 SILC_STR_UI_XNSTRING_ALLOC(&payload->ke_grp_list,
143 payload->ke_grp_len),
144 SILC_STR_UI_SHORT(&payload->pkcs_alg_len),
147 status = SILC_SKE_STATUS_ERROR;
151 if (payload->pkcs_alg_len < 1) {
152 SILC_LOG_DEBUG(("Bad payload length"));
153 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
157 len2 += len = payload->ke_grp_len + 2;
158 silc_buffer_pull(buffer, len);
160 /* Parse PKCS alg list */
162 silc_buffer_unformat(buffer,
163 SILC_STR_UI_XNSTRING_ALLOC(&payload->pkcs_alg_list,
164 payload->pkcs_alg_len),
165 SILC_STR_UI_SHORT(&payload->enc_alg_len),
168 status = SILC_SKE_STATUS_ERROR;
172 if (payload->enc_alg_len < 1) {
173 SILC_LOG_DEBUG(("Bad payload length"));
174 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
178 len2 += len = payload->pkcs_alg_len + 2;
179 silc_buffer_pull(buffer, len);
181 /* Parse encryption alg list */
183 silc_buffer_unformat(buffer,
184 SILC_STR_UI_XNSTRING_ALLOC(&payload->enc_alg_list,
185 payload->enc_alg_len),
186 SILC_STR_UI_SHORT(&payload->hash_alg_len),
189 status = SILC_SKE_STATUS_ERROR;
193 if (payload->hash_alg_len < 1) {
194 SILC_LOG_DEBUG(("Bad payload length"));
195 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
199 len2 += len = payload->enc_alg_len + 2;
200 silc_buffer_pull(buffer, len);
202 /* Parse hash alg list */
204 silc_buffer_unformat(buffer,
205 SILC_STR_UI_XNSTRING_ALLOC(&payload->hash_alg_list,
206 payload->hash_alg_len),
207 SILC_STR_UI_SHORT(&payload->comp_alg_len),
210 status = SILC_SKE_STATUS_ERROR;
214 len2 += len = payload->hash_alg_len + 2;
215 silc_buffer_pull(buffer, len);
217 /* Parse compression alg list */
218 if (payload->comp_alg_len) {
220 silc_buffer_unformat(buffer,
221 SILC_STR_UI_XNSTRING_ALLOC(&payload->comp_alg_list,
222 payload->comp_alg_len),
225 status = SILC_SKE_STATUS_ERROR;
230 silc_buffer_push(buffer, len2);
232 /* Return the payload */
233 *return_payload = payload;
235 return SILC_SKE_STATUS_OK;
238 silc_ske_payload_start_free(payload);
240 ske->status = status;
244 /* Free's Start Payload */
246 void silc_ske_payload_start_free(SilcSKEStartPayload *payload)
250 silc_free(payload->cookie);
251 if (payload->version)
252 silc_free(payload->version);
253 if (payload->ke_grp_list)
254 silc_free(payload->ke_grp_list);
255 if (payload->pkcs_alg_list)
256 silc_free(payload->pkcs_alg_list);
257 if (payload->enc_alg_list)
258 silc_free(payload->enc_alg_list);
259 if (payload->hash_alg_list)
260 silc_free(payload->hash_alg_list);
261 if (payload->comp_alg_list)
262 silc_free(payload->comp_alg_list);
267 /* Encodes Key Exchange 1 Payload into a SILC Buffer to be sent
270 SilcSKEStatus silc_ske_payload_one_encode(SilcSKE ske,
271 SilcSKEOnePayload *payload,
272 SilcBuffer *return_buffer)
275 unsigned char *e_str;
279 SILC_LOG_DEBUG(("Encoding KE 1 Payload"));
282 return SILC_SKE_STATUS_ERROR;
284 /* Encode the integer into binary data */
285 e_str = silc_mp_mp2bin(&payload->e, &e_len);
287 return SILC_SKE_STATUS_ERROR;
289 /* Allocate channel payload buffer. The length of the buffer
291 buf = silc_buffer_alloc(e_len + 2 + payload->pk_len + 2 + 2);
292 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
294 /* Encode the payload */
295 ret = silc_buffer_format(buf,
296 SILC_STR_UI_SHORT(payload->pk_len),
297 SILC_STR_UI_SHORT(payload->pk_type),
298 SILC_STR_UI_XNSTRING(payload->pk_data,
300 SILC_STR_UI_SHORT(e_len),
301 SILC_STR_UI_XNSTRING(e_str, e_len),
304 memset(e_str, 'F', e_len);
306 silc_buffer_free(buf);
307 return SILC_SKE_STATUS_ERROR;
310 /* Return encoded buffer */
311 *return_buffer = buf;
313 memset(e_str, 'F', e_len);
316 return SILC_SKE_STATUS_OK;
319 /* Parses the Key Exchange 1 Payload. Parsed data is returned
320 to allocated payload structure. */
322 SilcSKEStatus silc_ske_payload_one_decode(SilcSKE ske,
324 SilcSKEOnePayload **return_payload)
326 SilcSKEOnePayload *payload;
327 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
329 unsigned short e_len;
332 SILC_LOG_DEBUG(("Decoding Key Exchange 1 Payload"));
334 SILC_LOG_HEXDUMP(("KE 1 Payload"), buffer->data, buffer->len);
336 payload = silc_calloc(1, sizeof(*payload));
338 /* Parse start of the payload */
339 ret = silc_buffer_unformat(buffer,
340 SILC_STR_UI_SHORT(&payload->pk_len),
341 SILC_STR_UI_SHORT(&payload->pk_type),
344 status = SILC_SKE_STATUS_ERROR;
348 if (payload->pk_len < 5) {
349 status = SILC_SKE_STATUS_BAD_PAYLOAD;
353 /* Parse public key data */
354 silc_buffer_pull(buffer, 2 + 2);
355 ret = silc_buffer_unformat(buffer,
356 SILC_STR_UI_XNSTRING_ALLOC(&payload->pk_data,
358 SILC_STR_UI16_NSTRING_ALLOC(&e, &e_len),
361 status = SILC_SKE_STATUS_ERROR;
366 status = SILC_SKE_STATUS_BAD_PAYLOAD;
370 silc_buffer_push(buffer, 2 + 2);
372 if (payload->pk_len + 2 + 2 + 2 + e_len != buffer->len) {
373 status = SILC_SKE_STATUS_BAD_PAYLOAD;
377 /* Decode the HEX string to integer */
378 silc_mp_init(&payload->e);
379 silc_mp_bin2mp(e, e_len, &payload->e);
380 memset(e, 0, sizeof(e_len));
383 /* Return the payload */
384 *return_payload = payload;
386 return SILC_SKE_STATUS_OK;
390 ske->status = status;
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;
418 SILC_LOG_DEBUG(("Encoding KE 2 Payload"));
421 return SILC_SKE_STATUS_ERROR;
423 /* Encode the integer into HEX string */
424 f_str = silc_mp_mp2bin(&payload->f, &f_len);
426 /* Allocate channel payload buffer. The length of the buffer
427 is 2 + 2 + public key + 2 + f + 2 + signature. */
428 len = payload->pk_len + 2 + 2 + f_len + 2 + payload->sign_len + 2;
429 buf = silc_buffer_alloc(len);
430 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
432 /* Encode the payload */
433 ret = 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 memset(f_str, 'F', f_len);
447 silc_buffer_free(buf);
448 return SILC_SKE_STATUS_ERROR;
451 /* Return encoded buffer */
452 *return_buffer = buf;
454 memset(f_str, 'F', f_len);
457 return SILC_SKE_STATUS_OK;
460 /* Parses the Key Exchange 2 Payload. Parsed data is returned
461 to allocated payload structure. */
463 SilcSKEStatus silc_ske_payload_two_decode(SilcSKE ske,
465 SilcSKETwoPayload **return_payload)
467 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
468 SilcSKETwoPayload *payload;
470 unsigned short f_len;
471 unsigned int tot_len = 0, len2;
474 SILC_LOG_DEBUG(("Decoding Key Exchange 2 Payload"));
476 SILC_LOG_HEXDUMP(("KE 2 Payload"), buffer->data, buffer->len);
478 payload = silc_calloc(1, sizeof(*payload));
482 /* Parse start of the payload */
483 ret = silc_buffer_unformat(buffer,
484 SILC_STR_UI_SHORT(&payload->pk_len),
485 SILC_STR_UI_SHORT(&payload->pk_type),
488 status = SILC_SKE_STATUS_ERROR;
492 if (payload->pk_len < 5) {
493 status = SILC_SKE_STATUS_BAD_PAYLOAD;
497 tot_len += payload->pk_len + 4;
499 /* Parse PK data and the signature */
500 silc_buffer_pull(buffer, 4);
501 ret = silc_buffer_unformat(buffer,
502 SILC_STR_UI_XNSTRING_ALLOC(&payload->pk_data,
504 SILC_STR_UI16_NSTRING_ALLOC(&f, &f_len),
505 SILC_STR_UI16_NSTRING_ALLOC(&payload->sign_data,
509 status = SILC_SKE_STATUS_ERROR;
513 tot_len += f_len + 2;
514 tot_len += payload->sign_len + 2;
517 status = SILC_SKE_STATUS_BAD_PAYLOAD;
521 if (payload->sign_len < 3) {
522 status = SILC_SKE_STATUS_BAD_PAYLOAD;
526 if (tot_len != len2) {
527 status = SILC_SKE_STATUS_BAD_PAYLOAD;
531 /* Decode the HEX string to integer */
532 silc_mp_init(&payload->f);
533 silc_mp_bin2mp(f, f_len, &payload->f);
534 memset(f, 0, sizeof(f_len));
537 /* Return the payload */
538 *return_payload = payload;
540 return SILC_SKE_STATUS_OK;
543 if (payload->pk_data)
544 silc_free(payload->pk_data);
545 if (payload->sign_data)
546 silc_free(payload->sign_data);
548 ske->status = status;
552 /* Free's KE2 Payload */
554 void silc_ske_payload_two_free(SilcSKETwoPayload *payload)
557 if (payload->pk_data)
558 silc_free(payload->pk_data);
559 if (payload->sign_data)
560 silc_free(payload->sign_data);