xref: /freebsd/contrib/wpa/src/tls/tlsv1_client_read.c (revision 85732ac8bccbc0adcf5a261ea1ffec8ca7b3a92d)
139beb93cSSam Leffler /*
239beb93cSSam Leffler  * TLSv1 client - read handshake message
3780fb4a2SCy Schubert  * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
739beb93cSSam Leffler  */
839beb93cSSam Leffler 
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler 
1139beb93cSSam Leffler #include "common.h"
12e28a4053SRui Paulo #include "crypto/md5.h"
13e28a4053SRui Paulo #include "crypto/sha1.h"
14f05cddf9SRui Paulo #include "crypto/sha256.h"
15e28a4053SRui Paulo #include "crypto/tls.h"
1639beb93cSSam Leffler #include "x509v3.h"
1739beb93cSSam Leffler #include "tlsv1_common.h"
1839beb93cSSam Leffler #include "tlsv1_record.h"
1939beb93cSSam Leffler #include "tlsv1_client.h"
2039beb93cSSam Leffler #include "tlsv1_client_i.h"
2139beb93cSSam Leffler 
2239beb93cSSam Leffler static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
2339beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len);
2439beb93cSSam Leffler static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
2539beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len);
2639beb93cSSam Leffler static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
2739beb93cSSam Leffler 					 const u8 *in_data, size_t *in_len);
2839beb93cSSam Leffler 
2939beb93cSSam Leffler 
30780fb4a2SCy Schubert static int tls_version_disabled(struct tlsv1_client *conn, u16 ver)
31780fb4a2SCy Schubert {
32780fb4a2SCy Schubert 	return (((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
33780fb4a2SCy Schubert 		 ver == TLS_VERSION_1) ||
34780fb4a2SCy Schubert 		((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
35780fb4a2SCy Schubert 		 ver == TLS_VERSION_1_1) ||
36780fb4a2SCy Schubert 		((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
37780fb4a2SCy Schubert 		 ver == TLS_VERSION_1_2));
38780fb4a2SCy Schubert }
39780fb4a2SCy Schubert 
40780fb4a2SCy Schubert 
41780fb4a2SCy Schubert static int tls_process_server_hello_extensions(struct tlsv1_client *conn,
42780fb4a2SCy Schubert 					       const u8 *pos, size_t len)
43780fb4a2SCy Schubert {
44780fb4a2SCy Schubert 	const u8 *end = pos + len;
45780fb4a2SCy Schubert 
46780fb4a2SCy Schubert 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello extensions",
47780fb4a2SCy Schubert 		    pos, len);
48780fb4a2SCy Schubert 	while (pos < end) {
49780fb4a2SCy Schubert 		u16 ext, elen;
50780fb4a2SCy Schubert 
51780fb4a2SCy Schubert 		if (end - pos < 4) {
52780fb4a2SCy Schubert 			wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension header");
53780fb4a2SCy Schubert 			return -1;
54780fb4a2SCy Schubert 		}
55780fb4a2SCy Schubert 
56780fb4a2SCy Schubert 		ext = WPA_GET_BE16(pos);
57780fb4a2SCy Schubert 		pos += 2;
58780fb4a2SCy Schubert 		elen = WPA_GET_BE16(pos);
59780fb4a2SCy Schubert 		pos += 2;
60780fb4a2SCy Schubert 
61780fb4a2SCy Schubert 		if (elen > end - pos) {
62780fb4a2SCy Schubert 			wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension");
63780fb4a2SCy Schubert 			return -1;
64780fb4a2SCy Schubert 		}
65780fb4a2SCy Schubert 
66780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "TLSv1: ServerHello ExtensionType %u",
67780fb4a2SCy Schubert 			   ext);
68780fb4a2SCy Schubert 		wpa_hexdump(MSG_DEBUG, "TLSv1: ServerHello extension data",
69780fb4a2SCy Schubert 			    pos, elen);
70780fb4a2SCy Schubert 
71780fb4a2SCy Schubert 		pos += elen;
72780fb4a2SCy Schubert 	}
73780fb4a2SCy Schubert 
74780fb4a2SCy Schubert 	return 0;
75780fb4a2SCy Schubert }
76780fb4a2SCy Schubert 
77780fb4a2SCy Schubert 
7839beb93cSSam Leffler static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct,
7939beb93cSSam Leffler 				    const u8 *in_data, size_t *in_len)
8039beb93cSSam Leffler {
8139beb93cSSam Leffler 	const u8 *pos, *end;
8239beb93cSSam Leffler 	size_t left, len, i;
8339beb93cSSam Leffler 	u16 cipher_suite;
84f05cddf9SRui Paulo 	u16 tls_version;
8539beb93cSSam Leffler 
8639beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
8739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
8839beb93cSSam Leffler 			   "received content type 0x%x", ct);
8939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
9039beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
9139beb93cSSam Leffler 		return -1;
9239beb93cSSam Leffler 	}
9339beb93cSSam Leffler 
9439beb93cSSam Leffler 	pos = in_data;
9539beb93cSSam Leffler 	left = *in_len;
9639beb93cSSam Leffler 
9739beb93cSSam Leffler 	if (left < 4)
9839beb93cSSam Leffler 		goto decode_error;
9939beb93cSSam Leffler 
10039beb93cSSam Leffler 	/* HandshakeType msg_type */
10139beb93cSSam Leffler 	if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) {
10239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
10339beb93cSSam Leffler 			   "message %d (expected ServerHello)", *pos);
10439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
10539beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
10639beb93cSSam Leffler 		return -1;
10739beb93cSSam Leffler 	}
10839beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello");
10939beb93cSSam Leffler 	pos++;
11039beb93cSSam Leffler 	/* uint24 length */
11139beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
11239beb93cSSam Leffler 	pos += 3;
11339beb93cSSam Leffler 	left -= 4;
11439beb93cSSam Leffler 
11539beb93cSSam Leffler 	if (len > left)
11639beb93cSSam Leffler 		goto decode_error;
11739beb93cSSam Leffler 
11839beb93cSSam Leffler 	/* body - ServerHello */
11939beb93cSSam Leffler 
12039beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len);
12139beb93cSSam Leffler 	end = pos + len;
12239beb93cSSam Leffler 
12339beb93cSSam Leffler 	/* ProtocolVersion server_version */
12439beb93cSSam Leffler 	if (end - pos < 2)
12539beb93cSSam Leffler 		goto decode_error;
126f05cddf9SRui Paulo 	tls_version = WPA_GET_BE16(pos);
127780fb4a2SCy Schubert 	if (!tls_version_ok(tls_version) ||
128780fb4a2SCy Schubert 	    tls_version_disabled(conn, tls_version)) {
12939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "
130f05cddf9SRui Paulo 			   "ServerHello %u.%u", pos[0], pos[1]);
13139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
13239beb93cSSam Leffler 			  TLS_ALERT_PROTOCOL_VERSION);
13339beb93cSSam Leffler 		return -1;
13439beb93cSSam Leffler 	}
13539beb93cSSam Leffler 	pos += 2;
13639beb93cSSam Leffler 
137f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "TLSv1: Using TLS v%s",
138f05cddf9SRui Paulo 		   tls_version_str(tls_version));
139f05cddf9SRui Paulo 	conn->rl.tls_version = tls_version;
140f05cddf9SRui Paulo 
14139beb93cSSam Leffler 	/* Random random */
14239beb93cSSam Leffler 	if (end - pos < TLS_RANDOM_LEN)
14339beb93cSSam Leffler 		goto decode_error;
14439beb93cSSam Leffler 
14539beb93cSSam Leffler 	os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN);
14639beb93cSSam Leffler 	pos += TLS_RANDOM_LEN;
14739beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random",
14839beb93cSSam Leffler 		    conn->server_random, TLS_RANDOM_LEN);
14939beb93cSSam Leffler 
15039beb93cSSam Leffler 	/* SessionID session_id */
15139beb93cSSam Leffler 	if (end - pos < 1)
15239beb93cSSam Leffler 		goto decode_error;
15339beb93cSSam Leffler 	if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN)
15439beb93cSSam Leffler 		goto decode_error;
15539beb93cSSam Leffler 	if (conn->session_id_len && conn->session_id_len == *pos &&
15639beb93cSSam Leffler 	    os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) {
15739beb93cSSam Leffler 		pos += 1 + conn->session_id_len;
15839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session");
15939beb93cSSam Leffler 		conn->session_resumed = 1;
16039beb93cSSam Leffler 	} else {
16139beb93cSSam Leffler 		conn->session_id_len = *pos;
16239beb93cSSam Leffler 		pos++;
16339beb93cSSam Leffler 		os_memcpy(conn->session_id, pos, conn->session_id_len);
16439beb93cSSam Leffler 		pos += conn->session_id_len;
16539beb93cSSam Leffler 	}
16639beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id",
16739beb93cSSam Leffler 		    conn->session_id, conn->session_id_len);
16839beb93cSSam Leffler 
16939beb93cSSam Leffler 	/* CipherSuite cipher_suite */
17039beb93cSSam Leffler 	if (end - pos < 2)
17139beb93cSSam Leffler 		goto decode_error;
17239beb93cSSam Leffler 	cipher_suite = WPA_GET_BE16(pos);
17339beb93cSSam Leffler 	pos += 2;
17439beb93cSSam Leffler 	for (i = 0; i < conn->num_cipher_suites; i++) {
17539beb93cSSam Leffler 		if (cipher_suite == conn->cipher_suites[i])
17639beb93cSSam Leffler 			break;
17739beb93cSSam Leffler 	}
17839beb93cSSam Leffler 	if (i == conn->num_cipher_suites) {
17939beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
18039beb93cSSam Leffler 			   "cipher suite 0x%04x", cipher_suite);
18139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
18239beb93cSSam Leffler 			  TLS_ALERT_ILLEGAL_PARAMETER);
18339beb93cSSam Leffler 		return -1;
18439beb93cSSam Leffler 	}
18539beb93cSSam Leffler 
18639beb93cSSam Leffler 	if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) {
18739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different "
18839beb93cSSam Leffler 			   "cipher suite for a resumed connection (0x%04x != "
18939beb93cSSam Leffler 			   "0x%04x)", cipher_suite, conn->prev_cipher_suite);
19039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
19139beb93cSSam Leffler 			  TLS_ALERT_ILLEGAL_PARAMETER);
19239beb93cSSam Leffler 		return -1;
19339beb93cSSam Leffler 	}
19439beb93cSSam Leffler 
19539beb93cSSam Leffler 	if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) {
19639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for "
19739beb93cSSam Leffler 			   "record layer");
19839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
19939beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
20039beb93cSSam Leffler 		return -1;
20139beb93cSSam Leffler 	}
20239beb93cSSam Leffler 
20339beb93cSSam Leffler 	conn->prev_cipher_suite = cipher_suite;
20439beb93cSSam Leffler 
20539beb93cSSam Leffler 	/* CompressionMethod compression_method */
20639beb93cSSam Leffler 	if (end - pos < 1)
20739beb93cSSam Leffler 		goto decode_error;
20839beb93cSSam Leffler 	if (*pos != TLS_COMPRESSION_NULL) {
20939beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
21039beb93cSSam Leffler 			   "compression 0x%02x", *pos);
21139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
21239beb93cSSam Leffler 			  TLS_ALERT_ILLEGAL_PARAMETER);
21339beb93cSSam Leffler 		return -1;
21439beb93cSSam Leffler 	}
21539beb93cSSam Leffler 	pos++;
21639beb93cSSam Leffler 
217780fb4a2SCy Schubert 	if (end - pos >= 2) {
218780fb4a2SCy Schubert 		u16 ext_len;
219780fb4a2SCy Schubert 
220780fb4a2SCy Schubert 		ext_len = WPA_GET_BE16(pos);
221780fb4a2SCy Schubert 		pos += 2;
222780fb4a2SCy Schubert 		if (end - pos < ext_len) {
223780fb4a2SCy Schubert 			wpa_printf(MSG_INFO,
224780fb4a2SCy Schubert 				   "TLSv1: Invalid ServerHello extension length: %u (left: %u)",
225780fb4a2SCy Schubert 				   ext_len, (unsigned int) (end - pos));
226780fb4a2SCy Schubert 			goto decode_error;
227780fb4a2SCy Schubert 		}
228780fb4a2SCy Schubert 
229780fb4a2SCy Schubert 		if (tls_process_server_hello_extensions(conn, pos, ext_len))
230780fb4a2SCy Schubert 			goto decode_error;
231780fb4a2SCy Schubert 		pos += ext_len;
232780fb4a2SCy Schubert 	}
233780fb4a2SCy Schubert 
23439beb93cSSam Leffler 	if (end != pos) {
23539beb93cSSam Leffler 		wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the "
23639beb93cSSam Leffler 			    "end of ServerHello", pos, end - pos);
23739beb93cSSam Leffler 		goto decode_error;
23839beb93cSSam Leffler 	}
23939beb93cSSam Leffler 
24039beb93cSSam Leffler 	if (conn->session_ticket_included && conn->session_ticket_cb) {
24139beb93cSSam Leffler 		/* TODO: include SessionTicket extension if one was included in
24239beb93cSSam Leffler 		 * ServerHello */
24339beb93cSSam Leffler 		int res = conn->session_ticket_cb(
24439beb93cSSam Leffler 			conn->session_ticket_cb_ctx, NULL, 0,
24539beb93cSSam Leffler 			conn->client_random, conn->server_random,
24639beb93cSSam Leffler 			conn->master_secret);
24739beb93cSSam Leffler 		if (res < 0) {
24839beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback "
24939beb93cSSam Leffler 				   "indicated failure");
25039beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
25139beb93cSSam Leffler 				  TLS_ALERT_HANDSHAKE_FAILURE);
25239beb93cSSam Leffler 			return -1;
25339beb93cSSam Leffler 		}
25439beb93cSSam Leffler 		conn->use_session_ticket = !!res;
25539beb93cSSam Leffler 	}
25639beb93cSSam Leffler 
25739beb93cSSam Leffler 	if ((conn->session_resumed || conn->use_session_ticket) &&
25839beb93cSSam Leffler 	    tls_derive_keys(conn, NULL, 0)) {
25939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
26039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
26139beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
26239beb93cSSam Leffler 		return -1;
26339beb93cSSam Leffler 	}
26439beb93cSSam Leffler 
26539beb93cSSam Leffler 	*in_len = end - in_data;
26639beb93cSSam Leffler 
26739beb93cSSam Leffler 	conn->state = (conn->session_resumed || conn->use_session_ticket) ?
26839beb93cSSam Leffler 		SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE;
26939beb93cSSam Leffler 
27039beb93cSSam Leffler 	return 0;
27139beb93cSSam Leffler 
27239beb93cSSam Leffler decode_error:
27339beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello");
27439beb93cSSam Leffler 	tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
27539beb93cSSam Leffler 	return -1;
27639beb93cSSam Leffler }
27739beb93cSSam Leffler 
27839beb93cSSam Leffler 
279780fb4a2SCy Schubert static void tls_peer_cert_event(struct tlsv1_client *conn, int depth,
280780fb4a2SCy Schubert 				struct x509_certificate *cert)
281780fb4a2SCy Schubert {
282780fb4a2SCy Schubert 	union tls_event_data ev;
283780fb4a2SCy Schubert 	struct wpabuf *cert_buf = NULL;
284780fb4a2SCy Schubert #ifdef CONFIG_SHA256
285780fb4a2SCy Schubert 	u8 hash[32];
286780fb4a2SCy Schubert #endif /* CONFIG_SHA256 */
287780fb4a2SCy Schubert 	char subject[128];
288780fb4a2SCy Schubert 
289780fb4a2SCy Schubert 	if (!conn->event_cb)
290780fb4a2SCy Schubert 		return;
291780fb4a2SCy Schubert 
292780fb4a2SCy Schubert 	os_memset(&ev, 0, sizeof(ev));
293780fb4a2SCy Schubert 	if (conn->cred->cert_probe || conn->cert_in_cb) {
294780fb4a2SCy Schubert 		cert_buf = wpabuf_alloc_copy(cert->cert_start,
295780fb4a2SCy Schubert 					     cert->cert_len);
296780fb4a2SCy Schubert 		ev.peer_cert.cert = cert_buf;
297780fb4a2SCy Schubert 	}
298780fb4a2SCy Schubert #ifdef CONFIG_SHA256
299780fb4a2SCy Schubert 	if (cert_buf) {
300780fb4a2SCy Schubert 		const u8 *addr[1];
301780fb4a2SCy Schubert 		size_t len[1];
302780fb4a2SCy Schubert 		addr[0] = wpabuf_head(cert_buf);
303780fb4a2SCy Schubert 		len[0] = wpabuf_len(cert_buf);
304780fb4a2SCy Schubert 		if (sha256_vector(1, addr, len, hash) == 0) {
305780fb4a2SCy Schubert 			ev.peer_cert.hash = hash;
306780fb4a2SCy Schubert 			ev.peer_cert.hash_len = sizeof(hash);
307780fb4a2SCy Schubert 		}
308780fb4a2SCy Schubert 	}
309780fb4a2SCy Schubert #endif /* CONFIG_SHA256 */
310780fb4a2SCy Schubert 
311780fb4a2SCy Schubert 	ev.peer_cert.depth = depth;
312780fb4a2SCy Schubert 	x509_name_string(&cert->subject, subject, sizeof(subject));
313780fb4a2SCy Schubert 	ev.peer_cert.subject = subject;
314780fb4a2SCy Schubert 
315780fb4a2SCy Schubert 	conn->event_cb(conn->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
316780fb4a2SCy Schubert 	wpabuf_free(cert_buf);
317780fb4a2SCy Schubert }
318780fb4a2SCy Schubert 
319780fb4a2SCy Schubert 
320780fb4a2SCy Schubert static void tls_cert_chain_failure_event(struct tlsv1_client *conn, int depth,
321780fb4a2SCy Schubert 					 struct x509_certificate *cert,
322780fb4a2SCy Schubert 					 enum tls_fail_reason reason,
323780fb4a2SCy Schubert 					 const char *reason_txt)
324780fb4a2SCy Schubert {
325780fb4a2SCy Schubert 	struct wpabuf *cert_buf = NULL;
326780fb4a2SCy Schubert 	union tls_event_data ev;
327780fb4a2SCy Schubert 	char subject[128];
328780fb4a2SCy Schubert 
329780fb4a2SCy Schubert 	if (!conn->event_cb || !cert)
330780fb4a2SCy Schubert 		return;
331780fb4a2SCy Schubert 
332780fb4a2SCy Schubert 	os_memset(&ev, 0, sizeof(ev));
333780fb4a2SCy Schubert 	ev.cert_fail.depth = depth;
334780fb4a2SCy Schubert 	x509_name_string(&cert->subject, subject, sizeof(subject));
335780fb4a2SCy Schubert 	ev.peer_cert.subject = subject;
336780fb4a2SCy Schubert 	ev.cert_fail.reason = reason;
337780fb4a2SCy Schubert 	ev.cert_fail.reason_txt = reason_txt;
338780fb4a2SCy Schubert 	cert_buf = wpabuf_alloc_copy(cert->cert_start,
339780fb4a2SCy Schubert 				     cert->cert_len);
340780fb4a2SCy Schubert 	ev.cert_fail.cert = cert_buf;
341780fb4a2SCy Schubert 	conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
342780fb4a2SCy Schubert 	wpabuf_free(cert_buf);
343780fb4a2SCy Schubert }
344780fb4a2SCy Schubert 
345780fb4a2SCy Schubert 
34639beb93cSSam Leffler static int tls_process_certificate(struct tlsv1_client *conn, u8 ct,
34739beb93cSSam Leffler 				   const u8 *in_data, size_t *in_len)
34839beb93cSSam Leffler {
34939beb93cSSam Leffler 	const u8 *pos, *end;
35039beb93cSSam Leffler 	size_t left, len, list_len, cert_len, idx;
35139beb93cSSam Leffler 	u8 type;
35239beb93cSSam Leffler 	struct x509_certificate *chain = NULL, *last = NULL, *cert;
35339beb93cSSam Leffler 	int reason;
35439beb93cSSam Leffler 
35539beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
35639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
35739beb93cSSam Leffler 			   "received content type 0x%x", ct);
35839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
35939beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
36039beb93cSSam Leffler 		return -1;
36139beb93cSSam Leffler 	}
36239beb93cSSam Leffler 
36339beb93cSSam Leffler 	pos = in_data;
36439beb93cSSam Leffler 	left = *in_len;
36539beb93cSSam Leffler 
36639beb93cSSam Leffler 	if (left < 4) {
36739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message "
36839beb93cSSam Leffler 			   "(len=%lu)", (unsigned long) left);
36939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
37039beb93cSSam Leffler 		return -1;
37139beb93cSSam Leffler 	}
37239beb93cSSam Leffler 
37339beb93cSSam Leffler 	type = *pos++;
37439beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
37539beb93cSSam Leffler 	pos += 3;
37639beb93cSSam Leffler 	left -= 4;
37739beb93cSSam Leffler 
37839beb93cSSam Leffler 	if (len > left) {
37939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message "
38039beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
38139beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
38239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
38339beb93cSSam Leffler 		return -1;
38439beb93cSSam Leffler 	}
38539beb93cSSam Leffler 
38639beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE)
38739beb93cSSam Leffler 		return tls_process_server_key_exchange(conn, ct, in_data,
38839beb93cSSam Leffler 						       in_len);
38939beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
39039beb93cSSam Leffler 		return tls_process_certificate_request(conn, ct, in_data,
39139beb93cSSam Leffler 						       in_len);
39239beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
39339beb93cSSam Leffler 		return tls_process_server_hello_done(conn, ct, in_data,
39439beb93cSSam Leffler 						     in_len);
39539beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) {
39639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
39739beb93cSSam Leffler 			   "message %d (expected Certificate/"
39839beb93cSSam Leffler 			   "ServerKeyExchange/CertificateRequest/"
39939beb93cSSam Leffler 			   "ServerHelloDone)", type);
40039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
40139beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
40239beb93cSSam Leffler 		return -1;
40339beb93cSSam Leffler 	}
40439beb93cSSam Leffler 
40539beb93cSSam Leffler 	wpa_printf(MSG_DEBUG,
40639beb93cSSam Leffler 		   "TLSv1: Received Certificate (certificate_list len %lu)",
40739beb93cSSam Leffler 		   (unsigned long) len);
40839beb93cSSam Leffler 
40939beb93cSSam Leffler 	/*
41039beb93cSSam Leffler 	 * opaque ASN.1Cert<2^24-1>;
41139beb93cSSam Leffler 	 *
41239beb93cSSam Leffler 	 * struct {
41339beb93cSSam Leffler 	 *     ASN.1Cert certificate_list<1..2^24-1>;
41439beb93cSSam Leffler 	 * } Certificate;
41539beb93cSSam Leffler 	 */
41639beb93cSSam Leffler 
41739beb93cSSam Leffler 	end = pos + len;
41839beb93cSSam Leffler 
41939beb93cSSam Leffler 	if (end - pos < 3) {
42039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate "
42139beb93cSSam Leffler 			   "(left=%lu)", (unsigned long) left);
42239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
42339beb93cSSam Leffler 		return -1;
42439beb93cSSam Leffler 	}
42539beb93cSSam Leffler 
42639beb93cSSam Leffler 	list_len = WPA_GET_BE24(pos);
42739beb93cSSam Leffler 	pos += 3;
42839beb93cSSam Leffler 
42939beb93cSSam Leffler 	if ((size_t) (end - pos) != list_len) {
43039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list "
43139beb93cSSam Leffler 			   "length (len=%lu left=%lu)",
43239beb93cSSam Leffler 			   (unsigned long) list_len,
43339beb93cSSam Leffler 			   (unsigned long) (end - pos));
43439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
43539beb93cSSam Leffler 		return -1;
43639beb93cSSam Leffler 	}
43739beb93cSSam Leffler 
43839beb93cSSam Leffler 	idx = 0;
43939beb93cSSam Leffler 	while (pos < end) {
44039beb93cSSam Leffler 		if (end - pos < 3) {
44139beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
44239beb93cSSam Leffler 				   "certificate_list");
44339beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
44439beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
44539beb93cSSam Leffler 			x509_certificate_chain_free(chain);
44639beb93cSSam Leffler 			return -1;
44739beb93cSSam Leffler 		}
44839beb93cSSam Leffler 
44939beb93cSSam Leffler 		cert_len = WPA_GET_BE24(pos);
45039beb93cSSam Leffler 		pos += 3;
45139beb93cSSam Leffler 
45239beb93cSSam Leffler 		if ((size_t) (end - pos) < cert_len) {
45339beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate "
45439beb93cSSam Leffler 				   "length (len=%lu left=%lu)",
45539beb93cSSam Leffler 				   (unsigned long) cert_len,
45639beb93cSSam Leffler 				   (unsigned long) (end - pos));
45739beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
45839beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
45939beb93cSSam Leffler 			x509_certificate_chain_free(chain);
46039beb93cSSam Leffler 			return -1;
46139beb93cSSam Leffler 		}
46239beb93cSSam Leffler 
46339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)",
46439beb93cSSam Leffler 			   (unsigned long) idx, (unsigned long) cert_len);
46539beb93cSSam Leffler 
46639beb93cSSam Leffler 		if (idx == 0) {
46739beb93cSSam Leffler 			crypto_public_key_free(conn->server_rsa_key);
46839beb93cSSam Leffler 			if (tls_parse_cert(pos, cert_len,
46939beb93cSSam Leffler 					   &conn->server_rsa_key)) {
47039beb93cSSam Leffler 				wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
47139beb93cSSam Leffler 					   "the certificate");
47239beb93cSSam Leffler 				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
47339beb93cSSam Leffler 					  TLS_ALERT_BAD_CERTIFICATE);
47439beb93cSSam Leffler 				x509_certificate_chain_free(chain);
47539beb93cSSam Leffler 				return -1;
47639beb93cSSam Leffler 			}
47739beb93cSSam Leffler 		}
47839beb93cSSam Leffler 
47939beb93cSSam Leffler 		cert = x509_certificate_parse(pos, cert_len);
48039beb93cSSam Leffler 		if (cert == NULL) {
48139beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
48239beb93cSSam Leffler 				   "the certificate");
48339beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
48439beb93cSSam Leffler 				  TLS_ALERT_BAD_CERTIFICATE);
48539beb93cSSam Leffler 			x509_certificate_chain_free(chain);
48639beb93cSSam Leffler 			return -1;
48739beb93cSSam Leffler 		}
48839beb93cSSam Leffler 
489780fb4a2SCy Schubert 		tls_peer_cert_event(conn, idx, cert);
490780fb4a2SCy Schubert 
49139beb93cSSam Leffler 		if (last == NULL)
49239beb93cSSam Leffler 			chain = cert;
49339beb93cSSam Leffler 		else
49439beb93cSSam Leffler 			last->next = cert;
49539beb93cSSam Leffler 		last = cert;
49639beb93cSSam Leffler 
49739beb93cSSam Leffler 		idx++;
49839beb93cSSam Leffler 		pos += cert_len;
49939beb93cSSam Leffler 	}
50039beb93cSSam Leffler 
501780fb4a2SCy Schubert 	if (conn->cred && conn->cred->server_cert_only && chain) {
502780fb4a2SCy Schubert 		u8 hash[SHA256_MAC_LEN];
503780fb4a2SCy Schubert 		char buf[128];
504780fb4a2SCy Schubert 
505780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
506780fb4a2SCy Schubert 			   "TLSv1: Validate server certificate hash");
507780fb4a2SCy Schubert 		x509_name_string(&chain->subject, buf, sizeof(buf));
508780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "TLSv1: 0: %s", buf);
509780fb4a2SCy Schubert 		if (sha256_vector(1, &chain->cert_start, &chain->cert_len,
510780fb4a2SCy Schubert 				  hash) < 0 ||
511780fb4a2SCy Schubert 		    os_memcmp(conn->cred->srv_cert_hash, hash,
512780fb4a2SCy Schubert 			      SHA256_MAC_LEN) != 0) {
513780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
514780fb4a2SCy Schubert 				   "TLSv1: Server certificate hash mismatch");
515780fb4a2SCy Schubert 			wpa_hexdump(MSG_MSGDUMP, "TLSv1: SHA256 hash",
516780fb4a2SCy Schubert 				    hash, SHA256_MAC_LEN);
517780fb4a2SCy Schubert 			if (conn->event_cb) {
518780fb4a2SCy Schubert 				union tls_event_data ev;
519780fb4a2SCy Schubert 
520780fb4a2SCy Schubert 				os_memset(&ev, 0, sizeof(ev));
521780fb4a2SCy Schubert 				ev.cert_fail.reason = TLS_FAIL_UNSPECIFIED;
522780fb4a2SCy Schubert 				ev.cert_fail.reason_txt =
523780fb4a2SCy Schubert 					"Server certificate mismatch";
524780fb4a2SCy Schubert 				ev.cert_fail.subject = buf;
525780fb4a2SCy Schubert 				conn->event_cb(conn->cb_ctx,
526780fb4a2SCy Schubert 					       TLS_CERT_CHAIN_FAILURE, &ev);
527780fb4a2SCy Schubert 			}
528780fb4a2SCy Schubert 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
529780fb4a2SCy Schubert 				  TLS_ALERT_BAD_CERTIFICATE);
530780fb4a2SCy Schubert 			x509_certificate_chain_free(chain);
531780fb4a2SCy Schubert 			return -1;
532780fb4a2SCy Schubert 		}
533780fb4a2SCy Schubert 	} else if (conn->cred && conn->cred->cert_probe) {
534780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
535780fb4a2SCy Schubert 			   "TLSv1: Reject server certificate on probe-only rune");
536780fb4a2SCy Schubert 		if (conn->event_cb) {
537780fb4a2SCy Schubert 			union tls_event_data ev;
538780fb4a2SCy Schubert 			char buf[128];
539780fb4a2SCy Schubert 
540780fb4a2SCy Schubert 			os_memset(&ev, 0, sizeof(ev));
541780fb4a2SCy Schubert 			ev.cert_fail.reason = TLS_FAIL_SERVER_CHAIN_PROBE;
542780fb4a2SCy Schubert 			ev.cert_fail.reason_txt =
543780fb4a2SCy Schubert 				"Server certificate chain probe";
544780fb4a2SCy Schubert 			if (chain) {
545780fb4a2SCy Schubert 				x509_name_string(&chain->subject, buf,
546780fb4a2SCy Schubert 						 sizeof(buf));
547780fb4a2SCy Schubert 				ev.cert_fail.subject = buf;
548780fb4a2SCy Schubert 			}
549780fb4a2SCy Schubert 			conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE,
550780fb4a2SCy Schubert 				       &ev);
551780fb4a2SCy Schubert 		}
552780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
553780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE);
554780fb4a2SCy Schubert 		x509_certificate_chain_free(chain);
555780fb4a2SCy Schubert 		return -1;
556780fb4a2SCy Schubert 	} else if (conn->cred && conn->cred->ca_cert_verify &&
557780fb4a2SCy Schubert 		   x509_certificate_chain_validate(
558780fb4a2SCy Schubert 			   conn->cred->trusted_certs, chain, &reason,
559780fb4a2SCy Schubert 			   !!(conn->flags & TLS_CONN_DISABLE_TIME_CHECKS))
560f05cddf9SRui Paulo 		   < 0) {
56139beb93cSSam Leffler 		int tls_reason;
56239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain "
56339beb93cSSam Leffler 			   "validation failed (reason=%d)", reason);
56439beb93cSSam Leffler 		switch (reason) {
56539beb93cSSam Leffler 		case X509_VALIDATE_BAD_CERTIFICATE:
56639beb93cSSam Leffler 			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
567780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
568780fb4a2SCy Schubert 				conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE,
569780fb4a2SCy Schubert 				"bad certificate");
57039beb93cSSam Leffler 			break;
57139beb93cSSam Leffler 		case X509_VALIDATE_UNSUPPORTED_CERTIFICATE:
57239beb93cSSam Leffler 			tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE;
57339beb93cSSam Leffler 			break;
57439beb93cSSam Leffler 		case X509_VALIDATE_CERTIFICATE_REVOKED:
57539beb93cSSam Leffler 			tls_reason = TLS_ALERT_CERTIFICATE_REVOKED;
576780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
577780fb4a2SCy Schubert 				conn, 0, chain, TLS_FAIL_REVOKED,
578780fb4a2SCy Schubert 				"certificate revoked");
57939beb93cSSam Leffler 			break;
58039beb93cSSam Leffler 		case X509_VALIDATE_CERTIFICATE_EXPIRED:
58139beb93cSSam Leffler 			tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
582780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
583780fb4a2SCy Schubert 				conn, 0, chain, TLS_FAIL_EXPIRED,
584780fb4a2SCy Schubert 				"certificate has expired or is not yet valid");
58539beb93cSSam Leffler 			break;
58639beb93cSSam Leffler 		case X509_VALIDATE_CERTIFICATE_UNKNOWN:
58739beb93cSSam Leffler 			tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN;
58839beb93cSSam Leffler 			break;
58939beb93cSSam Leffler 		case X509_VALIDATE_UNKNOWN_CA:
59039beb93cSSam Leffler 			tls_reason = TLS_ALERT_UNKNOWN_CA;
591780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
592780fb4a2SCy Schubert 				conn, 0, chain, TLS_FAIL_UNTRUSTED,
593780fb4a2SCy Schubert 				"unknown CA");
59439beb93cSSam Leffler 			break;
59539beb93cSSam Leffler 		default:
59639beb93cSSam Leffler 			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
59739beb93cSSam Leffler 			break;
59839beb93cSSam Leffler 		}
59939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason);
60039beb93cSSam Leffler 		x509_certificate_chain_free(chain);
60139beb93cSSam Leffler 		return -1;
60239beb93cSSam Leffler 	}
60339beb93cSSam Leffler 
604780fb4a2SCy Schubert 	if (conn->cred && !conn->cred->server_cert_only && chain &&
605780fb4a2SCy Schubert 	    (chain->extensions_present & X509_EXT_EXT_KEY_USAGE) &&
606780fb4a2SCy Schubert 	    !(chain->ext_key_usage &
607780fb4a2SCy Schubert 	      (X509_EXT_KEY_USAGE_ANY | X509_EXT_KEY_USAGE_SERVER_AUTH))) {
608780fb4a2SCy Schubert 		tls_cert_chain_failure_event(
609780fb4a2SCy Schubert 			conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE,
610780fb4a2SCy Schubert 			"certificate not allowed for server authentication");
611780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
612780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE);
61339beb93cSSam Leffler 		x509_certificate_chain_free(chain);
614780fb4a2SCy Schubert 		return -1;
615780fb4a2SCy Schubert 	}
616780fb4a2SCy Schubert 
617780fb4a2SCy Schubert 	if (conn->flags & TLS_CONN_REQUEST_OCSP) {
618780fb4a2SCy Schubert 		x509_certificate_chain_free(conn->server_cert);
619780fb4a2SCy Schubert 		conn->server_cert = chain;
620780fb4a2SCy Schubert 	} else {
621780fb4a2SCy Schubert 		x509_certificate_chain_free(chain);
622780fb4a2SCy Schubert 	}
62339beb93cSSam Leffler 
62439beb93cSSam Leffler 	*in_len = end - in_data;
62539beb93cSSam Leffler 
62639beb93cSSam Leffler 	conn->state = SERVER_KEY_EXCHANGE;
62739beb93cSSam Leffler 
62839beb93cSSam Leffler 	return 0;
62939beb93cSSam Leffler }
63039beb93cSSam Leffler 
63139beb93cSSam Leffler 
6325b9c547cSRui Paulo static unsigned int count_bits(const u8 *val, size_t len)
63339beb93cSSam Leffler {
6345b9c547cSRui Paulo 	size_t i;
6355b9c547cSRui Paulo 	unsigned int bits;
6365b9c547cSRui Paulo 	u8 tmp;
6375b9c547cSRui Paulo 
6385b9c547cSRui Paulo 	for (i = 0; i < len; i++) {
6395b9c547cSRui Paulo 		if (val[i])
6405b9c547cSRui Paulo 			break;
6415b9c547cSRui Paulo 	}
6425b9c547cSRui Paulo 	if (i == len)
6435b9c547cSRui Paulo 		return 0;
6445b9c547cSRui Paulo 
6455b9c547cSRui Paulo 	bits = (len - i - 1) * 8;
6465b9c547cSRui Paulo 	tmp = val[i];
6475b9c547cSRui Paulo 	while (tmp) {
6485b9c547cSRui Paulo 		bits++;
6495b9c547cSRui Paulo 		tmp >>= 1;
6505b9c547cSRui Paulo 	}
6515b9c547cSRui Paulo 
6525b9c547cSRui Paulo 	return bits;
6535b9c547cSRui Paulo }
6545b9c547cSRui Paulo 
6555b9c547cSRui Paulo 
6565b9c547cSRui Paulo static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
6575b9c547cSRui Paulo 					const u8 *buf, size_t len,
6585b9c547cSRui Paulo 					tls_key_exchange key_exchange)
6595b9c547cSRui Paulo {
6605b9c547cSRui Paulo 	const u8 *pos, *end, *server_params, *server_params_end;
6615b9c547cSRui Paulo 	u8 alert;
6625b9c547cSRui Paulo 	unsigned int bits;
6635b9c547cSRui Paulo 	u16 val;
66439beb93cSSam Leffler 
66539beb93cSSam Leffler 	tlsv1_client_free_dh(conn);
66639beb93cSSam Leffler 
66739beb93cSSam Leffler 	pos = buf;
66839beb93cSSam Leffler 	end = buf + len;
66939beb93cSSam Leffler 
67039beb93cSSam Leffler 	if (end - pos < 3)
67139beb93cSSam Leffler 		goto fail;
6725b9c547cSRui Paulo 	server_params = pos;
6735b9c547cSRui Paulo 	val = WPA_GET_BE16(pos);
67439beb93cSSam Leffler 	pos += 2;
6755b9c547cSRui Paulo 	if (val == 0 || val > (size_t) (end - pos)) {
6765b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "TLSv1: Invalid dh_p length %u", val);
6775b9c547cSRui Paulo 		goto fail;
6785b9c547cSRui Paulo 	}
6795b9c547cSRui Paulo 	conn->dh_p_len = val;
6805b9c547cSRui Paulo 	bits = count_bits(pos, conn->dh_p_len);
6815b9c547cSRui Paulo 	if (bits < 768) {
6825b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "TLSv1: Reject under 768-bit DH prime (insecure; only %u bits)",
6835b9c547cSRui Paulo 			   bits);
6845b9c547cSRui Paulo 		wpa_hexdump(MSG_DEBUG, "TLSv1: Rejected DH prime",
6855b9c547cSRui Paulo 			    pos, conn->dh_p_len);
68639beb93cSSam Leffler 		goto fail;
68739beb93cSSam Leffler 	}
688*85732ac8SCy Schubert 	conn->dh_p = os_memdup(pos, conn->dh_p_len);
68939beb93cSSam Leffler 	if (conn->dh_p == NULL)
69039beb93cSSam Leffler 		goto fail;
69139beb93cSSam Leffler 	pos += conn->dh_p_len;
69239beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)",
69339beb93cSSam Leffler 		    conn->dh_p, conn->dh_p_len);
69439beb93cSSam Leffler 
69539beb93cSSam Leffler 	if (end - pos < 3)
69639beb93cSSam Leffler 		goto fail;
6975b9c547cSRui Paulo 	val = WPA_GET_BE16(pos);
69839beb93cSSam Leffler 	pos += 2;
6995b9c547cSRui Paulo 	if (val == 0 || val > (size_t) (end - pos))
70039beb93cSSam Leffler 		goto fail;
7015b9c547cSRui Paulo 	conn->dh_g_len = val;
702*85732ac8SCy Schubert 	conn->dh_g = os_memdup(pos, conn->dh_g_len);
70339beb93cSSam Leffler 	if (conn->dh_g == NULL)
70439beb93cSSam Leffler 		goto fail;
70539beb93cSSam Leffler 	pos += conn->dh_g_len;
70639beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)",
70739beb93cSSam Leffler 		    conn->dh_g, conn->dh_g_len);
70839beb93cSSam Leffler 	if (conn->dh_g_len == 1 && conn->dh_g[0] < 2)
70939beb93cSSam Leffler 		goto fail;
71039beb93cSSam Leffler 
71139beb93cSSam Leffler 	if (end - pos < 3)
71239beb93cSSam Leffler 		goto fail;
7135b9c547cSRui Paulo 	val = WPA_GET_BE16(pos);
71439beb93cSSam Leffler 	pos += 2;
7155b9c547cSRui Paulo 	if (val == 0 || val > (size_t) (end - pos))
71639beb93cSSam Leffler 		goto fail;
7175b9c547cSRui Paulo 	conn->dh_ys_len = val;
718*85732ac8SCy Schubert 	conn->dh_ys = os_memdup(pos, conn->dh_ys_len);
71939beb93cSSam Leffler 	if (conn->dh_ys == NULL)
72039beb93cSSam Leffler 		goto fail;
72139beb93cSSam Leffler 	pos += conn->dh_ys_len;
72239beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
72339beb93cSSam Leffler 		    conn->dh_ys, conn->dh_ys_len);
7245b9c547cSRui Paulo 	server_params_end = pos;
7255b9c547cSRui Paulo 
7265b9c547cSRui Paulo 	if (key_exchange == TLS_KEY_X_DHE_RSA) {
727780fb4a2SCy Schubert 		u8 hash[64];
7285b9c547cSRui Paulo 		int hlen;
7295b9c547cSRui Paulo 
7305b9c547cSRui Paulo 		if (conn->rl.tls_version == TLS_VERSION_1_2) {
7315b9c547cSRui Paulo #ifdef CONFIG_TLSV12
7325b9c547cSRui Paulo 			/*
7335b9c547cSRui Paulo 			 * RFC 5246, 4.7:
7345b9c547cSRui Paulo 			 * TLS v1.2 adds explicit indication of the used
7355b9c547cSRui Paulo 			 * signature and hash algorithms.
7365b9c547cSRui Paulo 			 *
7375b9c547cSRui Paulo 			 * struct {
7385b9c547cSRui Paulo 			 *   HashAlgorithm hash;
7395b9c547cSRui Paulo 			 *   SignatureAlgorithm signature;
7405b9c547cSRui Paulo 			 * } SignatureAndHashAlgorithm;
7415b9c547cSRui Paulo 			 */
7425b9c547cSRui Paulo 			if (end - pos < 2)
7435b9c547cSRui Paulo 				goto fail;
744780fb4a2SCy Schubert 			if ((pos[0] != TLS_HASH_ALG_SHA256 &&
745780fb4a2SCy Schubert 			     pos[0] != TLS_HASH_ALG_SHA384 &&
746780fb4a2SCy Schubert 			     pos[0] != TLS_HASH_ALG_SHA512) ||
7475b9c547cSRui Paulo 			    pos[1] != TLS_SIGN_ALG_RSA) {
7485b9c547cSRui Paulo 				wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/signature(%u) algorithm",
7495b9c547cSRui Paulo 					   pos[0], pos[1]);
7505b9c547cSRui Paulo 				goto fail;
7515b9c547cSRui Paulo 			}
7525b9c547cSRui Paulo 
7535b9c547cSRui Paulo 			hlen = tlsv12_key_x_server_params_hash(
754780fb4a2SCy Schubert 				conn->rl.tls_version, pos[0],
755780fb4a2SCy Schubert 				conn->client_random,
7565b9c547cSRui Paulo 				conn->server_random, server_params,
7575b9c547cSRui Paulo 				server_params_end - server_params, hash);
758780fb4a2SCy Schubert 			pos += 2;
7595b9c547cSRui Paulo #else /* CONFIG_TLSV12 */
7605b9c547cSRui Paulo 			goto fail;
7615b9c547cSRui Paulo #endif /* CONFIG_TLSV12 */
7625b9c547cSRui Paulo 		} else {
7635b9c547cSRui Paulo 			hlen = tls_key_x_server_params_hash(
7645b9c547cSRui Paulo 				conn->rl.tls_version, conn->client_random,
7655b9c547cSRui Paulo 				conn->server_random, server_params,
7665b9c547cSRui Paulo 				server_params_end - server_params, hash);
7675b9c547cSRui Paulo 		}
7685b9c547cSRui Paulo 
7695b9c547cSRui Paulo 		if (hlen < 0)
7705b9c547cSRui Paulo 			goto fail;
7715b9c547cSRui Paulo 		wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerKeyExchange hash",
7725b9c547cSRui Paulo 			    hash, hlen);
7735b9c547cSRui Paulo 
7745b9c547cSRui Paulo 		if (tls_verify_signature(conn->rl.tls_version,
7755b9c547cSRui Paulo 					 conn->server_rsa_key,
7765b9c547cSRui Paulo 					 hash, hlen, pos, end - pos,
7775b9c547cSRui Paulo 					 &alert) < 0)
7785b9c547cSRui Paulo 			goto fail;
7795b9c547cSRui Paulo 	}
78039beb93cSSam Leffler 
78139beb93cSSam Leffler 	return 0;
78239beb93cSSam Leffler 
78339beb93cSSam Leffler fail:
78439beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed");
78539beb93cSSam Leffler 	tlsv1_client_free_dh(conn);
78639beb93cSSam Leffler 	return -1;
78739beb93cSSam Leffler }
78839beb93cSSam Leffler 
78939beb93cSSam Leffler 
790780fb4a2SCy Schubert static enum tls_ocsp_result
791780fb4a2SCy Schubert tls_process_certificate_status_ocsp_response(struct tlsv1_client *conn,
792780fb4a2SCy Schubert 					     const u8 *pos, size_t len)
793780fb4a2SCy Schubert {
794780fb4a2SCy Schubert 	const u8 *end = pos + len;
795780fb4a2SCy Schubert 	u32 ocsp_resp_len;
796780fb4a2SCy Schubert 
797780fb4a2SCy Schubert 	/* opaque OCSPResponse<1..2^24-1>; */
798780fb4a2SCy Schubert 	if (end - pos < 3) {
799780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "TLSv1: Too short OCSPResponse");
800780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
801780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
802780fb4a2SCy Schubert 	}
803780fb4a2SCy Schubert 	ocsp_resp_len = WPA_GET_BE24(pos);
804780fb4a2SCy Schubert 	pos += 3;
805780fb4a2SCy Schubert 	if (end - pos < ocsp_resp_len) {
806780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "TLSv1: Truncated OCSPResponse");
807780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
808780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
809780fb4a2SCy Schubert 	}
810780fb4a2SCy Schubert 
811780fb4a2SCy Schubert 	return tls_process_ocsp_response(conn, pos, ocsp_resp_len);
812780fb4a2SCy Schubert }
813780fb4a2SCy Schubert 
814780fb4a2SCy Schubert 
815780fb4a2SCy Schubert static int tls_process_certificate_status(struct tlsv1_client *conn, u8 ct,
816780fb4a2SCy Schubert 					   const u8 *in_data, size_t *in_len)
817780fb4a2SCy Schubert {
818780fb4a2SCy Schubert 	const u8 *pos, *end;
819780fb4a2SCy Schubert 	size_t left, len;
820780fb4a2SCy Schubert 	u8 type, status_type;
821780fb4a2SCy Schubert 	enum tls_ocsp_result res;
822780fb4a2SCy Schubert 	struct x509_certificate *cert;
823780fb4a2SCy Schubert 	int depth;
824780fb4a2SCy Schubert 
825780fb4a2SCy Schubert 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
826780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
827780fb4a2SCy Schubert 			   "TLSv1: Expected Handshake; received content type 0x%x",
828780fb4a2SCy Schubert 			   ct);
829780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
830780fb4a2SCy Schubert 			  TLS_ALERT_UNEXPECTED_MESSAGE);
831780fb4a2SCy Schubert 		return -1;
832780fb4a2SCy Schubert 	}
833780fb4a2SCy Schubert 
834780fb4a2SCy Schubert 	pos = in_data;
835780fb4a2SCy Schubert 	left = *in_len;
836780fb4a2SCy Schubert 
837780fb4a2SCy Schubert 	if (left < 4) {
838780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
839780fb4a2SCy Schubert 			   "TLSv1: Too short CertificateStatus (left=%lu)",
840780fb4a2SCy Schubert 			   (unsigned long) left);
841780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
842780fb4a2SCy Schubert 		return -1;
843780fb4a2SCy Schubert 	}
844780fb4a2SCy Schubert 
845780fb4a2SCy Schubert 	type = *pos++;
846780fb4a2SCy Schubert 	len = WPA_GET_BE24(pos);
847780fb4a2SCy Schubert 	pos += 3;
848780fb4a2SCy Schubert 	left -= 4;
849780fb4a2SCy Schubert 
850780fb4a2SCy Schubert 	if (len > left) {
851780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
852780fb4a2SCy Schubert 			   "TLSv1: Mismatch in CertificateStatus length (len=%lu != left=%lu)",
853780fb4a2SCy Schubert 			   (unsigned long) len, (unsigned long) left);
854780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
855780fb4a2SCy Schubert 		return -1;
856780fb4a2SCy Schubert 	}
857780fb4a2SCy Schubert 
858780fb4a2SCy Schubert 	end = pos + len;
859780fb4a2SCy Schubert 
860780fb4a2SCy Schubert 	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS) {
861780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
862780fb4a2SCy Schubert 			   "TLSv1: Received unexpected handshake message %d (expected CertificateStatus)",
863780fb4a2SCy Schubert 			   type);
864780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
865780fb4a2SCy Schubert 			  TLS_ALERT_UNEXPECTED_MESSAGE);
866780fb4a2SCy Schubert 		return -1;
867780fb4a2SCy Schubert 	}
868780fb4a2SCy Schubert 
869780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateStatus");
870780fb4a2SCy Schubert 
871780fb4a2SCy Schubert 	/*
872780fb4a2SCy Schubert 	 * struct {
873780fb4a2SCy Schubert 	 *     CertificateStatusType status_type;
874780fb4a2SCy Schubert 	 *     select (status_type) {
875780fb4a2SCy Schubert 	 *         case ocsp: OCSPResponse;
876780fb4a2SCy Schubert 	 *         case ocsp_multi: OCSPResponseList;
877780fb4a2SCy Schubert 	 *     } response;
878780fb4a2SCy Schubert 	 * } CertificateStatus;
879780fb4a2SCy Schubert 	 */
880780fb4a2SCy Schubert 	if (end - pos < 1) {
881780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "TLSv1: Too short CertificateStatus");
882780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
883780fb4a2SCy Schubert 		return -1;
884780fb4a2SCy Schubert 	}
885780fb4a2SCy Schubert 	status_type = *pos++;
886780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatus status_type %u",
887780fb4a2SCy Schubert 		   status_type);
888780fb4a2SCy Schubert 
889780fb4a2SCy Schubert 	if (status_type == 1 /* ocsp */) {
890780fb4a2SCy Schubert 		res = tls_process_certificate_status_ocsp_response(
891780fb4a2SCy Schubert 			conn, pos, end - pos);
892780fb4a2SCy Schubert 	} else if (status_type == 2 /* ocsp_multi */) {
893780fb4a2SCy Schubert 		int good = 0, revoked = 0;
894780fb4a2SCy Schubert 		u32 resp_len;
895780fb4a2SCy Schubert 
896780fb4a2SCy Schubert 		res = TLS_OCSP_NO_RESPONSE;
897780fb4a2SCy Schubert 
898780fb4a2SCy Schubert 		/*
899780fb4a2SCy Schubert 		 * opaque OCSPResponse<0..2^24-1>;
900780fb4a2SCy Schubert 		 *
901780fb4a2SCy Schubert 		 * struct {
902780fb4a2SCy Schubert 		 *   OCSPResponse ocsp_response_list<1..2^24-1>;
903780fb4a2SCy Schubert 		 * } OCSPResponseList;
904780fb4a2SCy Schubert 		 */
905780fb4a2SCy Schubert 		if (end - pos < 3) {
906780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
907780fb4a2SCy Schubert 				   "TLSv1: Truncated OCSPResponseList");
908780fb4a2SCy Schubert 			res = TLS_OCSP_INVALID;
909780fb4a2SCy Schubert 			goto done;
910780fb4a2SCy Schubert 		}
911780fb4a2SCy Schubert 		resp_len = WPA_GET_BE24(pos);
912780fb4a2SCy Schubert 		pos += 3;
913780fb4a2SCy Schubert 		if (end - pos < resp_len) {
914780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
915780fb4a2SCy Schubert 				   "TLSv1: Truncated OCSPResponseList(len=%u)",
916780fb4a2SCy Schubert 				   resp_len);
917780fb4a2SCy Schubert 			res = TLS_OCSP_INVALID;
918780fb4a2SCy Schubert 			goto done;
919780fb4a2SCy Schubert 		}
920780fb4a2SCy Schubert 		end = pos + resp_len;
921780fb4a2SCy Schubert 
922780fb4a2SCy Schubert 		while (end - pos >= 3) {
923780fb4a2SCy Schubert 			resp_len = WPA_GET_BE24(pos);
924780fb4a2SCy Schubert 			pos += 3;
925780fb4a2SCy Schubert 			if (resp_len > end - pos) {
926780fb4a2SCy Schubert 				wpa_printf(MSG_DEBUG,
927780fb4a2SCy Schubert 					   "TLSv1: Truncated OCSPResponse(len=%u; left=%d) in ocsp_multi",
928780fb4a2SCy Schubert 					   resp_len, (int) (end - pos));
929780fb4a2SCy Schubert 				res = TLS_OCSP_INVALID;
930780fb4a2SCy Schubert 				break;
931780fb4a2SCy Schubert 			}
932780fb4a2SCy Schubert 			if (!resp_len)
933780fb4a2SCy Schubert 				continue; /* Skip an empty response */
934780fb4a2SCy Schubert 			res = tls_process_certificate_status_ocsp_response(
935780fb4a2SCy Schubert 				conn, pos - 3, resp_len + 3);
936780fb4a2SCy Schubert 			if (res == TLS_OCSP_REVOKED)
937780fb4a2SCy Schubert 				revoked++;
938780fb4a2SCy Schubert 			else if (res == TLS_OCSP_GOOD)
939780fb4a2SCy Schubert 				good++;
940780fb4a2SCy Schubert 			pos += resp_len;
941780fb4a2SCy Schubert 		}
942780fb4a2SCy Schubert 
943780fb4a2SCy Schubert 		if (revoked)
944780fb4a2SCy Schubert 			res = TLS_OCSP_REVOKED;
945780fb4a2SCy Schubert 		else if (good)
946780fb4a2SCy Schubert 			res = TLS_OCSP_GOOD;
947780fb4a2SCy Schubert 	} else {
948780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
949780fb4a2SCy Schubert 			   "TLSv1: Ignore unsupported CertificateStatus");
950780fb4a2SCy Schubert 		goto skip;
951780fb4a2SCy Schubert 	}
952780fb4a2SCy Schubert 
953780fb4a2SCy Schubert done:
954780fb4a2SCy Schubert 	if (res == TLS_OCSP_REVOKED) {
955780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
956780fb4a2SCy Schubert 			  TLS_ALERT_CERTIFICATE_REVOKED);
957780fb4a2SCy Schubert 		for (cert = conn->server_cert, depth = 0; cert;
958780fb4a2SCy Schubert 		     cert = cert->next, depth++) {
959780fb4a2SCy Schubert 			if (cert->ocsp_revoked) {
960780fb4a2SCy Schubert 				tls_cert_chain_failure_event(
961780fb4a2SCy Schubert 					conn, depth, cert, TLS_FAIL_REVOKED,
962780fb4a2SCy Schubert 					"certificate revoked");
963780fb4a2SCy Schubert 			}
964780fb4a2SCy Schubert 		}
965780fb4a2SCy Schubert 		return -1;
966780fb4a2SCy Schubert 	}
967780fb4a2SCy Schubert 
968780fb4a2SCy Schubert 	if (conn->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
969780fb4a2SCy Schubert 		/*
970780fb4a2SCy Schubert 		 * Verify that each certificate on the chain that is not part
971780fb4a2SCy Schubert 		 * of the trusted certificates has a good status. If not,
972780fb4a2SCy Schubert 		 * terminate handshake.
973780fb4a2SCy Schubert 		 */
974780fb4a2SCy Schubert 		for (cert = conn->server_cert, depth = 0; cert;
975780fb4a2SCy Schubert 		     cert = cert->next, depth++) {
976780fb4a2SCy Schubert 			if (!cert->ocsp_good) {
977780fb4a2SCy Schubert 				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
978780fb4a2SCy Schubert 					  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
979780fb4a2SCy Schubert 				tls_cert_chain_failure_event(
980780fb4a2SCy Schubert 					conn, depth, cert,
981780fb4a2SCy Schubert 					TLS_FAIL_UNSPECIFIED,
982780fb4a2SCy Schubert 					"bad certificate status response");
983780fb4a2SCy Schubert 				return -1;
984780fb4a2SCy Schubert 			}
985780fb4a2SCy Schubert 			if (cert->issuer_trusted)
986780fb4a2SCy Schubert 				break;
987780fb4a2SCy Schubert 		}
988780fb4a2SCy Schubert 	}
989780fb4a2SCy Schubert 
990780fb4a2SCy Schubert 	if ((conn->flags & TLS_CONN_REQUIRE_OCSP) && res != TLS_OCSP_GOOD) {
991780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
992780fb4a2SCy Schubert 			  res == TLS_OCSP_INVALID ? TLS_ALERT_DECODE_ERROR :
993780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
994780fb4a2SCy Schubert 		if (conn->server_cert)
995780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
996780fb4a2SCy Schubert 				conn, 0, conn->server_cert,
997780fb4a2SCy Schubert 				TLS_FAIL_UNSPECIFIED,
998780fb4a2SCy Schubert 				"bad certificate status response");
999780fb4a2SCy Schubert 		return -1;
1000780fb4a2SCy Schubert 	}
1001780fb4a2SCy Schubert 
1002780fb4a2SCy Schubert 	conn->ocsp_resp_received = 1;
1003780fb4a2SCy Schubert 
1004780fb4a2SCy Schubert skip:
1005780fb4a2SCy Schubert 	*in_len = end - in_data;
1006780fb4a2SCy Schubert 
1007780fb4a2SCy Schubert 	conn->state = SERVER_KEY_EXCHANGE;
1008780fb4a2SCy Schubert 
1009780fb4a2SCy Schubert 	return 0;
1010780fb4a2SCy Schubert }
1011780fb4a2SCy Schubert 
1012780fb4a2SCy Schubert 
101339beb93cSSam Leffler static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
101439beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len)
101539beb93cSSam Leffler {
101639beb93cSSam Leffler 	const u8 *pos, *end;
101739beb93cSSam Leffler 	size_t left, len;
101839beb93cSSam Leffler 	u8 type;
101939beb93cSSam Leffler 	const struct tls_cipher_suite *suite;
102039beb93cSSam Leffler 
102139beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
102239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
102339beb93cSSam Leffler 			   "received content type 0x%x", ct);
102439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
102539beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
102639beb93cSSam Leffler 		return -1;
102739beb93cSSam Leffler 	}
102839beb93cSSam Leffler 
102939beb93cSSam Leffler 	pos = in_data;
103039beb93cSSam Leffler 	left = *in_len;
103139beb93cSSam Leffler 
103239beb93cSSam Leffler 	if (left < 4) {
103339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange "
103439beb93cSSam Leffler 			   "(Left=%lu)", (unsigned long) left);
103539beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
103639beb93cSSam Leffler 		return -1;
103739beb93cSSam Leffler 	}
103839beb93cSSam Leffler 
103939beb93cSSam Leffler 	type = *pos++;
104039beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
104139beb93cSSam Leffler 	pos += 3;
104239beb93cSSam Leffler 	left -= 4;
104339beb93cSSam Leffler 
104439beb93cSSam Leffler 	if (len > left) {
104539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange "
104639beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
104739beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
104839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
104939beb93cSSam Leffler 		return -1;
105039beb93cSSam Leffler 	}
105139beb93cSSam Leffler 
105239beb93cSSam Leffler 	end = pos + len;
105339beb93cSSam Leffler 
1054780fb4a2SCy Schubert 	if ((conn->flags & TLS_CONN_REQUEST_OCSP) &&
1055780fb4a2SCy Schubert 	    type == TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS)
1056780fb4a2SCy Schubert 		return tls_process_certificate_status(conn, ct, in_data,
1057780fb4a2SCy Schubert 						      in_len);
105839beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
105939beb93cSSam Leffler 		return tls_process_certificate_request(conn, ct, in_data,
106039beb93cSSam Leffler 						       in_len);
106139beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
106239beb93cSSam Leffler 		return tls_process_server_hello_done(conn, ct, in_data,
106339beb93cSSam Leffler 						     in_len);
106439beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) {
106539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
106639beb93cSSam Leffler 			   "message %d (expected ServerKeyExchange/"
1067780fb4a2SCy Schubert 			   "CertificateRequest/ServerHelloDone%s)", type,
1068780fb4a2SCy Schubert 			   (conn->flags & TLS_CONN_REQUEST_OCSP) ?
1069780fb4a2SCy Schubert 			   "/CertificateStatus" : "");
107039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
107139beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
107239beb93cSSam Leffler 		return -1;
107339beb93cSSam Leffler 	}
107439beb93cSSam Leffler 
107539beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange");
107639beb93cSSam Leffler 
107739beb93cSSam Leffler 	if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) {
107839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed "
107939beb93cSSam Leffler 			   "with the selected cipher suite");
108039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
108139beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
108239beb93cSSam Leffler 		return -1;
108339beb93cSSam Leffler 	}
108439beb93cSSam Leffler 
108539beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len);
108639beb93cSSam Leffler 	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
10875b9c547cSRui Paulo 	if (suite && (suite->key_exchange == TLS_KEY_X_DH_anon ||
10885b9c547cSRui Paulo 		      suite->key_exchange == TLS_KEY_X_DHE_RSA)) {
10895b9c547cSRui Paulo 		if (tlsv1_process_diffie_hellman(conn, pos, len,
10905b9c547cSRui Paulo 						 suite->key_exchange) < 0) {
109139beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
109239beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
109339beb93cSSam Leffler 			return -1;
109439beb93cSSam Leffler 		}
109539beb93cSSam Leffler 	} else {
109639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange");
109739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
109839beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
109939beb93cSSam Leffler 		return -1;
110039beb93cSSam Leffler 	}
110139beb93cSSam Leffler 
110239beb93cSSam Leffler 	*in_len = end - in_data;
110339beb93cSSam Leffler 
110439beb93cSSam Leffler 	conn->state = SERVER_CERTIFICATE_REQUEST;
110539beb93cSSam Leffler 
110639beb93cSSam Leffler 	return 0;
110739beb93cSSam Leffler }
110839beb93cSSam Leffler 
110939beb93cSSam Leffler 
111039beb93cSSam Leffler static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
111139beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len)
111239beb93cSSam Leffler {
111339beb93cSSam Leffler 	const u8 *pos, *end;
111439beb93cSSam Leffler 	size_t left, len;
111539beb93cSSam Leffler 	u8 type;
111639beb93cSSam Leffler 
111739beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
111839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
111939beb93cSSam Leffler 			   "received content type 0x%x", ct);
112039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
112139beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
112239beb93cSSam Leffler 		return -1;
112339beb93cSSam Leffler 	}
112439beb93cSSam Leffler 
112539beb93cSSam Leffler 	pos = in_data;
112639beb93cSSam Leffler 	left = *in_len;
112739beb93cSSam Leffler 
112839beb93cSSam Leffler 	if (left < 4) {
112939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest "
113039beb93cSSam Leffler 			   "(left=%lu)", (unsigned long) left);
113139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
113239beb93cSSam Leffler 		return -1;
113339beb93cSSam Leffler 	}
113439beb93cSSam Leffler 
113539beb93cSSam Leffler 	type = *pos++;
113639beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
113739beb93cSSam Leffler 	pos += 3;
113839beb93cSSam Leffler 	left -= 4;
113939beb93cSSam Leffler 
114039beb93cSSam Leffler 	if (len > left) {
114139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest "
114239beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
114339beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
114439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
114539beb93cSSam Leffler 		return -1;
114639beb93cSSam Leffler 	}
114739beb93cSSam Leffler 
114839beb93cSSam Leffler 	end = pos + len;
114939beb93cSSam Leffler 
115039beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
115139beb93cSSam Leffler 		return tls_process_server_hello_done(conn, ct, in_data,
115239beb93cSSam Leffler 						     in_len);
115339beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) {
115439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
115539beb93cSSam Leffler 			   "message %d (expected CertificateRequest/"
115639beb93cSSam Leffler 			   "ServerHelloDone)", type);
115739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
115839beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
115939beb93cSSam Leffler 		return -1;
116039beb93cSSam Leffler 	}
116139beb93cSSam Leffler 
116239beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest");
116339beb93cSSam Leffler 
116439beb93cSSam Leffler 	conn->certificate_requested = 1;
116539beb93cSSam Leffler 
116639beb93cSSam Leffler 	*in_len = end - in_data;
116739beb93cSSam Leffler 
116839beb93cSSam Leffler 	conn->state = SERVER_HELLO_DONE;
116939beb93cSSam Leffler 
117039beb93cSSam Leffler 	return 0;
117139beb93cSSam Leffler }
117239beb93cSSam Leffler 
117339beb93cSSam Leffler 
117439beb93cSSam Leffler static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
117539beb93cSSam Leffler 					 const u8 *in_data, size_t *in_len)
117639beb93cSSam Leffler {
117739beb93cSSam Leffler 	const u8 *pos, *end;
117839beb93cSSam Leffler 	size_t left, len;
117939beb93cSSam Leffler 	u8 type;
118039beb93cSSam Leffler 
118139beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
118239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
118339beb93cSSam Leffler 			   "received content type 0x%x", ct);
118439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
118539beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
118639beb93cSSam Leffler 		return -1;
118739beb93cSSam Leffler 	}
118839beb93cSSam Leffler 
118939beb93cSSam Leffler 	pos = in_data;
119039beb93cSSam Leffler 	left = *in_len;
119139beb93cSSam Leffler 
119239beb93cSSam Leffler 	if (left < 4) {
119339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone "
119439beb93cSSam Leffler 			   "(left=%lu)", (unsigned long) left);
119539beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
119639beb93cSSam Leffler 		return -1;
119739beb93cSSam Leffler 	}
119839beb93cSSam Leffler 
119939beb93cSSam Leffler 	type = *pos++;
120039beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
120139beb93cSSam Leffler 	pos += 3;
120239beb93cSSam Leffler 	left -= 4;
120339beb93cSSam Leffler 
120439beb93cSSam Leffler 	if (len > left) {
120539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone "
120639beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
120739beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
120839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
120939beb93cSSam Leffler 		return -1;
121039beb93cSSam Leffler 	}
121139beb93cSSam Leffler 	end = pos + len;
121239beb93cSSam Leffler 
121339beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) {
121439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
121539beb93cSSam Leffler 			   "message %d (expected ServerHelloDone)", type);
121639beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
121739beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
121839beb93cSSam Leffler 		return -1;
121939beb93cSSam Leffler 	}
122039beb93cSSam Leffler 
122139beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone");
122239beb93cSSam Leffler 
1223780fb4a2SCy Schubert 	if ((conn->flags & TLS_CONN_REQUIRE_OCSP) &&
1224780fb4a2SCy Schubert 	    !conn->ocsp_resp_received) {
1225780fb4a2SCy Schubert 		wpa_printf(MSG_INFO,
1226780fb4a2SCy Schubert 			   "TLSv1: No OCSP response received - reject handshake");
1227780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1228780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
1229780fb4a2SCy Schubert 		return -1;
1230780fb4a2SCy Schubert 	}
1231780fb4a2SCy Schubert 
123239beb93cSSam Leffler 	*in_len = end - in_data;
123339beb93cSSam Leffler 
123439beb93cSSam Leffler 	conn->state = CLIENT_KEY_EXCHANGE;
123539beb93cSSam Leffler 
123639beb93cSSam Leffler 	return 0;
123739beb93cSSam Leffler }
123839beb93cSSam Leffler 
123939beb93cSSam Leffler 
124039beb93cSSam Leffler static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn,
124139beb93cSSam Leffler 						 u8 ct, const u8 *in_data,
124239beb93cSSam Leffler 						 size_t *in_len)
124339beb93cSSam Leffler {
124439beb93cSSam Leffler 	const u8 *pos;
124539beb93cSSam Leffler 	size_t left;
124639beb93cSSam Leffler 
124739beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
124839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
124939beb93cSSam Leffler 			   "received content type 0x%x", ct);
125039beb93cSSam Leffler 		if (conn->use_session_ticket) {
125139beb93cSSam Leffler 			int res;
125239beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Server may have "
125339beb93cSSam Leffler 				   "rejected SessionTicket");
125439beb93cSSam Leffler 			conn->use_session_ticket = 0;
125539beb93cSSam Leffler 
125639beb93cSSam Leffler 			/* Notify upper layers that SessionTicket failed */
125739beb93cSSam Leffler 			res = conn->session_ticket_cb(
125839beb93cSSam Leffler 				conn->session_ticket_cb_ctx, NULL, 0, NULL,
125939beb93cSSam Leffler 				NULL, NULL);
126039beb93cSSam Leffler 			if (res < 0) {
126139beb93cSSam Leffler 				wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket "
126239beb93cSSam Leffler 					   "callback indicated failure");
126339beb93cSSam Leffler 				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
126439beb93cSSam Leffler 					  TLS_ALERT_HANDSHAKE_FAILURE);
126539beb93cSSam Leffler 				return -1;
126639beb93cSSam Leffler 			}
126739beb93cSSam Leffler 
126839beb93cSSam Leffler 			conn->state = SERVER_CERTIFICATE;
126939beb93cSSam Leffler 			return tls_process_certificate(conn, ct, in_data,
127039beb93cSSam Leffler 						       in_len);
127139beb93cSSam Leffler 		}
127239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
127339beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
127439beb93cSSam Leffler 		return -1;
127539beb93cSSam Leffler 	}
127639beb93cSSam Leffler 
127739beb93cSSam Leffler 	pos = in_data;
127839beb93cSSam Leffler 	left = *in_len;
127939beb93cSSam Leffler 
128039beb93cSSam Leffler 	if (left < 1) {
128139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec");
128239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
128339beb93cSSam Leffler 		return -1;
128439beb93cSSam Leffler 	}
128539beb93cSSam Leffler 
128639beb93cSSam Leffler 	if (*pos != TLS_CHANGE_CIPHER_SPEC) {
128739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
128839beb93cSSam Leffler 			   "received data 0x%x", *pos);
128939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
129039beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
129139beb93cSSam Leffler 		return -1;
129239beb93cSSam Leffler 	}
129339beb93cSSam Leffler 
129439beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec");
129539beb93cSSam Leffler 	if (tlsv1_record_change_read_cipher(&conn->rl) < 0) {
129639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher "
129739beb93cSSam Leffler 			   "for record layer");
129839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
129939beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
130039beb93cSSam Leffler 		return -1;
130139beb93cSSam Leffler 	}
130239beb93cSSam Leffler 
130339beb93cSSam Leffler 	*in_len = pos + 1 - in_data;
130439beb93cSSam Leffler 
130539beb93cSSam Leffler 	conn->state = SERVER_FINISHED;
130639beb93cSSam Leffler 
130739beb93cSSam Leffler 	return 0;
130839beb93cSSam Leffler }
130939beb93cSSam Leffler 
131039beb93cSSam Leffler 
131139beb93cSSam Leffler static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct,
131239beb93cSSam Leffler 				       const u8 *in_data, size_t *in_len)
131339beb93cSSam Leffler {
131439beb93cSSam Leffler 	const u8 *pos, *end;
131539beb93cSSam Leffler 	size_t left, len, hlen;
131639beb93cSSam Leffler 	u8 verify_data[TLS_VERIFY_DATA_LEN];
131739beb93cSSam Leffler 	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
131839beb93cSSam Leffler 
131939beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
132039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; "
132139beb93cSSam Leffler 			   "received content type 0x%x", ct);
132239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
132339beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
132439beb93cSSam Leffler 		return -1;
132539beb93cSSam Leffler 	}
132639beb93cSSam Leffler 
132739beb93cSSam Leffler 	pos = in_data;
132839beb93cSSam Leffler 	left = *in_len;
132939beb93cSSam Leffler 
133039beb93cSSam Leffler 	if (left < 4) {
133139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for "
133239beb93cSSam Leffler 			   "Finished",
133339beb93cSSam Leffler 			   (unsigned long) left);
133439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
133539beb93cSSam Leffler 			  TLS_ALERT_DECODE_ERROR);
133639beb93cSSam Leffler 		return -1;
133739beb93cSSam Leffler 	}
133839beb93cSSam Leffler 
133939beb93cSSam Leffler 	if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) {
134039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received "
134139beb93cSSam Leffler 			   "type 0x%x", pos[0]);
134239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
134339beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
134439beb93cSSam Leffler 		return -1;
134539beb93cSSam Leffler 	}
134639beb93cSSam Leffler 
134739beb93cSSam Leffler 	len = WPA_GET_BE24(pos + 1);
134839beb93cSSam Leffler 
134939beb93cSSam Leffler 	pos += 4;
135039beb93cSSam Leffler 	left -= 4;
135139beb93cSSam Leffler 
135239beb93cSSam Leffler 	if (len > left) {
135339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished "
135439beb93cSSam Leffler 			   "(len=%lu > left=%lu)",
135539beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
135639beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
135739beb93cSSam Leffler 			  TLS_ALERT_DECODE_ERROR);
135839beb93cSSam Leffler 		return -1;
135939beb93cSSam Leffler 	}
136039beb93cSSam Leffler 	end = pos + len;
136139beb93cSSam Leffler 	if (len != TLS_VERIFY_DATA_LEN) {
136239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length "
136339beb93cSSam Leffler 			   "in Finished: %lu (expected %d)",
136439beb93cSSam Leffler 			   (unsigned long) len, TLS_VERIFY_DATA_LEN);
136539beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
136639beb93cSSam Leffler 			  TLS_ALERT_DECODE_ERROR);
136739beb93cSSam Leffler 		return -1;
136839beb93cSSam Leffler 	}
136939beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished",
137039beb93cSSam Leffler 		    pos, TLS_VERIFY_DATA_LEN);
137139beb93cSSam Leffler 
1372f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
1373f05cddf9SRui Paulo 	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
1374f05cddf9SRui Paulo 		hlen = SHA256_MAC_LEN;
1375f05cddf9SRui Paulo 		if (conn->verify.sha256_server == NULL ||
1376f05cddf9SRui Paulo 		    crypto_hash_finish(conn->verify.sha256_server, hash, &hlen)
1377f05cddf9SRui Paulo 		    < 0) {
1378f05cddf9SRui Paulo 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1379f05cddf9SRui Paulo 				  TLS_ALERT_INTERNAL_ERROR);
1380f05cddf9SRui Paulo 			conn->verify.sha256_server = NULL;
1381f05cddf9SRui Paulo 			return -1;
1382f05cddf9SRui Paulo 		}
1383f05cddf9SRui Paulo 		conn->verify.sha256_server = NULL;
1384f05cddf9SRui Paulo 	} else {
1385f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
1386f05cddf9SRui Paulo 
138739beb93cSSam Leffler 	hlen = MD5_MAC_LEN;
138839beb93cSSam Leffler 	if (conn->verify.md5_server == NULL ||
138939beb93cSSam Leffler 	    crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) {
139039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
139139beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
139239beb93cSSam Leffler 		conn->verify.md5_server = NULL;
139339beb93cSSam Leffler 		crypto_hash_finish(conn->verify.sha1_server, NULL, NULL);
139439beb93cSSam Leffler 		conn->verify.sha1_server = NULL;
139539beb93cSSam Leffler 		return -1;
139639beb93cSSam Leffler 	}
139739beb93cSSam Leffler 	conn->verify.md5_server = NULL;
139839beb93cSSam Leffler 	hlen = SHA1_MAC_LEN;
139939beb93cSSam Leffler 	if (conn->verify.sha1_server == NULL ||
140039beb93cSSam Leffler 	    crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN,
140139beb93cSSam Leffler 			       &hlen) < 0) {
140239beb93cSSam Leffler 		conn->verify.sha1_server = NULL;
140339beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
140439beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
140539beb93cSSam Leffler 		return -1;
140639beb93cSSam Leffler 	}
140739beb93cSSam Leffler 	conn->verify.sha1_server = NULL;
1408f05cddf9SRui Paulo 	hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
140939beb93cSSam Leffler 
1410f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
1411f05cddf9SRui Paulo 	}
1412f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
1413f05cddf9SRui Paulo 
1414f05cddf9SRui Paulo 	if (tls_prf(conn->rl.tls_version,
1415f05cddf9SRui Paulo 		    conn->master_secret, TLS_MASTER_SECRET_LEN,
1416f05cddf9SRui Paulo 		    "server finished", hash, hlen,
141739beb93cSSam Leffler 		    verify_data, TLS_VERIFY_DATA_LEN)) {
141839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data");
141939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
142039beb93cSSam Leffler 			  TLS_ALERT_DECRYPT_ERROR);
142139beb93cSSam Leffler 		return -1;
142239beb93cSSam Leffler 	}
142339beb93cSSam Leffler 	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
142439beb93cSSam Leffler 			verify_data, TLS_VERIFY_DATA_LEN);
142539beb93cSSam Leffler 
14265b9c547cSRui Paulo 	if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
142739beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data");
14285b9c547cSRui Paulo 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
14295b9c547cSRui Paulo 			  TLS_ALERT_DECRYPT_ERROR);
143039beb93cSSam Leffler 		return -1;
143139beb93cSSam Leffler 	}
143239beb93cSSam Leffler 
143339beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received Finished");
143439beb93cSSam Leffler 
143539beb93cSSam Leffler 	*in_len = end - in_data;
143639beb93cSSam Leffler 
143739beb93cSSam Leffler 	conn->state = (conn->session_resumed || conn->use_session_ticket) ?
143839beb93cSSam Leffler 		CHANGE_CIPHER_SPEC : ACK_FINISHED;
143939beb93cSSam Leffler 
144039beb93cSSam Leffler 	return 0;
144139beb93cSSam Leffler }
144239beb93cSSam Leffler 
144339beb93cSSam Leffler 
144439beb93cSSam Leffler static int tls_process_application_data(struct tlsv1_client *conn, u8 ct,
144539beb93cSSam Leffler 					const u8 *in_data, size_t *in_len,
144639beb93cSSam Leffler 					u8 **out_data, size_t *out_len)
144739beb93cSSam Leffler {
144839beb93cSSam Leffler 	const u8 *pos;
144939beb93cSSam Leffler 	size_t left;
145039beb93cSSam Leffler 
145139beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
145239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; "
145339beb93cSSam Leffler 			   "received content type 0x%x", ct);
145439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
145539beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
145639beb93cSSam Leffler 		return -1;
145739beb93cSSam Leffler 	}
145839beb93cSSam Leffler 
145939beb93cSSam Leffler 	pos = in_data;
146039beb93cSSam Leffler 	left = *in_len;
146139beb93cSSam Leffler 
146239beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake",
146339beb93cSSam Leffler 		    pos, left);
146439beb93cSSam Leffler 
146539beb93cSSam Leffler 	*out_data = os_malloc(left);
146639beb93cSSam Leffler 	if (*out_data) {
146739beb93cSSam Leffler 		os_memcpy(*out_data, pos, left);
146839beb93cSSam Leffler 		*out_len = left;
146939beb93cSSam Leffler 	}
147039beb93cSSam Leffler 
147139beb93cSSam Leffler 	return 0;
147239beb93cSSam Leffler }
147339beb93cSSam Leffler 
147439beb93cSSam Leffler 
147539beb93cSSam Leffler int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct,
147639beb93cSSam Leffler 				   const u8 *buf, size_t *len,
147739beb93cSSam Leffler 				   u8 **out_data, size_t *out_len)
147839beb93cSSam Leffler {
147939beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_ALERT) {
148039beb93cSSam Leffler 		if (*len < 2) {
148139beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow");
148239beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
148339beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
148439beb93cSSam Leffler 			return -1;
148539beb93cSSam Leffler 		}
148639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
148739beb93cSSam Leffler 			   buf[0], buf[1]);
148839beb93cSSam Leffler 		*len = 2;
148939beb93cSSam Leffler 		conn->state = FAILED;
149039beb93cSSam Leffler 		return -1;
149139beb93cSSam Leffler 	}
149239beb93cSSam Leffler 
149339beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 &&
149439beb93cSSam Leffler 	    buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) {
149539beb93cSSam Leffler 		size_t hr_len = WPA_GET_BE24(buf + 1);
149639beb93cSSam Leffler 		if (hr_len > *len - 4) {
149739beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow");
149839beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
149939beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
150039beb93cSSam Leffler 			return -1;
150139beb93cSSam Leffler 		}
150239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest");
150339beb93cSSam Leffler 		*len = 4 + hr_len;
150439beb93cSSam Leffler 		return 0;
150539beb93cSSam Leffler 	}
150639beb93cSSam Leffler 
150739beb93cSSam Leffler 	switch (conn->state) {
150839beb93cSSam Leffler 	case SERVER_HELLO:
150939beb93cSSam Leffler 		if (tls_process_server_hello(conn, ct, buf, len))
151039beb93cSSam Leffler 			return -1;
151139beb93cSSam Leffler 		break;
151239beb93cSSam Leffler 	case SERVER_CERTIFICATE:
151339beb93cSSam Leffler 		if (tls_process_certificate(conn, ct, buf, len))
151439beb93cSSam Leffler 			return -1;
151539beb93cSSam Leffler 		break;
151639beb93cSSam Leffler 	case SERVER_KEY_EXCHANGE:
151739beb93cSSam Leffler 		if (tls_process_server_key_exchange(conn, ct, buf, len))
151839beb93cSSam Leffler 			return -1;
151939beb93cSSam Leffler 		break;
152039beb93cSSam Leffler 	case SERVER_CERTIFICATE_REQUEST:
152139beb93cSSam Leffler 		if (tls_process_certificate_request(conn, ct, buf, len))
152239beb93cSSam Leffler 			return -1;
152339beb93cSSam Leffler 		break;
152439beb93cSSam Leffler 	case SERVER_HELLO_DONE:
152539beb93cSSam Leffler 		if (tls_process_server_hello_done(conn, ct, buf, len))
152639beb93cSSam Leffler 			return -1;
152739beb93cSSam Leffler 		break;
152839beb93cSSam Leffler 	case SERVER_CHANGE_CIPHER_SPEC:
152939beb93cSSam Leffler 		if (tls_process_server_change_cipher_spec(conn, ct, buf, len))
153039beb93cSSam Leffler 			return -1;
153139beb93cSSam Leffler 		break;
153239beb93cSSam Leffler 	case SERVER_FINISHED:
153339beb93cSSam Leffler 		if (tls_process_server_finished(conn, ct, buf, len))
153439beb93cSSam Leffler 			return -1;
153539beb93cSSam Leffler 		break;
153639beb93cSSam Leffler 	case ACK_FINISHED:
153739beb93cSSam Leffler 		if (out_data &&
153839beb93cSSam Leffler 		    tls_process_application_data(conn, ct, buf, len, out_data,
153939beb93cSSam Leffler 						 out_len))
154039beb93cSSam Leffler 			return -1;
154139beb93cSSam Leffler 		break;
154239beb93cSSam Leffler 	default:
154339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d "
154439beb93cSSam Leffler 			   "while processing received message",
154539beb93cSSam Leffler 			   conn->state);
154639beb93cSSam Leffler 		return -1;
154739beb93cSSam Leffler 	}
154839beb93cSSam Leffler 
154939beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
155039beb93cSSam Leffler 		tls_verify_hash_add(&conn->verify, buf, *len);
155139beb93cSSam Leffler 
155239beb93cSSam Leffler 	return 0;
155339beb93cSSam Leffler }
1554