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
42 #include "sipe-common.h"
43 #include "sipe-backend.h"
44 #include "sipe-cert-crypto.h"
48 * Private part of TLS state tracking
50 enum tls_handshake_state
{
51 TLS_HANDSHAKE_STATE_START
,
52 TLS_HANDSHAKE_STATE_SERVER_HELLO
,
53 TLS_HANDSHAKE_STATE_FINISHED
,
54 TLS_HANDSHAKE_STATE_COMPLETED
,
55 TLS_HANDSHAKE_STATE_FAILED
58 struct tls_internal_state
{
59 struct sipe_tls_state common
;
61 enum tls_handshake_state state
;
62 const guchar
*parse_buffer
;
69 * TLS message debugging
71 static void debug_hex(struct tls_internal_state
*state
,
72 gsize alternative_length
)
74 GString
*str
= state
->debug
;
81 bytes
= state
->parse_buffer
;
82 length
= alternative_length
? alternative_length
: state
->parse_length
;
85 while (length
-- > 0) {
88 } else if ((count
% 16) == 0) {
89 g_string_append(str
, "\n");
90 } else if ((count
% 8) == 0) {
91 g_string_append(str
, " ");
93 g_string_append_printf(str
, " %02X", *bytes
++);
95 g_string_append(str
, "\n");
98 #define debug_print(state, string) \
99 if (state->debug) g_string_append(state->debug, string)
100 #define debug_printf(state, format, ...) \
101 if (state->debug) g_string_append_printf(state->debug, format, __VA_ARGS__)
104 * Low-level data conversion routines
106 * - host alignment agnostic, i.e. can fetch a word from uneven address
107 * - TLS -> host endianess conversion
108 * - no length check, caller has to do it
109 * - don't modify state
111 static guint
lowlevel_integer_to_host(const guchar
*bytes
,
115 while (length
--) sum
= (sum
<< 8) + *bytes
++;
120 * Simple data type parser routines
122 static gboolean
parse_length_check(struct tls_internal_state
*state
,
126 if (length
> state
->parse_length
) {
127 SIPE_DEBUG_ERROR("parse_length_check: '%s' expected %" G_GSIZE_FORMAT
" bytes, remaining %" G_GSIZE_FORMAT
,
128 label
, length
, state
->parse_length
);
134 static gboolean
parse_integer_quiet(struct tls_internal_state
*state
,
139 if (!parse_length_check(state
, label
, length
)) return(FALSE
);
140 *result
= lowlevel_integer_to_host(state
->parse_buffer
, length
);
141 state
->parse_buffer
+= length
;
142 state
->parse_length
-= length
;
146 static gboolean
parse_integer(struct tls_internal_state
*state
,
151 if (!parse_integer_quiet(state
, label
, length
, result
)) return(FALSE
);
152 debug_printf(state
, "'%s/INTEGER%" G_GSIZE_FORMAT
" = %d\n",
153 label
, length
, *result
);
157 struct tls_parsed_integer
{
160 static gboolean
parse_integer_store(struct tls_internal_state
*state
,
165 if (!parse_integer(state
, label
, length
, &value
)) return(FALSE
);
167 struct tls_parsed_integer
*save
= g_new0(struct tls_parsed_integer
, 1);
169 g_hash_table_insert(state
->data
, (gpointer
) label
, save
);
175 * TLS message parsing
177 #define TLS_TYPE_FIXED 0x00
178 #define TLS_TYPE_ARRAY 0x01
179 #define TLS_TYPE_VECTOR 0x02
181 #define TLS_VECTOR_MAX8 255 /* 2^8 - 1 */
182 #define TLS_VECTOR_MAX16 65535 /* 2^16 - 1 */
183 #define TLS_VECTOR_MAX24 16777215 /* 2^24 - 1 */
185 struct parse_descriptor
;
186 typedef gboolean
parse_func(struct tls_internal_state
*state
,
187 const struct parse_descriptor
*desc
);
188 struct parse_descriptor
{
192 gsize min
; /* 0 for fixed/array */
196 #define TLS_PARSE_DESCRIPTOR_END { NULL, NULL, 0, 0, 0 }
198 static const struct parse_descriptor
const ClientHello
[] = {
199 { "Client Protocol Version", NULL
, TLS_TYPE_FIXED
, 0, 2 },
200 { "Random", NULL
, TLS_TYPE_ARRAY
, 0, 32 },
201 { "SessionID", NULL
, TLS_TYPE_VECTOR
, 0, 32 },
202 { "CipherSuite", NULL
, TLS_TYPE_VECTOR
, 2, TLS_VECTOR_MAX16
},
203 { "CompressionMethod", NULL
, TLS_TYPE_VECTOR
, 1, TLS_VECTOR_MAX8
},
204 TLS_PARSE_DESCRIPTOR_END
207 static const struct parse_descriptor
const ServerHello
[] = {
208 { "Server Protocol Version", NULL
, TLS_TYPE_FIXED
, 0, 2 },
209 { "Random", NULL
, TLS_TYPE_ARRAY
, 0, 32 },
210 { "SessionID", NULL
, TLS_TYPE_VECTOR
, 0, 32 },
211 { "CipherSuite", NULL
, TLS_TYPE_FIXED
, 0, 2 },
212 { "CompressionMethod", NULL
, TLS_TYPE_FIXED
, 0, 1 },
213 TLS_PARSE_DESCRIPTOR_END
216 static const struct parse_descriptor
const Certificate
[] = {
217 { "Certificate", NULL
, TLS_TYPE_VECTOR
, 0, TLS_VECTOR_MAX24
},
218 TLS_PARSE_DESCRIPTOR_END
221 static const struct parse_descriptor
const CertificateRequest
[] = {
222 { "CertificateType", NULL
, TLS_TYPE_VECTOR
, 1, TLS_VECTOR_MAX8
},
223 { "DistinguishedName", NULL
, TLS_TYPE_VECTOR
, 0, TLS_VECTOR_MAX16
},
224 TLS_PARSE_DESCRIPTOR_END
227 static const struct parse_descriptor
const ServerHelloDone
[] = {
228 TLS_PARSE_DESCRIPTOR_END
231 static gboolean
parse_ignored_field(struct tls_internal_state
*state
,
232 const struct parse_descriptor
*desc
)
234 gboolean success
= FALSE
;
236 switch (desc
->type
) {
240 success
= parse_integer(state
, desc
->label
, desc
->max
, &value
);
245 if (parse_length_check(state
, desc
->label
, desc
->max
)) {
247 debug_printf(state
, "%s/ARRAY[%" G_GSIZE_FORMAT
"]\n",
248 desc
->label
, desc
->max
);
249 debug_hex(state
, desc
->max
);
250 state
->parse_buffer
+= desc
->max
;
251 state
->parse_length
-= desc
->max
;
256 case TLS_TYPE_VECTOR
:
259 if (parse_integer_quiet(state
, desc
->label
,
260 (desc
->max
> TLS_VECTOR_MAX16
) ? 3 :
261 (desc
->max
> TLS_VECTOR_MAX8
) ? 2 : 1,
264 if (length
< desc
->min
) {
265 SIPE_DEBUG_ERROR("generic_parser: too short vector type %d (minimum %" G_GSIZE_FORMAT
")",
269 debug_printf(state
, "%s/VECTOR<%d>\n",
270 desc
->label
, length
);
272 debug_hex(state
, length
);
273 state
->parse_buffer
+= length
;
274 state
->parse_length
-= length
;
282 SIPE_DEBUG_ERROR("generic_parser: unknown descriptor type %d",
290 static gboolean
generic_parser(struct tls_internal_state
*state
,
291 const struct parse_descriptor
*desc
)
293 while (desc
->label
) {
296 (void)parse_integer_store
;
298 if (!parse_ignored_field(state
, desc
))
307 #define TLS_HANDSHAKE_HEADER_LENGTH 4
308 #define TLS_HANDSHAKE_OFFSET_TYPE 0
309 #define TLS_HANDSHAKE_TYPE_CLIENT_HELLO 1
310 #define TLS_HANDSHAKE_TYPE_SERVER_HELLO 2
311 #define TLS_HANDSHAKE_TYPE_CERTIFICATE 11
312 #define TLS_HANDSHAKE_TYPE_CERTIFICATE_REQ 13
313 #define TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE 14
314 #define TLS_HANDSHAKE_OFFSET_LENGTH 1
316 struct msg_descriptor
{
318 const gchar
*description
;
319 const struct parse_descriptor
*parse
;
322 static gboolean
handshake_parse(struct tls_internal_state
*state
)
324 static const struct msg_descriptor
const handshake_descriptors
[] = {
325 { TLS_HANDSHAKE_TYPE_CLIENT_HELLO
, "Client Hello", ClientHello
},
326 { TLS_HANDSHAKE_TYPE_SERVER_HELLO
, "Server Hello", ServerHello
},
327 { TLS_HANDSHAKE_TYPE_CERTIFICATE
, "Certificate", Certificate
},
328 { TLS_HANDSHAKE_TYPE_CERTIFICATE_REQ
, "Certificate Request", CertificateRequest
},
329 { TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE
, "Server Hello Done", ServerHelloDone
}
331 #define HANDSHAKE_DESCRIPTORS (sizeof(handshake_descriptors)/sizeof(struct msg_descriptor))
333 const guchar
*bytes
= state
->parse_buffer
;
334 gsize length
= state
->parse_length
;
335 gboolean success
= FALSE
;
338 const struct msg_descriptor
*desc
;
343 if (length
< TLS_HANDSHAKE_HEADER_LENGTH
) {
344 debug_print(state
, "CORRUPTED HANDSHAKE HEADER");
348 /* msg length check */
349 msg_length
= lowlevel_integer_to_host(bytes
+ TLS_HANDSHAKE_OFFSET_LENGTH
,
351 if (msg_length
> length
) {
352 debug_print(state
, "HANDSHAKE MESSAGE TOO LONG");
357 msg_type
= bytes
[TLS_HANDSHAKE_OFFSET_TYPE
];
358 for (desc
= handshake_descriptors
, i
= 0;
359 i
< HANDSHAKE_DESCRIPTORS
;
361 if (msg_type
== desc
->type
)
365 debug_printf(state
, "TLS handshake (%" G_GSIZE_FORMAT
" bytes) (%d)",
366 msg_length
, msg_type
);
368 state
->parse_buffer
= bytes
+ TLS_HANDSHAKE_HEADER_LENGTH
;
369 state
->parse_length
= msg_length
;
371 if (i
< HANDSHAKE_DESCRIPTORS
) {
372 debug_printf(state
, "%s\n", desc
->description
);
373 success
= generic_parser(state
, desc
->parse
);
377 debug_print(state
, "ignored\n");
382 bytes
+= TLS_HANDSHAKE_HEADER_LENGTH
+ msg_length
;
383 length
-= TLS_HANDSHAKE_HEADER_LENGTH
+ msg_length
;
385 debug_print(state
, "------\n");
394 static void free_parse_data(struct tls_internal_state
*state
)
397 g_hash_table_destroy(state
->data
);
402 #define TLS_RECORD_HEADER_LENGTH 5
403 #define TLS_RECORD_OFFSET_TYPE 0
404 #define TLS_RECORD_TYPE_HANDSHAKE 22
405 #define TLS_RECORD_OFFSET_MAJOR 1
406 #define TLS_RECORD_OFFSET_LENGTH 3
408 /* NOTE: we don't support record fragmentation */
409 static gboolean
tls_record_parse(struct tls_internal_state
*state
,
412 const guchar
*bytes
= incoming
? state
->common
.in_buffer
: state
->common
.out_buffer
;
413 gsize length
= incoming
? state
->common
.in_length
: state
->common
.out_length
;
415 const gchar
*version_str
;
417 gboolean success
= FALSE
;
419 debug_printf(state
, "TLS MESSAGE %s\n", incoming
? "INCOMING" : "OUTGOING");
421 /* truncated header check */
422 if (length
< TLS_RECORD_HEADER_LENGTH
) {
423 SIPE_DEBUG_ERROR("tls_record_parse: too short TLS record header (%" G_GSIZE_FORMAT
" bytes)",
428 /* protocol version check */
429 version
= lowlevel_integer_to_host(bytes
+ TLS_RECORD_OFFSET_MAJOR
, 2);
430 if (version
< 0x0301) {
431 SIPE_DEBUG_ERROR_NOFORMAT("tls_record_parse: SSL1/2/3 not supported");
436 version_str
= "1.0 (RFC2246)";
439 version_str
= "1.1 (RFC4346)";
442 version_str
= "<future protocol version>";
446 /* record length check */
447 record_length
= TLS_RECORD_HEADER_LENGTH
+
448 lowlevel_integer_to_host(bytes
+ TLS_RECORD_OFFSET_LENGTH
, 2);
449 if (record_length
> length
) {
450 SIPE_DEBUG_ERROR_NOFORMAT("tls_record_parse: record too long");
454 /* TLS record header OK */
455 debug_printf(state
, "TLS %s record (%" G_GSIZE_FORMAT
" bytes)\n",
456 version_str
, length
);
457 state
->parse_buffer
= bytes
+ TLS_RECORD_HEADER_LENGTH
;
458 state
->parse_length
= length
- TLS_RECORD_HEADER_LENGTH
;
460 /* Collect parser data for incoming messages */
462 state
->data
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
465 switch (bytes
[TLS_RECORD_OFFSET_TYPE
]) {
466 case TLS_RECORD_TYPE_HANDSHAKE
:
467 success
= handshake_parse(state
);
471 debug_print(state
, "Unsupported TLS message\n");
477 free_parse_data(state
);
480 SIPE_DEBUG_INFO_NOFORMAT(state
->debug
->str
);
481 g_string_truncate(state
->debug
, 0);
487 static const guchar
const client_hello
[] = {
490 /* Extracted from log file */
492 0x16, /* ContenType: handshake(22) */
493 0x03, 0x01, /* ProtocolVersion: 3.1 (= TLS 1.0) */
494 0x00, 0x48, /* length: 72 bytes */
495 /* TLS Record fragment -> 72 bytes */
496 /* Handshake (header) */
497 0x01, /* msg_type: client_hello(1) */
498 0x00, 0x00, 0x44, /* length: 68 bytes */
499 /* Handshake (body) */
501 0x03, 0x01, /* ProtocolVersion: 3.1 (= TLS 1.0) */
502 /* Random: (32 bytes) */
503 0x4e, 0x81, 0xa7, 0x63, /* uint32 gmt_unix_time */
504 0x15, 0xfd, 0x06, 0x46, /* random_bytes[28] */
505 0x0a, 0xb2, 0xdf, 0xf0,
506 0x85, 0x14, 0xac, 0x60,
507 0x7e, 0xda, 0x48, 0x3c,
508 0xb2, 0xad, 0x5b, 0x0f,
509 0xf3, 0xe4, 0x4e, 0x5d,
510 0x4b, 0x9f, 0x8e, 0xd6,
511 /* session_id: (0..32 bytes) */
512 0x00, /* = 0 -> no SessionID */
513 /* cipher_suites: (2..2^16-1 bytes) */
514 0x00, 0x16, /* = 22 bytes -> 11 CipherSuites */
515 0x00, 0x04, /* TLS_RSA_WITH_RC4_128_MD5 */
516 0x00, 0x05, /* TLS_RSA_WITH_RC4_128_SHA */
517 0x00, 0x0a, /* TLS_RSA_WITH_3DES_EDE_CBC_SHA */
518 0x00, 0x09, /* TLS_RSA_WITH_DES_CBC_SHA */
519 0x00, 0x64, /* NON-STANDARD */
520 0x00, 0x62, /* NON-STANDARD */
521 0x00, 0x03, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 */
522 0x00, 0x06, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 */
523 0x00, 0x13, /* TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA */
524 0x00, 0x12, /* TLS_DHE_DSS_WITH_DES_CBC_SHA */
525 0x00, 0x63, /* NON-STANDARD */
526 /* compr_methods: (1..2^8-1 bytes) */
527 0x01, /* = 1 byte -> 1 CompressionMethod */
529 /* TLS Extended Client Hello (RFC3546) */
530 /* extensions: (0..2^16-1) */
531 0x00, 0x05, /* = 5 bytes */
532 0xff, 0x01, /* ExtensionType: (= 0xFF01) */
533 /* extension_data: (0..2^16-1 byt) */
534 0x00, 0x01, /* = 1 byte */
538 0x16, /* ContenType: handshake(22) */
539 0x03, 0x01, /* ProtocolVersion: 3.1 (= TLS 1.0) */
540 0x00, 0x31, /* length: 49 bytes */
541 /* TLS Record fragment -> 72 bytes */
542 /* Handshake (header) */
543 0x01, /* msg_type: client_hello(1) */
544 0x00, 0x00, 0x2d, /* length: 45 bytes */
545 /* Handshake (body) */
547 0x03, 0x01, /* ProtocolVersion: 3.1 (= TLS 1.0) */
548 /* Random: (32 bytes) */
549 #define GMT_OFFSET 11
550 0x4e, 0x81, 0xa7, 0x63, /* uint32 gmt_unix_time */
551 #define RANDOM_OFFSET 15
552 0x15, 0xfd, 0x06, 0x46, /* random_bytes[28] */
553 0x0a, 0xb2, 0xdf, 0xf0,
554 0x85, 0x14, 0xac, 0x60,
555 0x7e, 0xda, 0x48, 0x3c,
556 0xb2, 0xad, 0x5b, 0x0f,
557 0xf3, 0xe4, 0x4e, 0x5d,
558 0x4b, 0x9f, 0x8e, 0xd6,
559 /* session_id: (0..32 bytes) */
560 0x00, /* = 0 -> no SessionID */
561 /* cipher_suites: (2..2^16-1 bytes) */
562 0x00, 0x06, /* = 6 bytes -> 3 CipherSuites */
563 0x00, 0x04, /* TLS_RSA_WITH_RC4_128_MD5 */
564 0x00, 0x05, /* TLS_RSA_WITH_RC4_128_SHA */
565 0x00, 0x03, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 */
566 /* compr_methods: (1..2^8-1 bytes) */
567 0x01, /* = 1 byte -> 1 CompressionMethod */
572 static gboolean
tls_client_hello(struct tls_internal_state
*state
)
574 guchar
*msg
= g_memdup(client_hello
, sizeof(client_hello
));
575 guint32 now
= time(NULL
);
576 guint32 now_N
= GUINT32_TO_BE(now
);
580 memcpy(msg
+ GMT_OFFSET
, &now_N
, sizeof(now_N
));
581 for (p
= msg
+ RANDOM_OFFSET
, i
= 0; i
< 2; i
++)
582 *p
++ = rand() & 0xFF;
584 state
->common
.out_buffer
= msg
;
585 state
->common
.out_length
= sizeof(client_hello
);
586 state
->state
= TLS_HANDSHAKE_STATE_SERVER_HELLO
;
588 if (sipe_backend_debug_enabled())
589 state
->debug
= g_string_new("");
591 tls_record_parse(state
, FALSE
);
596 static gboolean
tls_server_hello(struct tls_internal_state
*state
)
598 if (!tls_record_parse(state
, TRUE
))
602 free_parse_data(state
);
603 state
->common
.out_buffer
= NULL
;
604 state
->common
.out_length
= 0;
605 state
->state
= TLS_HANDSHAKE_STATE_FINISHED
;
607 tls_record_parse(state
, FALSE
);
609 return(state
->common
.out_buffer
!= NULL
);
612 static gboolean
tls_finished(struct tls_internal_state
*state
)
614 if (!tls_record_parse(state
, TRUE
))
617 /* TBD: data is really not needed? */
618 free_parse_data(state
);
620 state
->common
.out_buffer
= NULL
;
621 state
->common
.out_length
= 0;
622 state
->state
= TLS_HANDSHAKE_STATE_COMPLETED
;
630 struct sipe_tls_state
*sipe_tls_start(gpointer certificate
)
632 struct tls_internal_state
*state
;
637 state
= g_new0(struct tls_internal_state
, 1);
638 state
->certificate
= certificate
;
639 state
->state
= TLS_HANDSHAKE_STATE_START
;
641 return((struct sipe_tls_state
*) state
);
644 gboolean
sipe_tls_next(struct sipe_tls_state
*state
)
646 struct tls_internal_state
*internal
= (struct tls_internal_state
*) state
;
647 gboolean success
= FALSE
;
652 state
->out_buffer
= NULL
;
654 switch (internal
->state
) {
655 case TLS_HANDSHAKE_STATE_START
:
656 success
= tls_client_hello(internal
);
659 case TLS_HANDSHAKE_STATE_SERVER_HELLO
:
660 success
= tls_server_hello(internal
);
663 case TLS_HANDSHAKE_STATE_FINISHED
:
664 success
= tls_finished(internal
);
667 case TLS_HANDSHAKE_STATE_COMPLETED
:
668 case TLS_HANDSHAKE_STATE_FAILED
:
669 /* This should not happen */
670 SIPE_DEBUG_ERROR_NOFORMAT("sipe_tls_next: called in incorrect state!");
675 internal
->state
= TLS_HANDSHAKE_STATE_FAILED
;
681 void sipe_tls_free(struct sipe_tls_state
*state
)
684 struct tls_internal_state
*internal
= (struct tls_internal_state
*) state
;
686 free_parse_data(internal
);
688 g_string_free(internal
->debug
, TRUE
);
689 g_free(state
->session_key
);
690 g_free(state
->out_buffer
);