5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2000 - 2002 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "silcincludes.h"
23 /* Encodes Key Exchange Start Payload into a SILC Buffer to be sent
26 SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske,
27 SilcSKEStartPayload *payload,
28 SilcBuffer *return_buffer)
33 SILC_LOG_DEBUG(("Encoding KE Start Payload"));
36 return SILC_SKE_STATUS_ERROR;
38 buf = silc_buffer_alloc_size(payload->len);
40 return SILC_SKE_STATUS_OUT_OF_MEMORY;
42 /* Encode the payload */
43 ret = silc_buffer_format(buf,
44 SILC_STR_UI_CHAR(0), /* RESERVED field */
45 SILC_STR_UI_CHAR(payload->flags),
46 SILC_STR_UI_SHORT(payload->len),
47 SILC_STR_UI_XNSTRING(payload->cookie,
49 SILC_STR_UI_SHORT(payload->version_len),
50 SILC_STR_UI_XNSTRING(payload->version,
51 payload->version_len),
52 SILC_STR_UI_SHORT(payload->ke_grp_len),
53 SILC_STR_UI_XNSTRING(payload->ke_grp_list,
55 SILC_STR_UI_SHORT(payload->pkcs_alg_len),
56 SILC_STR_UI_XNSTRING(payload->pkcs_alg_list,
57 payload->pkcs_alg_len),
58 SILC_STR_UI_SHORT(payload->enc_alg_len),
59 SILC_STR_UI_XNSTRING(payload->enc_alg_list,
60 payload->enc_alg_len),
61 SILC_STR_UI_SHORT(payload->hash_alg_len),
62 SILC_STR_UI_XNSTRING(payload->hash_alg_list,
63 payload->hash_alg_len),
64 SILC_STR_UI_SHORT(payload->hmac_alg_len),
65 SILC_STR_UI_XNSTRING(payload->hmac_alg_list,
66 payload->hmac_alg_len),
67 SILC_STR_UI_SHORT(payload->comp_alg_len),
68 SILC_STR_UI_XNSTRING(payload->comp_alg_list,
69 payload->comp_alg_len),
72 silc_buffer_free(buf);
73 return SILC_SKE_STATUS_ERROR;
76 /* Return the encoded buffer */
79 SILC_LOG_HEXDUMP(("KE Start Payload"), buf->data, buf->len);
81 return SILC_SKE_STATUS_OK;
84 /* Parses the Key Exchange Start Payload. Parsed data is returned
85 to allocated payload structure. */
88 silc_ske_payload_start_decode(SilcSKE ske,
90 SilcSKEStartPayload **return_payload)
92 SilcSKEStartPayload *payload;
93 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
97 SILC_LOG_DEBUG(("Decoding Key Exchange Start Payload"));
99 SILC_LOG_HEXDUMP(("KE Start Payload"), buffer->data, buffer->len);
101 payload = silc_calloc(1, sizeof(*payload));
103 return SILC_SKE_STATUS_OUT_OF_MEMORY;
104 payload->cookie_len = SILC_SKE_COOKIE_LEN;
106 /* Parse start of the payload */
108 silc_buffer_unformat(buffer,
109 SILC_STR_UI_CHAR(&tmp), /* RESERVED Field */
110 SILC_STR_UI_CHAR(&payload->flags),
111 SILC_STR_UI_SHORT(&payload->len),
112 SILC_STR_UI_XNSTRING_ALLOC(&payload->cookie,
113 payload->cookie_len),
114 SILC_STR_UI16_NSTRING_ALLOC(&payload->version,
115 &payload->version_len),
116 SILC_STR_UI16_NSTRING_ALLOC(&payload->ke_grp_list,
117 &payload->ke_grp_len),
118 SILC_STR_UI16_NSTRING_ALLOC(&payload->pkcs_alg_list,
119 &payload->pkcs_alg_len),
120 SILC_STR_UI16_NSTRING_ALLOC(&payload->enc_alg_list,
121 &payload->enc_alg_len),
122 SILC_STR_UI16_NSTRING_ALLOC(&payload->hash_alg_list,
123 &payload->hash_alg_len),
124 SILC_STR_UI16_NSTRING_ALLOC(&payload->hmac_alg_list,
125 &payload->hmac_alg_len),
126 SILC_STR_UI16_NSTRING_ALLOC(&payload->comp_alg_list,
127 &payload->comp_alg_len),
130 SILC_LOG_ERROR(("Malformed KE Start Payload"));
131 status = SILC_SKE_STATUS_BAD_PAYLOAD;
136 SILC_LOG_ERROR(("Bad RESERVED field in KE Start Payload"));
137 status = SILC_SKE_STATUS_BAD_RESERVED_FIELD;
141 if (payload->len != buffer->len) {
142 SILC_LOG_ERROR(("Garbage after KE Start Payload"));
143 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
147 /* Check for mandatory fields */
148 if (!payload->cookie || !payload->version_len ||
149 !payload->ke_grp_len || !payload->pkcs_alg_len ||
150 !payload->enc_alg_len || !payload->hash_alg_len ||
151 !payload->hmac_alg_len) {
152 SILC_LOG_ERROR(("KE Start Payload is missing mandatory fields"));
153 status = SILC_SKE_STATUS_BAD_PAYLOAD;
157 /* Return the payload */
158 *return_payload = payload;
160 return SILC_SKE_STATUS_OK;
163 silc_ske_payload_start_free(payload);
165 ske->status = status;
169 /* Free's Start Payload */
171 void silc_ske_payload_start_free(SilcSKEStartPayload *payload)
174 silc_free(payload->cookie);
175 silc_free(payload->version);
176 silc_free(payload->ke_grp_list);
177 silc_free(payload->pkcs_alg_list);
178 silc_free(payload->enc_alg_list);
179 silc_free(payload->hash_alg_list);
180 silc_free(payload->hmac_alg_list);
181 silc_free(payload->comp_alg_list);
186 /* Encodes Key Exchange Payload into a SILC Buffer to be sent to the other
189 SilcSKEStatus silc_ske_payload_ke_encode(SilcSKE ske,
190 SilcSKEKEPayload *payload,
191 SilcBuffer *return_buffer)
194 unsigned char *x_str;
198 SILC_LOG_DEBUG(("Encoding KE Payload"));
201 return SILC_SKE_STATUS_ERROR;
203 if (ske->start_payload &&
204 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL &&
205 !payload->sign_data) {
206 SILC_LOG_DEBUG(("Signature data is missing"));
207 return SILC_SKE_STATUS_ERROR;
210 /* Encode the integer into binary data */
211 x_str = silc_mp_mp2bin(&payload->x, 0, &x_len);
213 /* Allocate channel payload buffer. The length of the buffer
214 is 4 + public key + 2 + x + 2 + signature. */
215 buf = silc_buffer_alloc_size(4 + payload->pk_len + 2 + x_len +
216 2 + payload->sign_len);
218 return SILC_SKE_STATUS_OUT_OF_MEMORY;
220 /* Encode the payload */
221 ret = silc_buffer_format(buf,
222 SILC_STR_UI_SHORT(payload->pk_len),
223 SILC_STR_UI_SHORT(payload->pk_type),
224 SILC_STR_UI_XNSTRING(payload->pk_data,
226 SILC_STR_UI_SHORT(x_len),
227 SILC_STR_UI_XNSTRING(x_str, x_len),
228 SILC_STR_UI_SHORT(payload->sign_len),
229 SILC_STR_UI_XNSTRING(payload->sign_data,
233 memset(x_str, 'F', x_len);
235 silc_buffer_free(buf);
236 return SILC_SKE_STATUS_ERROR;
239 /* Return encoded buffer */
240 *return_buffer = buf;
242 SILC_LOG_HEXDUMP(("KE Payload"), buf->data, buf->len);
244 memset(x_str, 'F', x_len);
247 return SILC_SKE_STATUS_OK;
250 /* Parses the Key Exchange Payload. Parsed data is returned to allocated
251 payload structure. */
253 SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske,
255 SilcSKEKEPayload **return_payload)
257 SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
258 SilcSKEKEPayload *payload;
259 unsigned char *x = NULL;
261 SilcUInt32 tot_len = 0, len2;
264 SILC_LOG_DEBUG(("Decoding Key Exchange Payload"));
266 SILC_LOG_HEXDUMP(("KE Payload"), buffer->data, buffer->len);
268 payload = silc_calloc(1, sizeof(*payload));
270 return SILC_SKE_STATUS_OUT_OF_MEMORY;
274 /* Parse start of the payload */
275 ret = silc_buffer_unformat(buffer,
276 SILC_STR_UI_SHORT(&payload->pk_len),
277 SILC_STR_UI_SHORT(&payload->pk_type),
280 SILC_LOG_ERROR(("Cannot decode public key from KE payload"));
281 status = SILC_SKE_STATUS_BAD_PAYLOAD;
285 if (ske->start_payload &&
286 ((payload->pk_type < SILC_SKE_PK_TYPE_SILC ||
287 payload->pk_type > SILC_SKE_PK_TYPE_SPKI) || !payload->pk_len)) {
288 SILC_LOG_ERROR(("Malformed public key in KE payload"));
289 status = SILC_SKE_STATUS_BAD_PAYLOAD;
293 tot_len += payload->pk_len + 4;
295 /* Parse PK data and the signature */
296 silc_buffer_pull(buffer, 4);
297 ret = silc_buffer_unformat(buffer,
298 SILC_STR_UI_XNSTRING_ALLOC(&payload->pk_data,
300 SILC_STR_UI16_NSTRING_ALLOC(&x, &x_len),
301 SILC_STR_UI16_NSTRING_ALLOC(&payload->sign_data,
305 SILC_LOG_ERROR(("Malformed KE Payload"));
306 status = SILC_SKE_STATUS_BAD_PAYLOAD;
310 tot_len += x_len + 2;
311 tot_len += payload->sign_len + 2;
314 SILC_LOG_ERROR(("Too short DH value in KE Payload"));
315 status = SILC_SKE_STATUS_BAD_PAYLOAD;
319 if (ske->start_payload &&
320 (ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) &&
321 (payload->sign_len < 3 || !payload->sign_data)) {
322 SILC_LOG_ERROR(("The signature data is missing - both parties are "
323 "required to do authentication"));
324 status = SILC_SKE_STATUS_BAD_PAYLOAD;
328 if (tot_len != len2) {
329 SILC_LOG_ERROR(("Garbage after KE payload"));
330 status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH;
334 /* Decode the binary data to integer */
335 silc_mp_init(&payload->x);
336 silc_mp_bin2mp(x, x_len, &payload->x);
337 memset(x, 0, sizeof(x_len));
340 /* Return the payload */
341 *return_payload = payload;
343 return SILC_SKE_STATUS_OK;
346 silc_free(payload->pk_data);
347 silc_free(payload->sign_data);
350 ske->status = status;
354 /* Free's KE Payload */
356 void silc_ske_payload_ke_free(SilcSKEKEPayload *payload)
359 silc_free(payload->pk_data);
360 silc_mp_uninit(&payload->x);
361 silc_free(payload->sign_data);