tls: add Change Cipher Spec & Finished messages
[siplcs.git] / src / core / sipe-tls.c
blobb5072f91afca44453cc1debb9cbb63d4075cf61d
1 /**
2 * @file sipe-tls.c
4 * pidgin-sipe
6 * Copyright (C) 2011 SIPE Project <http://sipe.sourceforge.net/>
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.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * TLS Protocol Version 1.0/1.1 - Handshake Messages
26 * TLS-DSK uses the handshake messages during authentication and session key
27 * exchange. This module *ONLY* implements this part of the TLS specification!
29 * Specification references:
31 * - RFC2246: http://www.ietf.org/rfc/rfc2246.txt
32 * - RFC3546: http://www.ietf.org/rfc/rfc3546.txt
33 * - RFC4346: http://www.ietf.org/rfc/rfc4346.txt
36 #include <stdlib.h>
37 #include <string.h>
38 #include <stdarg.h>
40 #include <glib.h>
42 #include "sipe-common.h"
43 #include "sipe-backend.h"
44 #include "sipe-cert-crypto.h"
45 #include "sipe-crypt.h"
46 #include "sipe-digest.h"
47 #include "sipe-svc.h"
48 #include "sipe-tls.h"
51 * Private part of TLS state tracking
53 enum tls_handshake_state {
54 TLS_HANDSHAKE_STATE_START,
55 TLS_HANDSHAKE_STATE_SERVER_HELLO,
56 TLS_HANDSHAKE_STATE_FINISHED,
57 TLS_HANDSHAKE_STATE_COMPLETED,
58 TLS_HANDSHAKE_STATE_FAILED
61 struct tls_internal_state {
62 struct sipe_tls_state common;
63 gpointer certificate;
64 enum tls_handshake_state state;
65 guchar *msg_current;
66 gsize msg_remainder;
67 GHashTable *data;
68 GString *debug;
69 gpointer md5_context;
70 gpointer sha1_context;
71 gpointer server_certificate;
72 guchar *master_secret;
73 struct sipe_svc_random client_random;
74 struct sipe_svc_random server_random;
78 * TLS messages & layout descriptors
81 /* constants */
82 #define TLS_VECTOR_MAX8 255 /* 2^8 - 1 */
83 #define TLS_VECTOR_MAX16 65535 /* 2^16 - 1 */
84 #define TLS_VECTOR_MAX24 16777215 /* 2^24 - 1 */
86 #define TLS_PROTOCOL_VERSION_1_0 0x0301
87 #define TLS_PROTOCOL_VERSION_1_1 0x0302
89 /* CipherSuites */
90 #define TLS_RSA_EXPORT_WITH_RC4_40_MD5 0x0003
91 #define TLS_RSA_WITH_RC4_128_MD5 0x0004
92 #define TLS_RSA_WITH_RC4_128_SHA 0x0005
94 /* CompressionMethods */
95 #define TLS_COMP_METHOD_NULL 0
97 /* various array lengths */
98 #define TLS_ARRAY_RANDOM_LENGTH 32
99 #define TLS_ARRAY_MASTER_SECRET_LENGTH 48
100 #define TLS_ARRAY_VERIFY_LENGTH 12
102 #define TLS_RECORD_HEADER_LENGTH 5
103 #define TLS_RECORD_OFFSET_TYPE 0
104 #define TLS_RECORD_TYPE_CHANGE_CIPHER_SPEC 20
105 #define TLS_RECORD_TYPE_HANDSHAKE 22
106 #define TLS_RECORD_OFFSET_VERSION 1
107 #define TLS_RECORD_OFFSET_LENGTH 3
109 #define TLS_HANDSHAKE_HEADER_LENGTH 4
110 #define TLS_HANDSHAKE_OFFSET_TYPE 0
111 #define TLS_HANDSHAKE_TYPE_CLIENT_HELLO 1
112 #define TLS_HANDSHAKE_TYPE_SERVER_HELLO 2
113 #define TLS_HANDSHAKE_TYPE_CERTIFICATE 11
114 #define TLS_HANDSHAKE_TYPE_CERTIFICATE_REQ 13
115 #define TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE 14
116 #define TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY 15
117 #define TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE 16
118 #define TLS_HANDSHAKE_TYPE_FINISHED 20
119 #define TLS_HANDSHAKE_OFFSET_LENGTH 1
121 struct layout_descriptor;
122 typedef gboolean parse_func(struct tls_internal_state *state,
123 const struct layout_descriptor *desc);
125 /* Defines the strictest alignment requirement */
126 struct tls_compile_integer;
127 typedef void compile_func(struct tls_internal_state *state,
128 const struct layout_descriptor *desc,
129 const struct tls_compile_integer *data);
131 struct layout_descriptor {
132 const gchar *label;
133 parse_func *parser;
134 compile_func *compiler;
135 gsize min; /* 0 for fixed/array */
136 gsize max;
137 gsize offset;
140 #define TLS_LAYOUT_DESCRIPTOR_END { NULL, NULL, NULL, 0, 0, 0 }
141 #define TLS_LAYOUT_IS_VALID(desc) (desc->label)
143 struct msg_descriptor {
144 const struct msg_descriptor *next;
145 const gchar *description;
146 const struct layout_descriptor *layouts;
147 guint type;
150 /* parsed data */
151 struct tls_parsed_integer {
152 guint value;
155 struct tls_parsed_array {
156 gsize length; /* bytes */
157 const guchar data[0];
160 /* compile data */
161 struct tls_compile_integer {
162 gsize value;
165 struct tls_compile_array {
166 gsize elements; /* unused */
167 guchar placeholder[];
170 struct tls_compile_random {
171 gsize elements; /* unused */
172 guchar random[TLS_ARRAY_RANDOM_LENGTH];
175 struct tls_compile_verify {
176 gsize elements; /* unused */
177 guchar verify[TLS_ARRAY_VERIFY_LENGTH];
180 struct tls_compile_vector {
181 gsize elements; /* VECTOR */
182 guint placeholder[];
185 struct tls_compile_sessionid {
186 gsize elements; /* VECTOR */
189 struct tls_compile_cipher {
190 gsize elements; /* VECTOR */
191 guint suites[3];
194 struct tls_compile_compression {
195 gsize elements; /* VECTOR */
196 guint methods[1];
199 /* compiled message */
200 struct tls_compiled_message {
201 gsize size;
202 guchar data[];
206 * TLS message debugging
208 static void debug_hex(struct tls_internal_state *state,
209 gsize alternative_length)
211 GString *str = state->debug;
212 const guchar *bytes;
213 gsize length;
214 gint count;
216 if (!str) return;
218 bytes = state->msg_current;
219 length = alternative_length ? alternative_length : state->msg_remainder;
220 count = -1;
222 while (length-- > 0) {
223 if (++count == 0) {
224 /* do nothing */;
225 } else if ((count % 16) == 0) {
226 g_string_append(str, "\n");
227 } else if ((count % 8) == 0) {
228 g_string_append(str, " ");
230 g_string_append_printf(str, " %02X", *bytes++);
232 g_string_append(str, "\n");
235 #define debug_print(state, string) \
236 if (state->debug) g_string_append(state->debug, string)
237 #define debug_printf(state, format, ...) \
238 if (state->debug) g_string_append_printf(state->debug, format, __VA_ARGS__)
241 * TLS Pseudorandom Function (PRF) - RFC2246, Section 5
243 static guchar *sipe_tls_p_md5(const guchar *secret,
244 gsize secret_length,
245 const guchar *seed,
246 gsize seed_length,
247 gsize output_length)
249 guchar *output = NULL;
252 * output_length == 0 -> illegal
253 * output_length == 1..16 -> iterations = 1
254 * output_length == 17..32 -> iterations = 2
256 if (secret && seed && (output_length > 0)) {
257 guint iterations = (output_length + SIPE_DIGEST_HMAC_MD5_LENGTH - 1) / SIPE_DIGEST_HMAC_MD5_LENGTH;
258 guchar *concat = g_malloc(SIPE_DIGEST_HMAC_MD5_LENGTH + seed_length);
259 guchar A[SIPE_DIGEST_HMAC_MD5_LENGTH];
260 guchar *p;
262 SIPE_DEBUG_INFO("p_md5: secret %" G_GSIZE_FORMAT " bytes, seed %" G_GSIZE_FORMAT " bytes",
263 secret_length, seed_length);
264 SIPE_DEBUG_INFO("p_md5: output %" G_GSIZE_FORMAT " bytes -> %d iterations",
265 output_length, iterations);
267 /* A(1) = HMAC_MD5(secret, A(0)), A(0) = seed */
268 sipe_digest_hmac_md5(secret, secret_length,
269 seed, seed_length,
272 /* Each iteration adds SIPE_DIGEST_HMAC_MD5_LENGTH bytes */
273 p = output = g_malloc(iterations * SIPE_DIGEST_HMAC_MD5_LENGTH);
275 while (iterations-- > 0) {
276 /* P_MD5(i) = HMAC_MD5(secret, A(i) + seed), i = 1, 2, ... */
277 guchar P[SIPE_DIGEST_HMAC_MD5_LENGTH];
278 memcpy(concat, A, SIPE_DIGEST_HMAC_MD5_LENGTH);
279 memcpy(concat + SIPE_DIGEST_HMAC_MD5_LENGTH, seed, seed_length);
280 sipe_digest_hmac_md5(secret, secret_length,
281 concat, SIPE_DIGEST_HMAC_MD5_LENGTH + seed_length,
283 memcpy(p, P, SIPE_DIGEST_HMAC_MD5_LENGTH);
284 p += SIPE_DIGEST_HMAC_MD5_LENGTH;
286 /* A(i+1) = HMAC_MD5(secret, A(i)) */
287 sipe_digest_hmac_md5(secret, secret_length,
288 A, SIPE_DIGEST_HMAC_MD5_LENGTH,
291 g_free(concat);
294 return(output);
297 guchar *sipe_tls_p_sha1(const guchar *secret,
298 gsize secret_length,
299 const guchar *seed,
300 gsize seed_length,
301 gsize output_length)
303 guchar *output = NULL;
306 * output_length == 0 -> illegal
307 * output_length == 1..20 -> iterations = 1
308 * output_length == 21..40 -> iterations = 2
310 if (secret && seed && (output_length > 0)) {
311 guint iterations = (output_length + SIPE_DIGEST_HMAC_SHA1_LENGTH - 1) / SIPE_DIGEST_HMAC_SHA1_LENGTH;
312 guchar *concat = g_malloc(SIPE_DIGEST_HMAC_SHA1_LENGTH + seed_length);
313 guchar A[SIPE_DIGEST_HMAC_SHA1_LENGTH];
314 guchar *p;
316 SIPE_DEBUG_INFO("p_sha1: secret %" G_GSIZE_FORMAT " bytes, seed %" G_GSIZE_FORMAT " bytes",
317 secret_length, seed_length);
318 SIPE_DEBUG_INFO("p_sha1: output %" G_GSIZE_FORMAT " bytes -> %d iterations",
319 output_length, iterations);
321 /* A(1) = HMAC_SHA1(secret, A(0)), A(0) = seed */
322 sipe_digest_hmac_sha1(secret, secret_length,
323 seed, seed_length,
326 /* Each iteration adds SIPE_DIGEST_HMAC_SHA1_LENGTH bytes */
327 p = output = g_malloc(iterations * SIPE_DIGEST_HMAC_SHA1_LENGTH);
329 while (iterations-- > 0) {
330 /* P_SHA1(i) = HMAC_SHA1(secret, A(i) + seed), i = 1, 2, ... */
331 guchar P[SIPE_DIGEST_HMAC_SHA1_LENGTH];
332 memcpy(concat, A, SIPE_DIGEST_HMAC_SHA1_LENGTH);
333 memcpy(concat + SIPE_DIGEST_HMAC_SHA1_LENGTH, seed, seed_length);
334 sipe_digest_hmac_sha1(secret, secret_length,
335 concat, SIPE_DIGEST_HMAC_SHA1_LENGTH + seed_length,
337 memcpy(p, P, SIPE_DIGEST_HMAC_SHA1_LENGTH);
338 p += SIPE_DIGEST_HMAC_SHA1_LENGTH;
340 /* A(i+1) = HMAC_SHA1(secret, A(i)) */
341 sipe_digest_hmac_sha1(secret, secret_length,
342 A, SIPE_DIGEST_HMAC_SHA1_LENGTH,
345 g_free(concat);
348 return(output);
351 static guchar *sipe_tls_prf(const guchar *secret,
352 gsize secret_length,
353 const guchar *label,
354 gsize label_length,
355 const guchar *seed,
356 gsize seed_length,
357 gsize output_length)
359 gsize half = (secret_length + 1) / 2;
360 gsize newseed_length = label_length + seed_length;
361 /* secret: used as S1; secret2: last half of original secret (S2) */
362 guchar *secret2 = g_memdup(secret + secret_length - half, half);
363 guchar *newseed = g_malloc(newseed_length);
364 guchar *md5, *dest;
365 guchar *sha1, *src;
368 * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
369 * P_SHA-1(S2, label + seed);
371 memcpy(newseed, label, label_length);
372 memcpy(newseed + label_length, seed, seed_length);
373 md5 = sipe_tls_p_md5(secret, half, newseed, newseed_length, output_length);
374 sha1 = sipe_tls_p_sha1(secret2, half, newseed, newseed_length, output_length);
375 for (dest = md5, src = sha1;
376 output_length > 0;
377 output_length--)
378 *dest++ ^= *src++;
380 g_free(sha1);
381 g_free(newseed);
382 g_free(secret2);
384 return(md5);
388 * TLS data parsers
390 * Low-level data conversion routines
392 * - host alignment agnostic, i.e. can fetch a word from uneven address
393 * - TLS -> host endianess conversion
394 * - no length check, caller has to do it
395 * - don't modify state
397 static guint lowlevel_integer_to_host(const guchar *bytes,
398 gsize length)
400 guint sum = 0;
401 while (length--) sum = (sum << 8) + *bytes++;
402 return(sum);
406 * Generic data type parser routines
408 static gboolean msg_remainder_check(struct tls_internal_state *state,
409 const gchar *label,
410 gsize length)
412 if (length > state->msg_remainder) {
413 SIPE_DEBUG_ERROR("msg_remainder_check: '%s' expected %" G_GSIZE_FORMAT " bytes, remaining %" G_GSIZE_FORMAT,
414 label, length, state->msg_remainder);
415 return(FALSE);
417 return(TRUE);
420 static gboolean parse_integer_quiet(struct tls_internal_state *state,
421 const gchar *label,
422 gsize length,
423 guint *result)
425 if (!msg_remainder_check(state, label, length)) return(FALSE);
426 *result = lowlevel_integer_to_host(state->msg_current, length);
427 state->msg_current += length;
428 state->msg_remainder -= length;
429 return(TRUE);
432 static gboolean parse_integer(struct tls_internal_state *state,
433 const struct layout_descriptor *desc)
435 guint value;
436 if (!parse_integer_quiet(state, desc->label, desc->max, &value))
437 return(FALSE);
438 debug_printf(state, "%s/INTEGER%" G_GSIZE_FORMAT " = %d\n",
439 desc->label, desc->max, value);
440 if (state->data) {
441 struct tls_parsed_integer *save = g_new0(struct tls_parsed_integer, 1);
442 save->value = value;
443 g_hash_table_insert(state->data, (gpointer) desc->label, save);
445 return(TRUE);
448 static gboolean parse_array(struct tls_internal_state *state,
449 const struct layout_descriptor *desc)
451 if (!msg_remainder_check(state, desc->label, desc->max))
452 return(FALSE);
453 debug_printf(state, "%s/ARRAY[%" G_GSIZE_FORMAT "]\n",
454 desc->label, desc->max);
455 if (state->data) {
456 struct tls_parsed_array *save = g_malloc0(sizeof(struct tls_parsed_array) +
457 desc->max);
458 save->length = desc->max;
459 memcpy((guchar *)save->data, state->msg_current, desc->max);
460 g_hash_table_insert(state->data, (gpointer) desc->label, save);
463 state->msg_current += desc->max;
464 state->msg_remainder -= desc->max;
465 return(TRUE);
468 static gboolean parse_vector(struct tls_internal_state *state,
469 const struct layout_descriptor *desc)
471 guint length;
472 if (!parse_integer_quiet(state, desc->label,
473 (desc->max > TLS_VECTOR_MAX16) ? 3 :
474 (desc->max > TLS_VECTOR_MAX8) ? 2 : 1,
475 &length))
476 return(FALSE);
477 if (length < desc->min) {
478 SIPE_DEBUG_ERROR("parse_vector: '%s' too short %d, expected %" G_GSIZE_FORMAT,
479 desc->label, length, desc->min);
480 return(FALSE);
482 debug_printf(state, "%s/VECTOR<%d>\n", desc->label, length);
483 if (state->data) {
484 struct tls_parsed_array *save = g_malloc0(sizeof(struct tls_parsed_array) +
485 length);
486 save->length = length;
487 memcpy((guchar *)save->data, state->msg_current, length);
488 g_hash_table_insert(state->data, (gpointer) desc->label, save);
490 state->msg_current += length;
491 state->msg_remainder -= length;
492 return(TRUE);
496 * Specific data type parser routines
499 /* TBD... */
502 * TLS data compilers
504 * Low-level data conversion routines
506 * - host alignment agnostic, i.e. can fetch a word from uneven address
507 * - host -> TLS host endianess conversion
508 * - don't modify state
510 static void lowlevel_integer_to_tls(guchar *bytes,
511 gsize length,
512 guint value)
514 while (length--) {
515 bytes[length] = value & 0xFF;
516 value >>= 8;
521 * Generic data type compiler routines
523 static void compile_integer(struct tls_internal_state *state,
524 const struct layout_descriptor *desc,
525 const struct tls_compile_integer *data)
527 lowlevel_integer_to_tls(state->msg_current, desc->max, data->value);
528 state->msg_current += desc->max;
531 static void compile_array(struct tls_internal_state *state,
532 const struct layout_descriptor *desc,
533 const struct tls_compile_integer *data)
535 const struct tls_compile_array *array = (struct tls_compile_array *) data;
536 memcpy(state->msg_current, array->placeholder, desc->max);
537 state->msg_current += desc->max;
540 static void compile_vector(struct tls_internal_state *state,
541 const struct layout_descriptor *desc,
542 const struct tls_compile_integer *data)
544 const struct tls_compile_vector *vector = (struct tls_compile_vector *) data;
545 gsize length = vector->elements;
546 gsize length_field = (desc->max > TLS_VECTOR_MAX16) ? 3 :
547 (desc->max > TLS_VECTOR_MAX8) ? 2 : 1;
549 lowlevel_integer_to_tls(state->msg_current, length_field, length);
550 state->msg_current += length_field;
551 memcpy(state->msg_current, vector->placeholder, length);
552 state->msg_current += length;
555 static void compile_vector_int2(struct tls_internal_state *state,
556 const struct layout_descriptor *desc,
557 const struct tls_compile_integer *data)
559 const struct tls_compile_vector *vector = (struct tls_compile_vector *) data;
560 gsize elements = vector->elements;
561 gsize length = elements * sizeof(guint16);
562 gsize length_field = (desc->max > TLS_VECTOR_MAX16) ? 3 :
563 (desc->max > TLS_VECTOR_MAX8) ? 2 : 1;
564 const guint *p = vector->placeholder;
566 lowlevel_integer_to_tls(state->msg_current, length_field, length);
567 state->msg_current += length_field;
568 while (elements--) {
569 lowlevel_integer_to_tls(state->msg_current, sizeof(guint16), *p++);
570 state->msg_current += sizeof(guint16);
575 * Specific data type compiler routines
578 /* TBD... */
581 * TLS handshake message layout descriptors
583 struct ClientHello_host {
584 struct tls_compile_integer protocol_version;
585 struct tls_compile_random random;
586 struct tls_compile_sessionid sessionid;
587 struct tls_compile_cipher cipher;
588 struct tls_compile_compression compression;
590 #define CLIENTHELLO_OFFSET(a) offsetof(struct ClientHello_host, a)
592 static const struct layout_descriptor const ClientHello_l[] = {
593 { "Client Protocol Version", parse_integer, compile_integer, 0, 2, CLIENTHELLO_OFFSET(protocol_version) },
594 { "Random", parse_array, compile_array, 0, TLS_ARRAY_RANDOM_LENGTH, CLIENTHELLO_OFFSET(random) },
595 { "SessionID", parse_vector, compile_vector, 0, 32, CLIENTHELLO_OFFSET(sessionid) },
596 { "CipherSuite", parse_vector, compile_vector_int2, 2, TLS_VECTOR_MAX16, CLIENTHELLO_OFFSET(cipher)},
597 { "CompressionMethod", parse_vector, compile_vector, 1, TLS_VECTOR_MAX8, CLIENTHELLO_OFFSET(compression) },
598 TLS_LAYOUT_DESCRIPTOR_END
600 static const struct msg_descriptor const ClientHello_m = {
601 NULL, "Client Hello", ClientHello_l, TLS_HANDSHAKE_TYPE_CLIENT_HELLO
604 static const struct layout_descriptor const ServerHello_l[] = {
605 { "Server Protocol Version", parse_integer, NULL, 0, 2, 0 },
606 { "Random", parse_array, NULL, 0, TLS_ARRAY_RANDOM_LENGTH, 0 },
607 { "SessionID", parse_vector, NULL, 0, 32, 0 },
608 { "CipherSuite", parse_integer, NULL, 0, 2, 0 },
609 { "CompressionMethod", parse_integer, NULL, 0, 1, 0 },
610 TLS_LAYOUT_DESCRIPTOR_END
612 static const struct msg_descriptor const ServerHello_m = {
613 &ClientHello_m, "Server Hello", ServerHello_l, TLS_HANDSHAKE_TYPE_SERVER_HELLO
616 struct Certificate_host {
617 struct tls_compile_vector certificate;
619 #define CERTIFICATE_OFFSET(a) offsetof(struct Certificate_host, a)
621 static const struct layout_descriptor const Certificate_l[] = {
622 { "Certificate", parse_vector, compile_vector, 0, TLS_VECTOR_MAX24, CERTIFICATE_OFFSET(certificate) },
623 TLS_LAYOUT_DESCRIPTOR_END
625 static const struct msg_descriptor const Certificate_m = {
626 &ServerHello_m, "Certificate", Certificate_l, TLS_HANDSHAKE_TYPE_CERTIFICATE
629 static const struct layout_descriptor const CertificateRequest_l[] = {
630 { "CertificateType", parse_vector, NULL, 1, TLS_VECTOR_MAX8, 0 },
631 { "DistinguishedName", parse_vector, NULL, 0, TLS_VECTOR_MAX16, 0 },
632 TLS_LAYOUT_DESCRIPTOR_END
634 static const struct msg_descriptor const CertificateRequest_m = {
635 &Certificate_m, "Certificate Request", CertificateRequest_l, TLS_HANDSHAKE_TYPE_CERTIFICATE_REQ
638 static const struct layout_descriptor const ServerHelloDone_l[] = {
639 TLS_LAYOUT_DESCRIPTOR_END
641 static const struct msg_descriptor const ServerHelloDone_m = {
642 &CertificateRequest_m, "Server Hello Done", ServerHelloDone_l, TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE
645 struct ClientKeyExchange_host {
646 struct tls_compile_vector secret;
648 #define CLIENTKEYEXCHANGE_OFFSET(a) offsetof(struct ClientKeyExchange_host, a)
650 static const struct layout_descriptor const ClientKeyExchange_l[] = {
651 { "Exchange Keys", parse_vector, compile_vector, 0, TLS_VECTOR_MAX16, CLIENTKEYEXCHANGE_OFFSET(secret) },
652 TLS_LAYOUT_DESCRIPTOR_END
654 static const struct msg_descriptor const ClientKeyExchange_m = {
655 &ServerHelloDone_m, "Client Key Exchange", ClientKeyExchange_l, TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE
658 struct CertificateVerify_host {
659 struct tls_compile_vector signature;
661 #define CERTIFICATEVERIFY_OFFSET(a) offsetof(struct CertificateVerify_host, a)
663 static const struct layout_descriptor const CertificateVerify_l[] = {
664 { "Signature", parse_vector, compile_vector, 0, TLS_VECTOR_MAX16, CERTIFICATEVERIFY_OFFSET(signature) },
665 TLS_LAYOUT_DESCRIPTOR_END
667 static const struct msg_descriptor const CertificateVerify_m = {
668 &ClientKeyExchange_m, "Certificate Verify", CertificateVerify_l, TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY
671 struct Finished_host {
672 struct tls_compile_verify verify;
674 #define FINISHED_OFFSET(a) offsetof(struct Finished_host, a)
676 static const struct layout_descriptor const Finished_l[] = {
677 { "Verify Data", parse_array, compile_array, 0, TLS_ARRAY_VERIFY_LENGTH, FINISHED_OFFSET(verify) },
678 TLS_LAYOUT_DESCRIPTOR_END
680 static const struct msg_descriptor const Finished_m = {
681 &CertificateVerify_m, "Finished", Finished_l, TLS_HANDSHAKE_TYPE_FINISHED
684 #define HANDSHAKE_MSG_DESCRIPTORS &Finished_m
687 * TLS message parsers
689 static gboolean handshake_parse(struct tls_internal_state *state)
691 const guchar *bytes = state->msg_current;
692 gsize length = state->msg_remainder;
693 gboolean success = FALSE;
695 while (length > 0) {
696 const struct msg_descriptor *desc;
697 gsize msg_length;
698 guint msg_type;
700 /* header check */
701 if (length < TLS_HANDSHAKE_HEADER_LENGTH) {
702 debug_print(state, "CORRUPTED HANDSHAKE HEADER");
703 break;
706 /* msg length check */
707 msg_length = lowlevel_integer_to_host(bytes + TLS_HANDSHAKE_OFFSET_LENGTH,
709 if (msg_length > length) {
710 debug_print(state, "HANDSHAKE MESSAGE TOO LONG");
711 break;
714 /* msg type */
715 msg_type = bytes[TLS_HANDSHAKE_OFFSET_TYPE];
716 for (desc = HANDSHAKE_MSG_DESCRIPTORS;
717 desc;
718 desc = desc->next)
719 if (msg_type == desc->type)
720 break;
722 debug_printf(state, "TLS handshake (%" G_GSIZE_FORMAT " bytes) (%d)",
723 msg_length, msg_type);
725 state->msg_current = (guchar *) bytes + TLS_HANDSHAKE_HEADER_LENGTH;
726 state->msg_remainder = msg_length;
728 if (desc->layouts) {
729 const struct layout_descriptor *ldesc = desc->layouts;
731 debug_printf(state, "%s\n", desc->description);
732 while (TLS_LAYOUT_IS_VALID(ldesc)) {
733 success = ldesc->parser(state, ldesc);
734 if (!success)
735 break;
736 ldesc++;
738 if (!success)
739 break;
740 } else {
741 debug_print(state, "ignored\n");
742 debug_hex(state, 0);
745 /* next message */
746 bytes += TLS_HANDSHAKE_HEADER_LENGTH + msg_length;
747 length -= TLS_HANDSHAKE_HEADER_LENGTH + msg_length;
748 if (length > 0) {
749 debug_print(state, "------\n");
750 } else {
751 success = TRUE;
755 return(success);
758 static void free_parse_data(struct tls_internal_state *state)
760 if (state->data) {
761 g_hash_table_destroy(state->data);
762 state->data = NULL;
766 /* NOTE: we don't support record fragmentation */
767 static gboolean tls_record_parse(struct tls_internal_state *state,
768 gboolean incoming)
770 const guchar *bytes = incoming ? state->common.in_buffer : state->common.out_buffer;
771 gsize length = incoming ? state->common.in_length : state->common.out_length;
772 guint version;
773 const gchar *version_str;
774 gsize record_length;
775 gboolean success = FALSE;
777 debug_printf(state, "TLS MESSAGE %s\n", incoming ? "INCOMING" : "OUTGOING");
779 /* truncated header check */
780 if (length < TLS_RECORD_HEADER_LENGTH) {
781 SIPE_DEBUG_ERROR("tls_record_parse: too short TLS record header (%" G_GSIZE_FORMAT " bytes)",
782 length);
783 return(FALSE);
786 /* protocol version check */
787 version = lowlevel_integer_to_host(bytes + TLS_RECORD_OFFSET_VERSION, 2);
788 if (version < TLS_PROTOCOL_VERSION_1_0) {
789 SIPE_DEBUG_ERROR_NOFORMAT("tls_record_parse: SSL1/2/3 not supported");
790 return(FALSE);
792 switch (version) {
793 case TLS_PROTOCOL_VERSION_1_0:
794 version_str = "1.0 (RFC2246)";
795 break;
796 case TLS_PROTOCOL_VERSION_1_1:
797 version_str = "1.1 (RFC4346)";
798 break;
799 default:
800 version_str = "<future protocol version>";
801 break;
804 /* record length check */
805 record_length = TLS_RECORD_HEADER_LENGTH +
806 lowlevel_integer_to_host(bytes + TLS_RECORD_OFFSET_LENGTH, 2);
807 if (record_length > length) {
808 SIPE_DEBUG_ERROR_NOFORMAT("tls_record_parse: record too long");
809 return(FALSE);
812 /* TLS record header OK */
813 debug_printf(state, "TLS %s record (%" G_GSIZE_FORMAT " bytes)\n",
814 version_str, length);
815 state->msg_current = (guchar *) bytes + TLS_RECORD_HEADER_LENGTH;
816 state->msg_remainder = length - TLS_RECORD_HEADER_LENGTH;
818 /* Add incoming message contents to digest contexts */
819 if (incoming) {
820 sipe_digest_md5_update(state->md5_context,
821 state->msg_current,
822 state->msg_remainder);
823 sipe_digest_sha1_update(state->sha1_context,
824 state->msg_current,
825 state->msg_remainder);
828 /* Collect parser data for incoming messages */
829 if (incoming)
830 state->data = g_hash_table_new_full(g_str_hash, g_str_equal,
831 NULL, g_free);
833 switch (bytes[TLS_RECORD_OFFSET_TYPE]) {
834 case TLS_RECORD_TYPE_HANDSHAKE:
835 success = handshake_parse(state);
836 break;
838 default:
839 debug_print(state, "Unsupported TLS message\n");
840 debug_hex(state, 0);
841 break;
844 if (!success)
845 free_parse_data(state);
847 if (state->debug) {
848 SIPE_DEBUG_INFO_NOFORMAT(state->debug->str);
849 g_string_truncate(state->debug, 0);
852 return(success);
856 * TLS message compiler
858 static void compile_tls_record(struct tls_internal_state *state,
859 ...)
861 gsize total_size = 0;
862 guchar *current;
863 va_list ap;
865 /* calculate message size */
866 va_start(ap, state);
867 while (1) {
868 const struct tls_compiled_message *msg = va_arg(ap, struct tls_compiled_message *);
869 if (!msg) break;
870 total_size += msg->size;
872 va_end(ap);
874 SIPE_DEBUG_INFO("compile_tls_record: total size %" G_GSIZE_FORMAT,
875 total_size);
877 state->common.out_buffer = current = g_malloc(total_size + TLS_RECORD_HEADER_LENGTH);
878 state->common.out_length = total_size + TLS_RECORD_HEADER_LENGTH;
880 /* add TLS record header */
881 current[TLS_RECORD_OFFSET_TYPE] = TLS_RECORD_TYPE_HANDSHAKE;
882 lowlevel_integer_to_tls(current + TLS_RECORD_OFFSET_VERSION, 2,
883 TLS_PROTOCOL_VERSION_1_0);
884 lowlevel_integer_to_tls(current + TLS_RECORD_OFFSET_LENGTH, 2,
885 total_size);
886 current += TLS_RECORD_HEADER_LENGTH;
888 /* copy messages */
889 va_start(ap, state);
890 while (1) {
891 const struct tls_compiled_message *msg = va_arg(ap, struct tls_compiled_message *);
892 if (!msg) break;
894 memcpy(current, msg->data, msg->size);
895 current += msg->size;
897 va_end(ap);
900 static struct tls_compiled_message *compile_handshake_msg(struct tls_internal_state *state,
901 const struct msg_descriptor *desc,
902 gpointer data,
903 gsize size)
906 * Estimate the size of the compiled message
908 * The data structures in the host format have zero or more padding
909 * bytes added by the compiler to ensure correct element alignments.
910 * So the sizeof() of the data structure is always equal or greater
911 * than the space needed for the compiled data. By adding the space
912 * required for the headers we arrive at a safe estimate
914 * Therefore we don't need space checks in the compiler functions
916 gsize total_size = sizeof(struct tls_compiled_message) +
917 size + TLS_HANDSHAKE_HEADER_LENGTH;
918 struct tls_compiled_message *msg = g_malloc(total_size);
919 guchar *handshake = msg->data;
920 const struct layout_descriptor *ldesc = desc->layouts;
921 gsize length;
923 SIPE_DEBUG_INFO("compile_handshake_msg: buffer size %" G_GSIZE_FORMAT,
924 total_size);
926 /* add TLS handshake header */
927 handshake[TLS_HANDSHAKE_OFFSET_TYPE] = desc->type;
928 state->msg_current = handshake + TLS_HANDSHAKE_HEADER_LENGTH;
930 while (TLS_LAYOUT_IS_VALID(ldesc)) {
932 * Avoid "cast increases required alignment" errors
934 * (void *) tells the compiler that we know what we're
935 * doing, i.e. we know that the calculated address
936 * points to correctly aligned data.
938 ldesc->compiler(state, ldesc,
939 (void *) ((guchar *) data + ldesc->offset));
940 ldesc++;
943 length = state->msg_current - handshake - TLS_HANDSHAKE_HEADER_LENGTH;
944 lowlevel_integer_to_tls(handshake + TLS_HANDSHAKE_OFFSET_LENGTH,
945 3, length);
946 SIPE_DEBUG_INFO("compile_handshake_msg: (%d)%s, size %" G_GSIZE_FORMAT,
947 desc->type, desc->description, length);
949 msg->size = length + TLS_HANDSHAKE_HEADER_LENGTH;
951 /* update digest contexts */
952 sipe_digest_md5_update(state->md5_context, handshake, msg->size);
953 sipe_digest_sha1_update(state->sha1_context, handshake, msg->size);
955 return(msg);
958 static struct tls_compiled_message *tls_client_certificate(struct tls_internal_state *state)
960 struct Certificate_host *certificate;
961 gsize certificate_length = sipe_cert_crypto_raw_length(state->certificate);
962 struct tls_compiled_message *msg;
964 /* setup our response */
965 /* Client Certificate is VECTOR_MAX24 of VECTOR_MAX24s */
966 certificate = g_malloc0(sizeof(struct Certificate_host) + 3 +
967 certificate_length);
968 certificate->certificate.elements = certificate_length + 3;
969 lowlevel_integer_to_tls((guchar *) certificate->certificate.placeholder, 3,
970 certificate_length);
971 memcpy((guchar *) certificate->certificate.placeholder + 3,
972 sipe_cert_crypto_raw(state->certificate),
973 certificate_length);
975 msg = compile_handshake_msg(state, &Certificate_m, certificate,
976 sizeof(struct Certificate_host) + certificate_length);
977 g_free(certificate);
979 return(msg);
982 static struct tls_compiled_message *tls_client_key_exchange(struct tls_internal_state *state)
984 struct tls_parsed_array *server_random;
985 struct tls_parsed_array *server_certificate;
986 struct ClientKeyExchange_host *exchange;
987 gsize server_certificate_length;
988 struct sipe_svc_random pre_master_secret;
989 guchar *random;
990 struct tls_compiled_message *msg;
992 /* check for required data fields */
993 server_random = g_hash_table_lookup(state->data, "Random");
994 if (!server_random) {
995 SIPE_DEBUG_ERROR_NOFORMAT("tls_client_key_exchange: no server random");
996 return(NULL);
998 server_certificate = g_hash_table_lookup(state->data, "Certificate");
999 /* Server Certificate is VECTOR_MAX24 of VECTOR_MAX24s */
1000 if (!server_certificate || (server_certificate->length < 3)) {
1001 SIPE_DEBUG_ERROR_NOFORMAT("tls_client_key_exchange: no server certificate");
1002 return(FALSE);
1004 SIPE_DEBUG_INFO("tls_client_key_exchange: server certificate list %" G_GSIZE_FORMAT" bytes",
1005 server_certificate->length);
1006 /* first certificate is the server certificate */
1007 server_certificate_length = lowlevel_integer_to_host(server_certificate->data,
1009 SIPE_DEBUG_INFO("tls_client_key_exchange: server certificate %" G_GSIZE_FORMAT" bytes",
1010 server_certificate_length);
1011 if ((server_certificate_length + 3) > server_certificate->length) {
1012 SIPE_DEBUG_ERROR_NOFORMAT("tls_client_key_exchange: truncated server certificate");
1014 state->server_certificate = sipe_cert_crypto_import(server_certificate->data + 3,
1015 server_certificate_length);
1016 if (!state->server_certificate) {
1017 SIPE_DEBUG_ERROR_NOFORMAT("tls_client_key_exchange: corrupted server certificate");
1018 return(FALSE);
1020 /* server public key modulus length */
1021 server_certificate_length = sipe_cert_crypto_modulus_length(state->server_certificate);
1022 if (server_certificate_length < TLS_ARRAY_MASTER_SECRET_LENGTH) {
1023 SIPE_DEBUG_ERROR("tls_client_key_exchange: server public key strength too low (%" G_GSIZE_FORMAT ")",
1024 server_certificate_length);
1025 return(FALSE);
1027 SIPE_DEBUG_INFO("tls_client_key_exchange: server public key strength = %" G_GSIZE_FORMAT,
1028 server_certificate_length);
1030 /* found all the required fields */
1031 state->server_random.length = server_random->length;
1032 state->server_random.buffer = g_memdup(server_random->data,
1033 server_random->length);
1035 /* Calculate master secret */
1036 sipe_svc_fill_random(&pre_master_secret,
1037 TLS_ARRAY_MASTER_SECRET_LENGTH * 8); /* bits */
1038 lowlevel_integer_to_tls(pre_master_secret.buffer, 2,
1039 TLS_PROTOCOL_VERSION_1_0);
1040 random = g_malloc(TLS_ARRAY_RANDOM_LENGTH * 2);
1041 memcpy(random,
1042 state->client_random.buffer,
1043 TLS_ARRAY_RANDOM_LENGTH);
1044 memcpy(random + TLS_ARRAY_RANDOM_LENGTH,
1045 state->server_random.buffer,
1046 TLS_ARRAY_RANDOM_LENGTH);
1048 * master_secret = PRF(pre_master_secret, "master secret",
1049 * ClientHello.random + ServerHello.random)
1051 state->master_secret = sipe_tls_prf(pre_master_secret.buffer,
1052 pre_master_secret.length,
1053 (guchar *) "master secret",
1055 random,
1056 TLS_ARRAY_RANDOM_LENGTH * 2,
1057 TLS_ARRAY_MASTER_SECRET_LENGTH);
1058 g_free(random);
1059 if (state->debug) {
1060 guint i = TLS_ARRAY_MASTER_SECRET_LENGTH;
1061 guchar *p = state->master_secret;
1062 g_string_append(state->debug, "tls_client_key_exchange: master secret ");
1063 while (i--) g_string_append_printf(state->debug, "%02X", *p++);
1064 SIPE_DEBUG_INFO_NOFORMAT(state->debug->str);
1065 g_string_truncate(state->debug, 0);
1068 /* ClientKeyExchange */
1069 exchange = g_malloc0(sizeof(struct ClientKeyExchange_host) +
1070 server_certificate_length);
1071 exchange->secret.elements = server_certificate_length;
1072 if (!sipe_crypt_rsa_encrypt(sipe_cert_crypto_public_key(state->server_certificate),
1073 TLS_ARRAY_MASTER_SECRET_LENGTH,
1074 pre_master_secret.buffer,
1075 (guchar *) exchange->secret.placeholder)) {
1076 SIPE_DEBUG_ERROR_NOFORMAT("tls_client_key_exchange: encryption of pre-master secret failed");
1077 sipe_svc_free_random(&pre_master_secret);
1078 g_free(exchange);
1079 return(NULL);
1081 sipe_svc_free_random(&pre_master_secret);
1083 msg = compile_handshake_msg(state, &ClientKeyExchange_m, exchange,
1084 sizeof(struct ClientKeyExchange_host) + server_certificate_length);
1085 g_free(exchange);
1087 return(msg);
1090 static struct tls_compiled_message *tls_certificate_verify(struct tls_internal_state *state)
1092 struct CertificateVerify_host *verify;
1093 struct tls_compiled_message *msg;
1094 guchar *digests = g_malloc(SIPE_DIGEST_MD5_LENGTH + SIPE_DIGEST_SHA1_LENGTH);
1095 guchar *signature;
1096 gsize length;
1098 /* calculate digests */
1099 sipe_digest_md5_end(state->md5_context, digests);
1100 sipe_digest_sha1_end(state->sha1_context, digests + SIPE_DIGEST_MD5_LENGTH);
1102 /* sign digests */
1103 signature = sipe_crypt_rsa_sign(sipe_cert_crypto_private_key(state->certificate),
1104 digests,
1105 SIPE_DIGEST_MD5_LENGTH + SIPE_DIGEST_SHA1_LENGTH,
1106 &length);
1107 g_free(digests);
1108 if (!signature) {
1109 SIPE_DEBUG_ERROR_NOFORMAT("tls_certificate_verify: signing of handshake digests failed");
1110 return(NULL);
1113 /* CertificateVerify */
1114 verify = g_malloc0(sizeof(struct CertificateVerify_host) +
1115 length);
1116 verify->signature.elements = length;
1117 memcpy(verify->signature.placeholder, signature, length);
1119 msg = compile_handshake_msg(state, &CertificateVerify_m, verify,
1120 sizeof(struct CertificateVerify_host) + length);
1121 g_free(verify);
1123 return(msg);
1126 static struct tls_compiled_message *tls_client_finished(struct tls_internal_state *state)
1128 guchar *digests = g_malloc(SIPE_DIGEST_MD5_LENGTH + SIPE_DIGEST_SHA1_LENGTH);
1129 guchar *verify;
1130 struct tls_compiled_message *cmsg;
1131 struct Finished_host msg;
1133 /* calculate digests */
1134 sipe_digest_md5_end(state->md5_context, digests);
1135 sipe_digest_sha1_end(state->sha1_context, digests + SIPE_DIGEST_MD5_LENGTH);
1138 * verify_data = PRF(master_secret, "client finished",
1139 * MD5(handshake_messages) +
1140 * SHA-1(handshake_messages)) [0..11];
1142 verify = sipe_tls_prf(state->master_secret,
1143 TLS_ARRAY_MASTER_SECRET_LENGTH,
1144 (guchar *) "client finished",
1146 digests,
1147 SIPE_DIGEST_MD5_LENGTH + SIPE_DIGEST_SHA1_LENGTH,
1148 TLS_ARRAY_VERIFY_LENGTH);
1149 g_free(digests);
1150 memcpy(msg.verify.verify, verify, TLS_ARRAY_VERIFY_LENGTH);
1151 g_free(verify);
1153 cmsg = compile_handshake_msg(state, &Finished_m, &msg, sizeof(msg));
1155 return(cmsg);
1159 * TLS state handling
1162 static gboolean tls_client_hello(struct tls_internal_state *state)
1164 guint32 now = time(NULL);
1165 guint32 now_N = GUINT32_TO_BE(now);
1166 struct ClientHello_host msg = {
1167 { TLS_PROTOCOL_VERSION_1_0 },
1168 { 0, { } },
1169 { 0 /* empty SessionID */ },
1170 { 3,
1172 TLS_RSA_WITH_RC4_128_MD5,
1173 TLS_RSA_WITH_RC4_128_SHA,
1174 TLS_RSA_EXPORT_WITH_RC4_40_MD5
1177 { 1,
1179 TLS_COMP_METHOD_NULL
1183 struct tls_compiled_message *cmsg;
1185 /* First 4 bytes of client_random is the current timestamp */
1186 sipe_svc_fill_random(&state->client_random,
1187 TLS_ARRAY_RANDOM_LENGTH * 8); /* -> bits */
1188 memcpy(state->client_random.buffer, &now_N, sizeof(now_N));
1189 memcpy(msg.random.random, state->client_random.buffer,
1190 TLS_ARRAY_RANDOM_LENGTH);
1192 cmsg = compile_handshake_msg(state, &ClientHello_m, &msg, sizeof(msg));
1193 compile_tls_record(state, cmsg, NULL);
1194 g_free(cmsg);
1196 if (sipe_backend_debug_enabled())
1197 state->debug = g_string_new("");
1199 state->state = TLS_HANDSHAKE_STATE_SERVER_HELLO;
1200 return(tls_record_parse(state, FALSE));
1203 static gboolean tls_server_hello(struct tls_internal_state *state)
1205 struct tls_compiled_message *certificate = NULL;
1206 struct tls_compiled_message *exchange = NULL;
1207 struct tls_compiled_message *verify = NULL;
1208 struct tls_compiled_message *finished = NULL;
1209 gboolean success = FALSE;
1211 if (!tls_record_parse(state, TRUE))
1212 return(FALSE);
1214 if (((certificate = tls_client_certificate(state)) != NULL) &&
1215 ((exchange = tls_client_key_exchange(state)) != NULL) &&
1216 ((verify = tls_certificate_verify(state)) != NULL) &&
1217 ((finished = tls_client_finished(state)) != NULL)) {
1219 /* Part 1 */
1220 compile_tls_record(state, certificate, exchange, verify, NULL);
1222 success = tls_record_parse(state, FALSE);
1223 if (success) {
1224 guchar *part1 = state->common.out_buffer;
1225 gsize part1_length = state->common.out_length;
1227 state->common.out_buffer = NULL;
1229 /* Part 3 */
1230 compile_tls_record(state, finished, NULL);
1231 /* TBD: part 3 needs to be encrypted! */
1233 success = tls_record_parse(state, FALSE);
1234 if (success) {
1235 guchar *part3 = state->common.out_buffer;
1236 gsize part3_length = state->common.out_length;
1237 /* ChangeCipherSpec is always the same */
1238 static const guchar const part2[] = {
1239 TLS_RECORD_TYPE_CHANGE_CIPHER_SPEC,
1240 (TLS_PROTOCOL_VERSION_1_0 >> 8) & 0xFF,
1241 TLS_PROTOCOL_VERSION_1_0 & 0xFF,
1242 0x00, 0x01, /* length: 1 byte */
1243 0x01 /* change_cipher_spec(1) */
1245 gsize length = part1_length +
1246 sizeof(part2) +
1247 part3_length;
1248 guchar *merged = g_malloc(length);
1250 /* merge TLS records */
1251 memcpy(merged, part1, part1_length);
1252 memcpy(merged + part1_length, part2, sizeof(part2));
1253 memcpy(merged + part1_length + sizeof(part2), part3, part3_length);
1254 g_free(part3);
1256 /* replace output buffer with merged message */
1257 state->common.out_buffer = merged;
1258 state->common.out_length = length;
1260 state->state = TLS_HANDSHAKE_STATE_FINISHED;
1263 g_free(part1);
1267 g_free(finished);
1268 g_free(verify);
1269 g_free(exchange);
1270 g_free(certificate);
1271 free_parse_data(state);
1273 return(success);
1276 static gboolean tls_finished(struct tls_internal_state *state)
1278 if (!tls_record_parse(state, TRUE))
1279 return(FALSE);
1281 /* TBD: data is really not needed? */
1282 free_parse_data(state);
1284 state->common.out_buffer = NULL;
1285 state->common.out_length = 0;
1286 state->state = TLS_HANDSHAKE_STATE_COMPLETED;
1288 /* temporary */
1289 return(TRUE);
1293 * TLS public API
1296 struct sipe_tls_state *sipe_tls_start(gpointer certificate)
1298 struct tls_internal_state *state;
1300 if (!certificate)
1301 return(NULL);
1303 state = g_new0(struct tls_internal_state, 1);
1304 state->certificate = certificate;
1305 state->state = TLS_HANDSHAKE_STATE_START;
1306 state->md5_context = sipe_digest_md5_start();
1307 state->sha1_context = sipe_digest_sha1_start();
1309 return((struct sipe_tls_state *) state);
1312 gboolean sipe_tls_next(struct sipe_tls_state *state)
1314 struct tls_internal_state *internal = (struct tls_internal_state *) state;
1315 gboolean success = FALSE;
1317 if (!state)
1318 return(FALSE);
1320 state->out_buffer = NULL;
1322 switch (internal->state) {
1323 case TLS_HANDSHAKE_STATE_START:
1324 success = tls_client_hello(internal);
1325 break;
1327 case TLS_HANDSHAKE_STATE_SERVER_HELLO:
1328 success = tls_server_hello(internal);
1329 break;
1331 case TLS_HANDSHAKE_STATE_FINISHED:
1332 success = tls_finished(internal);
1333 break;
1335 case TLS_HANDSHAKE_STATE_COMPLETED:
1336 case TLS_HANDSHAKE_STATE_FAILED:
1337 /* This should not happen */
1338 SIPE_DEBUG_ERROR_NOFORMAT("sipe_tls_next: called in incorrect state!");
1339 break;
1342 if (!success) {
1343 internal->state = TLS_HANDSHAKE_STATE_FAILED;
1346 return(success);
1349 void sipe_tls_free(struct sipe_tls_state *state)
1351 if (state) {
1352 struct tls_internal_state *internal = (struct tls_internal_state *) state;
1354 free_parse_data(internal);
1355 if (internal->debug)
1356 g_string_free(internal->debug, TRUE);
1357 sipe_svc_free_random(&internal->client_random);
1358 sipe_svc_free_random(&internal->server_random);
1359 if (internal->md5_context)
1360 sipe_digest_md5_destroy(internal->md5_context);
1361 if (internal->sha1_context)
1362 sipe_digest_sha1_destroy(internal->sha1_context);
1363 sipe_cert_crypto_destroy(internal->server_certificate);
1364 g_free(state->session_key);
1365 g_free(state->out_buffer);
1366 g_free(state);
1371 Local Variables:
1372 mode: c
1373 c-file-style: "bsd"
1374 indent-tabs-mode: t
1375 tab-width: 8
1376 End: