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->hmac_alg_len),
66 SILC_STR_UI_XNSTRING(payload->hmac_alg_list,
67 payload->hmac_alg_len),
68 SILC_STR_UI_SHORT(payload->comp_alg_len),
69 SILC_STR_UI_XNSTRING(payload->comp_alg_list,
70 payload->comp_alg_len),
73 silc_buffer_free(buf);
74 return SILC_SKE_STATUS_ERROR;
77 /* Return the encoded buffer */
80 SILC_LOG_HEXDUMP(("KE Start Payload"), buf->data, buf->len);
82 return SILC_SKE_STATUS_OK;
85 /* Parses the Key Exchange Start Payload. Parsed data is returned
86 to allocated payload structure. */
89 silc_ske_payload_start_decode(SilcSKE ske,
91 SilcSKEStartPayload **return_payload)
93 SilcSKEStartPayload *payload;
94 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
98 SILC_LOG_DEBUG(("Decoding Key Exchange Start Payload"));
100 SILC_LOG_HEXDUMP(("KE Start Payload"), buffer->data, buffer->len);
102 payload = silc_calloc(1, sizeof(*payload));
103 payload->cookie_len = SILC_SKE_COOKIE_LEN;
105 /* Parse start of the payload */
107 silc_buffer_unformat(buffer,
108 SILC_STR_UI_CHAR(&tmp), /* RESERVED Field */
109 SILC_STR_UI_CHAR(&payload->flags),
110 SILC_STR_UI_SHORT(&payload->len),
111 SILC_STR_UI_XNSTRING_ALLOC(&payload->cookie,
112 payload->cookie_len),
113 SILC_STR_UI16_NSTRING_ALLOC(&payload->version,
114 &payload->version_len),
115 SILC_STR_UI_SHORT(&payload->ke_grp_len),
118 status = SILC_SKE_STATUS_ERROR;
123 SILC_LOG_DEBUG(("Bad reserved field"));
124 status = SILC_SKE_STATUS_BAD_RESERVED_FIELD;
128 if (payload->len != buffer->len) {
129 SILC_LOG_DEBUG(("Bad payload length"));
130 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
134 if (payload->ke_grp_len < 1) {
135 SILC_LOG_DEBUG(("Bad payload length"));
136 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
140 len2 = len = 1 + 1 + 2 + payload->cookie_len + 2 + payload->version_len + 2;
141 silc_buffer_pull(buffer, len);
143 /* Parse group list */
144 ret = silc_buffer_unformat(buffer,
145 SILC_STR_UI_XNSTRING_ALLOC(&payload->ke_grp_list,
146 payload->ke_grp_len),
147 SILC_STR_UI_SHORT(&payload->pkcs_alg_len),
150 status = SILC_SKE_STATUS_ERROR;
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 /* Parse PKCS alg list */
165 silc_buffer_unformat(buffer,
166 SILC_STR_UI_XNSTRING_ALLOC(&payload->pkcs_alg_list,
167 payload->pkcs_alg_len),
168 SILC_STR_UI_SHORT(&payload->enc_alg_len),
171 status = SILC_SKE_STATUS_ERROR;
175 if (payload->enc_alg_len < 1) {
176 SILC_LOG_DEBUG(("Bad payload length"));
177 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
181 len2 += len = payload->pkcs_alg_len + 2;
182 silc_buffer_pull(buffer, len);
184 /* Parse encryption alg list */
186 silc_buffer_unformat(buffer,
187 SILC_STR_UI_XNSTRING_ALLOC(&payload->enc_alg_list,
188 payload->enc_alg_len),
189 SILC_STR_UI_SHORT(&payload->hash_alg_len),
192 status = SILC_SKE_STATUS_ERROR;
196 if (payload->hash_alg_len < 1) {
197 SILC_LOG_DEBUG(("Bad payload length"));
198 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
202 len2 += len = payload->enc_alg_len + 2;
203 silc_buffer_pull(buffer, len);
205 /* Parse hash alg list */
207 silc_buffer_unformat(buffer,
208 SILC_STR_UI_XNSTRING_ALLOC(&payload->hash_alg_list,
209 payload->hash_alg_len),
210 SILC_STR_UI_SHORT(&payload->hmac_alg_len),
213 status = SILC_SKE_STATUS_ERROR;
217 len2 += len = payload->hash_alg_len + 2;
218 silc_buffer_pull(buffer, len);
220 /* Parse HMAC list */
222 silc_buffer_unformat(buffer,
223 SILC_STR_UI_XNSTRING_ALLOC(&payload->hmac_alg_list,
224 payload->hmac_alg_len),
225 SILC_STR_UI_SHORT(&payload->comp_alg_len),
228 status = SILC_SKE_STATUS_ERROR;
232 len2 += len = payload->hmac_alg_len + 2;
233 silc_buffer_pull(buffer, len);
235 /* Parse compression alg list */
236 if (payload->comp_alg_len) {
238 silc_buffer_unformat(buffer,
239 SILC_STR_UI_XNSTRING_ALLOC(&payload->comp_alg_list,
240 payload->comp_alg_len),
243 status = SILC_SKE_STATUS_ERROR;
248 silc_buffer_push(buffer, len2);
250 /* Return the payload */
251 *return_payload = payload;
253 return SILC_SKE_STATUS_OK;
256 silc_ske_payload_start_free(payload);
258 ske->status = status;
262 /* Free's Start Payload */
264 void silc_ske_payload_start_free(SilcSKEStartPayload *payload)
268 silc_free(payload->cookie);
269 if (payload->version)
270 silc_free(payload->version);
271 if (payload->ke_grp_list)
272 silc_free(payload->ke_grp_list);
273 if (payload->pkcs_alg_list)
274 silc_free(payload->pkcs_alg_list);
275 if (payload->enc_alg_list)
276 silc_free(payload->enc_alg_list);
277 if (payload->hash_alg_list)
278 silc_free(payload->hash_alg_list);
279 if (payload->hmac_alg_list)
280 silc_free(payload->hmac_alg_list);
281 if (payload->comp_alg_list)
282 silc_free(payload->comp_alg_list);
287 /* Encodes Key Exchange 1 Payload into a SILC Buffer to be sent
290 SilcSKEStatus silc_ske_payload_one_encode(SilcSKE ske,
291 SilcSKEOnePayload *payload,
292 SilcBuffer *return_buffer)
295 unsigned char *e_str;
299 SILC_LOG_DEBUG(("Encoding KE 1 Payload"));
302 return SILC_SKE_STATUS_ERROR;
304 /* Encode the integer into binary data */
305 e_str = silc_mp_mp2bin(&payload->e, 0, &e_len);
307 return SILC_SKE_STATUS_ERROR;
309 /* Allocate channel payload buffer. The length of the buffer
311 buf = silc_buffer_alloc(e_len + 2 + payload->pk_len + 2 + 2);
312 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
314 /* Encode the payload */
315 ret = silc_buffer_format(buf,
316 SILC_STR_UI_SHORT(payload->pk_len),
317 SILC_STR_UI_SHORT(payload->pk_type),
318 SILC_STR_UI_XNSTRING(payload->pk_data,
320 SILC_STR_UI_SHORT(e_len),
321 SILC_STR_UI_XNSTRING(e_str, e_len),
324 memset(e_str, 'F', e_len);
326 silc_buffer_free(buf);
327 return SILC_SKE_STATUS_ERROR;
330 /* Return encoded buffer */
331 *return_buffer = buf;
333 memset(e_str, 'F', e_len);
336 return SILC_SKE_STATUS_OK;
339 /* Parses the Key Exchange 1 Payload. Parsed data is returned
340 to allocated payload structure. */
342 SilcSKEStatus silc_ske_payload_one_decode(SilcSKE ske,
344 SilcSKEOnePayload **return_payload)
346 SilcSKEOnePayload *payload;
347 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
349 unsigned short e_len;
352 SILC_LOG_DEBUG(("Decoding Key Exchange 1 Payload"));
354 SILC_LOG_HEXDUMP(("KE 1 Payload"), buffer->data, buffer->len);
356 payload = silc_calloc(1, sizeof(*payload));
358 /* Parse start of the payload */
359 ret = silc_buffer_unformat(buffer,
360 SILC_STR_UI_SHORT(&payload->pk_len),
361 SILC_STR_UI_SHORT(&payload->pk_type),
364 status = SILC_SKE_STATUS_ERROR;
368 if (payload->pk_len < 5) {
369 status = SILC_SKE_STATUS_BAD_PAYLOAD;
373 /* Parse public key data */
374 silc_buffer_pull(buffer, 2 + 2);
375 ret = silc_buffer_unformat(buffer,
376 SILC_STR_UI_XNSTRING_ALLOC(&payload->pk_data,
378 SILC_STR_UI16_NSTRING_ALLOC(&e, &e_len),
381 status = SILC_SKE_STATUS_ERROR;
386 status = SILC_SKE_STATUS_BAD_PAYLOAD;
390 silc_buffer_push(buffer, 2 + 2);
392 if (payload->pk_len + 2 + 2 + 2 + e_len != buffer->len) {
393 status = SILC_SKE_STATUS_BAD_PAYLOAD;
397 /* Decode the HEX string to integer */
398 silc_mp_init(&payload->e);
399 silc_mp_bin2mp(e, e_len, &payload->e);
400 memset(e, 0, sizeof(e_len));
403 /* Return the payload */
404 *return_payload = payload;
406 return SILC_SKE_STATUS_OK;
410 ske->status = status;
414 /* Free's KE1 Payload */
416 void silc_ske_payload_one_free(SilcSKEOnePayload *payload)
419 if (payload->pk_data)
420 silc_free(payload->pk_data);
425 /* Encodes Key Exchange 2 Payload into a SILC Buffer to be sent
428 SilcSKEStatus silc_ske_payload_two_encode(SilcSKE ske,
429 SilcSKETwoPayload *payload,
430 SilcBuffer *return_buffer)
433 unsigned char *f_str;
438 SILC_LOG_DEBUG(("Encoding KE 2 Payload"));
441 return SILC_SKE_STATUS_ERROR;
443 /* Encode the integer into HEX string */
444 f_str = silc_mp_mp2bin(&payload->f, 0, &f_len);
446 /* Allocate channel payload buffer. The length of the buffer
447 is 2 + 2 + public key + 2 + f + 2 + signature. */
448 len = payload->pk_len + 2 + 2 + f_len + 2 + payload->sign_len + 2;
449 buf = silc_buffer_alloc(len);
450 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
452 /* Encode the payload */
453 ret = silc_buffer_format(buf,
454 SILC_STR_UI_SHORT(payload->pk_len),
455 SILC_STR_UI_SHORT(payload->pk_type),
456 SILC_STR_UI_XNSTRING(payload->pk_data,
458 SILC_STR_UI_SHORT(f_len),
459 SILC_STR_UI_XNSTRING(f_str, f_len),
460 SILC_STR_UI_SHORT(payload->sign_len),
461 SILC_STR_UI_XNSTRING(payload->sign_data,
465 memset(f_str, 'F', f_len);
467 silc_buffer_free(buf);
468 return SILC_SKE_STATUS_ERROR;
471 /* Return encoded buffer */
472 *return_buffer = buf;
474 memset(f_str, 'F', f_len);
477 return SILC_SKE_STATUS_OK;
480 /* Parses the Key Exchange 2 Payload. Parsed data is returned
481 to allocated payload structure. */
483 SilcSKEStatus silc_ske_payload_two_decode(SilcSKE ske,
485 SilcSKETwoPayload **return_payload)
487 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
488 SilcSKETwoPayload *payload;
490 unsigned short f_len;
491 unsigned int tot_len = 0, len2;
494 SILC_LOG_DEBUG(("Decoding Key Exchange 2 Payload"));
496 SILC_LOG_HEXDUMP(("KE 2 Payload"), buffer->data, buffer->len);
498 payload = silc_calloc(1, sizeof(*payload));
502 /* Parse start of the payload */
503 ret = silc_buffer_unformat(buffer,
504 SILC_STR_UI_SHORT(&payload->pk_len),
505 SILC_STR_UI_SHORT(&payload->pk_type),
508 status = SILC_SKE_STATUS_ERROR;
512 if (payload->pk_len < 5) {
513 status = SILC_SKE_STATUS_BAD_PAYLOAD;
517 tot_len += payload->pk_len + 4;
519 /* Parse PK data and the signature */
520 silc_buffer_pull(buffer, 4);
521 ret = silc_buffer_unformat(buffer,
522 SILC_STR_UI_XNSTRING_ALLOC(&payload->pk_data,
524 SILC_STR_UI16_NSTRING_ALLOC(&f, &f_len),
525 SILC_STR_UI16_NSTRING_ALLOC(&payload->sign_data,
529 status = SILC_SKE_STATUS_ERROR;
533 tot_len += f_len + 2;
534 tot_len += payload->sign_len + 2;
537 status = SILC_SKE_STATUS_BAD_PAYLOAD;
541 if (payload->sign_len < 3) {
542 status = SILC_SKE_STATUS_BAD_PAYLOAD;
546 if (tot_len != len2) {
547 status = SILC_SKE_STATUS_BAD_PAYLOAD;
551 /* Decode the HEX string to integer */
552 silc_mp_init(&payload->f);
553 silc_mp_bin2mp(f, f_len, &payload->f);
554 memset(f, 0, sizeof(f_len));
557 /* Return the payload */
558 *return_payload = payload;
560 return SILC_SKE_STATUS_OK;
563 if (payload->pk_data)
564 silc_free(payload->pk_data);
565 if (payload->sign_data)
566 silc_free(payload->sign_data);
568 ske->status = status;
572 /* Free's KE2 Payload */
574 void silc_ske_payload_two_free(SilcSKETwoPayload *payload)
577 if (payload->pk_data)
578 silc_free(payload->pk_data);
579 if (payload->sign_data)
580 silc_free(payload->sign_data);