hostapd: Update vendor branch to 0.6.10
[dragonfly.git] / contrib / hostapd / src / tls / tlsv1_client_read.c
blobee20330ce2c6b6174da4f034cf39a48fa49df013
1 /*
2 * TLSv1 client - read handshake message
3 * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
17 #include "common.h"
18 #include "md5.h"
19 #include "sha1.h"
20 #include "x509v3.h"
21 #include "tls.h"
22 #include "tlsv1_common.h"
23 #include "tlsv1_record.h"
24 #include "tlsv1_client.h"
25 #include "tlsv1_client_i.h"
27 static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
28 const u8 *in_data, size_t *in_len);
29 static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
30 const u8 *in_data, size_t *in_len);
31 static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
32 const u8 *in_data, size_t *in_len);
35 static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct,
36 const u8 *in_data, size_t *in_len)
38 const u8 *pos, *end;
39 size_t left, len, i;
40 u16 cipher_suite;
42 if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
43 wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
44 "received content type 0x%x", ct);
45 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
46 TLS_ALERT_UNEXPECTED_MESSAGE);
47 return -1;
50 pos = in_data;
51 left = *in_len;
53 if (left < 4)
54 goto decode_error;
56 /* HandshakeType msg_type */
57 if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) {
58 wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
59 "message %d (expected ServerHello)", *pos);
60 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
61 TLS_ALERT_UNEXPECTED_MESSAGE);
62 return -1;
64 wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello");
65 pos++;
66 /* uint24 length */
67 len = WPA_GET_BE24(pos);
68 pos += 3;
69 left -= 4;
71 if (len > left)
72 goto decode_error;
74 /* body - ServerHello */
76 wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len);
77 end = pos + len;
79 /* ProtocolVersion server_version */
80 if (end - pos < 2)
81 goto decode_error;
82 if (WPA_GET_BE16(pos) != TLS_VERSION) {
83 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "
84 "ServerHello");
85 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
86 TLS_ALERT_PROTOCOL_VERSION);
87 return -1;
89 pos += 2;
91 /* Random random */
92 if (end - pos < TLS_RANDOM_LEN)
93 goto decode_error;
95 os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN);
96 pos += TLS_RANDOM_LEN;
97 wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random",
98 conn->server_random, TLS_RANDOM_LEN);
100 /* SessionID session_id */
101 if (end - pos < 1)
102 goto decode_error;
103 if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN)
104 goto decode_error;
105 if (conn->session_id_len && conn->session_id_len == *pos &&
106 os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) {
107 pos += 1 + conn->session_id_len;
108 wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session");
109 conn->session_resumed = 1;
110 } else {
111 conn->session_id_len = *pos;
112 pos++;
113 os_memcpy(conn->session_id, pos, conn->session_id_len);
114 pos += conn->session_id_len;
116 wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id",
117 conn->session_id, conn->session_id_len);
119 /* CipherSuite cipher_suite */
120 if (end - pos < 2)
121 goto decode_error;
122 cipher_suite = WPA_GET_BE16(pos);
123 pos += 2;
124 for (i = 0; i < conn->num_cipher_suites; i++) {
125 if (cipher_suite == conn->cipher_suites[i])
126 break;
128 if (i == conn->num_cipher_suites) {
129 wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
130 "cipher suite 0x%04x", cipher_suite);
131 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
132 TLS_ALERT_ILLEGAL_PARAMETER);
133 return -1;
136 if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) {
137 wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different "
138 "cipher suite for a resumed connection (0x%04x != "
139 "0x%04x)", cipher_suite, conn->prev_cipher_suite);
140 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
141 TLS_ALERT_ILLEGAL_PARAMETER);
142 return -1;
145 if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) {
146 wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for "
147 "record layer");
148 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
149 TLS_ALERT_INTERNAL_ERROR);
150 return -1;
153 conn->prev_cipher_suite = cipher_suite;
155 /* CompressionMethod compression_method */
156 if (end - pos < 1)
157 goto decode_error;
158 if (*pos != TLS_COMPRESSION_NULL) {
159 wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
160 "compression 0x%02x", *pos);
161 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
162 TLS_ALERT_ILLEGAL_PARAMETER);
163 return -1;
165 pos++;
167 if (end != pos) {
168 /* TODO: ServerHello extensions */
169 wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the "
170 "end of ServerHello", pos, end - pos);
171 goto decode_error;
174 if (conn->session_ticket_included && conn->session_ticket_cb) {
175 /* TODO: include SessionTicket extension if one was included in
176 * ServerHello */
177 int res = conn->session_ticket_cb(
178 conn->session_ticket_cb_ctx, NULL, 0,
179 conn->client_random, conn->server_random,
180 conn->master_secret);
181 if (res < 0) {
182 wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback "
183 "indicated failure");
184 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
185 TLS_ALERT_HANDSHAKE_FAILURE);
186 return -1;
188 conn->use_session_ticket = !!res;
191 if ((conn->session_resumed || conn->use_session_ticket) &&
192 tls_derive_keys(conn, NULL, 0)) {
193 wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
194 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
195 TLS_ALERT_INTERNAL_ERROR);
196 return -1;
199 *in_len = end - in_data;
201 conn->state = (conn->session_resumed || conn->use_session_ticket) ?
202 SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE;
204 return 0;
206 decode_error:
207 wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello");
208 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
209 return -1;
213 static int tls_process_certificate(struct tlsv1_client *conn, u8 ct,
214 const u8 *in_data, size_t *in_len)
216 const u8 *pos, *end;
217 size_t left, len, list_len, cert_len, idx;
218 u8 type;
219 struct x509_certificate *chain = NULL, *last = NULL, *cert;
220 int reason;
222 if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
223 wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
224 "received content type 0x%x", ct);
225 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
226 TLS_ALERT_UNEXPECTED_MESSAGE);
227 return -1;
230 pos = in_data;
231 left = *in_len;
233 if (left < 4) {
234 wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message "
235 "(len=%lu)", (unsigned long) left);
236 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
237 return -1;
240 type = *pos++;
241 len = WPA_GET_BE24(pos);
242 pos += 3;
243 left -= 4;
245 if (len > left) {
246 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message "
247 "length (len=%lu != left=%lu)",
248 (unsigned long) len, (unsigned long) left);
249 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
250 return -1;
253 if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE)
254 return tls_process_server_key_exchange(conn, ct, in_data,
255 in_len);
256 if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
257 return tls_process_certificate_request(conn, ct, in_data,
258 in_len);
259 if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
260 return tls_process_server_hello_done(conn, ct, in_data,
261 in_len);
262 if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) {
263 wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
264 "message %d (expected Certificate/"
265 "ServerKeyExchange/CertificateRequest/"
266 "ServerHelloDone)", type);
267 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
268 TLS_ALERT_UNEXPECTED_MESSAGE);
269 return -1;
272 wpa_printf(MSG_DEBUG,
273 "TLSv1: Received Certificate (certificate_list len %lu)",
274 (unsigned long) len);
277 * opaque ASN.1Cert<2^24-1>;
279 * struct {
280 * ASN.1Cert certificate_list<1..2^24-1>;
281 * } Certificate;
284 end = pos + len;
286 if (end - pos < 3) {
287 wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate "
288 "(left=%lu)", (unsigned long) left);
289 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
290 return -1;
293 list_len = WPA_GET_BE24(pos);
294 pos += 3;
296 if ((size_t) (end - pos) != list_len) {
297 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list "
298 "length (len=%lu left=%lu)",
299 (unsigned long) list_len,
300 (unsigned long) (end - pos));
301 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
302 return -1;
305 idx = 0;
306 while (pos < end) {
307 if (end - pos < 3) {
308 wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
309 "certificate_list");
310 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
311 TLS_ALERT_DECODE_ERROR);
312 x509_certificate_chain_free(chain);
313 return -1;
316 cert_len = WPA_GET_BE24(pos);
317 pos += 3;
319 if ((size_t) (end - pos) < cert_len) {
320 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate "
321 "length (len=%lu left=%lu)",
322 (unsigned long) cert_len,
323 (unsigned long) (end - pos));
324 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
325 TLS_ALERT_DECODE_ERROR);
326 x509_certificate_chain_free(chain);
327 return -1;
330 wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)",
331 (unsigned long) idx, (unsigned long) cert_len);
333 if (idx == 0) {
334 crypto_public_key_free(conn->server_rsa_key);
335 if (tls_parse_cert(pos, cert_len,
336 &conn->server_rsa_key)) {
337 wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
338 "the certificate");
339 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
340 TLS_ALERT_BAD_CERTIFICATE);
341 x509_certificate_chain_free(chain);
342 return -1;
346 cert = x509_certificate_parse(pos, cert_len);
347 if (cert == NULL) {
348 wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
349 "the certificate");
350 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
351 TLS_ALERT_BAD_CERTIFICATE);
352 x509_certificate_chain_free(chain);
353 return -1;
356 if (last == NULL)
357 chain = cert;
358 else
359 last->next = cert;
360 last = cert;
362 idx++;
363 pos += cert_len;
366 if (conn->cred &&
367 x509_certificate_chain_validate(conn->cred->trusted_certs, chain,
368 &reason) < 0) {
369 int tls_reason;
370 wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain "
371 "validation failed (reason=%d)", reason);
372 switch (reason) {
373 case X509_VALIDATE_BAD_CERTIFICATE:
374 tls_reason = TLS_ALERT_BAD_CERTIFICATE;
375 break;
376 case X509_VALIDATE_UNSUPPORTED_CERTIFICATE:
377 tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE;
378 break;
379 case X509_VALIDATE_CERTIFICATE_REVOKED:
380 tls_reason = TLS_ALERT_CERTIFICATE_REVOKED;
381 break;
382 case X509_VALIDATE_CERTIFICATE_EXPIRED:
383 tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
384 break;
385 case X509_VALIDATE_CERTIFICATE_UNKNOWN:
386 tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN;
387 break;
388 case X509_VALIDATE_UNKNOWN_CA:
389 tls_reason = TLS_ALERT_UNKNOWN_CA;
390 break;
391 default:
392 tls_reason = TLS_ALERT_BAD_CERTIFICATE;
393 break;
395 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason);
396 x509_certificate_chain_free(chain);
397 return -1;
400 x509_certificate_chain_free(chain);
402 *in_len = end - in_data;
404 conn->state = SERVER_KEY_EXCHANGE;
406 return 0;
410 static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
411 const u8 *buf, size_t len)
413 const u8 *pos, *end;
415 tlsv1_client_free_dh(conn);
417 pos = buf;
418 end = buf + len;
420 if (end - pos < 3)
421 goto fail;
422 conn->dh_p_len = WPA_GET_BE16(pos);
423 pos += 2;
424 if (conn->dh_p_len == 0 || end - pos < (int) conn->dh_p_len) {
425 wpa_printf(MSG_DEBUG, "TLSv1: Invalid dh_p length %lu",
426 (unsigned long) conn->dh_p_len);
427 goto fail;
429 conn->dh_p = os_malloc(conn->dh_p_len);
430 if (conn->dh_p == NULL)
431 goto fail;
432 os_memcpy(conn->dh_p, pos, conn->dh_p_len);
433 pos += conn->dh_p_len;
434 wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)",
435 conn->dh_p, conn->dh_p_len);
437 if (end - pos < 3)
438 goto fail;
439 conn->dh_g_len = WPA_GET_BE16(pos);
440 pos += 2;
441 if (conn->dh_g_len == 0 || end - pos < (int) conn->dh_g_len)
442 goto fail;
443 conn->dh_g = os_malloc(conn->dh_g_len);
444 if (conn->dh_g == NULL)
445 goto fail;
446 os_memcpy(conn->dh_g, pos, conn->dh_g_len);
447 pos += conn->dh_g_len;
448 wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)",
449 conn->dh_g, conn->dh_g_len);
450 if (conn->dh_g_len == 1 && conn->dh_g[0] < 2)
451 goto fail;
453 if (end - pos < 3)
454 goto fail;
455 conn->dh_ys_len = WPA_GET_BE16(pos);
456 pos += 2;
457 if (conn->dh_ys_len == 0 || end - pos < (int) conn->dh_ys_len)
458 goto fail;
459 conn->dh_ys = os_malloc(conn->dh_ys_len);
460 if (conn->dh_ys == NULL)
461 goto fail;
462 os_memcpy(conn->dh_ys, pos, conn->dh_ys_len);
463 pos += conn->dh_ys_len;
464 wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
465 conn->dh_ys, conn->dh_ys_len);
467 return 0;
469 fail:
470 wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed");
471 tlsv1_client_free_dh(conn);
472 return -1;
476 static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
477 const u8 *in_data, size_t *in_len)
479 const u8 *pos, *end;
480 size_t left, len;
481 u8 type;
482 const struct tls_cipher_suite *suite;
484 if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
485 wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
486 "received content type 0x%x", ct);
487 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
488 TLS_ALERT_UNEXPECTED_MESSAGE);
489 return -1;
492 pos = in_data;
493 left = *in_len;
495 if (left < 4) {
496 wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange "
497 "(Left=%lu)", (unsigned long) left);
498 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
499 return -1;
502 type = *pos++;
503 len = WPA_GET_BE24(pos);
504 pos += 3;
505 left -= 4;
507 if (len > left) {
508 wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange "
509 "length (len=%lu != left=%lu)",
510 (unsigned long) len, (unsigned long) left);
511 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
512 return -1;
515 end = pos + len;
517 if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
518 return tls_process_certificate_request(conn, ct, in_data,
519 in_len);
520 if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
521 return tls_process_server_hello_done(conn, ct, in_data,
522 in_len);
523 if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) {
524 wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
525 "message %d (expected ServerKeyExchange/"
526 "CertificateRequest/ServerHelloDone)", type);
527 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
528 TLS_ALERT_UNEXPECTED_MESSAGE);
529 return -1;
532 wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange");
534 if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) {
535 wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed "
536 "with the selected cipher suite");
537 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
538 TLS_ALERT_UNEXPECTED_MESSAGE);
539 return -1;
542 wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len);
543 suite = tls_get_cipher_suite(conn->rl.cipher_suite);
544 if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) {
545 if (tlsv1_process_diffie_hellman(conn, pos, len) < 0) {
546 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
547 TLS_ALERT_DECODE_ERROR);
548 return -1;
550 } else {
551 wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange");
552 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
553 TLS_ALERT_UNEXPECTED_MESSAGE);
554 return -1;
557 *in_len = end - in_data;
559 conn->state = SERVER_CERTIFICATE_REQUEST;
561 return 0;
565 static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
566 const u8 *in_data, size_t *in_len)
568 const u8 *pos, *end;
569 size_t left, len;
570 u8 type;
572 if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
573 wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
574 "received content type 0x%x", ct);
575 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
576 TLS_ALERT_UNEXPECTED_MESSAGE);
577 return -1;
580 pos = in_data;
581 left = *in_len;
583 if (left < 4) {
584 wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest "
585 "(left=%lu)", (unsigned long) left);
586 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
587 return -1;
590 type = *pos++;
591 len = WPA_GET_BE24(pos);
592 pos += 3;
593 left -= 4;
595 if (len > left) {
596 wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest "
597 "length (len=%lu != left=%lu)",
598 (unsigned long) len, (unsigned long) left);
599 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
600 return -1;
603 end = pos + len;
605 if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
606 return tls_process_server_hello_done(conn, ct, in_data,
607 in_len);
608 if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) {
609 wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
610 "message %d (expected CertificateRequest/"
611 "ServerHelloDone)", type);
612 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
613 TLS_ALERT_UNEXPECTED_MESSAGE);
614 return -1;
617 wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest");
619 conn->certificate_requested = 1;
621 *in_len = end - in_data;
623 conn->state = SERVER_HELLO_DONE;
625 return 0;
629 static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
630 const u8 *in_data, size_t *in_len)
632 const u8 *pos, *end;
633 size_t left, len;
634 u8 type;
636 if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
637 wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
638 "received content type 0x%x", ct);
639 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
640 TLS_ALERT_UNEXPECTED_MESSAGE);
641 return -1;
644 pos = in_data;
645 left = *in_len;
647 if (left < 4) {
648 wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone "
649 "(left=%lu)", (unsigned long) left);
650 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
651 return -1;
654 type = *pos++;
655 len = WPA_GET_BE24(pos);
656 pos += 3;
657 left -= 4;
659 if (len > left) {
660 wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone "
661 "length (len=%lu != left=%lu)",
662 (unsigned long) len, (unsigned long) left);
663 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
664 return -1;
666 end = pos + len;
668 if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) {
669 wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
670 "message %d (expected ServerHelloDone)", type);
671 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
672 TLS_ALERT_UNEXPECTED_MESSAGE);
673 return -1;
676 wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone");
678 *in_len = end - in_data;
680 conn->state = CLIENT_KEY_EXCHANGE;
682 return 0;
686 static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn,
687 u8 ct, const u8 *in_data,
688 size_t *in_len)
690 const u8 *pos;
691 size_t left;
693 if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
694 wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
695 "received content type 0x%x", ct);
696 if (conn->use_session_ticket) {
697 int res;
698 wpa_printf(MSG_DEBUG, "TLSv1: Server may have "
699 "rejected SessionTicket");
700 conn->use_session_ticket = 0;
702 /* Notify upper layers that SessionTicket failed */
703 res = conn->session_ticket_cb(
704 conn->session_ticket_cb_ctx, NULL, 0, NULL,
705 NULL, NULL);
706 if (res < 0) {
707 wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket "
708 "callback indicated failure");
709 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
710 TLS_ALERT_HANDSHAKE_FAILURE);
711 return -1;
714 conn->state = SERVER_CERTIFICATE;
715 return tls_process_certificate(conn, ct, in_data,
716 in_len);
718 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
719 TLS_ALERT_UNEXPECTED_MESSAGE);
720 return -1;
723 pos = in_data;
724 left = *in_len;
726 if (left < 1) {
727 wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec");
728 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
729 return -1;
732 if (*pos != TLS_CHANGE_CIPHER_SPEC) {
733 wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
734 "received data 0x%x", *pos);
735 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
736 TLS_ALERT_UNEXPECTED_MESSAGE);
737 return -1;
740 wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec");
741 if (tlsv1_record_change_read_cipher(&conn->rl) < 0) {
742 wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher "
743 "for record layer");
744 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
745 TLS_ALERT_INTERNAL_ERROR);
746 return -1;
749 *in_len = pos + 1 - in_data;
751 conn->state = SERVER_FINISHED;
753 return 0;
757 static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct,
758 const u8 *in_data, size_t *in_len)
760 const u8 *pos, *end;
761 size_t left, len, hlen;
762 u8 verify_data[TLS_VERIFY_DATA_LEN];
763 u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
765 if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
766 wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; "
767 "received content type 0x%x", ct);
768 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
769 TLS_ALERT_UNEXPECTED_MESSAGE);
770 return -1;
773 pos = in_data;
774 left = *in_len;
776 if (left < 4) {
777 wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for "
778 "Finished",
779 (unsigned long) left);
780 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
781 TLS_ALERT_DECODE_ERROR);
782 return -1;
785 if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) {
786 wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received "
787 "type 0x%x", pos[0]);
788 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
789 TLS_ALERT_UNEXPECTED_MESSAGE);
790 return -1;
793 len = WPA_GET_BE24(pos + 1);
795 pos += 4;
796 left -= 4;
798 if (len > left) {
799 wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished "
800 "(len=%lu > left=%lu)",
801 (unsigned long) len, (unsigned long) left);
802 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
803 TLS_ALERT_DECODE_ERROR);
804 return -1;
806 end = pos + len;
807 if (len != TLS_VERIFY_DATA_LEN) {
808 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length "
809 "in Finished: %lu (expected %d)",
810 (unsigned long) len, TLS_VERIFY_DATA_LEN);
811 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
812 TLS_ALERT_DECODE_ERROR);
813 return -1;
815 wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished",
816 pos, TLS_VERIFY_DATA_LEN);
818 hlen = MD5_MAC_LEN;
819 if (conn->verify.md5_server == NULL ||
820 crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) {
821 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
822 TLS_ALERT_INTERNAL_ERROR);
823 conn->verify.md5_server = NULL;
824 crypto_hash_finish(conn->verify.sha1_server, NULL, NULL);
825 conn->verify.sha1_server = NULL;
826 return -1;
828 conn->verify.md5_server = NULL;
829 hlen = SHA1_MAC_LEN;
830 if (conn->verify.sha1_server == NULL ||
831 crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN,
832 &hlen) < 0) {
833 conn->verify.sha1_server = NULL;
834 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
835 TLS_ALERT_INTERNAL_ERROR);
836 return -1;
838 conn->verify.sha1_server = NULL;
840 if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,
841 "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN,
842 verify_data, TLS_VERIFY_DATA_LEN)) {
843 wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data");
844 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
845 TLS_ALERT_DECRYPT_ERROR);
846 return -1;
848 wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
849 verify_data, TLS_VERIFY_DATA_LEN);
851 if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
852 wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data");
853 return -1;
856 wpa_printf(MSG_DEBUG, "TLSv1: Received Finished");
858 *in_len = end - in_data;
860 conn->state = (conn->session_resumed || conn->use_session_ticket) ?
861 CHANGE_CIPHER_SPEC : ACK_FINISHED;
863 return 0;
867 static int tls_process_application_data(struct tlsv1_client *conn, u8 ct,
868 const u8 *in_data, size_t *in_len,
869 u8 **out_data, size_t *out_len)
871 const u8 *pos;
872 size_t left;
874 if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
875 wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; "
876 "received content type 0x%x", ct);
877 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
878 TLS_ALERT_UNEXPECTED_MESSAGE);
879 return -1;
882 pos = in_data;
883 left = *in_len;
885 wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake",
886 pos, left);
888 *out_data = os_malloc(left);
889 if (*out_data) {
890 os_memcpy(*out_data, pos, left);
891 *out_len = left;
894 return 0;
898 int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct,
899 const u8 *buf, size_t *len,
900 u8 **out_data, size_t *out_len)
902 if (ct == TLS_CONTENT_TYPE_ALERT) {
903 if (*len < 2) {
904 wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow");
905 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
906 TLS_ALERT_DECODE_ERROR);
907 return -1;
909 wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
910 buf[0], buf[1]);
911 *len = 2;
912 conn->state = FAILED;
913 return -1;
916 if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 &&
917 buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) {
918 size_t hr_len = WPA_GET_BE24(buf + 1);
919 if (hr_len > *len - 4) {
920 wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow");
921 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
922 TLS_ALERT_DECODE_ERROR);
923 return -1;
925 wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest");
926 *len = 4 + hr_len;
927 return 0;
930 switch (conn->state) {
931 case SERVER_HELLO:
932 if (tls_process_server_hello(conn, ct, buf, len))
933 return -1;
934 break;
935 case SERVER_CERTIFICATE:
936 if (tls_process_certificate(conn, ct, buf, len))
937 return -1;
938 break;
939 case SERVER_KEY_EXCHANGE:
940 if (tls_process_server_key_exchange(conn, ct, buf, len))
941 return -1;
942 break;
943 case SERVER_CERTIFICATE_REQUEST:
944 if (tls_process_certificate_request(conn, ct, buf, len))
945 return -1;
946 break;
947 case SERVER_HELLO_DONE:
948 if (tls_process_server_hello_done(conn, ct, buf, len))
949 return -1;
950 break;
951 case SERVER_CHANGE_CIPHER_SPEC:
952 if (tls_process_server_change_cipher_spec(conn, ct, buf, len))
953 return -1;
954 break;
955 case SERVER_FINISHED:
956 if (tls_process_server_finished(conn, ct, buf, len))
957 return -1;
958 break;
959 case ACK_FINISHED:
960 if (out_data &&
961 tls_process_application_data(conn, ct, buf, len, out_data,
962 out_len))
963 return -1;
964 break;
965 default:
966 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d "
967 "while processing received message",
968 conn->state);
969 return -1;
972 if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
973 tls_verify_hash_add(&conn->verify, buf, *len);
975 return 0;