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
;
67 * TLS message debugging
69 static void debug_hex(GString
*str
,
70 struct tls_internal_state
*state
)
78 bytes
= state
->parse_buffer
;
79 length
= state
->parse_length
;
82 while (length
-- > 0) {
85 } else if ((count
% 16) == 0) {
86 g_string_append(str
, "\n");
87 } else if ((count
% 8) == 0) {
88 g_string_append(str
, " ");
90 g_string_append_printf(str
, " %02X", *bytes
++);
92 g_string_append(str
, "\n");
95 static void debug_print(GString
*str
,
99 g_string_append(str
, string
);
102 static void debug_printf(GString
*str
,
104 ...) G_GNUC_PRINTF(2, 3);
105 static void debug_printf(GString
*str
,
113 va_start(ap
, format
);
114 g_string_append_vprintf(str
, format
, ap
);
120 * TLS message parsing
122 struct parse_descriptor
{
126 struct msg_descriptor
{
128 const gchar
*description
;
129 const struct parse_descriptor
*parse
;
132 static void free_parsed_data(gpointer parsed_data
)
138 static gpointer
generic_parser(struct tls_internal_state
*state
,
141 const struct parse_descriptor
*desc
,
142 gpointer parsed_data
)
145 debug_hex(str
, state
);
152 #define TLS_HANDSHAKE_HEADER_LENGTH 4
153 #define TLS_HANDSHAKE_OFFSET_TYPE 0
154 #define TLS_HANDSHAKE_TYPE_CLIENT_HELLO 1
155 #define TLS_HANDSHAKE_TYPE_SERVER_HELLO 2
156 #define TLS_HANDSHAKE_TYPE_CERTIFICATE 11
157 #define TLS_HANDSHAKE_TYPE_CERTIFICATE_REQ 13
158 #define TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE 14
159 #define TLS_HANDSHAKE_OFFSET_LENGTH 1
161 static gpointer
handshake_parse(struct tls_internal_state
*state
,
165 static const struct msg_descriptor
const handshake_descriptors
[] = {
166 { TLS_HANDSHAKE_TYPE_CLIENT_HELLO
, "Client Hello", NULL
},
167 { TLS_HANDSHAKE_TYPE_SERVER_HELLO
, "Server Hello", NULL
},
168 { TLS_HANDSHAKE_TYPE_CERTIFICATE
, "Certificate", NULL
},
169 { TLS_HANDSHAKE_TYPE_CERTIFICATE_REQ
, "Certificate Request", NULL
},
170 { TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE
, "Server Hello Done", NULL
}
172 #define HANDSHAKE_DESCRIPTORS (sizeof(handshake_descriptors)/sizeof(struct msg_descriptor))
174 const guchar
*bytes
= state
->parse_buffer
;
175 gsize length
= state
->parse_length
;
176 gpointer parsed_data
= NULL
;
177 gboolean success
= FALSE
;
180 const struct msg_descriptor
*desc
;
185 if (length
< TLS_HANDSHAKE_HEADER_LENGTH
) {
186 debug_print(str
, "CORRUPTED HANDSHAKE HEADER");
190 /* msg length check */
191 msg_length
= (bytes
[TLS_HANDSHAKE_OFFSET_LENGTH
] << 16) +
192 (bytes
[TLS_HANDSHAKE_OFFSET_LENGTH
+ 1] << 8) +
193 bytes
[TLS_HANDSHAKE_OFFSET_LENGTH
+ 2];
194 if (msg_length
> length
) {
195 debug_print(str
, "HANDSHAKE MESSAGE TOO LONG");
200 msg_type
= bytes
[TLS_HANDSHAKE_OFFSET_TYPE
];
201 for (desc
= handshake_descriptors
, i
= 0;
202 i
< HANDSHAKE_DESCRIPTORS
;
204 if (msg_type
== desc
->type
)
208 debug_printf(str
, "TLS handshake (%" G_GSIZE_FORMAT
" bytes) (%d)",
209 msg_length
, msg_type
);
211 state
->parse_buffer
= bytes
+ TLS_HANDSHAKE_HEADER_LENGTH
;
212 state
->parse_length
= msg_length
;
214 if (i
< HANDSHAKE_DESCRIPTORS
) {
215 debug_printf(str
, "%s\n", desc
->description
);
216 parsed_data
= generic_parser(state
,
227 debug_print(str
, "ignored\n");
228 debug_hex(str
, state
);
232 bytes
+= TLS_HANDSHAKE_HEADER_LENGTH
+ msg_length
;
233 length
-= TLS_HANDSHAKE_HEADER_LENGTH
+ msg_length
;
235 debug_print(str
, "------\n");
242 free_parsed_data(parsed_data
);
249 #define TLS_RECORD_HEADER_LENGTH 5
250 #define TLS_RECORD_OFFSET_TYPE 0
251 #define TLS_RECORD_TYPE_HANDSHAKE 22
252 #define TLS_RECORD_OFFSET_MAJOR 1
253 #define TLS_RECORD_OFFSET_MINOR 2
254 #define TLS_RECORD_OFFSET_LENGTH 3
256 /* NOTE: we don't support record fragmentation */
257 static gpointer
tls_record_parse(struct tls_internal_state
*state
,
260 const guchar
*bytes
= incoming
? state
->common
.in_buffer
: state
->common
.out_buffer
;
261 gsize length
= incoming
? state
->common
.in_length
: state
->common
.out_length
;
262 gpointer parsed_data
= NULL
;
264 const gchar
*version
= NULL
;
270 if (sipe_backend_debug_enabled()) {
271 str
= g_string_new("");
272 debug_printf(str
, "TLS MESSAGE %s\n",
273 incoming
? "INCOMING" : "OUTGOING");
276 /* truncated header check */
277 if (length
< TLS_RECORD_HEADER_LENGTH
) {
278 SIPE_DEBUG_ERROR("tls_record_parse: too short TLS record header (%" G_GSIZE_FORMAT
" bytes)",
283 /* protocol version check */
284 major
= bytes
[TLS_RECORD_OFFSET_MAJOR
];
285 minor
= bytes
[TLS_RECORD_OFFSET_MINOR
];
287 SIPE_DEBUG_ERROR_NOFORMAT("tls_record_parse: SSL1/2 not supported");
293 SIPE_DEBUG_ERROR_NOFORMAT("tls_record_parse: SSL3.0 not supported");
296 version
= "1.0 (RFC2246)";
299 version
= "1.1 (RFC4346)";
304 /* should be backwards compatible */
305 version
= "<future protocol version>";
308 /* record length check */
309 record_length
= TLS_RECORD_HEADER_LENGTH
+
310 (bytes
[TLS_RECORD_OFFSET_LENGTH
] << 8) +
311 bytes
[TLS_RECORD_OFFSET_LENGTH
+ 1];
312 if (record_length
> length
) {
313 SIPE_DEBUG_ERROR_NOFORMAT("tls_record_parse: record too long");
317 /* TLS record header OK */
318 debug_printf(str
, "TLS %s record (%" G_GSIZE_FORMAT
" bytes)\n",
320 content_type
= bytes
[TLS_RECORD_OFFSET_TYPE
];
321 state
->parse_buffer
= bytes
+ TLS_RECORD_HEADER_LENGTH
;
322 state
->parse_length
= length
- TLS_RECORD_HEADER_LENGTH
;
324 switch (content_type
) {
325 case TLS_RECORD_TYPE_HANDSHAKE
:
326 parsed_data
= handshake_parse(state
, incoming
, str
);
330 debug_printf(str
, "TLS ignored type %d\n", content_type
);
331 debug_hex(str
, state
);
336 SIPE_DEBUG_INFO_NOFORMAT(str
->str
);
337 g_string_free(str
, TRUE
);
343 static const guchar
const client_hello
[] = {
346 /* Extracted from log file */
348 0x16, /* ContenType: handshake(22) */
349 0x03, 0x01, /* ProtocolVersion: 3.1 (= TLS 1.0) */
350 0x00, 0x48, /* length: 72 bytes */
351 /* TLS Record fragment -> 72 bytes */
352 /* Handshake (header) */
353 0x01, /* msg_type: client_hello(1) */
354 0x00, 0x00, 0x44, /* length: 68 bytes */
355 /* Handshake (body) */
357 0x03, 0x01, /* ProtocolVersion: 3.1 (= TLS 1.0) */
358 /* Random: (32 bytes) */
359 0x4e, 0x81, 0xa7, 0x63, /* uint32 gmt_unix_time */
360 0x15, 0xfd, 0x06, 0x46, /* random_bytes[28] */
361 0x0a, 0xb2, 0xdf, 0xf0,
362 0x85, 0x14, 0xac, 0x60,
363 0x7e, 0xda, 0x48, 0x3c,
364 0xb2, 0xad, 0x5b, 0x0f,
365 0xf3, 0xe4, 0x4e, 0x5d,
366 0x4b, 0x9f, 0x8e, 0xd6,
367 /* session_id: (0..32 bytes) */
368 0x00, /* = 0 -> no SessionID */
369 /* cipher_suites: (2..2^16-1 bytes) */
370 0x00, 0x16, /* = 22 bytes -> 11 CipherSuites */
371 0x00, 0x04, /* TLS_RSA_WITH_RC4_128_MD5 */
372 0x00, 0x05, /* TLS_RSA_WITH_RC4_128_SHA */
373 0x00, 0x0a, /* TLS_RSA_WITH_3DES_EDE_CBC_SHA */
374 0x00, 0x09, /* TLS_RSA_WITH_DES_CBC_SHA */
375 0x00, 0x64, /* NON-STANDARD */
376 0x00, 0x62, /* NON-STANDARD */
377 0x00, 0x03, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 */
378 0x00, 0x06, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 */
379 0x00, 0x13, /* TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA */
380 0x00, 0x12, /* TLS_DHE_DSS_WITH_DES_CBC_SHA */
381 0x00, 0x63, /* NON-STANDARD */
382 /* compr_methods: (1..2^8-1 bytes) */
383 0x01, /* = 1 byte -> 1 CompressionMethod */
385 /* TLS Extended Client Hello (RFC3546) */
386 /* extensions: (0..2^16-1) */
387 0x00, 0x05, /* = 5 bytes */
388 0xff, 0x01, /* ExtensionType: (= 0xFF01) */
389 /* extension_data: (0..2^16-1 byt) */
390 0x00, 0x01, /* = 1 byte */
394 0x16, /* ContenType: handshake(22) */
395 0x03, 0x01, /* ProtocolVersion: 3.1 (= TLS 1.0) */
396 0x00, 0x31, /* length: 49 bytes */
397 /* TLS Record fragment -> 72 bytes */
398 /* Handshake (header) */
399 0x01, /* msg_type: client_hello(1) */
400 0x00, 0x00, 0x2d, /* length: 45 bytes */
401 /* Handshake (body) */
403 0x03, 0x01, /* ProtocolVersion: 3.1 (= TLS 1.0) */
404 /* Random: (32 bytes) */
405 #define GMT_OFFSET 11
406 0x4e, 0x81, 0xa7, 0x63, /* uint32 gmt_unix_time */
407 #define RANDOM_OFFSET 15
408 0x15, 0xfd, 0x06, 0x46, /* random_bytes[28] */
409 0x0a, 0xb2, 0xdf, 0xf0,
410 0x85, 0x14, 0xac, 0x60,
411 0x7e, 0xda, 0x48, 0x3c,
412 0xb2, 0xad, 0x5b, 0x0f,
413 0xf3, 0xe4, 0x4e, 0x5d,
414 0x4b, 0x9f, 0x8e, 0xd6,
415 /* session_id: (0..32 bytes) */
416 0x00, /* = 0 -> no SessionID */
417 /* cipher_suites: (2..2^16-1 bytes) */
418 0x00, 0x06, /* = 6 bytes -> 3 CipherSuites */
419 0x00, 0x04, /* TLS_RSA_WITH_RC4_128_MD5 */
420 0x00, 0x05, /* TLS_RSA_WITH_RC4_128_SHA */
421 0x00, 0x03, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 */
422 /* compr_methods: (1..2^8-1 bytes) */
423 0x01, /* = 1 byte -> 1 CompressionMethod */
428 static gboolean
tls_client_hello(struct tls_internal_state
*state
)
430 guchar
*msg
= g_memdup(client_hello
, sizeof(client_hello
));
431 guint32 now
= time(NULL
);
432 guint32 now_N
= GUINT32_TO_BE(now
);
436 memcpy(msg
+ GMT_OFFSET
, &now_N
, sizeof(now_N
));
437 for (p
= msg
+ RANDOM_OFFSET
, i
= 0; i
< 2; i
++)
438 *p
++ = rand() & 0xFF;
440 state
->common
.out_buffer
= msg
;
441 state
->common
.out_length
= sizeof(client_hello
);
442 state
->state
= TLS_HANDSHAKE_STATE_SERVER_HELLO
;
444 tls_record_parse(state
, FALSE
);
449 static gboolean
tls_server_hello(struct tls_internal_state
*state
)
451 gpointer parsed_data
= tls_record_parse(state
, TRUE
);
457 state
->common
.out_buffer
= NULL
;
458 state
->common
.out_length
= 0;
459 state
->state
= TLS_HANDSHAKE_STATE_FINISHED
;
461 tls_record_parse(state
, FALSE
);
463 return(state
->common
.out_buffer
!= NULL
);
466 static gboolean
tls_finished(struct tls_internal_state
*state
)
468 gpointer parsed_data
= tls_record_parse(state
, TRUE
);
473 /* TBD: data is really not needed? */
474 free_parsed_data(parsed_data
);
476 state
->common
.out_buffer
= NULL
;
477 state
->common
.out_length
= 0;
478 state
->state
= TLS_HANDSHAKE_STATE_COMPLETED
;
486 struct sipe_tls_state
*sipe_tls_start(gpointer certificate
)
488 struct tls_internal_state
*state
;
493 state
= g_new0(struct tls_internal_state
, 1);
494 state
->certificate
= certificate
;
495 state
->state
= TLS_HANDSHAKE_STATE_START
;
497 return((struct sipe_tls_state
*) state
);
500 gboolean
sipe_tls_next(struct sipe_tls_state
*state
)
502 struct tls_internal_state
*internal
= (struct tls_internal_state
*) state
;
503 gboolean success
= FALSE
;
508 state
->out_buffer
= NULL
;
510 switch (internal
->state
) {
511 case TLS_HANDSHAKE_STATE_START
:
512 success
= tls_client_hello(internal
);
515 case TLS_HANDSHAKE_STATE_SERVER_HELLO
:
516 success
= tls_server_hello(internal
);
519 case TLS_HANDSHAKE_STATE_FINISHED
:
520 success
= tls_finished(internal
);
523 case TLS_HANDSHAKE_STATE_COMPLETED
:
524 case TLS_HANDSHAKE_STATE_FAILED
:
525 /* This should not happen */
526 SIPE_DEBUG_ERROR_NOFORMAT("sipe_tls_next: called in incorrect state!");
531 internal
->state
= TLS_HANDSHAKE_STATE_FAILED
;
537 void sipe_tls_free(struct sipe_tls_state
*state
)
540 g_free(state
->session_key
);
541 g_free(state
->out_buffer
);