xref: /freebsd/contrib/wpa/src/tls/tlsv1_client_read.c (revision 780fb4a2fa9a9aee5ac48a60b790f567c0dc13e9)
139beb93cSSam Leffler /*
239beb93cSSam Leffler  * TLSv1 client - read handshake message
3*780fb4a2SCy 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 
30*780fb4a2SCy Schubert static int tls_version_disabled(struct tlsv1_client *conn, u16 ver)
31*780fb4a2SCy Schubert {
32*780fb4a2SCy Schubert 	return (((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
33*780fb4a2SCy Schubert 		 ver == TLS_VERSION_1) ||
34*780fb4a2SCy Schubert 		((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
35*780fb4a2SCy Schubert 		 ver == TLS_VERSION_1_1) ||
36*780fb4a2SCy Schubert 		((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
37*780fb4a2SCy Schubert 		 ver == TLS_VERSION_1_2));
38*780fb4a2SCy Schubert }
39*780fb4a2SCy Schubert 
40*780fb4a2SCy Schubert 
41*780fb4a2SCy Schubert static int tls_process_server_hello_extensions(struct tlsv1_client *conn,
42*780fb4a2SCy Schubert 					       const u8 *pos, size_t len)
43*780fb4a2SCy Schubert {
44*780fb4a2SCy Schubert 	const u8 *end = pos + len;
45*780fb4a2SCy Schubert 
46*780fb4a2SCy Schubert 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello extensions",
47*780fb4a2SCy Schubert 		    pos, len);
48*780fb4a2SCy Schubert 	while (pos < end) {
49*780fb4a2SCy Schubert 		u16 ext, elen;
50*780fb4a2SCy Schubert 
51*780fb4a2SCy Schubert 		if (end - pos < 4) {
52*780fb4a2SCy Schubert 			wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension header");
53*780fb4a2SCy Schubert 			return -1;
54*780fb4a2SCy Schubert 		}
55*780fb4a2SCy Schubert 
56*780fb4a2SCy Schubert 		ext = WPA_GET_BE16(pos);
57*780fb4a2SCy Schubert 		pos += 2;
58*780fb4a2SCy Schubert 		elen = WPA_GET_BE16(pos);
59*780fb4a2SCy Schubert 		pos += 2;
60*780fb4a2SCy Schubert 
61*780fb4a2SCy Schubert 		if (elen > end - pos) {
62*780fb4a2SCy Schubert 			wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension");
63*780fb4a2SCy Schubert 			return -1;
64*780fb4a2SCy Schubert 		}
65*780fb4a2SCy Schubert 
66*780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "TLSv1: ServerHello ExtensionType %u",
67*780fb4a2SCy Schubert 			   ext);
68*780fb4a2SCy Schubert 		wpa_hexdump(MSG_DEBUG, "TLSv1: ServerHello extension data",
69*780fb4a2SCy Schubert 			    pos, elen);
70*780fb4a2SCy Schubert 
71*780fb4a2SCy Schubert 		pos += elen;
72*780fb4a2SCy Schubert 	}
73*780fb4a2SCy Schubert 
74*780fb4a2SCy Schubert 	return 0;
75*780fb4a2SCy Schubert }
76*780fb4a2SCy Schubert 
77*780fb4a2SCy 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);
127*780fb4a2SCy Schubert 	if (!tls_version_ok(tls_version) ||
128*780fb4a2SCy 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 
217*780fb4a2SCy Schubert 	if (end - pos >= 2) {
218*780fb4a2SCy Schubert 		u16 ext_len;
219*780fb4a2SCy Schubert 
220*780fb4a2SCy Schubert 		ext_len = WPA_GET_BE16(pos);
221*780fb4a2SCy Schubert 		pos += 2;
222*780fb4a2SCy Schubert 		if (end - pos < ext_len) {
223*780fb4a2SCy Schubert 			wpa_printf(MSG_INFO,
224*780fb4a2SCy Schubert 				   "TLSv1: Invalid ServerHello extension length: %u (left: %u)",
225*780fb4a2SCy Schubert 				   ext_len, (unsigned int) (end - pos));
226*780fb4a2SCy Schubert 			goto decode_error;
227*780fb4a2SCy Schubert 		}
228*780fb4a2SCy Schubert 
229*780fb4a2SCy Schubert 		if (tls_process_server_hello_extensions(conn, pos, ext_len))
230*780fb4a2SCy Schubert 			goto decode_error;
231*780fb4a2SCy Schubert 		pos += ext_len;
232*780fb4a2SCy Schubert 	}
233*780fb4a2SCy 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 
279*780fb4a2SCy Schubert static void tls_peer_cert_event(struct tlsv1_client *conn, int depth,
280*780fb4a2SCy Schubert 				struct x509_certificate *cert)
281*780fb4a2SCy Schubert {
282*780fb4a2SCy Schubert 	union tls_event_data ev;
283*780fb4a2SCy Schubert 	struct wpabuf *cert_buf = NULL;
284*780fb4a2SCy Schubert #ifdef CONFIG_SHA256
285*780fb4a2SCy Schubert 	u8 hash[32];
286*780fb4a2SCy Schubert #endif /* CONFIG_SHA256 */
287*780fb4a2SCy Schubert 	char subject[128];
288*780fb4a2SCy Schubert 
289*780fb4a2SCy Schubert 	if (!conn->event_cb)
290*780fb4a2SCy Schubert 		return;
291*780fb4a2SCy Schubert 
292*780fb4a2SCy Schubert 	os_memset(&ev, 0, sizeof(ev));
293*780fb4a2SCy Schubert 	if (conn->cred->cert_probe || conn->cert_in_cb) {
294*780fb4a2SCy Schubert 		cert_buf = wpabuf_alloc_copy(cert->cert_start,
295*780fb4a2SCy Schubert 					     cert->cert_len);
296*780fb4a2SCy Schubert 		ev.peer_cert.cert = cert_buf;
297*780fb4a2SCy Schubert 	}
298*780fb4a2SCy Schubert #ifdef CONFIG_SHA256
299*780fb4a2SCy Schubert 	if (cert_buf) {
300*780fb4a2SCy Schubert 		const u8 *addr[1];
301*780fb4a2SCy Schubert 		size_t len[1];
302*780fb4a2SCy Schubert 		addr[0] = wpabuf_head(cert_buf);
303*780fb4a2SCy Schubert 		len[0] = wpabuf_len(cert_buf);
304*780fb4a2SCy Schubert 		if (sha256_vector(1, addr, len, hash) == 0) {
305*780fb4a2SCy Schubert 			ev.peer_cert.hash = hash;
306*780fb4a2SCy Schubert 			ev.peer_cert.hash_len = sizeof(hash);
307*780fb4a2SCy Schubert 		}
308*780fb4a2SCy Schubert 	}
309*780fb4a2SCy Schubert #endif /* CONFIG_SHA256 */
310*780fb4a2SCy Schubert 
311*780fb4a2SCy Schubert 	ev.peer_cert.depth = depth;
312*780fb4a2SCy Schubert 	x509_name_string(&cert->subject, subject, sizeof(subject));
313*780fb4a2SCy Schubert 	ev.peer_cert.subject = subject;
314*780fb4a2SCy Schubert 
315*780fb4a2SCy Schubert 	conn->event_cb(conn->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
316*780fb4a2SCy Schubert 	wpabuf_free(cert_buf);
317*780fb4a2SCy Schubert }
318*780fb4a2SCy Schubert 
319*780fb4a2SCy Schubert 
320*780fb4a2SCy Schubert static void tls_cert_chain_failure_event(struct tlsv1_client *conn, int depth,
321*780fb4a2SCy Schubert 					 struct x509_certificate *cert,
322*780fb4a2SCy Schubert 					 enum tls_fail_reason reason,
323*780fb4a2SCy Schubert 					 const char *reason_txt)
324*780fb4a2SCy Schubert {
325*780fb4a2SCy Schubert 	struct wpabuf *cert_buf = NULL;
326*780fb4a2SCy Schubert 	union tls_event_data ev;
327*780fb4a2SCy Schubert 	char subject[128];
328*780fb4a2SCy Schubert 
329*780fb4a2SCy Schubert 	if (!conn->event_cb || !cert)
330*780fb4a2SCy Schubert 		return;
331*780fb4a2SCy Schubert 
332*780fb4a2SCy Schubert 	os_memset(&ev, 0, sizeof(ev));
333*780fb4a2SCy Schubert 	ev.cert_fail.depth = depth;
334*780fb4a2SCy Schubert 	x509_name_string(&cert->subject, subject, sizeof(subject));
335*780fb4a2SCy Schubert 	ev.peer_cert.subject = subject;
336*780fb4a2SCy Schubert 	ev.cert_fail.reason = reason;
337*780fb4a2SCy Schubert 	ev.cert_fail.reason_txt = reason_txt;
338*780fb4a2SCy Schubert 	cert_buf = wpabuf_alloc_copy(cert->cert_start,
339*780fb4a2SCy Schubert 				     cert->cert_len);
340*780fb4a2SCy Schubert 	ev.cert_fail.cert = cert_buf;
341*780fb4a2SCy Schubert 	conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
342*780fb4a2SCy Schubert 	wpabuf_free(cert_buf);
343*780fb4a2SCy Schubert }
344*780fb4a2SCy Schubert 
345*780fb4a2SCy 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 
489*780fb4a2SCy Schubert 		tls_peer_cert_event(conn, idx, cert);
490*780fb4a2SCy 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 
501*780fb4a2SCy Schubert 	if (conn->cred && conn->cred->server_cert_only && chain) {
502*780fb4a2SCy Schubert 		u8 hash[SHA256_MAC_LEN];
503*780fb4a2SCy Schubert 		char buf[128];
504*780fb4a2SCy Schubert 
505*780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
506*780fb4a2SCy Schubert 			   "TLSv1: Validate server certificate hash");
507*780fb4a2SCy Schubert 		x509_name_string(&chain->subject, buf, sizeof(buf));
508*780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "TLSv1: 0: %s", buf);
509*780fb4a2SCy Schubert 		if (sha256_vector(1, &chain->cert_start, &chain->cert_len,
510*780fb4a2SCy Schubert 				  hash) < 0 ||
511*780fb4a2SCy Schubert 		    os_memcmp(conn->cred->srv_cert_hash, hash,
512*780fb4a2SCy Schubert 			      SHA256_MAC_LEN) != 0) {
513*780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
514*780fb4a2SCy Schubert 				   "TLSv1: Server certificate hash mismatch");
515*780fb4a2SCy Schubert 			wpa_hexdump(MSG_MSGDUMP, "TLSv1: SHA256 hash",
516*780fb4a2SCy Schubert 				    hash, SHA256_MAC_LEN);
517*780fb4a2SCy Schubert 			if (conn->event_cb) {
518*780fb4a2SCy Schubert 				union tls_event_data ev;
519*780fb4a2SCy Schubert 
520*780fb4a2SCy Schubert 				os_memset(&ev, 0, sizeof(ev));
521*780fb4a2SCy Schubert 				ev.cert_fail.reason = TLS_FAIL_UNSPECIFIED;
522*780fb4a2SCy Schubert 				ev.cert_fail.reason_txt =
523*780fb4a2SCy Schubert 					"Server certificate mismatch";
524*780fb4a2SCy Schubert 				ev.cert_fail.subject = buf;
525*780fb4a2SCy Schubert 				conn->event_cb(conn->cb_ctx,
526*780fb4a2SCy Schubert 					       TLS_CERT_CHAIN_FAILURE, &ev);
527*780fb4a2SCy Schubert 			}
528*780fb4a2SCy Schubert 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
529*780fb4a2SCy Schubert 				  TLS_ALERT_BAD_CERTIFICATE);
530*780fb4a2SCy Schubert 			x509_certificate_chain_free(chain);
531*780fb4a2SCy Schubert 			return -1;
532*780fb4a2SCy Schubert 		}
533*780fb4a2SCy Schubert 	} else if (conn->cred && conn->cred->cert_probe) {
534*780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
535*780fb4a2SCy Schubert 			   "TLSv1: Reject server certificate on probe-only rune");
536*780fb4a2SCy Schubert 		if (conn->event_cb) {
537*780fb4a2SCy Schubert 			union tls_event_data ev;
538*780fb4a2SCy Schubert 			char buf[128];
539*780fb4a2SCy Schubert 
540*780fb4a2SCy Schubert 			os_memset(&ev, 0, sizeof(ev));
541*780fb4a2SCy Schubert 			ev.cert_fail.reason = TLS_FAIL_SERVER_CHAIN_PROBE;
542*780fb4a2SCy Schubert 			ev.cert_fail.reason_txt =
543*780fb4a2SCy Schubert 				"Server certificate chain probe";
544*780fb4a2SCy Schubert 			if (chain) {
545*780fb4a2SCy Schubert 				x509_name_string(&chain->subject, buf,
546*780fb4a2SCy Schubert 						 sizeof(buf));
547*780fb4a2SCy Schubert 				ev.cert_fail.subject = buf;
548*780fb4a2SCy Schubert 			}
549*780fb4a2SCy Schubert 			conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE,
550*780fb4a2SCy Schubert 				       &ev);
551*780fb4a2SCy Schubert 		}
552*780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
553*780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE);
554*780fb4a2SCy Schubert 		x509_certificate_chain_free(chain);
555*780fb4a2SCy Schubert 		return -1;
556*780fb4a2SCy Schubert 	} else if (conn->cred && conn->cred->ca_cert_verify &&
557*780fb4a2SCy Schubert 		   x509_certificate_chain_validate(
558*780fb4a2SCy Schubert 			   conn->cred->trusted_certs, chain, &reason,
559*780fb4a2SCy 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;
567*780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
568*780fb4a2SCy Schubert 				conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE,
569*780fb4a2SCy 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;
576*780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
577*780fb4a2SCy Schubert 				conn, 0, chain, TLS_FAIL_REVOKED,
578*780fb4a2SCy Schubert 				"certificate revoked");
57939beb93cSSam Leffler 			break;
58039beb93cSSam Leffler 		case X509_VALIDATE_CERTIFICATE_EXPIRED:
58139beb93cSSam Leffler 			tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
582*780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
583*780fb4a2SCy Schubert 				conn, 0, chain, TLS_FAIL_EXPIRED,
584*780fb4a2SCy 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;
591*780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
592*780fb4a2SCy Schubert 				conn, 0, chain, TLS_FAIL_UNTRUSTED,
593*780fb4a2SCy 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 
604*780fb4a2SCy Schubert 	if (conn->cred && !conn->cred->server_cert_only && chain &&
605*780fb4a2SCy Schubert 	    (chain->extensions_present & X509_EXT_EXT_KEY_USAGE) &&
606*780fb4a2SCy Schubert 	    !(chain->ext_key_usage &
607*780fb4a2SCy Schubert 	      (X509_EXT_KEY_USAGE_ANY | X509_EXT_KEY_USAGE_SERVER_AUTH))) {
608*780fb4a2SCy Schubert 		tls_cert_chain_failure_event(
609*780fb4a2SCy Schubert 			conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE,
610*780fb4a2SCy Schubert 			"certificate not allowed for server authentication");
611*780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
612*780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE);
61339beb93cSSam Leffler 		x509_certificate_chain_free(chain);
614*780fb4a2SCy Schubert 		return -1;
615*780fb4a2SCy Schubert 	}
616*780fb4a2SCy Schubert 
617*780fb4a2SCy Schubert 	if (conn->flags & TLS_CONN_REQUEST_OCSP) {
618*780fb4a2SCy Schubert 		x509_certificate_chain_free(conn->server_cert);
619*780fb4a2SCy Schubert 		conn->server_cert = chain;
620*780fb4a2SCy Schubert 	} else {
621*780fb4a2SCy Schubert 		x509_certificate_chain_free(chain);
622*780fb4a2SCy 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 	}
68839beb93cSSam Leffler 	conn->dh_p = os_malloc(conn->dh_p_len);
68939beb93cSSam Leffler 	if (conn->dh_p == NULL)
69039beb93cSSam Leffler 		goto fail;
69139beb93cSSam Leffler 	os_memcpy(conn->dh_p, pos, conn->dh_p_len);
69239beb93cSSam Leffler 	pos += conn->dh_p_len;
69339beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)",
69439beb93cSSam Leffler 		    conn->dh_p, conn->dh_p_len);
69539beb93cSSam Leffler 
69639beb93cSSam Leffler 	if (end - pos < 3)
69739beb93cSSam Leffler 		goto fail;
6985b9c547cSRui Paulo 	val = WPA_GET_BE16(pos);
69939beb93cSSam Leffler 	pos += 2;
7005b9c547cSRui Paulo 	if (val == 0 || val > (size_t) (end - pos))
70139beb93cSSam Leffler 		goto fail;
7025b9c547cSRui Paulo 	conn->dh_g_len = val;
70339beb93cSSam Leffler 	conn->dh_g = os_malloc(conn->dh_g_len);
70439beb93cSSam Leffler 	if (conn->dh_g == NULL)
70539beb93cSSam Leffler 		goto fail;
70639beb93cSSam Leffler 	os_memcpy(conn->dh_g, pos, conn->dh_g_len);
70739beb93cSSam Leffler 	pos += conn->dh_g_len;
70839beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)",
70939beb93cSSam Leffler 		    conn->dh_g, conn->dh_g_len);
71039beb93cSSam Leffler 	if (conn->dh_g_len == 1 && conn->dh_g[0] < 2)
71139beb93cSSam Leffler 		goto fail;
71239beb93cSSam Leffler 
71339beb93cSSam Leffler 	if (end - pos < 3)
71439beb93cSSam Leffler 		goto fail;
7155b9c547cSRui Paulo 	val = WPA_GET_BE16(pos);
71639beb93cSSam Leffler 	pos += 2;
7175b9c547cSRui Paulo 	if (val == 0 || val > (size_t) (end - pos))
71839beb93cSSam Leffler 		goto fail;
7195b9c547cSRui Paulo 	conn->dh_ys_len = val;
72039beb93cSSam Leffler 	conn->dh_ys = os_malloc(conn->dh_ys_len);
72139beb93cSSam Leffler 	if (conn->dh_ys == NULL)
72239beb93cSSam Leffler 		goto fail;
72339beb93cSSam Leffler 	os_memcpy(conn->dh_ys, pos, conn->dh_ys_len);
72439beb93cSSam Leffler 	pos += conn->dh_ys_len;
72539beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
72639beb93cSSam Leffler 		    conn->dh_ys, conn->dh_ys_len);
7275b9c547cSRui Paulo 	server_params_end = pos;
7285b9c547cSRui Paulo 
7295b9c547cSRui Paulo 	if (key_exchange == TLS_KEY_X_DHE_RSA) {
730*780fb4a2SCy Schubert 		u8 hash[64];
7315b9c547cSRui Paulo 		int hlen;
7325b9c547cSRui Paulo 
7335b9c547cSRui Paulo 		if (conn->rl.tls_version == TLS_VERSION_1_2) {
7345b9c547cSRui Paulo #ifdef CONFIG_TLSV12
7355b9c547cSRui Paulo 			/*
7365b9c547cSRui Paulo 			 * RFC 5246, 4.7:
7375b9c547cSRui Paulo 			 * TLS v1.2 adds explicit indication of the used
7385b9c547cSRui Paulo 			 * signature and hash algorithms.
7395b9c547cSRui Paulo 			 *
7405b9c547cSRui Paulo 			 * struct {
7415b9c547cSRui Paulo 			 *   HashAlgorithm hash;
7425b9c547cSRui Paulo 			 *   SignatureAlgorithm signature;
7435b9c547cSRui Paulo 			 * } SignatureAndHashAlgorithm;
7445b9c547cSRui Paulo 			 */
7455b9c547cSRui Paulo 			if (end - pos < 2)
7465b9c547cSRui Paulo 				goto fail;
747*780fb4a2SCy Schubert 			if ((pos[0] != TLS_HASH_ALG_SHA256 &&
748*780fb4a2SCy Schubert 			     pos[0] != TLS_HASH_ALG_SHA384 &&
749*780fb4a2SCy Schubert 			     pos[0] != TLS_HASH_ALG_SHA512) ||
7505b9c547cSRui Paulo 			    pos[1] != TLS_SIGN_ALG_RSA) {
7515b9c547cSRui Paulo 				wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/signature(%u) algorithm",
7525b9c547cSRui Paulo 					   pos[0], pos[1]);
7535b9c547cSRui Paulo 				goto fail;
7545b9c547cSRui Paulo 			}
7555b9c547cSRui Paulo 
7565b9c547cSRui Paulo 			hlen = tlsv12_key_x_server_params_hash(
757*780fb4a2SCy Schubert 				conn->rl.tls_version, pos[0],
758*780fb4a2SCy Schubert 				conn->client_random,
7595b9c547cSRui Paulo 				conn->server_random, server_params,
7605b9c547cSRui Paulo 				server_params_end - server_params, hash);
761*780fb4a2SCy Schubert 			pos += 2;
7625b9c547cSRui Paulo #else /* CONFIG_TLSV12 */
7635b9c547cSRui Paulo 			goto fail;
7645b9c547cSRui Paulo #endif /* CONFIG_TLSV12 */
7655b9c547cSRui Paulo 		} else {
7665b9c547cSRui Paulo 			hlen = tls_key_x_server_params_hash(
7675b9c547cSRui Paulo 				conn->rl.tls_version, conn->client_random,
7685b9c547cSRui Paulo 				conn->server_random, server_params,
7695b9c547cSRui Paulo 				server_params_end - server_params, hash);
7705b9c547cSRui Paulo 		}
7715b9c547cSRui Paulo 
7725b9c547cSRui Paulo 		if (hlen < 0)
7735b9c547cSRui Paulo 			goto fail;
7745b9c547cSRui Paulo 		wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerKeyExchange hash",
7755b9c547cSRui Paulo 			    hash, hlen);
7765b9c547cSRui Paulo 
7775b9c547cSRui Paulo 		if (tls_verify_signature(conn->rl.tls_version,
7785b9c547cSRui Paulo 					 conn->server_rsa_key,
7795b9c547cSRui Paulo 					 hash, hlen, pos, end - pos,
7805b9c547cSRui Paulo 					 &alert) < 0)
7815b9c547cSRui Paulo 			goto fail;
7825b9c547cSRui Paulo 	}
78339beb93cSSam Leffler 
78439beb93cSSam Leffler 	return 0;
78539beb93cSSam Leffler 
78639beb93cSSam Leffler fail:
78739beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed");
78839beb93cSSam Leffler 	tlsv1_client_free_dh(conn);
78939beb93cSSam Leffler 	return -1;
79039beb93cSSam Leffler }
79139beb93cSSam Leffler 
79239beb93cSSam Leffler 
793*780fb4a2SCy Schubert static enum tls_ocsp_result
794*780fb4a2SCy Schubert tls_process_certificate_status_ocsp_response(struct tlsv1_client *conn,
795*780fb4a2SCy Schubert 					     const u8 *pos, size_t len)
796*780fb4a2SCy Schubert {
797*780fb4a2SCy Schubert 	const u8 *end = pos + len;
798*780fb4a2SCy Schubert 	u32 ocsp_resp_len;
799*780fb4a2SCy Schubert 
800*780fb4a2SCy Schubert 	/* opaque OCSPResponse<1..2^24-1>; */
801*780fb4a2SCy Schubert 	if (end - pos < 3) {
802*780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "TLSv1: Too short OCSPResponse");
803*780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
804*780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
805*780fb4a2SCy Schubert 	}
806*780fb4a2SCy Schubert 	ocsp_resp_len = WPA_GET_BE24(pos);
807*780fb4a2SCy Schubert 	pos += 3;
808*780fb4a2SCy Schubert 	if (end - pos < ocsp_resp_len) {
809*780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "TLSv1: Truncated OCSPResponse");
810*780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
811*780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
812*780fb4a2SCy Schubert 	}
813*780fb4a2SCy Schubert 
814*780fb4a2SCy Schubert 	return tls_process_ocsp_response(conn, pos, ocsp_resp_len);
815*780fb4a2SCy Schubert }
816*780fb4a2SCy Schubert 
817*780fb4a2SCy Schubert 
818*780fb4a2SCy Schubert static int tls_process_certificate_status(struct tlsv1_client *conn, u8 ct,
819*780fb4a2SCy Schubert 					   const u8 *in_data, size_t *in_len)
820*780fb4a2SCy Schubert {
821*780fb4a2SCy Schubert 	const u8 *pos, *end;
822*780fb4a2SCy Schubert 	size_t left, len;
823*780fb4a2SCy Schubert 	u8 type, status_type;
824*780fb4a2SCy Schubert 	enum tls_ocsp_result res;
825*780fb4a2SCy Schubert 	struct x509_certificate *cert;
826*780fb4a2SCy Schubert 	int depth;
827*780fb4a2SCy Schubert 
828*780fb4a2SCy Schubert 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
829*780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
830*780fb4a2SCy Schubert 			   "TLSv1: Expected Handshake; received content type 0x%x",
831*780fb4a2SCy Schubert 			   ct);
832*780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
833*780fb4a2SCy Schubert 			  TLS_ALERT_UNEXPECTED_MESSAGE);
834*780fb4a2SCy Schubert 		return -1;
835*780fb4a2SCy Schubert 	}
836*780fb4a2SCy Schubert 
837*780fb4a2SCy Schubert 	pos = in_data;
838*780fb4a2SCy Schubert 	left = *in_len;
839*780fb4a2SCy Schubert 
840*780fb4a2SCy Schubert 	if (left < 4) {
841*780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
842*780fb4a2SCy Schubert 			   "TLSv1: Too short CertificateStatus (left=%lu)",
843*780fb4a2SCy Schubert 			   (unsigned long) left);
844*780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
845*780fb4a2SCy Schubert 		return -1;
846*780fb4a2SCy Schubert 	}
847*780fb4a2SCy Schubert 
848*780fb4a2SCy Schubert 	type = *pos++;
849*780fb4a2SCy Schubert 	len = WPA_GET_BE24(pos);
850*780fb4a2SCy Schubert 	pos += 3;
851*780fb4a2SCy Schubert 	left -= 4;
852*780fb4a2SCy Schubert 
853*780fb4a2SCy Schubert 	if (len > left) {
854*780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
855*780fb4a2SCy Schubert 			   "TLSv1: Mismatch in CertificateStatus length (len=%lu != left=%lu)",
856*780fb4a2SCy Schubert 			   (unsigned long) len, (unsigned long) left);
857*780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
858*780fb4a2SCy Schubert 		return -1;
859*780fb4a2SCy Schubert 	}
860*780fb4a2SCy Schubert 
861*780fb4a2SCy Schubert 	end = pos + len;
862*780fb4a2SCy Schubert 
863*780fb4a2SCy Schubert 	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS) {
864*780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
865*780fb4a2SCy Schubert 			   "TLSv1: Received unexpected handshake message %d (expected CertificateStatus)",
866*780fb4a2SCy Schubert 			   type);
867*780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
868*780fb4a2SCy Schubert 			  TLS_ALERT_UNEXPECTED_MESSAGE);
869*780fb4a2SCy Schubert 		return -1;
870*780fb4a2SCy Schubert 	}
871*780fb4a2SCy Schubert 
872*780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateStatus");
873*780fb4a2SCy Schubert 
874*780fb4a2SCy Schubert 	/*
875*780fb4a2SCy Schubert 	 * struct {
876*780fb4a2SCy Schubert 	 *     CertificateStatusType status_type;
877*780fb4a2SCy Schubert 	 *     select (status_type) {
878*780fb4a2SCy Schubert 	 *         case ocsp: OCSPResponse;
879*780fb4a2SCy Schubert 	 *         case ocsp_multi: OCSPResponseList;
880*780fb4a2SCy Schubert 	 *     } response;
881*780fb4a2SCy Schubert 	 * } CertificateStatus;
882*780fb4a2SCy Schubert 	 */
883*780fb4a2SCy Schubert 	if (end - pos < 1) {
884*780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "TLSv1: Too short CertificateStatus");
885*780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
886*780fb4a2SCy Schubert 		return -1;
887*780fb4a2SCy Schubert 	}
888*780fb4a2SCy Schubert 	status_type = *pos++;
889*780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatus status_type %u",
890*780fb4a2SCy Schubert 		   status_type);
891*780fb4a2SCy Schubert 
892*780fb4a2SCy Schubert 	if (status_type == 1 /* ocsp */) {
893*780fb4a2SCy Schubert 		res = tls_process_certificate_status_ocsp_response(
894*780fb4a2SCy Schubert 			conn, pos, end - pos);
895*780fb4a2SCy Schubert 	} else if (status_type == 2 /* ocsp_multi */) {
896*780fb4a2SCy Schubert 		int good = 0, revoked = 0;
897*780fb4a2SCy Schubert 		u32 resp_len;
898*780fb4a2SCy Schubert 
899*780fb4a2SCy Schubert 		res = TLS_OCSP_NO_RESPONSE;
900*780fb4a2SCy Schubert 
901*780fb4a2SCy Schubert 		/*
902*780fb4a2SCy Schubert 		 * opaque OCSPResponse<0..2^24-1>;
903*780fb4a2SCy Schubert 		 *
904*780fb4a2SCy Schubert 		 * struct {
905*780fb4a2SCy Schubert 		 *   OCSPResponse ocsp_response_list<1..2^24-1>;
906*780fb4a2SCy Schubert 		 * } OCSPResponseList;
907*780fb4a2SCy Schubert 		 */
908*780fb4a2SCy Schubert 		if (end - pos < 3) {
909*780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
910*780fb4a2SCy Schubert 				   "TLSv1: Truncated OCSPResponseList");
911*780fb4a2SCy Schubert 			res = TLS_OCSP_INVALID;
912*780fb4a2SCy Schubert 			goto done;
913*780fb4a2SCy Schubert 		}
914*780fb4a2SCy Schubert 		resp_len = WPA_GET_BE24(pos);
915*780fb4a2SCy Schubert 		pos += 3;
916*780fb4a2SCy Schubert 		if (end - pos < resp_len) {
917*780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
918*780fb4a2SCy Schubert 				   "TLSv1: Truncated OCSPResponseList(len=%u)",
919*780fb4a2SCy Schubert 				   resp_len);
920*780fb4a2SCy Schubert 			res = TLS_OCSP_INVALID;
921*780fb4a2SCy Schubert 			goto done;
922*780fb4a2SCy Schubert 		}
923*780fb4a2SCy Schubert 		end = pos + resp_len;
924*780fb4a2SCy Schubert 
925*780fb4a2SCy Schubert 		while (end - pos >= 3) {
926*780fb4a2SCy Schubert 			resp_len = WPA_GET_BE24(pos);
927*780fb4a2SCy Schubert 			pos += 3;
928*780fb4a2SCy Schubert 			if (resp_len > end - pos) {
929*780fb4a2SCy Schubert 				wpa_printf(MSG_DEBUG,
930*780fb4a2SCy Schubert 					   "TLSv1: Truncated OCSPResponse(len=%u; left=%d) in ocsp_multi",
931*780fb4a2SCy Schubert 					   resp_len, (int) (end - pos));
932*780fb4a2SCy Schubert 				res = TLS_OCSP_INVALID;
933*780fb4a2SCy Schubert 				break;
934*780fb4a2SCy Schubert 			}
935*780fb4a2SCy Schubert 			if (!resp_len)
936*780fb4a2SCy Schubert 				continue; /* Skip an empty response */
937*780fb4a2SCy Schubert 			res = tls_process_certificate_status_ocsp_response(
938*780fb4a2SCy Schubert 				conn, pos - 3, resp_len + 3);
939*780fb4a2SCy Schubert 			if (res == TLS_OCSP_REVOKED)
940*780fb4a2SCy Schubert 				revoked++;
941*780fb4a2SCy Schubert 			else if (res == TLS_OCSP_GOOD)
942*780fb4a2SCy Schubert 				good++;
943*780fb4a2SCy Schubert 			pos += resp_len;
944*780fb4a2SCy Schubert 		}
945*780fb4a2SCy Schubert 
946*780fb4a2SCy Schubert 		if (revoked)
947*780fb4a2SCy Schubert 			res = TLS_OCSP_REVOKED;
948*780fb4a2SCy Schubert 		else if (good)
949*780fb4a2SCy Schubert 			res = TLS_OCSP_GOOD;
950*780fb4a2SCy Schubert 	} else {
951*780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
952*780fb4a2SCy Schubert 			   "TLSv1: Ignore unsupported CertificateStatus");
953*780fb4a2SCy Schubert 		goto skip;
954*780fb4a2SCy Schubert 	}
955*780fb4a2SCy Schubert 
956*780fb4a2SCy Schubert done:
957*780fb4a2SCy Schubert 	if (res == TLS_OCSP_REVOKED) {
958*780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
959*780fb4a2SCy Schubert 			  TLS_ALERT_CERTIFICATE_REVOKED);
960*780fb4a2SCy Schubert 		for (cert = conn->server_cert, depth = 0; cert;
961*780fb4a2SCy Schubert 		     cert = cert->next, depth++) {
962*780fb4a2SCy Schubert 			if (cert->ocsp_revoked) {
963*780fb4a2SCy Schubert 				tls_cert_chain_failure_event(
964*780fb4a2SCy Schubert 					conn, depth, cert, TLS_FAIL_REVOKED,
965*780fb4a2SCy Schubert 					"certificate revoked");
966*780fb4a2SCy Schubert 			}
967*780fb4a2SCy Schubert 		}
968*780fb4a2SCy Schubert 		return -1;
969*780fb4a2SCy Schubert 	}
970*780fb4a2SCy Schubert 
971*780fb4a2SCy Schubert 	if (conn->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
972*780fb4a2SCy Schubert 		/*
973*780fb4a2SCy Schubert 		 * Verify that each certificate on the chain that is not part
974*780fb4a2SCy Schubert 		 * of the trusted certificates has a good status. If not,
975*780fb4a2SCy Schubert 		 * terminate handshake.
976*780fb4a2SCy Schubert 		 */
977*780fb4a2SCy Schubert 		for (cert = conn->server_cert, depth = 0; cert;
978*780fb4a2SCy Schubert 		     cert = cert->next, depth++) {
979*780fb4a2SCy Schubert 			if (!cert->ocsp_good) {
980*780fb4a2SCy Schubert 				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
981*780fb4a2SCy Schubert 					  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
982*780fb4a2SCy Schubert 				tls_cert_chain_failure_event(
983*780fb4a2SCy Schubert 					conn, depth, cert,
984*780fb4a2SCy Schubert 					TLS_FAIL_UNSPECIFIED,
985*780fb4a2SCy Schubert 					"bad certificate status response");
986*780fb4a2SCy Schubert 				return -1;
987*780fb4a2SCy Schubert 			}
988*780fb4a2SCy Schubert 			if (cert->issuer_trusted)
989*780fb4a2SCy Schubert 				break;
990*780fb4a2SCy Schubert 		}
991*780fb4a2SCy Schubert 	}
992*780fb4a2SCy Schubert 
993*780fb4a2SCy Schubert 	if ((conn->flags & TLS_CONN_REQUIRE_OCSP) && res != TLS_OCSP_GOOD) {
994*780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
995*780fb4a2SCy Schubert 			  res == TLS_OCSP_INVALID ? TLS_ALERT_DECODE_ERROR :
996*780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
997*780fb4a2SCy Schubert 		if (conn->server_cert)
998*780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
999*780fb4a2SCy Schubert 				conn, 0, conn->server_cert,
1000*780fb4a2SCy Schubert 				TLS_FAIL_UNSPECIFIED,
1001*780fb4a2SCy Schubert 				"bad certificate status response");
1002*780fb4a2SCy Schubert 		return -1;
1003*780fb4a2SCy Schubert 	}
1004*780fb4a2SCy Schubert 
1005*780fb4a2SCy Schubert 	conn->ocsp_resp_received = 1;
1006*780fb4a2SCy Schubert 
1007*780fb4a2SCy Schubert skip:
1008*780fb4a2SCy Schubert 	*in_len = end - in_data;
1009*780fb4a2SCy Schubert 
1010*780fb4a2SCy Schubert 	conn->state = SERVER_KEY_EXCHANGE;
1011*780fb4a2SCy Schubert 
1012*780fb4a2SCy Schubert 	return 0;
1013*780fb4a2SCy Schubert }
1014*780fb4a2SCy Schubert 
1015*780fb4a2SCy Schubert 
101639beb93cSSam Leffler static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
101739beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len)
101839beb93cSSam Leffler {
101939beb93cSSam Leffler 	const u8 *pos, *end;
102039beb93cSSam Leffler 	size_t left, len;
102139beb93cSSam Leffler 	u8 type;
102239beb93cSSam Leffler 	const struct tls_cipher_suite *suite;
102339beb93cSSam Leffler 
102439beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
102539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
102639beb93cSSam Leffler 			   "received content type 0x%x", ct);
102739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
102839beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
102939beb93cSSam Leffler 		return -1;
103039beb93cSSam Leffler 	}
103139beb93cSSam Leffler 
103239beb93cSSam Leffler 	pos = in_data;
103339beb93cSSam Leffler 	left = *in_len;
103439beb93cSSam Leffler 
103539beb93cSSam Leffler 	if (left < 4) {
103639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange "
103739beb93cSSam Leffler 			   "(Left=%lu)", (unsigned long) left);
103839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
103939beb93cSSam Leffler 		return -1;
104039beb93cSSam Leffler 	}
104139beb93cSSam Leffler 
104239beb93cSSam Leffler 	type = *pos++;
104339beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
104439beb93cSSam Leffler 	pos += 3;
104539beb93cSSam Leffler 	left -= 4;
104639beb93cSSam Leffler 
104739beb93cSSam Leffler 	if (len > left) {
104839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange "
104939beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
105039beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
105139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
105239beb93cSSam Leffler 		return -1;
105339beb93cSSam Leffler 	}
105439beb93cSSam Leffler 
105539beb93cSSam Leffler 	end = pos + len;
105639beb93cSSam Leffler 
1057*780fb4a2SCy Schubert 	if ((conn->flags & TLS_CONN_REQUEST_OCSP) &&
1058*780fb4a2SCy Schubert 	    type == TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS)
1059*780fb4a2SCy Schubert 		return tls_process_certificate_status(conn, ct, in_data,
1060*780fb4a2SCy Schubert 						      in_len);
106139beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
106239beb93cSSam Leffler 		return tls_process_certificate_request(conn, ct, in_data,
106339beb93cSSam Leffler 						       in_len);
106439beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
106539beb93cSSam Leffler 		return tls_process_server_hello_done(conn, ct, in_data,
106639beb93cSSam Leffler 						     in_len);
106739beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) {
106839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
106939beb93cSSam Leffler 			   "message %d (expected ServerKeyExchange/"
1070*780fb4a2SCy Schubert 			   "CertificateRequest/ServerHelloDone%s)", type,
1071*780fb4a2SCy Schubert 			   (conn->flags & TLS_CONN_REQUEST_OCSP) ?
1072*780fb4a2SCy Schubert 			   "/CertificateStatus" : "");
107339beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
107439beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
107539beb93cSSam Leffler 		return -1;
107639beb93cSSam Leffler 	}
107739beb93cSSam Leffler 
107839beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange");
107939beb93cSSam Leffler 
108039beb93cSSam Leffler 	if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) {
108139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed "
108239beb93cSSam Leffler 			   "with the selected cipher suite");
108339beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
108439beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
108539beb93cSSam Leffler 		return -1;
108639beb93cSSam Leffler 	}
108739beb93cSSam Leffler 
108839beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len);
108939beb93cSSam Leffler 	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
10905b9c547cSRui Paulo 	if (suite && (suite->key_exchange == TLS_KEY_X_DH_anon ||
10915b9c547cSRui Paulo 		      suite->key_exchange == TLS_KEY_X_DHE_RSA)) {
10925b9c547cSRui Paulo 		if (tlsv1_process_diffie_hellman(conn, pos, len,
10935b9c547cSRui Paulo 						 suite->key_exchange) < 0) {
109439beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
109539beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
109639beb93cSSam Leffler 			return -1;
109739beb93cSSam Leffler 		}
109839beb93cSSam Leffler 	} else {
109939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange");
110039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
110139beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
110239beb93cSSam Leffler 		return -1;
110339beb93cSSam Leffler 	}
110439beb93cSSam Leffler 
110539beb93cSSam Leffler 	*in_len = end - in_data;
110639beb93cSSam Leffler 
110739beb93cSSam Leffler 	conn->state = SERVER_CERTIFICATE_REQUEST;
110839beb93cSSam Leffler 
110939beb93cSSam Leffler 	return 0;
111039beb93cSSam Leffler }
111139beb93cSSam Leffler 
111239beb93cSSam Leffler 
111339beb93cSSam Leffler static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
111439beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len)
111539beb93cSSam Leffler {
111639beb93cSSam Leffler 	const u8 *pos, *end;
111739beb93cSSam Leffler 	size_t left, len;
111839beb93cSSam Leffler 	u8 type;
111939beb93cSSam Leffler 
112039beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
112139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
112239beb93cSSam Leffler 			   "received content type 0x%x", ct);
112339beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
112439beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
112539beb93cSSam Leffler 		return -1;
112639beb93cSSam Leffler 	}
112739beb93cSSam Leffler 
112839beb93cSSam Leffler 	pos = in_data;
112939beb93cSSam Leffler 	left = *in_len;
113039beb93cSSam Leffler 
113139beb93cSSam Leffler 	if (left < 4) {
113239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest "
113339beb93cSSam Leffler 			   "(left=%lu)", (unsigned long) left);
113439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
113539beb93cSSam Leffler 		return -1;
113639beb93cSSam Leffler 	}
113739beb93cSSam Leffler 
113839beb93cSSam Leffler 	type = *pos++;
113939beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
114039beb93cSSam Leffler 	pos += 3;
114139beb93cSSam Leffler 	left -= 4;
114239beb93cSSam Leffler 
114339beb93cSSam Leffler 	if (len > left) {
114439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest "
114539beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
114639beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
114739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
114839beb93cSSam Leffler 		return -1;
114939beb93cSSam Leffler 	}
115039beb93cSSam Leffler 
115139beb93cSSam Leffler 	end = pos + len;
115239beb93cSSam Leffler 
115339beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
115439beb93cSSam Leffler 		return tls_process_server_hello_done(conn, ct, in_data,
115539beb93cSSam Leffler 						     in_len);
115639beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) {
115739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
115839beb93cSSam Leffler 			   "message %d (expected CertificateRequest/"
115939beb93cSSam Leffler 			   "ServerHelloDone)", type);
116039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
116139beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
116239beb93cSSam Leffler 		return -1;
116339beb93cSSam Leffler 	}
116439beb93cSSam Leffler 
116539beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest");
116639beb93cSSam Leffler 
116739beb93cSSam Leffler 	conn->certificate_requested = 1;
116839beb93cSSam Leffler 
116939beb93cSSam Leffler 	*in_len = end - in_data;
117039beb93cSSam Leffler 
117139beb93cSSam Leffler 	conn->state = SERVER_HELLO_DONE;
117239beb93cSSam Leffler 
117339beb93cSSam Leffler 	return 0;
117439beb93cSSam Leffler }
117539beb93cSSam Leffler 
117639beb93cSSam Leffler 
117739beb93cSSam Leffler static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
117839beb93cSSam Leffler 					 const u8 *in_data, size_t *in_len)
117939beb93cSSam Leffler {
118039beb93cSSam Leffler 	const u8 *pos, *end;
118139beb93cSSam Leffler 	size_t left, len;
118239beb93cSSam Leffler 	u8 type;
118339beb93cSSam Leffler 
118439beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
118539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
118639beb93cSSam Leffler 			   "received content type 0x%x", ct);
118739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
118839beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
118939beb93cSSam Leffler 		return -1;
119039beb93cSSam Leffler 	}
119139beb93cSSam Leffler 
119239beb93cSSam Leffler 	pos = in_data;
119339beb93cSSam Leffler 	left = *in_len;
119439beb93cSSam Leffler 
119539beb93cSSam Leffler 	if (left < 4) {
119639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone "
119739beb93cSSam Leffler 			   "(left=%lu)", (unsigned long) left);
119839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
119939beb93cSSam Leffler 		return -1;
120039beb93cSSam Leffler 	}
120139beb93cSSam Leffler 
120239beb93cSSam Leffler 	type = *pos++;
120339beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
120439beb93cSSam Leffler 	pos += 3;
120539beb93cSSam Leffler 	left -= 4;
120639beb93cSSam Leffler 
120739beb93cSSam Leffler 	if (len > left) {
120839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone "
120939beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
121039beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
121139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
121239beb93cSSam Leffler 		return -1;
121339beb93cSSam Leffler 	}
121439beb93cSSam Leffler 	end = pos + len;
121539beb93cSSam Leffler 
121639beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) {
121739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
121839beb93cSSam Leffler 			   "message %d (expected ServerHelloDone)", type);
121939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
122039beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
122139beb93cSSam Leffler 		return -1;
122239beb93cSSam Leffler 	}
122339beb93cSSam Leffler 
122439beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone");
122539beb93cSSam Leffler 
1226*780fb4a2SCy Schubert 	if ((conn->flags & TLS_CONN_REQUIRE_OCSP) &&
1227*780fb4a2SCy Schubert 	    !conn->ocsp_resp_received) {
1228*780fb4a2SCy Schubert 		wpa_printf(MSG_INFO,
1229*780fb4a2SCy Schubert 			   "TLSv1: No OCSP response received - reject handshake");
1230*780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1231*780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
1232*780fb4a2SCy Schubert 		return -1;
1233*780fb4a2SCy Schubert 	}
1234*780fb4a2SCy Schubert 
123539beb93cSSam Leffler 	*in_len = end - in_data;
123639beb93cSSam Leffler 
123739beb93cSSam Leffler 	conn->state = CLIENT_KEY_EXCHANGE;
123839beb93cSSam Leffler 
123939beb93cSSam Leffler 	return 0;
124039beb93cSSam Leffler }
124139beb93cSSam Leffler 
124239beb93cSSam Leffler 
124339beb93cSSam Leffler static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn,
124439beb93cSSam Leffler 						 u8 ct, const u8 *in_data,
124539beb93cSSam Leffler 						 size_t *in_len)
124639beb93cSSam Leffler {
124739beb93cSSam Leffler 	const u8 *pos;
124839beb93cSSam Leffler 	size_t left;
124939beb93cSSam Leffler 
125039beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
125139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
125239beb93cSSam Leffler 			   "received content type 0x%x", ct);
125339beb93cSSam Leffler 		if (conn->use_session_ticket) {
125439beb93cSSam Leffler 			int res;
125539beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Server may have "
125639beb93cSSam Leffler 				   "rejected SessionTicket");
125739beb93cSSam Leffler 			conn->use_session_ticket = 0;
125839beb93cSSam Leffler 
125939beb93cSSam Leffler 			/* Notify upper layers that SessionTicket failed */
126039beb93cSSam Leffler 			res = conn->session_ticket_cb(
126139beb93cSSam Leffler 				conn->session_ticket_cb_ctx, NULL, 0, NULL,
126239beb93cSSam Leffler 				NULL, NULL);
126339beb93cSSam Leffler 			if (res < 0) {
126439beb93cSSam Leffler 				wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket "
126539beb93cSSam Leffler 					   "callback indicated failure");
126639beb93cSSam Leffler 				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
126739beb93cSSam Leffler 					  TLS_ALERT_HANDSHAKE_FAILURE);
126839beb93cSSam Leffler 				return -1;
126939beb93cSSam Leffler 			}
127039beb93cSSam Leffler 
127139beb93cSSam Leffler 			conn->state = SERVER_CERTIFICATE;
127239beb93cSSam Leffler 			return tls_process_certificate(conn, ct, in_data,
127339beb93cSSam Leffler 						       in_len);
127439beb93cSSam Leffler 		}
127539beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
127639beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
127739beb93cSSam Leffler 		return -1;
127839beb93cSSam Leffler 	}
127939beb93cSSam Leffler 
128039beb93cSSam Leffler 	pos = in_data;
128139beb93cSSam Leffler 	left = *in_len;
128239beb93cSSam Leffler 
128339beb93cSSam Leffler 	if (left < 1) {
128439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec");
128539beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
128639beb93cSSam Leffler 		return -1;
128739beb93cSSam Leffler 	}
128839beb93cSSam Leffler 
128939beb93cSSam Leffler 	if (*pos != TLS_CHANGE_CIPHER_SPEC) {
129039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
129139beb93cSSam Leffler 			   "received data 0x%x", *pos);
129239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
129339beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
129439beb93cSSam Leffler 		return -1;
129539beb93cSSam Leffler 	}
129639beb93cSSam Leffler 
129739beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec");
129839beb93cSSam Leffler 	if (tlsv1_record_change_read_cipher(&conn->rl) < 0) {
129939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher "
130039beb93cSSam Leffler 			   "for record layer");
130139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
130239beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
130339beb93cSSam Leffler 		return -1;
130439beb93cSSam Leffler 	}
130539beb93cSSam Leffler 
130639beb93cSSam Leffler 	*in_len = pos + 1 - in_data;
130739beb93cSSam Leffler 
130839beb93cSSam Leffler 	conn->state = SERVER_FINISHED;
130939beb93cSSam Leffler 
131039beb93cSSam Leffler 	return 0;
131139beb93cSSam Leffler }
131239beb93cSSam Leffler 
131339beb93cSSam Leffler 
131439beb93cSSam Leffler static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct,
131539beb93cSSam Leffler 				       const u8 *in_data, size_t *in_len)
131639beb93cSSam Leffler {
131739beb93cSSam Leffler 	const u8 *pos, *end;
131839beb93cSSam Leffler 	size_t left, len, hlen;
131939beb93cSSam Leffler 	u8 verify_data[TLS_VERIFY_DATA_LEN];
132039beb93cSSam Leffler 	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
132139beb93cSSam Leffler 
132239beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
132339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; "
132439beb93cSSam Leffler 			   "received content type 0x%x", ct);
132539beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
132639beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
132739beb93cSSam Leffler 		return -1;
132839beb93cSSam Leffler 	}
132939beb93cSSam Leffler 
133039beb93cSSam Leffler 	pos = in_data;
133139beb93cSSam Leffler 	left = *in_len;
133239beb93cSSam Leffler 
133339beb93cSSam Leffler 	if (left < 4) {
133439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for "
133539beb93cSSam Leffler 			   "Finished",
133639beb93cSSam Leffler 			   (unsigned long) left);
133739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
133839beb93cSSam Leffler 			  TLS_ALERT_DECODE_ERROR);
133939beb93cSSam Leffler 		return -1;
134039beb93cSSam Leffler 	}
134139beb93cSSam Leffler 
134239beb93cSSam Leffler 	if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) {
134339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received "
134439beb93cSSam Leffler 			   "type 0x%x", pos[0]);
134539beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
134639beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
134739beb93cSSam Leffler 		return -1;
134839beb93cSSam Leffler 	}
134939beb93cSSam Leffler 
135039beb93cSSam Leffler 	len = WPA_GET_BE24(pos + 1);
135139beb93cSSam Leffler 
135239beb93cSSam Leffler 	pos += 4;
135339beb93cSSam Leffler 	left -= 4;
135439beb93cSSam Leffler 
135539beb93cSSam Leffler 	if (len > left) {
135639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished "
135739beb93cSSam Leffler 			   "(len=%lu > left=%lu)",
135839beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
135939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
136039beb93cSSam Leffler 			  TLS_ALERT_DECODE_ERROR);
136139beb93cSSam Leffler 		return -1;
136239beb93cSSam Leffler 	}
136339beb93cSSam Leffler 	end = pos + len;
136439beb93cSSam Leffler 	if (len != TLS_VERIFY_DATA_LEN) {
136539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length "
136639beb93cSSam Leffler 			   "in Finished: %lu (expected %d)",
136739beb93cSSam Leffler 			   (unsigned long) len, TLS_VERIFY_DATA_LEN);
136839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
136939beb93cSSam Leffler 			  TLS_ALERT_DECODE_ERROR);
137039beb93cSSam Leffler 		return -1;
137139beb93cSSam Leffler 	}
137239beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished",
137339beb93cSSam Leffler 		    pos, TLS_VERIFY_DATA_LEN);
137439beb93cSSam Leffler 
1375f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
1376f05cddf9SRui Paulo 	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
1377f05cddf9SRui Paulo 		hlen = SHA256_MAC_LEN;
1378f05cddf9SRui Paulo 		if (conn->verify.sha256_server == NULL ||
1379f05cddf9SRui Paulo 		    crypto_hash_finish(conn->verify.sha256_server, hash, &hlen)
1380f05cddf9SRui Paulo 		    < 0) {
1381f05cddf9SRui Paulo 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1382f05cddf9SRui Paulo 				  TLS_ALERT_INTERNAL_ERROR);
1383f05cddf9SRui Paulo 			conn->verify.sha256_server = NULL;
1384f05cddf9SRui Paulo 			return -1;
1385f05cddf9SRui Paulo 		}
1386f05cddf9SRui Paulo 		conn->verify.sha256_server = NULL;
1387f05cddf9SRui Paulo 	} else {
1388f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
1389f05cddf9SRui Paulo 
139039beb93cSSam Leffler 	hlen = MD5_MAC_LEN;
139139beb93cSSam Leffler 	if (conn->verify.md5_server == NULL ||
139239beb93cSSam Leffler 	    crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) {
139339beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
139439beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
139539beb93cSSam Leffler 		conn->verify.md5_server = NULL;
139639beb93cSSam Leffler 		crypto_hash_finish(conn->verify.sha1_server, NULL, NULL);
139739beb93cSSam Leffler 		conn->verify.sha1_server = NULL;
139839beb93cSSam Leffler 		return -1;
139939beb93cSSam Leffler 	}
140039beb93cSSam Leffler 	conn->verify.md5_server = NULL;
140139beb93cSSam Leffler 	hlen = SHA1_MAC_LEN;
140239beb93cSSam Leffler 	if (conn->verify.sha1_server == NULL ||
140339beb93cSSam Leffler 	    crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN,
140439beb93cSSam Leffler 			       &hlen) < 0) {
140539beb93cSSam Leffler 		conn->verify.sha1_server = NULL;
140639beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
140739beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
140839beb93cSSam Leffler 		return -1;
140939beb93cSSam Leffler 	}
141039beb93cSSam Leffler 	conn->verify.sha1_server = NULL;
1411f05cddf9SRui Paulo 	hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
141239beb93cSSam Leffler 
1413f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
1414f05cddf9SRui Paulo 	}
1415f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
1416f05cddf9SRui Paulo 
1417f05cddf9SRui Paulo 	if (tls_prf(conn->rl.tls_version,
1418f05cddf9SRui Paulo 		    conn->master_secret, TLS_MASTER_SECRET_LEN,
1419f05cddf9SRui Paulo 		    "server finished", hash, hlen,
142039beb93cSSam Leffler 		    verify_data, TLS_VERIFY_DATA_LEN)) {
142139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data");
142239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
142339beb93cSSam Leffler 			  TLS_ALERT_DECRYPT_ERROR);
142439beb93cSSam Leffler 		return -1;
142539beb93cSSam Leffler 	}
142639beb93cSSam Leffler 	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
142739beb93cSSam Leffler 			verify_data, TLS_VERIFY_DATA_LEN);
142839beb93cSSam Leffler 
14295b9c547cSRui Paulo 	if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
143039beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data");
14315b9c547cSRui Paulo 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
14325b9c547cSRui Paulo 			  TLS_ALERT_DECRYPT_ERROR);
143339beb93cSSam Leffler 		return -1;
143439beb93cSSam Leffler 	}
143539beb93cSSam Leffler 
143639beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received Finished");
143739beb93cSSam Leffler 
143839beb93cSSam Leffler 	*in_len = end - in_data;
143939beb93cSSam Leffler 
144039beb93cSSam Leffler 	conn->state = (conn->session_resumed || conn->use_session_ticket) ?
144139beb93cSSam Leffler 		CHANGE_CIPHER_SPEC : ACK_FINISHED;
144239beb93cSSam Leffler 
144339beb93cSSam Leffler 	return 0;
144439beb93cSSam Leffler }
144539beb93cSSam Leffler 
144639beb93cSSam Leffler 
144739beb93cSSam Leffler static int tls_process_application_data(struct tlsv1_client *conn, u8 ct,
144839beb93cSSam Leffler 					const u8 *in_data, size_t *in_len,
144939beb93cSSam Leffler 					u8 **out_data, size_t *out_len)
145039beb93cSSam Leffler {
145139beb93cSSam Leffler 	const u8 *pos;
145239beb93cSSam Leffler 	size_t left;
145339beb93cSSam Leffler 
145439beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
145539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; "
145639beb93cSSam Leffler 			   "received content type 0x%x", ct);
145739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
145839beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
145939beb93cSSam Leffler 		return -1;
146039beb93cSSam Leffler 	}
146139beb93cSSam Leffler 
146239beb93cSSam Leffler 	pos = in_data;
146339beb93cSSam Leffler 	left = *in_len;
146439beb93cSSam Leffler 
146539beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake",
146639beb93cSSam Leffler 		    pos, left);
146739beb93cSSam Leffler 
146839beb93cSSam Leffler 	*out_data = os_malloc(left);
146939beb93cSSam Leffler 	if (*out_data) {
147039beb93cSSam Leffler 		os_memcpy(*out_data, pos, left);
147139beb93cSSam Leffler 		*out_len = left;
147239beb93cSSam Leffler 	}
147339beb93cSSam Leffler 
147439beb93cSSam Leffler 	return 0;
147539beb93cSSam Leffler }
147639beb93cSSam Leffler 
147739beb93cSSam Leffler 
147839beb93cSSam Leffler int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct,
147939beb93cSSam Leffler 				   const u8 *buf, size_t *len,
148039beb93cSSam Leffler 				   u8 **out_data, size_t *out_len)
148139beb93cSSam Leffler {
148239beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_ALERT) {
148339beb93cSSam Leffler 		if (*len < 2) {
148439beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow");
148539beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
148639beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
148739beb93cSSam Leffler 			return -1;
148839beb93cSSam Leffler 		}
148939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
149039beb93cSSam Leffler 			   buf[0], buf[1]);
149139beb93cSSam Leffler 		*len = 2;
149239beb93cSSam Leffler 		conn->state = FAILED;
149339beb93cSSam Leffler 		return -1;
149439beb93cSSam Leffler 	}
149539beb93cSSam Leffler 
149639beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 &&
149739beb93cSSam Leffler 	    buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) {
149839beb93cSSam Leffler 		size_t hr_len = WPA_GET_BE24(buf + 1);
149939beb93cSSam Leffler 		if (hr_len > *len - 4) {
150039beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow");
150139beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
150239beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
150339beb93cSSam Leffler 			return -1;
150439beb93cSSam Leffler 		}
150539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest");
150639beb93cSSam Leffler 		*len = 4 + hr_len;
150739beb93cSSam Leffler 		return 0;
150839beb93cSSam Leffler 	}
150939beb93cSSam Leffler 
151039beb93cSSam Leffler 	switch (conn->state) {
151139beb93cSSam Leffler 	case SERVER_HELLO:
151239beb93cSSam Leffler 		if (tls_process_server_hello(conn, ct, buf, len))
151339beb93cSSam Leffler 			return -1;
151439beb93cSSam Leffler 		break;
151539beb93cSSam Leffler 	case SERVER_CERTIFICATE:
151639beb93cSSam Leffler 		if (tls_process_certificate(conn, ct, buf, len))
151739beb93cSSam Leffler 			return -1;
151839beb93cSSam Leffler 		break;
151939beb93cSSam Leffler 	case SERVER_KEY_EXCHANGE:
152039beb93cSSam Leffler 		if (tls_process_server_key_exchange(conn, ct, buf, len))
152139beb93cSSam Leffler 			return -1;
152239beb93cSSam Leffler 		break;
152339beb93cSSam Leffler 	case SERVER_CERTIFICATE_REQUEST:
152439beb93cSSam Leffler 		if (tls_process_certificate_request(conn, ct, buf, len))
152539beb93cSSam Leffler 			return -1;
152639beb93cSSam Leffler 		break;
152739beb93cSSam Leffler 	case SERVER_HELLO_DONE:
152839beb93cSSam Leffler 		if (tls_process_server_hello_done(conn, ct, buf, len))
152939beb93cSSam Leffler 			return -1;
153039beb93cSSam Leffler 		break;
153139beb93cSSam Leffler 	case SERVER_CHANGE_CIPHER_SPEC:
153239beb93cSSam Leffler 		if (tls_process_server_change_cipher_spec(conn, ct, buf, len))
153339beb93cSSam Leffler 			return -1;
153439beb93cSSam Leffler 		break;
153539beb93cSSam Leffler 	case SERVER_FINISHED:
153639beb93cSSam Leffler 		if (tls_process_server_finished(conn, ct, buf, len))
153739beb93cSSam Leffler 			return -1;
153839beb93cSSam Leffler 		break;
153939beb93cSSam Leffler 	case ACK_FINISHED:
154039beb93cSSam Leffler 		if (out_data &&
154139beb93cSSam Leffler 		    tls_process_application_data(conn, ct, buf, len, out_data,
154239beb93cSSam Leffler 						 out_len))
154339beb93cSSam Leffler 			return -1;
154439beb93cSSam Leffler 		break;
154539beb93cSSam Leffler 	default:
154639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d "
154739beb93cSSam Leffler 			   "while processing received message",
154839beb93cSSam Leffler 			   conn->state);
154939beb93cSSam Leffler 		return -1;
155039beb93cSSam Leffler 	}
155139beb93cSSam Leffler 
155239beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
155339beb93cSSam Leffler 		tls_verify_hash_add(&conn->verify, buf, *len);
155439beb93cSSam Leffler 
155539beb93cSSam Leffler 	return 0;
155639beb93cSSam Leffler }
1557