tls: encrypt Finished message
[siplcs.git] / src / core / sipe-tls.c
blob674118a3b4beaccaf35b49970bb8d9577d9e5c79
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 struct sipe_svc_random client_random;
73 struct sipe_svc_random server_random;
74 struct sipe_svc_random pre_master_secret;
75 gsize mac_length;
76 gsize key_length;
77 guchar *master_secret;
78 guchar *key_block;
79 const guchar *client_write_mac_secret;
80 const guchar *server_write_mac_secret;
81 const guchar *client_write_secret;
82 const guchar *server_write_secret;
83 void (*mac_func)(const guchar *key, gsize key_length,
84 const guchar *data, gsize data_length,
85 guchar *digest);
86 gpointer cipher_context;
87 guint64 sequence_number;
91 * TLS messages & layout descriptors
94 /* constants */
95 #define TLS_VECTOR_MAX8 255 /* 2^8 - 1 */
96 #define TLS_VECTOR_MAX16 65535 /* 2^16 - 1 */
97 #define TLS_VECTOR_MAX24 16777215 /* 2^24 - 1 */
99 #define TLS_PROTOCOL_VERSION_1_0 0x0301
100 #define TLS_PROTOCOL_VERSION_1_1 0x0302
102 /* CipherSuites */
103 #define TLS_RSA_EXPORT_WITH_RC4_40_MD5 0x0003
104 #define TLS_RSA_WITH_RC4_128_MD5 0x0004
105 #define TLS_RSA_WITH_RC4_128_SHA 0x0005
107 /* CompressionMethods */
108 #define TLS_COMP_METHOD_NULL 0
110 /* various array lengths */
111 #define TLS_ARRAY_RANDOM_LENGTH 32
112 #define TLS_ARRAY_MASTER_SECRET_LENGTH 48
113 #define TLS_ARRAY_VERIFY_LENGTH 12
115 #define TLS_RECORD_HEADER_LENGTH 5
116 #define TLS_RECORD_OFFSET_TYPE 0
117 #define TLS_RECORD_TYPE_CHANGE_CIPHER_SPEC 20
118 #define TLS_RECORD_TYPE_HANDSHAKE 22
119 #define TLS_RECORD_OFFSET_VERSION 1
120 #define TLS_RECORD_OFFSET_LENGTH 3
122 #define TLS_HANDSHAKE_HEADER_LENGTH 4
123 #define TLS_HANDSHAKE_OFFSET_TYPE 0
124 #define TLS_HANDSHAKE_TYPE_CLIENT_HELLO 1
125 #define TLS_HANDSHAKE_TYPE_SERVER_HELLO 2
126 #define TLS_HANDSHAKE_TYPE_CERTIFICATE 11
127 #define TLS_HANDSHAKE_TYPE_CERTIFICATE_REQ 13
128 #define TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE 14
129 #define TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY 15
130 #define TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE 16
131 #define TLS_HANDSHAKE_TYPE_FINISHED 20
132 #define TLS_HANDSHAKE_OFFSET_LENGTH 1
134 struct layout_descriptor;
135 typedef gboolean parse_func(struct tls_internal_state *state,
136 const struct layout_descriptor *desc);
138 /* Defines the strictest alignment requirement */
139 struct tls_compile_integer;
140 typedef void compile_func(struct tls_internal_state *state,
141 const struct layout_descriptor *desc,
142 const struct tls_compile_integer *data);
144 struct layout_descriptor {
145 const gchar *label;
146 parse_func *parser;
147 compile_func *compiler;
148 gsize min; /* 0 for fixed/array */
149 gsize max;
150 gsize offset;
153 #define TLS_LAYOUT_DESCRIPTOR_END { NULL, NULL, NULL, 0, 0, 0 }
154 #define TLS_LAYOUT_IS_VALID(desc) (desc->label)
156 struct msg_descriptor {
157 const struct msg_descriptor *next;
158 const gchar *description;
159 const struct layout_descriptor *layouts;
160 guint type;
163 /* parsed data */
164 struct tls_parsed_integer {
165 guint value;
168 struct tls_parsed_array {
169 gsize length; /* bytes */
170 const guchar data[0];
173 /* compile data */
174 struct tls_compile_integer {
175 gsize value;
178 struct tls_compile_array {
179 gsize elements; /* unused */
180 guchar placeholder[];
183 struct tls_compile_random {
184 gsize elements; /* unused */
185 guchar random[TLS_ARRAY_RANDOM_LENGTH];
188 struct tls_compile_verify {
189 gsize elements; /* unused */
190 guchar verify[TLS_ARRAY_VERIFY_LENGTH];
193 struct tls_compile_vector {
194 gsize elements; /* VECTOR */
195 guint placeholder[];
198 struct tls_compile_sessionid {
199 gsize elements; /* VECTOR */
202 struct tls_compile_cipher {
203 gsize elements; /* VECTOR */
204 guint suites[3];
207 struct tls_compile_compression {
208 gsize elements; /* VECTOR */
209 guint methods[1];
212 /* compiled message */
213 struct tls_compiled_message {
214 gsize size;
215 guchar data[];
219 * TLS message debugging
221 static void debug_hex(struct tls_internal_state *state,
222 gsize alternative_length)
224 GString *str = state->debug;
225 const guchar *bytes;
226 gsize length;
227 gint count;
229 if (!str) return;
231 bytes = state->msg_current;
232 length = alternative_length ? alternative_length : state->msg_remainder;
233 count = -1;
235 while (length-- > 0) {
236 if (++count == 0) {
237 /* do nothing */;
238 } else if ((count % 16) == 0) {
239 g_string_append(str, "\n");
240 } else if ((count % 8) == 0) {
241 g_string_append(str, " ");
243 g_string_append_printf(str, " %02X", *bytes++);
245 g_string_append(str, "\n");
248 #define debug_print(state, string) \
249 if (state->debug) g_string_append(state->debug, string)
250 #define debug_printf(state, format, ...) \
251 if (state->debug) g_string_append_printf(state->debug, format, __VA_ARGS__)
254 * TLS Pseudorandom Function (PRF) - RFC2246, Section 5
256 static guchar *sipe_tls_p_md5(const guchar *secret,
257 gsize secret_length,
258 const guchar *seed,
259 gsize seed_length,
260 gsize output_length)
262 guchar *output = NULL;
265 * output_length == 0 -> illegal
266 * output_length == 1..16 -> iterations = 1
267 * output_length == 17..32 -> iterations = 2
269 if (secret && seed && (output_length > 0)) {
270 guint iterations = (output_length + SIPE_DIGEST_HMAC_MD5_LENGTH - 1) / SIPE_DIGEST_HMAC_MD5_LENGTH;
271 guchar *concat = g_malloc(SIPE_DIGEST_HMAC_MD5_LENGTH + seed_length);
272 guchar A[SIPE_DIGEST_HMAC_MD5_LENGTH];
273 guchar *p;
275 SIPE_DEBUG_INFO("p_md5: secret %" G_GSIZE_FORMAT " bytes, seed %" G_GSIZE_FORMAT " bytes",
276 secret_length, seed_length);
277 SIPE_DEBUG_INFO("p_md5: output %" G_GSIZE_FORMAT " bytes -> %d iterations",
278 output_length, iterations);
280 /* A(1) = HMAC_MD5(secret, A(0)), A(0) = seed */
281 sipe_digest_hmac_md5(secret, secret_length,
282 seed, seed_length,
285 /* Each iteration adds SIPE_DIGEST_HMAC_MD5_LENGTH bytes */
286 p = output = g_malloc(iterations * SIPE_DIGEST_HMAC_MD5_LENGTH);
288 while (iterations-- > 0) {
289 /* P_MD5(i) = HMAC_MD5(secret, A(i) + seed), i = 1, 2, ... */
290 guchar P[SIPE_DIGEST_HMAC_MD5_LENGTH];
291 memcpy(concat, A, SIPE_DIGEST_HMAC_MD5_LENGTH);
292 memcpy(concat + SIPE_DIGEST_HMAC_MD5_LENGTH, seed, seed_length);
293 sipe_digest_hmac_md5(secret, secret_length,
294 concat, SIPE_DIGEST_HMAC_MD5_LENGTH + seed_length,
296 memcpy(p, P, SIPE_DIGEST_HMAC_MD5_LENGTH);
297 p += SIPE_DIGEST_HMAC_MD5_LENGTH;
299 /* A(i+1) = HMAC_MD5(secret, A(i)) */
300 sipe_digest_hmac_md5(secret, secret_length,
301 A, SIPE_DIGEST_HMAC_MD5_LENGTH,
304 g_free(concat);
307 return(output);
310 guchar *sipe_tls_p_sha1(const guchar *secret,
311 gsize secret_length,
312 const guchar *seed,
313 gsize seed_length,
314 gsize output_length)
316 guchar *output = NULL;
319 * output_length == 0 -> illegal
320 * output_length == 1..20 -> iterations = 1
321 * output_length == 21..40 -> iterations = 2
323 if (secret && seed && (output_length > 0)) {
324 guint iterations = (output_length + SIPE_DIGEST_HMAC_SHA1_LENGTH - 1) / SIPE_DIGEST_HMAC_SHA1_LENGTH;
325 guchar *concat = g_malloc(SIPE_DIGEST_HMAC_SHA1_LENGTH + seed_length);
326 guchar A[SIPE_DIGEST_HMAC_SHA1_LENGTH];
327 guchar *p;
329 SIPE_DEBUG_INFO("p_sha1: secret %" G_GSIZE_FORMAT " bytes, seed %" G_GSIZE_FORMAT " bytes",
330 secret_length, seed_length);
331 SIPE_DEBUG_INFO("p_sha1: output %" G_GSIZE_FORMAT " bytes -> %d iterations",
332 output_length, iterations);
334 /* A(1) = HMAC_SHA1(secret, A(0)), A(0) = seed */
335 sipe_digest_hmac_sha1(secret, secret_length,
336 seed, seed_length,
339 /* Each iteration adds SIPE_DIGEST_HMAC_SHA1_LENGTH bytes */
340 p = output = g_malloc(iterations * SIPE_DIGEST_HMAC_SHA1_LENGTH);
342 while (iterations-- > 0) {
343 /* P_SHA1(i) = HMAC_SHA1(secret, A(i) + seed), i = 1, 2, ... */
344 guchar P[SIPE_DIGEST_HMAC_SHA1_LENGTH];
345 memcpy(concat, A, SIPE_DIGEST_HMAC_SHA1_LENGTH);
346 memcpy(concat + SIPE_DIGEST_HMAC_SHA1_LENGTH, seed, seed_length);
347 sipe_digest_hmac_sha1(secret, secret_length,
348 concat, SIPE_DIGEST_HMAC_SHA1_LENGTH + seed_length,
350 memcpy(p, P, SIPE_DIGEST_HMAC_SHA1_LENGTH);
351 p += SIPE_DIGEST_HMAC_SHA1_LENGTH;
353 /* A(i+1) = HMAC_SHA1(secret, A(i)) */
354 sipe_digest_hmac_sha1(secret, secret_length,
355 A, SIPE_DIGEST_HMAC_SHA1_LENGTH,
358 g_free(concat);
361 return(output);
364 static guchar *sipe_tls_prf(const guchar *secret,
365 gsize secret_length,
366 const guchar *label,
367 gsize label_length,
368 const guchar *seed,
369 gsize seed_length,
370 gsize output_length)
372 gsize half = (secret_length + 1) / 2;
373 gsize newseed_length = label_length + seed_length;
374 /* secret: used as S1; secret2: last half of original secret (S2) */
375 guchar *secret2 = g_memdup(secret + secret_length - half, half);
376 guchar *newseed = g_malloc(newseed_length);
377 guchar *md5, *dest;
378 guchar *sha1, *src;
381 * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
382 * P_SHA-1(S2, label + seed);
384 memcpy(newseed, label, label_length);
385 memcpy(newseed + label_length, seed, seed_length);
386 md5 = sipe_tls_p_md5(secret, half, newseed, newseed_length, output_length);
387 sha1 = sipe_tls_p_sha1(secret2, half, newseed, newseed_length, output_length);
388 for (dest = md5, src = sha1;
389 output_length > 0;
390 output_length--)
391 *dest++ ^= *src++;
393 g_free(sha1);
394 g_free(newseed);
395 g_free(secret2);
397 return(md5);
401 * TLS data parsers
403 * Low-level data conversion routines
405 * - host alignment agnostic, i.e. can fetch a word from uneven address
406 * - TLS -> host endianess conversion
407 * - no length check, caller has to do it
408 * - don't modify state
410 static guint lowlevel_integer_to_host(const guchar *bytes,
411 gsize length)
413 guint sum = 0;
414 while (length--) sum = (sum << 8) + *bytes++;
415 return(sum);
419 * Generic data type parser routines
421 static gboolean msg_remainder_check(struct tls_internal_state *state,
422 const gchar *label,
423 gsize length)
425 if (length > state->msg_remainder) {
426 SIPE_DEBUG_ERROR("msg_remainder_check: '%s' expected %" G_GSIZE_FORMAT " bytes, remaining %" G_GSIZE_FORMAT,
427 label, length, state->msg_remainder);
428 return(FALSE);
430 return(TRUE);
433 static gboolean parse_integer_quiet(struct tls_internal_state *state,
434 const gchar *label,
435 gsize length,
436 guint *result)
438 if (!msg_remainder_check(state, label, length)) return(FALSE);
439 *result = lowlevel_integer_to_host(state->msg_current, length);
440 state->msg_current += length;
441 state->msg_remainder -= length;
442 return(TRUE);
445 static gboolean parse_integer(struct tls_internal_state *state,
446 const struct layout_descriptor *desc)
448 guint value;
449 if (!parse_integer_quiet(state, desc->label, desc->max, &value))
450 return(FALSE);
451 debug_printf(state, "%s/INTEGER%" G_GSIZE_FORMAT " = %d\n",
452 desc->label, desc->max, value);
453 if (state->data) {
454 struct tls_parsed_integer *save = g_new0(struct tls_parsed_integer, 1);
455 save->value = value;
456 g_hash_table_insert(state->data, (gpointer) desc->label, save);
458 return(TRUE);
461 static gboolean parse_array(struct tls_internal_state *state,
462 const struct layout_descriptor *desc)
464 if (!msg_remainder_check(state, desc->label, desc->max))
465 return(FALSE);
466 debug_printf(state, "%s/ARRAY[%" G_GSIZE_FORMAT "]\n",
467 desc->label, desc->max);
468 if (state->data) {
469 struct tls_parsed_array *save = g_malloc0(sizeof(struct tls_parsed_array) +
470 desc->max);
471 save->length = desc->max;
472 memcpy((guchar *)save->data, state->msg_current, desc->max);
473 g_hash_table_insert(state->data, (gpointer) desc->label, save);
476 state->msg_current += desc->max;
477 state->msg_remainder -= desc->max;
478 return(TRUE);
481 static gboolean parse_vector(struct tls_internal_state *state,
482 const struct layout_descriptor *desc)
484 guint length;
485 if (!parse_integer_quiet(state, desc->label,
486 (desc->max > TLS_VECTOR_MAX16) ? 3 :
487 (desc->max > TLS_VECTOR_MAX8) ? 2 : 1,
488 &length))
489 return(FALSE);
490 if (length < desc->min) {
491 SIPE_DEBUG_ERROR("parse_vector: '%s' too short %d, expected %" G_GSIZE_FORMAT,
492 desc->label, length, desc->min);
493 return(FALSE);
495 debug_printf(state, "%s/VECTOR<%d>\n", desc->label, length);
496 if (state->data) {
497 struct tls_parsed_array *save = g_malloc0(sizeof(struct tls_parsed_array) +
498 length);
499 save->length = length;
500 memcpy((guchar *)save->data, state->msg_current, length);
501 g_hash_table_insert(state->data, (gpointer) desc->label, save);
503 state->msg_current += length;
504 state->msg_remainder -= length;
505 return(TRUE);
509 * Specific data type parser routines
512 /* TBD... */
515 * TLS data compilers
517 * Low-level data conversion routines
519 * - host alignment agnostic, i.e. can fetch a word from uneven address
520 * - host -> TLS host endianess conversion
521 * - don't modify state
523 static void lowlevel_integer_to_tls(guchar *bytes,
524 gsize length,
525 guint value)
527 while (length--) {
528 bytes[length] = value & 0xFF;
529 value >>= 8;
534 * Generic data type compiler routines
536 static void compile_integer(struct tls_internal_state *state,
537 const struct layout_descriptor *desc,
538 const struct tls_compile_integer *data)
540 lowlevel_integer_to_tls(state->msg_current, desc->max, data->value);
541 state->msg_current += desc->max;
544 static void compile_array(struct tls_internal_state *state,
545 const struct layout_descriptor *desc,
546 const struct tls_compile_integer *data)
548 const struct tls_compile_array *array = (struct tls_compile_array *) data;
549 memcpy(state->msg_current, array->placeholder, desc->max);
550 state->msg_current += desc->max;
553 static void compile_vector(struct tls_internal_state *state,
554 const struct layout_descriptor *desc,
555 const struct tls_compile_integer *data)
557 const struct tls_compile_vector *vector = (struct tls_compile_vector *) data;
558 gsize length = vector->elements;
559 gsize length_field = (desc->max > TLS_VECTOR_MAX16) ? 3 :
560 (desc->max > TLS_VECTOR_MAX8) ? 2 : 1;
562 lowlevel_integer_to_tls(state->msg_current, length_field, length);
563 state->msg_current += length_field;
564 memcpy(state->msg_current, vector->placeholder, length);
565 state->msg_current += length;
568 static void compile_vector_int2(struct tls_internal_state *state,
569 const struct layout_descriptor *desc,
570 const struct tls_compile_integer *data)
572 const struct tls_compile_vector *vector = (struct tls_compile_vector *) data;
573 gsize elements = vector->elements;
574 gsize length = elements * sizeof(guint16);
575 gsize length_field = (desc->max > TLS_VECTOR_MAX16) ? 3 :
576 (desc->max > TLS_VECTOR_MAX8) ? 2 : 1;
577 const guint *p = vector->placeholder;
579 lowlevel_integer_to_tls(state->msg_current, length_field, length);
580 state->msg_current += length_field;
581 while (elements--) {
582 lowlevel_integer_to_tls(state->msg_current, sizeof(guint16), *p++);
583 state->msg_current += sizeof(guint16);
588 * Specific data type compiler routines
591 /* TBD... */
594 * TLS handshake message layout descriptors
596 struct ClientHello_host {
597 struct tls_compile_integer protocol_version;
598 struct tls_compile_random random;
599 struct tls_compile_sessionid sessionid;
600 struct tls_compile_cipher cipher;
601 struct tls_compile_compression compression;
603 #define CLIENTHELLO_OFFSET(a) offsetof(struct ClientHello_host, a)
605 static const struct layout_descriptor const ClientHello_l[] = {
606 { "Client Protocol Version", parse_integer, compile_integer, 0, 2, CLIENTHELLO_OFFSET(protocol_version) },
607 { "Random", parse_array, compile_array, 0, TLS_ARRAY_RANDOM_LENGTH, CLIENTHELLO_OFFSET(random) },
608 { "SessionID", parse_vector, compile_vector, 0, 32, CLIENTHELLO_OFFSET(sessionid) },
609 { "CipherSuite", parse_vector, compile_vector_int2, 2, TLS_VECTOR_MAX16, CLIENTHELLO_OFFSET(cipher)},
610 { "CompressionMethod", parse_vector, compile_vector, 1, TLS_VECTOR_MAX8, CLIENTHELLO_OFFSET(compression) },
611 TLS_LAYOUT_DESCRIPTOR_END
613 static const struct msg_descriptor const ClientHello_m = {
614 NULL, "Client Hello", ClientHello_l, TLS_HANDSHAKE_TYPE_CLIENT_HELLO
617 static const struct layout_descriptor const ServerHello_l[] = {
618 { "Server Protocol Version", parse_integer, NULL, 0, 2, 0 },
619 { "Random", parse_array, NULL, 0, TLS_ARRAY_RANDOM_LENGTH, 0 },
620 { "SessionID", parse_vector, NULL, 0, 32, 0 },
621 { "CipherSuite", parse_integer, NULL, 0, 2, 0 },
622 { "CompressionMethod", parse_integer, NULL, 0, 1, 0 },
623 TLS_LAYOUT_DESCRIPTOR_END
625 static const struct msg_descriptor const ServerHello_m = {
626 &ClientHello_m, "Server Hello", ServerHello_l, TLS_HANDSHAKE_TYPE_SERVER_HELLO
629 struct Certificate_host {
630 struct tls_compile_vector certificate;
632 #define CERTIFICATE_OFFSET(a) offsetof(struct Certificate_host, a)
634 static const struct layout_descriptor const Certificate_l[] = {
635 { "Certificate", parse_vector, compile_vector, 0, TLS_VECTOR_MAX24, CERTIFICATE_OFFSET(certificate) },
636 TLS_LAYOUT_DESCRIPTOR_END
638 static const struct msg_descriptor const Certificate_m = {
639 &ServerHello_m, "Certificate", Certificate_l, TLS_HANDSHAKE_TYPE_CERTIFICATE
642 static const struct layout_descriptor const CertificateRequest_l[] = {
643 { "CertificateType", parse_vector, NULL, 1, TLS_VECTOR_MAX8, 0 },
644 { "DistinguishedName", parse_vector, NULL, 0, TLS_VECTOR_MAX16, 0 },
645 TLS_LAYOUT_DESCRIPTOR_END
647 static const struct msg_descriptor const CertificateRequest_m = {
648 &Certificate_m, "Certificate Request", CertificateRequest_l, TLS_HANDSHAKE_TYPE_CERTIFICATE_REQ
651 static const struct layout_descriptor const ServerHelloDone_l[] = {
652 TLS_LAYOUT_DESCRIPTOR_END
654 static const struct msg_descriptor const ServerHelloDone_m = {
655 &CertificateRequest_m, "Server Hello Done", ServerHelloDone_l, TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE
658 struct ClientKeyExchange_host {
659 struct tls_compile_vector secret;
661 #define CLIENTKEYEXCHANGE_OFFSET(a) offsetof(struct ClientKeyExchange_host, a)
663 static const struct layout_descriptor const ClientKeyExchange_l[] = {
664 { "Exchange Keys", parse_vector, compile_vector, 0, TLS_VECTOR_MAX16, CLIENTKEYEXCHANGE_OFFSET(secret) },
665 TLS_LAYOUT_DESCRIPTOR_END
667 static const struct msg_descriptor const ClientKeyExchange_m = {
668 &ServerHelloDone_m, "Client Key Exchange", ClientKeyExchange_l, TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE
671 struct CertificateVerify_host {
672 struct tls_compile_vector signature;
674 #define CERTIFICATEVERIFY_OFFSET(a) offsetof(struct CertificateVerify_host, a)
676 static const struct layout_descriptor const CertificateVerify_l[] = {
677 { "Signature", parse_vector, compile_vector, 0, TLS_VECTOR_MAX16, CERTIFICATEVERIFY_OFFSET(signature) },
678 TLS_LAYOUT_DESCRIPTOR_END
680 static const struct msg_descriptor const CertificateVerify_m = {
681 &ClientKeyExchange_m, "Certificate Verify", CertificateVerify_l, TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY
684 struct Finished_host {
685 struct tls_compile_verify verify;
687 #define FINISHED_OFFSET(a) offsetof(struct Finished_host, a)
689 static const struct layout_descriptor const Finished_l[] = {
690 { "Verify Data", parse_array, compile_array, 0, TLS_ARRAY_VERIFY_LENGTH, FINISHED_OFFSET(verify) },
691 TLS_LAYOUT_DESCRIPTOR_END
693 static const struct msg_descriptor const Finished_m = {
694 &CertificateVerify_m, "Finished", Finished_l, TLS_HANDSHAKE_TYPE_FINISHED
697 #define HANDSHAKE_MSG_DESCRIPTORS &Finished_m
700 * TLS message parsers
702 static gboolean handshake_parse(struct tls_internal_state *state)
704 const guchar *bytes = state->msg_current;
705 gsize length = state->msg_remainder;
706 gboolean success = FALSE;
708 while (length > 0) {
709 const struct msg_descriptor *desc;
710 gsize msg_length;
711 guint msg_type;
713 /* header check */
714 if (length < TLS_HANDSHAKE_HEADER_LENGTH) {
715 debug_print(state, "CORRUPTED HANDSHAKE HEADER");
716 break;
719 /* msg length check */
720 msg_length = lowlevel_integer_to_host(bytes + TLS_HANDSHAKE_OFFSET_LENGTH,
722 if (msg_length > length) {
723 debug_print(state, "HANDSHAKE MESSAGE TOO LONG");
724 break;
727 /* msg type */
728 msg_type = bytes[TLS_HANDSHAKE_OFFSET_TYPE];
729 for (desc = HANDSHAKE_MSG_DESCRIPTORS;
730 desc;
731 desc = desc->next)
732 if (msg_type == desc->type)
733 break;
735 debug_printf(state, "TLS handshake (%" G_GSIZE_FORMAT " bytes) (%d)",
736 msg_length, msg_type);
738 state->msg_current = (guchar *) bytes + TLS_HANDSHAKE_HEADER_LENGTH;
739 state->msg_remainder = msg_length;
741 if (desc->layouts) {
742 const struct layout_descriptor *ldesc = desc->layouts;
744 debug_printf(state, "%s\n", desc->description);
745 while (TLS_LAYOUT_IS_VALID(ldesc)) {
746 success = ldesc->parser(state, ldesc);
747 if (!success)
748 break;
749 ldesc++;
751 if (!success)
752 break;
753 } else {
754 debug_print(state, "ignored\n");
755 debug_hex(state, 0);
758 /* next message */
759 bytes += TLS_HANDSHAKE_HEADER_LENGTH + msg_length;
760 length -= TLS_HANDSHAKE_HEADER_LENGTH + msg_length;
761 if (length > 0) {
762 debug_print(state, "------\n");
763 } else {
764 success = TRUE;
768 return(success);
771 static void free_parse_data(struct tls_internal_state *state)
773 if (state->data) {
774 g_hash_table_destroy(state->data);
775 state->data = NULL;
779 /* NOTE: we don't support record fragmentation */
780 static gboolean tls_record_parse(struct tls_internal_state *state,
781 gboolean incoming)
783 const guchar *bytes = incoming ? state->common.in_buffer : state->common.out_buffer;
784 gsize length = incoming ? state->common.in_length : state->common.out_length;
785 guint version;
786 const gchar *version_str;
787 gsize record_length;
788 gboolean success = FALSE;
790 debug_printf(state, "TLS MESSAGE %s\n", incoming ? "INCOMING" : "OUTGOING");
792 /* truncated header check */
793 if (length < TLS_RECORD_HEADER_LENGTH) {
794 SIPE_DEBUG_ERROR("tls_record_parse: too short TLS record header (%" G_GSIZE_FORMAT " bytes)",
795 length);
796 return(FALSE);
799 /* protocol version check */
800 version = lowlevel_integer_to_host(bytes + TLS_RECORD_OFFSET_VERSION, 2);
801 if (version < TLS_PROTOCOL_VERSION_1_0) {
802 SIPE_DEBUG_ERROR_NOFORMAT("tls_record_parse: SSL1/2/3 not supported");
803 return(FALSE);
805 switch (version) {
806 case TLS_PROTOCOL_VERSION_1_0:
807 version_str = "1.0 (RFC2246)";
808 break;
809 case TLS_PROTOCOL_VERSION_1_1:
810 version_str = "1.1 (RFC4346)";
811 break;
812 default:
813 version_str = "<future protocol version>";
814 break;
817 /* record length check */
818 record_length = TLS_RECORD_HEADER_LENGTH +
819 lowlevel_integer_to_host(bytes + TLS_RECORD_OFFSET_LENGTH, 2);
820 if (record_length > length) {
821 SIPE_DEBUG_ERROR_NOFORMAT("tls_record_parse: record too long");
822 return(FALSE);
825 /* TLS record header OK */
826 debug_printf(state, "TLS %s record (%" G_GSIZE_FORMAT " bytes)\n",
827 version_str, length);
828 state->msg_current = (guchar *) bytes + TLS_RECORD_HEADER_LENGTH;
829 state->msg_remainder = length - TLS_RECORD_HEADER_LENGTH;
831 /* Add incoming message contents to digest contexts */
832 if (incoming) {
833 sipe_digest_md5_update(state->md5_context,
834 state->msg_current,
835 state->msg_remainder);
836 sipe_digest_sha1_update(state->sha1_context,
837 state->msg_current,
838 state->msg_remainder);
841 /* Collect parser data for incoming messages */
842 if (incoming)
843 state->data = g_hash_table_new_full(g_str_hash, g_str_equal,
844 NULL, g_free);
846 switch (bytes[TLS_RECORD_OFFSET_TYPE]) {
847 case TLS_RECORD_TYPE_HANDSHAKE:
848 success = handshake_parse(state);
849 break;
851 default:
852 debug_print(state, "Unsupported TLS message\n");
853 debug_hex(state, 0);
854 break;
857 if (!success)
858 free_parse_data(state);
860 if (state->debug) {
861 SIPE_DEBUG_INFO_NOFORMAT(state->debug->str);
862 g_string_truncate(state->debug, 0);
865 return(success);
869 * TLS message compiler
871 static void compile_tls_record(struct tls_internal_state *state,
872 ...)
874 gsize total_size = 0;
875 guchar *current;
876 va_list ap;
878 /* calculate message size */
879 va_start(ap, state);
880 while (1) {
881 const struct tls_compiled_message *msg = va_arg(ap, struct tls_compiled_message *);
882 if (!msg) break;
883 total_size += msg->size;
885 va_end(ap);
887 SIPE_DEBUG_INFO("compile_tls_record: total size %" G_GSIZE_FORMAT,
888 total_size);
890 state->common.out_buffer = current = g_malloc(total_size + TLS_RECORD_HEADER_LENGTH);
891 state->common.out_length = total_size + TLS_RECORD_HEADER_LENGTH;
893 /* add TLS record header */
894 current[TLS_RECORD_OFFSET_TYPE] = TLS_RECORD_TYPE_HANDSHAKE;
895 lowlevel_integer_to_tls(current + TLS_RECORD_OFFSET_VERSION, 2,
896 TLS_PROTOCOL_VERSION_1_0);
897 lowlevel_integer_to_tls(current + TLS_RECORD_OFFSET_LENGTH, 2,
898 total_size);
899 current += TLS_RECORD_HEADER_LENGTH;
901 /* copy messages */
902 va_start(ap, state);
903 while (1) {
904 const struct tls_compiled_message *msg = va_arg(ap, struct tls_compiled_message *);
905 if (!msg) break;
907 memcpy(current, msg->data, msg->size);
908 current += msg->size;
910 va_end(ap);
913 static void compile_encrypted_tls_record(struct tls_internal_state *state,
914 const struct tls_compiled_message *msg)
916 guchar *plaintext;
917 gsize plaintext_length;
918 guchar *mac;
919 gsize mac_length;
920 guchar *message;
921 guchar *encrypted;
922 gsize encrypted_length;
924 /* Create plaintext TLS record */
925 compile_tls_record(state, msg, NULL);
926 plaintext = state->common.out_buffer;
927 plaintext_length = state->common.out_length;
929 /* Prepare encryption buffer */
930 encrypted_length = plaintext_length + state->mac_length;
931 SIPE_DEBUG_INFO("compile_encrypted_tls_record: total size %" G_GSIZE_FORMAT,
932 encrypted_length - TLS_RECORD_HEADER_LENGTH);
933 message = g_malloc(encrypted_length);
934 memcpy(message, plaintext, plaintext_length);
935 lowlevel_integer_to_tls(message + TLS_RECORD_OFFSET_LENGTH, 2,
936 encrypted_length - TLS_RECORD_HEADER_LENGTH);
938 /* Calculate MAC */
939 mac_length = sizeof(guint64) + plaintext_length;
940 mac = g_malloc(mac_length);
941 lowlevel_integer_to_tls(mac,
942 sizeof(guint64),
943 state->sequence_number++);
944 memcpy(mac + sizeof(guint64), plaintext, plaintext_length);
945 state->mac_func(state->client_write_mac_secret,
946 state->mac_length,
947 mac,
948 mac_length,
949 message + encrypted_length - state->mac_length);
951 /* Encrypt message + MAC */
952 encrypted = g_malloc(encrypted_length);
953 memcpy(encrypted, message, TLS_RECORD_HEADER_LENGTH);
954 sipe_crypt_tls_stream(state->cipher_context,
955 message + TLS_RECORD_HEADER_LENGTH,
956 encrypted_length - TLS_RECORD_HEADER_LENGTH,
957 encrypted + TLS_RECORD_HEADER_LENGTH);
959 g_free(message);
960 g_free(mac);
961 g_free(plaintext);
963 /* swap buffers */
964 state->common.out_buffer = encrypted;
965 state->common.out_length = encrypted_length;
968 static struct tls_compiled_message *compile_handshake_msg(struct tls_internal_state *state,
969 const struct msg_descriptor *desc,
970 gpointer data,
971 gsize size)
974 * Estimate the size of the compiled message
976 * The data structures in the host format have zero or more padding
977 * bytes added by the compiler to ensure correct element alignments.
978 * So the sizeof() of the data structure is always equal or greater
979 * than the space needed for the compiled data. By adding the space
980 * required for the headers we arrive at a safe estimate
982 * Therefore we don't need space checks in the compiler functions
984 gsize total_size = sizeof(struct tls_compiled_message) +
985 size + TLS_HANDSHAKE_HEADER_LENGTH;
986 struct tls_compiled_message *msg = g_malloc(total_size);
987 guchar *handshake = msg->data;
988 const struct layout_descriptor *ldesc = desc->layouts;
989 gsize length;
991 SIPE_DEBUG_INFO("compile_handshake_msg: buffer size %" G_GSIZE_FORMAT,
992 total_size);
994 /* add TLS handshake header */
995 handshake[TLS_HANDSHAKE_OFFSET_TYPE] = desc->type;
996 state->msg_current = handshake + TLS_HANDSHAKE_HEADER_LENGTH;
998 while (TLS_LAYOUT_IS_VALID(ldesc)) {
1000 * Avoid "cast increases required alignment" errors
1002 * (void *) tells the compiler that we know what we're
1003 * doing, i.e. we know that the calculated address
1004 * points to correctly aligned data.
1006 ldesc->compiler(state, ldesc,
1007 (void *) ((guchar *) data + ldesc->offset));
1008 ldesc++;
1011 length = state->msg_current - handshake - TLS_HANDSHAKE_HEADER_LENGTH;
1012 lowlevel_integer_to_tls(handshake + TLS_HANDSHAKE_OFFSET_LENGTH,
1013 3, length);
1014 SIPE_DEBUG_INFO("compile_handshake_msg: (%d)%s, size %" G_GSIZE_FORMAT,
1015 desc->type, desc->description, length);
1017 msg->size = length + TLS_HANDSHAKE_HEADER_LENGTH;
1019 /* update digest contexts */
1020 sipe_digest_md5_update(state->md5_context, handshake, msg->size);
1021 sipe_digest_sha1_update(state->sha1_context, handshake, msg->size);
1023 return(msg);
1027 * Specific TLS data verficiation & message compilers
1029 static struct tls_compiled_message *tls_client_certificate(struct tls_internal_state *state)
1031 struct Certificate_host *certificate;
1032 gsize certificate_length = sipe_cert_crypto_raw_length(state->certificate);
1033 struct tls_compiled_message *msg;
1035 /* setup our response */
1036 /* Client Certificate is VECTOR_MAX24 of VECTOR_MAX24s */
1037 certificate = g_malloc0(sizeof(struct Certificate_host) + 3 +
1038 certificate_length);
1039 certificate->certificate.elements = certificate_length + 3;
1040 lowlevel_integer_to_tls((guchar *) certificate->certificate.placeholder, 3,
1041 certificate_length);
1042 memcpy((guchar *) certificate->certificate.placeholder + 3,
1043 sipe_cert_crypto_raw(state->certificate),
1044 certificate_length);
1046 msg = compile_handshake_msg(state, &Certificate_m, certificate,
1047 sizeof(struct Certificate_host) + certificate_length);
1048 g_free(certificate);
1050 return(msg);
1053 static gboolean check_cipher_suite(struct tls_internal_state *state)
1055 struct tls_parsed_integer *cipher_suite = g_hash_table_lookup(state->data,
1056 "CipherSuite");
1057 const gchar *label = NULL;
1059 if (!cipher_suite) {
1060 SIPE_DEBUG_ERROR_NOFORMAT("check_cipher_suite: server didn't specify the cipher suite");
1061 return(FALSE);
1064 switch (cipher_suite->value) {
1065 case TLS_RSA_EXPORT_WITH_RC4_40_MD5:
1066 state->mac_length = SIPE_DIGEST_HMAC_MD5_LENGTH;
1067 state->key_length = 40 / 8;
1068 state->mac_func = sipe_digest_hmac_md5;
1069 label = "MD5";
1070 break;
1072 case TLS_RSA_WITH_RC4_128_MD5:
1073 state->mac_length = SIPE_DIGEST_HMAC_MD5_LENGTH;
1074 state->key_length = 128 / 8;
1075 state->mac_func = sipe_digest_hmac_md5;
1076 label = "MD5";
1077 break;
1079 case TLS_RSA_WITH_RC4_128_SHA:
1080 state->mac_length = SIPE_DIGEST_HMAC_SHA1_LENGTH;
1081 state->key_length = 128 / 8;
1082 state->mac_func = sipe_digest_hmac_sha1;
1083 label = "SHA-1";
1084 break;
1086 default:
1087 SIPE_DEBUG_ERROR("check_cipher_suite: unsupported cipher suite %d",
1088 cipher_suite->value);
1089 break;
1092 if (label)
1093 SIPE_DEBUG_INFO("check_cipher_suite: KEY(stream cipher RC4) %" G_GSIZE_FORMAT ", MAC(%s) %" G_GSIZE_FORMAT,
1094 state->key_length, label, state->mac_length);
1096 return(label != NULL);
1099 static void debug_secrets(struct tls_internal_state *state,
1100 const gchar *label,
1101 const guchar *secret,
1102 gsize secret_length)
1104 if (state->debug) {
1105 g_string_append_printf(state->debug, "tls_calculate_secrets: %s ",
1106 label);
1107 while (secret_length--)
1108 g_string_append_printf(state->debug, "%02X", *secret++);
1109 SIPE_DEBUG_INFO_NOFORMAT(state->debug->str);
1110 g_string_truncate(state->debug, 0);
1114 static void tls_calculate_secrets(struct tls_internal_state *state)
1116 gsize length = 2 * (state->mac_length + state->key_length);
1117 guchar *random;
1119 /* Generate pre-master secret */
1120 sipe_svc_fill_random(&state->pre_master_secret,
1121 TLS_ARRAY_MASTER_SECRET_LENGTH * 8); /* bits */
1122 lowlevel_integer_to_tls(state->pre_master_secret.buffer, 2,
1123 TLS_PROTOCOL_VERSION_1_0);
1124 debug_secrets(state, "pre-master secret",
1125 state->pre_master_secret.buffer,
1126 state->pre_master_secret.length);
1129 * Calculate master secret
1131 * master_secret = PRF(pre_master_secret,
1132 * "master secret",
1133 * ClientHello.random + ServerHello.random)
1135 random = g_malloc(TLS_ARRAY_RANDOM_LENGTH * 2);
1136 memcpy(random,
1137 state->client_random.buffer,
1138 TLS_ARRAY_RANDOM_LENGTH);
1139 memcpy(random + TLS_ARRAY_RANDOM_LENGTH,
1140 state->server_random.buffer,
1141 TLS_ARRAY_RANDOM_LENGTH);
1142 state->master_secret = sipe_tls_prf(state->pre_master_secret.buffer,
1143 state->pre_master_secret.length,
1144 (guchar *) "master secret",
1146 random,
1147 TLS_ARRAY_RANDOM_LENGTH * 2,
1148 TLS_ARRAY_MASTER_SECRET_LENGTH);
1149 debug_secrets(state, "master secret",
1150 state->master_secret,
1151 TLS_ARRAY_MASTER_SECRET_LENGTH);
1154 * Calculate session key material
1156 * key_block = PRF(master_secret,
1157 * "key expansion",
1158 * ServerHello.random + ClientHello.random)
1160 SIPE_DEBUG_INFO("tls_calculate_secrets: key_block length %" G_GSIZE_FORMAT,
1161 length);
1162 memcpy(random,
1163 state->server_random.buffer,
1164 TLS_ARRAY_RANDOM_LENGTH);
1165 memcpy(random + TLS_ARRAY_RANDOM_LENGTH,
1166 state->client_random.buffer,
1167 TLS_ARRAY_RANDOM_LENGTH);
1168 state->key_block = sipe_tls_prf(state->master_secret,
1169 TLS_ARRAY_MASTER_SECRET_LENGTH,
1170 (guchar *) "key expansion",
1172 random,
1173 TLS_ARRAY_RANDOM_LENGTH * 2,
1174 length);
1175 g_free(random);
1176 debug_secrets(state, "key block", state->key_block, length);
1178 /* partition key block */
1179 state->client_write_mac_secret = state->key_block;
1180 state->server_write_mac_secret = state->key_block + state->mac_length;
1181 state->client_write_secret = state->key_block + 2 * state->mac_length;
1182 state->server_write_secret = state->key_block + 2 * state->mac_length + state->key_length;
1184 /* initialize cipher context */
1185 state->cipher_context = sipe_crypt_tls_start(state->client_write_secret,
1186 state->key_length);
1189 static struct tls_compiled_message *tls_client_key_exchange(struct tls_internal_state *state)
1191 struct tls_parsed_array *server_random;
1192 struct tls_parsed_array *server_certificate;
1193 struct ClientKeyExchange_host *exchange;
1194 gsize server_certificate_length;
1195 struct tls_compiled_message *msg;
1197 /* check for required data fields */
1198 if (!check_cipher_suite(state))
1199 return(NULL);
1200 server_random = g_hash_table_lookup(state->data, "Random");
1201 if (!server_random) {
1202 SIPE_DEBUG_ERROR_NOFORMAT("tls_client_key_exchange: no server random");
1203 return(NULL);
1205 server_certificate = g_hash_table_lookup(state->data, "Certificate");
1206 /* Server Certificate is VECTOR_MAX24 of VECTOR_MAX24s */
1207 if (!server_certificate || (server_certificate->length < 3)) {
1208 SIPE_DEBUG_ERROR_NOFORMAT("tls_client_key_exchange: no server certificate");
1209 return(FALSE);
1211 SIPE_DEBUG_INFO("tls_client_key_exchange: server certificate list %" G_GSIZE_FORMAT" bytes",
1212 server_certificate->length);
1213 /* first certificate is the server certificate */
1214 server_certificate_length = lowlevel_integer_to_host(server_certificate->data,
1216 SIPE_DEBUG_INFO("tls_client_key_exchange: server certificate %" G_GSIZE_FORMAT" bytes",
1217 server_certificate_length);
1218 if ((server_certificate_length + 3) > server_certificate->length) {
1219 SIPE_DEBUG_ERROR_NOFORMAT("tls_client_key_exchange: truncated server certificate");
1221 state->server_certificate = sipe_cert_crypto_import(server_certificate->data + 3,
1222 server_certificate_length);
1223 if (!state->server_certificate) {
1224 SIPE_DEBUG_ERROR_NOFORMAT("tls_client_key_exchange: corrupted server certificate");
1225 return(FALSE);
1227 /* server public key modulus length */
1228 server_certificate_length = sipe_cert_crypto_modulus_length(state->server_certificate);
1229 if (server_certificate_length < TLS_ARRAY_MASTER_SECRET_LENGTH) {
1230 SIPE_DEBUG_ERROR("tls_client_key_exchange: server public key strength too low (%" G_GSIZE_FORMAT ")",
1231 server_certificate_length);
1232 return(FALSE);
1234 SIPE_DEBUG_INFO("tls_client_key_exchange: server public key strength = %" G_GSIZE_FORMAT,
1235 server_certificate_length);
1237 /* found all the required fields */
1238 state->server_random.length = server_random->length;
1239 state->server_random.buffer = g_memdup(server_random->data,
1240 server_random->length);
1241 tls_calculate_secrets(state);
1243 /* ClientKeyExchange */
1244 exchange = g_malloc0(sizeof(struct ClientKeyExchange_host) +
1245 server_certificate_length);
1246 exchange->secret.elements = server_certificate_length;
1247 if (!sipe_crypt_rsa_encrypt(sipe_cert_crypto_public_key(state->server_certificate),
1248 TLS_ARRAY_MASTER_SECRET_LENGTH,
1249 state->pre_master_secret.buffer,
1250 (guchar *) exchange->secret.placeholder)) {
1251 SIPE_DEBUG_ERROR_NOFORMAT("tls_client_key_exchange: encryption of pre-master secret failed");
1252 g_free(exchange);
1253 return(NULL);
1256 msg = compile_handshake_msg(state, &ClientKeyExchange_m, exchange,
1257 sizeof(struct ClientKeyExchange_host) + server_certificate_length);
1258 g_free(exchange);
1260 return(msg);
1263 static struct tls_compiled_message *tls_certificate_verify(struct tls_internal_state *state)
1265 struct CertificateVerify_host *verify;
1266 struct tls_compiled_message *msg;
1267 guchar *digests = g_malloc(SIPE_DIGEST_MD5_LENGTH + SIPE_DIGEST_SHA1_LENGTH);
1268 guchar *signature;
1269 gsize length;
1271 /* calculate digests */
1272 sipe_digest_md5_end(state->md5_context, digests);
1273 sipe_digest_sha1_end(state->sha1_context, digests + SIPE_DIGEST_MD5_LENGTH);
1275 /* sign digests */
1276 signature = sipe_crypt_rsa_sign(sipe_cert_crypto_private_key(state->certificate),
1277 digests,
1278 SIPE_DIGEST_MD5_LENGTH + SIPE_DIGEST_SHA1_LENGTH,
1279 &length);
1280 g_free(digests);
1281 if (!signature) {
1282 SIPE_DEBUG_ERROR_NOFORMAT("tls_certificate_verify: signing of handshake digests failed");
1283 return(NULL);
1286 /* CertificateVerify */
1287 verify = g_malloc0(sizeof(struct CertificateVerify_host) +
1288 length);
1289 verify->signature.elements = length;
1290 memcpy(verify->signature.placeholder, signature, length);
1292 msg = compile_handshake_msg(state, &CertificateVerify_m, verify,
1293 sizeof(struct CertificateVerify_host) + length);
1294 g_free(verify);
1296 return(msg);
1299 static struct tls_compiled_message *tls_client_finished(struct tls_internal_state *state)
1301 guchar *digests = g_malloc(SIPE_DIGEST_MD5_LENGTH + SIPE_DIGEST_SHA1_LENGTH);
1302 guchar *verify;
1303 struct tls_compiled_message *cmsg;
1304 struct Finished_host msg;
1306 /* calculate digests */
1307 sipe_digest_md5_end(state->md5_context, digests);
1308 sipe_digest_sha1_end(state->sha1_context, digests + SIPE_DIGEST_MD5_LENGTH);
1311 * verify_data = PRF(master_secret, "client finished",
1312 * MD5(handshake_messages) +
1313 * SHA-1(handshake_messages)) [0..11];
1315 verify = sipe_tls_prf(state->master_secret,
1316 TLS_ARRAY_MASTER_SECRET_LENGTH,
1317 (guchar *) "client finished",
1319 digests,
1320 SIPE_DIGEST_MD5_LENGTH + SIPE_DIGEST_SHA1_LENGTH,
1321 TLS_ARRAY_VERIFY_LENGTH);
1322 g_free(digests);
1323 memcpy(msg.verify.verify, verify, TLS_ARRAY_VERIFY_LENGTH);
1324 g_free(verify);
1326 cmsg = compile_handshake_msg(state, &Finished_m, &msg, sizeof(msg));
1328 return(cmsg);
1332 * TLS state handling
1335 static gboolean tls_client_hello(struct tls_internal_state *state)
1337 guint32 now = time(NULL);
1338 guint32 now_N = GUINT32_TO_BE(now);
1339 struct ClientHello_host msg = {
1340 { TLS_PROTOCOL_VERSION_1_0 },
1341 { 0, { } },
1342 { 0 /* empty SessionID */ },
1343 { 3,
1345 TLS_RSA_WITH_RC4_128_MD5,
1346 TLS_RSA_WITH_RC4_128_SHA,
1347 TLS_RSA_EXPORT_WITH_RC4_40_MD5
1350 { 1,
1352 TLS_COMP_METHOD_NULL
1356 struct tls_compiled_message *cmsg;
1358 /* First 4 bytes of client_random is the current timestamp */
1359 sipe_svc_fill_random(&state->client_random,
1360 TLS_ARRAY_RANDOM_LENGTH * 8); /* -> bits */
1361 memcpy(state->client_random.buffer, &now_N, sizeof(now_N));
1362 memcpy(msg.random.random, state->client_random.buffer,
1363 TLS_ARRAY_RANDOM_LENGTH);
1365 cmsg = compile_handshake_msg(state, &ClientHello_m, &msg, sizeof(msg));
1366 compile_tls_record(state, cmsg, NULL);
1367 g_free(cmsg);
1369 if (sipe_backend_debug_enabled())
1370 state->debug = g_string_new("");
1372 state->state = TLS_HANDSHAKE_STATE_SERVER_HELLO;
1373 return(tls_record_parse(state, FALSE));
1376 static gboolean tls_server_hello(struct tls_internal_state *state)
1378 struct tls_compiled_message *certificate = NULL;
1379 struct tls_compiled_message *exchange = NULL;
1380 struct tls_compiled_message *verify = NULL;
1381 struct tls_compiled_message *finished = NULL;
1382 gboolean success = FALSE;
1384 if (!tls_record_parse(state, TRUE))
1385 return(FALSE);
1387 if (((certificate = tls_client_certificate(state)) != NULL) &&
1388 ((exchange = tls_client_key_exchange(state)) != NULL) &&
1389 ((verify = tls_certificate_verify(state)) != NULL) &&
1390 ((finished = tls_client_finished(state)) != NULL)) {
1392 /* Part 1 */
1393 compile_tls_record(state, certificate, exchange, verify, NULL);
1395 success = tls_record_parse(state, FALSE);
1396 if (success) {
1397 guchar *part1 = state->common.out_buffer;
1398 gsize part1_length = state->common.out_length;
1399 guchar *part3;
1400 gsize part3_length;
1401 guchar *merged;
1402 gsize length;
1403 /* ChangeCipherSpec is always the same */
1404 static const guchar const part2[] = {
1405 TLS_RECORD_TYPE_CHANGE_CIPHER_SPEC,
1406 (TLS_PROTOCOL_VERSION_1_0 >> 8) & 0xFF,
1407 TLS_PROTOCOL_VERSION_1_0 & 0xFF,
1408 0x00, 0x01, /* length: 1 byte */
1409 0x01 /* change_cipher_spec(1) */
1412 state->common.out_buffer = NULL;
1414 /* Part 3 - this is the first encrypted record */
1415 compile_encrypted_tls_record(state, finished);
1416 part3 = state->common.out_buffer;
1417 part3_length = state->common.out_length;
1419 /* merge TLS records */
1420 length = part1_length + sizeof(part2) + part3_length;
1421 merged = g_malloc(length);
1423 memcpy(merged, part1, part1_length);
1424 memcpy(merged + part1_length, part2, sizeof(part2));
1425 memcpy(merged + part1_length + sizeof(part2), part3, part3_length);
1426 g_free(part3);
1427 g_free(part1);
1429 /* replace output buffer with merged message */
1430 state->common.out_buffer = merged;
1431 state->common.out_length = length;
1433 state->state = TLS_HANDSHAKE_STATE_FINISHED;
1437 g_free(finished);
1438 g_free(verify);
1439 g_free(exchange);
1440 g_free(certificate);
1441 free_parse_data(state);
1443 return(success);
1446 static gboolean tls_finished(struct tls_internal_state *state)
1448 if (!tls_record_parse(state, TRUE))
1449 return(FALSE);
1451 /* TBD: data is really not needed? */
1452 free_parse_data(state);
1454 state->common.out_buffer = NULL;
1455 state->common.out_length = 0;
1456 state->state = TLS_HANDSHAKE_STATE_COMPLETED;
1458 /* temporary */
1459 return(TRUE);
1463 * TLS public API
1466 struct sipe_tls_state *sipe_tls_start(gpointer certificate)
1468 struct tls_internal_state *state;
1470 if (!certificate)
1471 return(NULL);
1473 state = g_new0(struct tls_internal_state, 1);
1474 state->certificate = certificate;
1475 state->state = TLS_HANDSHAKE_STATE_START;
1476 state->md5_context = sipe_digest_md5_start();
1477 state->sha1_context = sipe_digest_sha1_start();
1479 return((struct sipe_tls_state *) state);
1482 gboolean sipe_tls_next(struct sipe_tls_state *state)
1484 struct tls_internal_state *internal = (struct tls_internal_state *) state;
1485 gboolean success = FALSE;
1487 if (!state)
1488 return(FALSE);
1490 state->out_buffer = NULL;
1492 switch (internal->state) {
1493 case TLS_HANDSHAKE_STATE_START:
1494 success = tls_client_hello(internal);
1495 break;
1497 case TLS_HANDSHAKE_STATE_SERVER_HELLO:
1498 success = tls_server_hello(internal);
1499 break;
1501 case TLS_HANDSHAKE_STATE_FINISHED:
1502 success = tls_finished(internal);
1503 break;
1505 case TLS_HANDSHAKE_STATE_COMPLETED:
1506 case TLS_HANDSHAKE_STATE_FAILED:
1507 /* This should not happen */
1508 SIPE_DEBUG_ERROR_NOFORMAT("sipe_tls_next: called in incorrect state!");
1509 break;
1512 if (!success) {
1513 internal->state = TLS_HANDSHAKE_STATE_FAILED;
1516 return(success);
1519 void sipe_tls_free(struct sipe_tls_state *state)
1521 if (state) {
1522 struct tls_internal_state *internal = (struct tls_internal_state *) state;
1524 free_parse_data(internal);
1525 if (internal->debug)
1526 g_string_free(internal->debug, TRUE);
1527 g_free(internal->key_block);
1528 g_free(internal->master_secret);
1529 sipe_svc_free_random(&internal->pre_master_secret);
1530 sipe_svc_free_random(&internal->client_random);
1531 sipe_svc_free_random(&internal->server_random);
1532 if (internal->cipher_context)
1533 sipe_crypt_tls_destroy(internal->cipher_context);
1534 if (internal->md5_context)
1535 sipe_digest_md5_destroy(internal->md5_context);
1536 if (internal->sha1_context)
1537 sipe_digest_sha1_destroy(internal->sha1_context);
1538 sipe_cert_crypto_destroy(internal->server_certificate);
1539 g_free(state->session_key);
1540 g_free(state->out_buffer);
1541 g_free(state);
1546 Local Variables:
1547 mode: c
1548 c-file-style: "bsd"
1549 indent-tabs-mode: t
1550 tab-width: 8
1551 End: