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
;
65 * TLS message debugging
67 static void debug_hex(GString
*str
,
75 while (length
-- > 0) {
78 } else if ((count
% 16) == 0) {
79 g_string_append(str
, "\n");
80 } else if ((count
% 8) == 0) {
81 g_string_append(str
, " ");
83 g_string_append_printf(str
, " %02X", *bytes
++);
85 g_string_append(str
, "\n");
88 static void debug_print(GString
*str
,
92 g_string_append(str
, string
);
95 static void debug_printf(GString
*str
,
97 ...) G_GNUC_PRINTF(2, 3);
98 static void debug_printf(GString
*str
,
106 va_start(ap
, format
);
107 g_string_append_vprintf(str
, format
, ap
);
113 * TLS message parsing
115 struct parse_descriptor
{
119 struct msg_descriptor
{
121 const gchar
*description
;
122 const struct parse_descriptor
*parse
;
125 static void free_parsed_data(gpointer parsed_data
)
131 static gpointer
generic_parser(const guchar
*bytes
,
135 const struct parse_descriptor
*desc
,
136 gpointer parsed_data
)
139 debug_hex(str
, bytes
, length
);
146 #define TLS_HANDSHAKE_HEADER_LENGTH 4
147 #define TLS_HANDSHAKE_OFFSET_TYPE 0
148 #define TLS_HANDSHAKE_TYPE_CLIENT_HELLO 1
149 #define TLS_HANDSHAKE_TYPE_SERVER_HELLO 2
150 #define TLS_HANDSHAKE_TYPE_CERTIFICATE 11
151 #define TLS_HANDSHAKE_TYPE_CERTIFICATE_REQ 13
152 #define TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE 14
153 #define TLS_HANDSHAKE_OFFSET_LENGTH 1
155 static gpointer
handshake_parse(const guchar
*bytes
,
160 static const struct msg_descriptor
const handshake_descriptors
[] = {
161 { TLS_HANDSHAKE_TYPE_CLIENT_HELLO
, "Client Hello", NULL
},
162 { TLS_HANDSHAKE_TYPE_SERVER_HELLO
, "Server Hello", NULL
},
163 { TLS_HANDSHAKE_TYPE_CERTIFICATE
, "Certificate", NULL
},
164 { TLS_HANDSHAKE_TYPE_CERTIFICATE_REQ
, "Certificate Request", NULL
},
165 { TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE
, "Server Hello Done", NULL
}
167 #define HANDSHAKE_DESCRIPTORS (sizeof(handshake_descriptors)/sizeof(struct msg_descriptor))
169 gpointer parsed_data
= NULL
;
170 gboolean success
= FALSE
;
173 const struct msg_descriptor
*desc
;
178 if (length
< TLS_HANDSHAKE_HEADER_LENGTH
) {
179 debug_print(str
, "CORRUPTED HANDSHAKE HEADER");
183 /* msg length check */
184 msg_length
= (bytes
[TLS_HANDSHAKE_OFFSET_LENGTH
] << 16) +
185 (bytes
[TLS_HANDSHAKE_OFFSET_LENGTH
+ 1] << 8) +
186 bytes
[TLS_HANDSHAKE_OFFSET_LENGTH
+ 2];
187 if (msg_length
> length
) {
188 debug_print(str
, "HANDSHAKE MESSAGE TOO LONG");
193 msg_type
= bytes
[TLS_HANDSHAKE_OFFSET_TYPE
];
194 for (desc
= handshake_descriptors
, i
= 0;
195 i
< HANDSHAKE_DESCRIPTORS
;
197 if (msg_type
== desc
->type
)
201 debug_printf(str
, "TLS handshake (%" G_GSIZE_FORMAT
" bytes) (%d)",
202 msg_length
, msg_type
);
204 length
-= TLS_HANDSHAKE_HEADER_LENGTH
;
205 bytes
+= TLS_HANDSHAKE_HEADER_LENGTH
;
207 if (i
< HANDSHAKE_DESCRIPTORS
) {
208 debug_printf(str
, "%s\n", desc
->description
);
209 parsed_data
= generic_parser(bytes
,
221 debug_print(str
, "ignored\n");
222 debug_hex(str
, bytes
, msg_length
);
226 length
-= msg_length
;
229 debug_print(str
, "------\n");
236 free_parsed_data(parsed_data
);
243 #define TLS_RECORD_HEADER_LENGTH 5
244 #define TLS_RECORD_OFFSET_TYPE 0
245 #define TLS_RECORD_TYPE_HANDSHAKE 22
246 #define TLS_RECORD_OFFSET_MAJOR 1
247 #define TLS_RECORD_OFFSET_MINOR 2
248 #define TLS_RECORD_OFFSET_LENGTH 3
250 /* NOTE: we don't support record fragmentation */
251 static gpointer
tls_record_parse(const guchar
*bytes
,
255 gpointer parsed_data
= NULL
;
257 const gchar
*version
= NULL
;
263 if (sipe_backend_debug_enabled()) {
264 str
= g_string_new("");
265 debug_printf(str
, "TLS MESSAGE %s\n",
266 incoming
? "INCOMING" : "OUTGOING");
269 /* truncated header check */
270 if (length
< TLS_RECORD_HEADER_LENGTH
) {
271 SIPE_DEBUG_ERROR("tls_record_parse: too short TLS record header (%" G_GSIZE_FORMAT
" bytes)",
276 /* protocol version check */
277 major
= bytes
[TLS_RECORD_OFFSET_MAJOR
];
278 minor
= bytes
[TLS_RECORD_OFFSET_MINOR
];
280 SIPE_DEBUG_ERROR_NOFORMAT("tls_record_parse: SSL1/2 not supported");
286 SIPE_DEBUG_ERROR_NOFORMAT("tls_record_parse: SSL3.0 not supported");
289 version
= "1.0 (RFC2246)";
292 version
= "1.1 (RFC4346)";
297 /* should be backwards compatible */
298 version
= "<future protocol version>";
301 /* record length check */
302 record_length
= TLS_RECORD_HEADER_LENGTH
+
303 (bytes
[TLS_RECORD_OFFSET_LENGTH
] << 8) +
304 bytes
[TLS_RECORD_OFFSET_LENGTH
+ 1];
305 if (record_length
> length
) {
306 SIPE_DEBUG_ERROR_NOFORMAT("tls_record_parse: record too long");
310 /* TLS record header OK */
311 debug_printf(str
, "TLS %s record (%" G_GSIZE_FORMAT
" bytes)\n",
313 content_type
= bytes
[TLS_RECORD_OFFSET_TYPE
];
314 length
-= TLS_RECORD_HEADER_LENGTH
;
315 bytes
+= TLS_RECORD_HEADER_LENGTH
;
317 switch (content_type
) {
318 case TLS_RECORD_TYPE_HANDSHAKE
:
319 parsed_data
= handshake_parse(bytes
, length
, incoming
, str
);
323 debug_printf(str
, "TLS ignored type %d\n", content_type
);
324 debug_hex(str
, bytes
, length
);
329 SIPE_DEBUG_INFO_NOFORMAT(str
->str
);
330 g_string_free(str
, TRUE
);
336 static const guchar
const client_hello
[] = {
339 /* Extracted from log file */
341 0x16, /* ContenType: handshake(22) */
342 0x03, 0x01, /* ProtocolVersion: 3.1 (= TLS 1.0) */
343 0x00, 0x48, /* length: 72 bytes */
344 /* TLS Record fragment -> 72 bytes */
345 /* Handshake (header) */
346 0x01, /* msg_type: client_hello(1) */
347 0x00, 0x00, 0x44, /* length: 68 bytes */
348 /* Handshake (body) */
350 0x03, 0x01, /* ProtocolVersion: 3.1 (= TLS 1.0) */
351 /* Random: (32 bytes) */
352 0x4e, 0x81, 0xa7, 0x63, /* uint32 gmt_unix_time */
353 0x15, 0xfd, 0x06, 0x46, /* random_bytes[28] */
354 0x0a, 0xb2, 0xdf, 0xf0,
355 0x85, 0x14, 0xac, 0x60,
356 0x7e, 0xda, 0x48, 0x3c,
357 0xb2, 0xad, 0x5b, 0x0f,
358 0xf3, 0xe4, 0x4e, 0x5d,
359 0x4b, 0x9f, 0x8e, 0xd6,
360 /* session_id: (0..32 bytes) */
361 0x00, /* = 0 -> no SessionID */
362 /* cipher_suites: (2..2^16-1 bytes) */
363 0x00, 0x16, /* = 22 bytes -> 11 CipherSuites */
364 0x00, 0x04, /* TLS_RSA_WITH_RC4_128_MD5 */
365 0x00, 0x05, /* TLS_RSA_WITH_RC4_128_SHA */
366 0x00, 0x0a, /* TLS_RSA_WITH_3DES_EDE_CBC_SHA */
367 0x00, 0x09, /* TLS_RSA_WITH_DES_CBC_SHA */
368 0x00, 0x64, /* NON-STANDARD */
369 0x00, 0x62, /* NON-STANDARD */
370 0x00, 0x03, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 */
371 0x00, 0x06, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 */
372 0x00, 0x13, /* TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA */
373 0x00, 0x12, /* TLS_DHE_DSS_WITH_DES_CBC_SHA */
374 0x00, 0x63, /* NON-STANDARD */
375 /* compr_methods: (1..2^8-1 bytes) */
376 0x01, /* = 1 byte -> 1 CompressionMethod */
378 /* TLS Extended Client Hello (RFC3546) */
379 /* extensions: (0..2^16-1) */
380 0x00, 0x05, /* = 5 bytes */
381 0xff, 0x01, /* ExtensionType: (= 0xFF01) */
382 /* extension_data: (0..2^16-1 byt) */
383 0x00, 0x01, /* = 1 byte */
387 0x16, /* ContenType: handshake(22) */
388 0x03, 0x01, /* ProtocolVersion: 3.1 (= TLS 1.0) */
389 0x00, 0x31, /* length: 49 bytes */
390 /* TLS Record fragment -> 72 bytes */
391 /* Handshake (header) */
392 0x01, /* msg_type: client_hello(1) */
393 0x00, 0x00, 0x2d, /* length: 45 bytes */
394 /* Handshake (body) */
396 0x03, 0x01, /* ProtocolVersion: 3.1 (= TLS 1.0) */
397 /* Random: (32 bytes) */
398 #define GMT_OFFSET 11
399 0x4e, 0x81, 0xa7, 0x63, /* uint32 gmt_unix_time */
400 #define RANDOM_OFFSET 15
401 0x15, 0xfd, 0x06, 0x46, /* random_bytes[28] */
402 0x0a, 0xb2, 0xdf, 0xf0,
403 0x85, 0x14, 0xac, 0x60,
404 0x7e, 0xda, 0x48, 0x3c,
405 0xb2, 0xad, 0x5b, 0x0f,
406 0xf3, 0xe4, 0x4e, 0x5d,
407 0x4b, 0x9f, 0x8e, 0xd6,
408 /* session_id: (0..32 bytes) */
409 0x00, /* = 0 -> no SessionID */
410 /* cipher_suites: (2..2^16-1 bytes) */
411 0x00, 0x06, /* = 6 bytes -> 3 CipherSuites */
412 0x00, 0x04, /* TLS_RSA_WITH_RC4_128_MD5 */
413 0x00, 0x05, /* TLS_RSA_WITH_RC4_128_SHA */
414 0x00, 0x03, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 */
415 /* compr_methods: (1..2^8-1 bytes) */
416 0x01, /* = 1 byte -> 1 CompressionMethod */
421 static gboolean
tls_client_hello(struct tls_internal_state
*state
)
423 guchar
*msg
= g_memdup(client_hello
, sizeof(client_hello
));
424 guint32 now
= time(NULL
);
425 guint32 now_N
= GUINT32_TO_BE(now
);
429 memcpy(msg
+ GMT_OFFSET
, &now_N
, sizeof(now_N
));
430 for (p
= msg
+ RANDOM_OFFSET
, i
= 0; i
< 2; i
++)
431 *p
++ = rand() & 0xFF;
433 state
->common
.out_buffer
= msg
;
434 state
->common
.out_length
= sizeof(client_hello
);
435 state
->state
= TLS_HANDSHAKE_STATE_SERVER_HELLO
;
437 tls_record_parse(msg
, sizeof(client_hello
), FALSE
);
442 static gboolean
tls_server_hello(struct tls_internal_state
*state
)
444 gpointer parsed_data
= tls_record_parse(state
->common
.in_buffer
,
445 state
->common
.in_length
,
452 state
->common
.out_buffer
= NULL
;
453 state
->common
.out_length
= 0;
454 state
->state
= TLS_HANDSHAKE_STATE_FINISHED
;
456 tls_record_parse(state
->common
.out_buffer
,
457 state
->common
.out_length
,
460 return(state
->common
.out_buffer
!= NULL
);
463 static gboolean
tls_finished(struct tls_internal_state
*state
)
465 gpointer parsed_data
= tls_record_parse(state
->common
.in_buffer
,
466 state
->common
.in_length
,
472 /* TBD: data is really not needed? */
473 free_parsed_data(parsed_data
);
475 state
->common
.out_buffer
= NULL
;
476 state
->common
.out_length
= 0;
477 state
->state
= TLS_HANDSHAKE_STATE_COMPLETED
;
485 struct sipe_tls_state
*sipe_tls_start(gpointer certificate
)
487 struct tls_internal_state
*state
;
492 state
= g_new0(struct tls_internal_state
, 1);
493 state
->certificate
= certificate
;
494 state
->state
= TLS_HANDSHAKE_STATE_START
;
496 return((struct sipe_tls_state
*) state
);
499 gboolean
sipe_tls_next(struct sipe_tls_state
*state
)
501 struct tls_internal_state
*internal
= (struct tls_internal_state
*) state
;
502 gboolean success
= FALSE
;
507 state
->out_buffer
= NULL
;
509 switch (internal
->state
) {
510 case TLS_HANDSHAKE_STATE_START
:
511 success
= tls_client_hello(internal
);
514 case TLS_HANDSHAKE_STATE_SERVER_HELLO
:
515 success
= tls_server_hello(internal
);
518 case TLS_HANDSHAKE_STATE_FINISHED
:
519 success
= tls_finished(internal
);
522 case TLS_HANDSHAKE_STATE_COMPLETED
:
523 case TLS_HANDSHAKE_STATE_FAILED
:
524 /* This should not happen */
525 SIPE_DEBUG_ERROR_NOFORMAT("sipe_tls_next: called in incorrect state!");
530 internal
->state
= TLS_HANDSHAKE_STATE_FAILED
;
536 void sipe_tls_free(struct sipe_tls_state
*state
)
539 g_free(state
->session_key
);
540 g_free(state
->out_buffer
);