xref: /freebsd/contrib/wpa/src/tls/tlsv1_client_read.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
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 
tls_version_disabled(struct tlsv1_client * conn,u16 ver)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 
tls_process_server_hello_extensions(struct tlsv1_client * conn,const u8 * pos,size_t len)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 
tls_process_server_hello(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)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 
tls_peer_cert_event(struct tlsv1_client * conn,int depth,struct x509_certificate * cert)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));
2934bc52338SCy Schubert 	if ((conn->cred && 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 
315c1d255d3SCy Schubert 	if (cert->extensions_present & X509_EXT_CERTIFICATE_POLICY) {
316c1d255d3SCy Schubert 		if (cert->certificate_policy & X509_EXT_CERT_POLICY_TOD_STRICT)
317c1d255d3SCy Schubert 			ev.peer_cert.tod = 1;
318c1d255d3SCy Schubert 		else if (cert->certificate_policy &
319c1d255d3SCy Schubert 			 X509_EXT_CERT_POLICY_TOD_TOFU)
320c1d255d3SCy Schubert 			ev.peer_cert.tod = 2;
321c1d255d3SCy Schubert 	}
322c1d255d3SCy Schubert 
323780fb4a2SCy Schubert 	conn->event_cb(conn->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
324780fb4a2SCy Schubert 	wpabuf_free(cert_buf);
325780fb4a2SCy Schubert }
326780fb4a2SCy Schubert 
327780fb4a2SCy Schubert 
tls_cert_chain_failure_event(struct tlsv1_client * conn,int depth,struct x509_certificate * cert,enum tls_fail_reason reason,const char * reason_txt)328780fb4a2SCy Schubert static void tls_cert_chain_failure_event(struct tlsv1_client *conn, int depth,
329780fb4a2SCy Schubert 					 struct x509_certificate *cert,
330780fb4a2SCy Schubert 					 enum tls_fail_reason reason,
331780fb4a2SCy Schubert 					 const char *reason_txt)
332780fb4a2SCy Schubert {
333780fb4a2SCy Schubert 	struct wpabuf *cert_buf = NULL;
334780fb4a2SCy Schubert 	union tls_event_data ev;
335780fb4a2SCy Schubert 	char subject[128];
336780fb4a2SCy Schubert 
337780fb4a2SCy Schubert 	if (!conn->event_cb || !cert)
338780fb4a2SCy Schubert 		return;
339780fb4a2SCy Schubert 
340780fb4a2SCy Schubert 	os_memset(&ev, 0, sizeof(ev));
341780fb4a2SCy Schubert 	ev.cert_fail.depth = depth;
342780fb4a2SCy Schubert 	x509_name_string(&cert->subject, subject, sizeof(subject));
343780fb4a2SCy Schubert 	ev.peer_cert.subject = subject;
344780fb4a2SCy Schubert 	ev.cert_fail.reason = reason;
345780fb4a2SCy Schubert 	ev.cert_fail.reason_txt = reason_txt;
346780fb4a2SCy Schubert 	cert_buf = wpabuf_alloc_copy(cert->cert_start,
347780fb4a2SCy Schubert 				     cert->cert_len);
348780fb4a2SCy Schubert 	ev.cert_fail.cert = cert_buf;
349780fb4a2SCy Schubert 	conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
350780fb4a2SCy Schubert 	wpabuf_free(cert_buf);
351780fb4a2SCy Schubert }
352780fb4a2SCy Schubert 
353780fb4a2SCy Schubert 
tls_process_certificate(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)35439beb93cSSam Leffler static int tls_process_certificate(struct tlsv1_client *conn, u8 ct,
35539beb93cSSam Leffler 				   const u8 *in_data, size_t *in_len)
35639beb93cSSam Leffler {
35739beb93cSSam Leffler 	const u8 *pos, *end;
35839beb93cSSam Leffler 	size_t left, len, list_len, cert_len, idx;
35939beb93cSSam Leffler 	u8 type;
36039beb93cSSam Leffler 	struct x509_certificate *chain = NULL, *last = NULL, *cert;
36139beb93cSSam Leffler 	int reason;
36239beb93cSSam Leffler 
36339beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
36439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
36539beb93cSSam Leffler 			   "received content type 0x%x", ct);
36639beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
36739beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
36839beb93cSSam Leffler 		return -1;
36939beb93cSSam Leffler 	}
37039beb93cSSam Leffler 
37139beb93cSSam Leffler 	pos = in_data;
37239beb93cSSam Leffler 	left = *in_len;
37339beb93cSSam Leffler 
37439beb93cSSam Leffler 	if (left < 4) {
37539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message "
37639beb93cSSam Leffler 			   "(len=%lu)", (unsigned long) left);
37739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
37839beb93cSSam Leffler 		return -1;
37939beb93cSSam Leffler 	}
38039beb93cSSam Leffler 
38139beb93cSSam Leffler 	type = *pos++;
38239beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
38339beb93cSSam Leffler 	pos += 3;
38439beb93cSSam Leffler 	left -= 4;
38539beb93cSSam Leffler 
38639beb93cSSam Leffler 	if (len > left) {
38739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message "
38839beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
38939beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
39039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
39139beb93cSSam Leffler 		return -1;
39239beb93cSSam Leffler 	}
39339beb93cSSam Leffler 
39439beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE)
39539beb93cSSam Leffler 		return tls_process_server_key_exchange(conn, ct, in_data,
39639beb93cSSam Leffler 						       in_len);
39739beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
39839beb93cSSam Leffler 		return tls_process_certificate_request(conn, ct, in_data,
39939beb93cSSam Leffler 						       in_len);
40039beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
40139beb93cSSam Leffler 		return tls_process_server_hello_done(conn, ct, in_data,
40239beb93cSSam Leffler 						     in_len);
40339beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) {
40439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
40539beb93cSSam Leffler 			   "message %d (expected Certificate/"
40639beb93cSSam Leffler 			   "ServerKeyExchange/CertificateRequest/"
40739beb93cSSam Leffler 			   "ServerHelloDone)", type);
40839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
40939beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
41039beb93cSSam Leffler 		return -1;
41139beb93cSSam Leffler 	}
41239beb93cSSam Leffler 
41339beb93cSSam Leffler 	wpa_printf(MSG_DEBUG,
41439beb93cSSam Leffler 		   "TLSv1: Received Certificate (certificate_list len %lu)",
41539beb93cSSam Leffler 		   (unsigned long) len);
41639beb93cSSam Leffler 
41739beb93cSSam Leffler 	/*
41839beb93cSSam Leffler 	 * opaque ASN.1Cert<2^24-1>;
41939beb93cSSam Leffler 	 *
42039beb93cSSam Leffler 	 * struct {
42139beb93cSSam Leffler 	 *     ASN.1Cert certificate_list<1..2^24-1>;
42239beb93cSSam Leffler 	 * } Certificate;
42339beb93cSSam Leffler 	 */
42439beb93cSSam Leffler 
42539beb93cSSam Leffler 	end = pos + len;
42639beb93cSSam Leffler 
42739beb93cSSam Leffler 	if (end - pos < 3) {
42839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate "
42939beb93cSSam Leffler 			   "(left=%lu)", (unsigned long) left);
43039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
43139beb93cSSam Leffler 		return -1;
43239beb93cSSam Leffler 	}
43339beb93cSSam Leffler 
43439beb93cSSam Leffler 	list_len = WPA_GET_BE24(pos);
43539beb93cSSam Leffler 	pos += 3;
43639beb93cSSam Leffler 
43739beb93cSSam Leffler 	if ((size_t) (end - pos) != list_len) {
43839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list "
43939beb93cSSam Leffler 			   "length (len=%lu left=%lu)",
44039beb93cSSam Leffler 			   (unsigned long) list_len,
44139beb93cSSam Leffler 			   (unsigned long) (end - pos));
44239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
44339beb93cSSam Leffler 		return -1;
44439beb93cSSam Leffler 	}
44539beb93cSSam Leffler 
44639beb93cSSam Leffler 	idx = 0;
44739beb93cSSam Leffler 	while (pos < end) {
44839beb93cSSam Leffler 		if (end - pos < 3) {
44939beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
45039beb93cSSam Leffler 				   "certificate_list");
45139beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
45239beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
45339beb93cSSam Leffler 			x509_certificate_chain_free(chain);
45439beb93cSSam Leffler 			return -1;
45539beb93cSSam Leffler 		}
45639beb93cSSam Leffler 
45739beb93cSSam Leffler 		cert_len = WPA_GET_BE24(pos);
45839beb93cSSam Leffler 		pos += 3;
45939beb93cSSam Leffler 
46039beb93cSSam Leffler 		if ((size_t) (end - pos) < cert_len) {
46139beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate "
46239beb93cSSam Leffler 				   "length (len=%lu left=%lu)",
46339beb93cSSam Leffler 				   (unsigned long) cert_len,
46439beb93cSSam Leffler 				   (unsigned long) (end - pos));
46539beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
46639beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
46739beb93cSSam Leffler 			x509_certificate_chain_free(chain);
46839beb93cSSam Leffler 			return -1;
46939beb93cSSam Leffler 		}
47039beb93cSSam Leffler 
47139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)",
47239beb93cSSam Leffler 			   (unsigned long) idx, (unsigned long) cert_len);
47339beb93cSSam Leffler 
47439beb93cSSam Leffler 		if (idx == 0) {
47539beb93cSSam Leffler 			crypto_public_key_free(conn->server_rsa_key);
47639beb93cSSam Leffler 			if (tls_parse_cert(pos, cert_len,
47739beb93cSSam Leffler 					   &conn->server_rsa_key)) {
47839beb93cSSam Leffler 				wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
47939beb93cSSam Leffler 					   "the certificate");
48039beb93cSSam Leffler 				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
48139beb93cSSam Leffler 					  TLS_ALERT_BAD_CERTIFICATE);
48239beb93cSSam Leffler 				x509_certificate_chain_free(chain);
48339beb93cSSam Leffler 				return -1;
48439beb93cSSam Leffler 			}
48539beb93cSSam Leffler 		}
48639beb93cSSam Leffler 
48739beb93cSSam Leffler 		cert = x509_certificate_parse(pos, cert_len);
48839beb93cSSam Leffler 		if (cert == NULL) {
48939beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
49039beb93cSSam Leffler 				   "the certificate");
49139beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
49239beb93cSSam Leffler 				  TLS_ALERT_BAD_CERTIFICATE);
49339beb93cSSam Leffler 			x509_certificate_chain_free(chain);
49439beb93cSSam Leffler 			return -1;
49539beb93cSSam Leffler 		}
49639beb93cSSam Leffler 
497780fb4a2SCy Schubert 		tls_peer_cert_event(conn, idx, cert);
498780fb4a2SCy Schubert 
49939beb93cSSam Leffler 		if (last == NULL)
50039beb93cSSam Leffler 			chain = cert;
50139beb93cSSam Leffler 		else
50239beb93cSSam Leffler 			last->next = cert;
50339beb93cSSam Leffler 		last = cert;
50439beb93cSSam Leffler 
50539beb93cSSam Leffler 		idx++;
50639beb93cSSam Leffler 		pos += cert_len;
50739beb93cSSam Leffler 	}
50839beb93cSSam Leffler 
509780fb4a2SCy Schubert 	if (conn->cred && conn->cred->server_cert_only && chain) {
510780fb4a2SCy Schubert 		u8 hash[SHA256_MAC_LEN];
511780fb4a2SCy Schubert 		char buf[128];
512780fb4a2SCy Schubert 
513780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
514780fb4a2SCy Schubert 			   "TLSv1: Validate server certificate hash");
515780fb4a2SCy Schubert 		x509_name_string(&chain->subject, buf, sizeof(buf));
516780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "TLSv1: 0: %s", buf);
517780fb4a2SCy Schubert 		if (sha256_vector(1, &chain->cert_start, &chain->cert_len,
518780fb4a2SCy Schubert 				  hash) < 0 ||
519780fb4a2SCy Schubert 		    os_memcmp(conn->cred->srv_cert_hash, hash,
520780fb4a2SCy Schubert 			      SHA256_MAC_LEN) != 0) {
521780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
522780fb4a2SCy Schubert 				   "TLSv1: Server certificate hash mismatch");
523780fb4a2SCy Schubert 			wpa_hexdump(MSG_MSGDUMP, "TLSv1: SHA256 hash",
524780fb4a2SCy Schubert 				    hash, SHA256_MAC_LEN);
525780fb4a2SCy Schubert 			if (conn->event_cb) {
526780fb4a2SCy Schubert 				union tls_event_data ev;
527780fb4a2SCy Schubert 
528780fb4a2SCy Schubert 				os_memset(&ev, 0, sizeof(ev));
529780fb4a2SCy Schubert 				ev.cert_fail.reason = TLS_FAIL_UNSPECIFIED;
530780fb4a2SCy Schubert 				ev.cert_fail.reason_txt =
531780fb4a2SCy Schubert 					"Server certificate mismatch";
532780fb4a2SCy Schubert 				ev.cert_fail.subject = buf;
533780fb4a2SCy Schubert 				conn->event_cb(conn->cb_ctx,
534780fb4a2SCy Schubert 					       TLS_CERT_CHAIN_FAILURE, &ev);
535780fb4a2SCy Schubert 			}
536780fb4a2SCy Schubert 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
537780fb4a2SCy Schubert 				  TLS_ALERT_BAD_CERTIFICATE);
538780fb4a2SCy Schubert 			x509_certificate_chain_free(chain);
539780fb4a2SCy Schubert 			return -1;
540780fb4a2SCy Schubert 		}
541780fb4a2SCy Schubert 	} else if (conn->cred && conn->cred->cert_probe) {
542780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
543c1d255d3SCy Schubert 			   "TLSv1: Reject server certificate on probe-only run");
544780fb4a2SCy Schubert 		if (conn->event_cb) {
545780fb4a2SCy Schubert 			union tls_event_data ev;
546780fb4a2SCy Schubert 			char buf[128];
547780fb4a2SCy Schubert 
548780fb4a2SCy Schubert 			os_memset(&ev, 0, sizeof(ev));
549780fb4a2SCy Schubert 			ev.cert_fail.reason = TLS_FAIL_SERVER_CHAIN_PROBE;
550780fb4a2SCy Schubert 			ev.cert_fail.reason_txt =
551780fb4a2SCy Schubert 				"Server certificate chain probe";
552780fb4a2SCy Schubert 			if (chain) {
553780fb4a2SCy Schubert 				x509_name_string(&chain->subject, buf,
554780fb4a2SCy Schubert 						 sizeof(buf));
555780fb4a2SCy Schubert 				ev.cert_fail.subject = buf;
556780fb4a2SCy Schubert 			}
557780fb4a2SCy Schubert 			conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE,
558780fb4a2SCy Schubert 				       &ev);
559780fb4a2SCy Schubert 		}
560780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
561780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE);
562780fb4a2SCy Schubert 		x509_certificate_chain_free(chain);
563780fb4a2SCy Schubert 		return -1;
564780fb4a2SCy Schubert 	} else if (conn->cred && conn->cred->ca_cert_verify &&
565780fb4a2SCy Schubert 		   x509_certificate_chain_validate(
566780fb4a2SCy Schubert 			   conn->cred->trusted_certs, chain, &reason,
567780fb4a2SCy Schubert 			   !!(conn->flags & TLS_CONN_DISABLE_TIME_CHECKS))
568f05cddf9SRui Paulo 		   < 0) {
56939beb93cSSam Leffler 		int tls_reason;
57039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain "
57139beb93cSSam Leffler 			   "validation failed (reason=%d)", reason);
57239beb93cSSam Leffler 		switch (reason) {
57339beb93cSSam Leffler 		case X509_VALIDATE_BAD_CERTIFICATE:
57439beb93cSSam Leffler 			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
575780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
576780fb4a2SCy Schubert 				conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE,
577780fb4a2SCy Schubert 				"bad certificate");
57839beb93cSSam Leffler 			break;
57939beb93cSSam Leffler 		case X509_VALIDATE_UNSUPPORTED_CERTIFICATE:
58039beb93cSSam Leffler 			tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE;
58139beb93cSSam Leffler 			break;
58239beb93cSSam Leffler 		case X509_VALIDATE_CERTIFICATE_REVOKED:
58339beb93cSSam Leffler 			tls_reason = TLS_ALERT_CERTIFICATE_REVOKED;
584780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
585780fb4a2SCy Schubert 				conn, 0, chain, TLS_FAIL_REVOKED,
586780fb4a2SCy Schubert 				"certificate revoked");
58739beb93cSSam Leffler 			break;
58839beb93cSSam Leffler 		case X509_VALIDATE_CERTIFICATE_EXPIRED:
58939beb93cSSam Leffler 			tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
590780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
591780fb4a2SCy Schubert 				conn, 0, chain, TLS_FAIL_EXPIRED,
592780fb4a2SCy Schubert 				"certificate has expired or is not yet valid");
59339beb93cSSam Leffler 			break;
59439beb93cSSam Leffler 		case X509_VALIDATE_CERTIFICATE_UNKNOWN:
59539beb93cSSam Leffler 			tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN;
59639beb93cSSam Leffler 			break;
59739beb93cSSam Leffler 		case X509_VALIDATE_UNKNOWN_CA:
59839beb93cSSam Leffler 			tls_reason = TLS_ALERT_UNKNOWN_CA;
599780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
600780fb4a2SCy Schubert 				conn, 0, chain, TLS_FAIL_UNTRUSTED,
601780fb4a2SCy Schubert 				"unknown CA");
60239beb93cSSam Leffler 			break;
60339beb93cSSam Leffler 		default:
60439beb93cSSam Leffler 			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
60539beb93cSSam Leffler 			break;
60639beb93cSSam Leffler 		}
60739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason);
60839beb93cSSam Leffler 		x509_certificate_chain_free(chain);
60939beb93cSSam Leffler 		return -1;
61039beb93cSSam Leffler 	}
61139beb93cSSam Leffler 
612780fb4a2SCy Schubert 	if (conn->cred && !conn->cred->server_cert_only && chain &&
613780fb4a2SCy Schubert 	    (chain->extensions_present & X509_EXT_EXT_KEY_USAGE) &&
614780fb4a2SCy Schubert 	    !(chain->ext_key_usage &
615780fb4a2SCy Schubert 	      (X509_EXT_KEY_USAGE_ANY | X509_EXT_KEY_USAGE_SERVER_AUTH))) {
616780fb4a2SCy Schubert 		tls_cert_chain_failure_event(
617780fb4a2SCy Schubert 			conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE,
618780fb4a2SCy Schubert 			"certificate not allowed for server authentication");
619780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
620780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE);
62139beb93cSSam Leffler 		x509_certificate_chain_free(chain);
622780fb4a2SCy Schubert 		return -1;
623780fb4a2SCy Schubert 	}
624780fb4a2SCy Schubert 
625780fb4a2SCy Schubert 	if (conn->flags & TLS_CONN_REQUEST_OCSP) {
626780fb4a2SCy Schubert 		x509_certificate_chain_free(conn->server_cert);
627780fb4a2SCy Schubert 		conn->server_cert = chain;
628780fb4a2SCy Schubert 	} else {
629780fb4a2SCy Schubert 		x509_certificate_chain_free(chain);
630780fb4a2SCy Schubert 	}
63139beb93cSSam Leffler 
63239beb93cSSam Leffler 	*in_len = end - in_data;
63339beb93cSSam Leffler 
63439beb93cSSam Leffler 	conn->state = SERVER_KEY_EXCHANGE;
63539beb93cSSam Leffler 
63639beb93cSSam Leffler 	return 0;
63739beb93cSSam Leffler }
63839beb93cSSam Leffler 
63939beb93cSSam Leffler 
count_bits(const u8 * val,size_t len)6405b9c547cSRui Paulo static unsigned int count_bits(const u8 *val, size_t len)
64139beb93cSSam Leffler {
6425b9c547cSRui Paulo 	size_t i;
6435b9c547cSRui Paulo 	unsigned int bits;
6445b9c547cSRui Paulo 	u8 tmp;
6455b9c547cSRui Paulo 
6465b9c547cSRui Paulo 	for (i = 0; i < len; i++) {
6475b9c547cSRui Paulo 		if (val[i])
6485b9c547cSRui Paulo 			break;
6495b9c547cSRui Paulo 	}
6505b9c547cSRui Paulo 	if (i == len)
6515b9c547cSRui Paulo 		return 0;
6525b9c547cSRui Paulo 
6535b9c547cSRui Paulo 	bits = (len - i - 1) * 8;
6545b9c547cSRui Paulo 	tmp = val[i];
6555b9c547cSRui Paulo 	while (tmp) {
6565b9c547cSRui Paulo 		bits++;
6575b9c547cSRui Paulo 		tmp >>= 1;
6585b9c547cSRui Paulo 	}
6595b9c547cSRui Paulo 
6605b9c547cSRui Paulo 	return bits;
6615b9c547cSRui Paulo }
6625b9c547cSRui Paulo 
6635b9c547cSRui Paulo 
tlsv1_process_diffie_hellman(struct tlsv1_client * conn,const u8 * buf,size_t len,tls_key_exchange key_exchange)6645b9c547cSRui Paulo static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
6655b9c547cSRui Paulo 					const u8 *buf, size_t len,
6665b9c547cSRui Paulo 					tls_key_exchange key_exchange)
6675b9c547cSRui Paulo {
6685b9c547cSRui Paulo 	const u8 *pos, *end, *server_params, *server_params_end;
6695b9c547cSRui Paulo 	u8 alert;
6705b9c547cSRui Paulo 	unsigned int bits;
6715b9c547cSRui Paulo 	u16 val;
67239beb93cSSam Leffler 
67339beb93cSSam Leffler 	tlsv1_client_free_dh(conn);
67439beb93cSSam Leffler 
67539beb93cSSam Leffler 	pos = buf;
67639beb93cSSam Leffler 	end = buf + len;
67739beb93cSSam Leffler 
67839beb93cSSam Leffler 	if (end - pos < 3)
67939beb93cSSam Leffler 		goto fail;
6805b9c547cSRui Paulo 	server_params = pos;
6815b9c547cSRui Paulo 	val = WPA_GET_BE16(pos);
68239beb93cSSam Leffler 	pos += 2;
6835b9c547cSRui Paulo 	if (val == 0 || val > (size_t) (end - pos)) {
6845b9c547cSRui Paulo 		wpa_printf(MSG_DEBUG, "TLSv1: Invalid dh_p length %u", val);
6855b9c547cSRui Paulo 		goto fail;
6865b9c547cSRui Paulo 	}
6875b9c547cSRui Paulo 	conn->dh_p_len = val;
6885b9c547cSRui Paulo 	bits = count_bits(pos, conn->dh_p_len);
6895b9c547cSRui Paulo 	if (bits < 768) {
6905b9c547cSRui Paulo 		wpa_printf(MSG_INFO, "TLSv1: Reject under 768-bit DH prime (insecure; only %u bits)",
6915b9c547cSRui Paulo 			   bits);
6925b9c547cSRui Paulo 		wpa_hexdump(MSG_DEBUG, "TLSv1: Rejected DH prime",
6935b9c547cSRui Paulo 			    pos, conn->dh_p_len);
69439beb93cSSam Leffler 		goto fail;
69539beb93cSSam Leffler 	}
69685732ac8SCy Schubert 	conn->dh_p = os_memdup(pos, conn->dh_p_len);
69739beb93cSSam Leffler 	if (conn->dh_p == NULL)
69839beb93cSSam Leffler 		goto fail;
69939beb93cSSam Leffler 	pos += conn->dh_p_len;
70039beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)",
70139beb93cSSam Leffler 		    conn->dh_p, conn->dh_p_len);
70239beb93cSSam Leffler 
70339beb93cSSam Leffler 	if (end - pos < 3)
70439beb93cSSam Leffler 		goto fail;
7055b9c547cSRui Paulo 	val = WPA_GET_BE16(pos);
70639beb93cSSam Leffler 	pos += 2;
7075b9c547cSRui Paulo 	if (val == 0 || val > (size_t) (end - pos))
70839beb93cSSam Leffler 		goto fail;
7095b9c547cSRui Paulo 	conn->dh_g_len = val;
71085732ac8SCy Schubert 	conn->dh_g = os_memdup(pos, conn->dh_g_len);
71139beb93cSSam Leffler 	if (conn->dh_g == NULL)
71239beb93cSSam Leffler 		goto fail;
71339beb93cSSam Leffler 	pos += conn->dh_g_len;
71439beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)",
71539beb93cSSam Leffler 		    conn->dh_g, conn->dh_g_len);
71639beb93cSSam Leffler 	if (conn->dh_g_len == 1 && conn->dh_g[0] < 2)
71739beb93cSSam Leffler 		goto fail;
71839beb93cSSam Leffler 
71939beb93cSSam Leffler 	if (end - pos < 3)
72039beb93cSSam Leffler 		goto fail;
7215b9c547cSRui Paulo 	val = WPA_GET_BE16(pos);
72239beb93cSSam Leffler 	pos += 2;
7235b9c547cSRui Paulo 	if (val == 0 || val > (size_t) (end - pos))
72439beb93cSSam Leffler 		goto fail;
7255b9c547cSRui Paulo 	conn->dh_ys_len = val;
72685732ac8SCy Schubert 	conn->dh_ys = os_memdup(pos, conn->dh_ys_len);
72739beb93cSSam Leffler 	if (conn->dh_ys == NULL)
72839beb93cSSam Leffler 		goto fail;
72939beb93cSSam Leffler 	pos += conn->dh_ys_len;
73039beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
73139beb93cSSam Leffler 		    conn->dh_ys, conn->dh_ys_len);
7325b9c547cSRui Paulo 	server_params_end = pos;
7335b9c547cSRui Paulo 
7345b9c547cSRui Paulo 	if (key_exchange == TLS_KEY_X_DHE_RSA) {
735780fb4a2SCy Schubert 		u8 hash[64];
7365b9c547cSRui Paulo 		int hlen;
7375b9c547cSRui Paulo 
7385b9c547cSRui Paulo 		if (conn->rl.tls_version == TLS_VERSION_1_2) {
7395b9c547cSRui Paulo #ifdef CONFIG_TLSV12
7405b9c547cSRui Paulo 			/*
7415b9c547cSRui Paulo 			 * RFC 5246, 4.7:
7425b9c547cSRui Paulo 			 * TLS v1.2 adds explicit indication of the used
7435b9c547cSRui Paulo 			 * signature and hash algorithms.
7445b9c547cSRui Paulo 			 *
7455b9c547cSRui Paulo 			 * struct {
7465b9c547cSRui Paulo 			 *   HashAlgorithm hash;
7475b9c547cSRui Paulo 			 *   SignatureAlgorithm signature;
7485b9c547cSRui Paulo 			 * } SignatureAndHashAlgorithm;
7495b9c547cSRui Paulo 			 */
7505b9c547cSRui Paulo 			if (end - pos < 2)
7515b9c547cSRui Paulo 				goto fail;
752780fb4a2SCy Schubert 			if ((pos[0] != TLS_HASH_ALG_SHA256 &&
753780fb4a2SCy Schubert 			     pos[0] != TLS_HASH_ALG_SHA384 &&
754780fb4a2SCy Schubert 			     pos[0] != TLS_HASH_ALG_SHA512) ||
7555b9c547cSRui Paulo 			    pos[1] != TLS_SIGN_ALG_RSA) {
7565b9c547cSRui Paulo 				wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/signature(%u) algorithm",
7575b9c547cSRui Paulo 					   pos[0], pos[1]);
7585b9c547cSRui Paulo 				goto fail;
7595b9c547cSRui Paulo 			}
7605b9c547cSRui Paulo 
7615b9c547cSRui Paulo 			hlen = tlsv12_key_x_server_params_hash(
762780fb4a2SCy Schubert 				conn->rl.tls_version, pos[0],
763780fb4a2SCy Schubert 				conn->client_random,
7645b9c547cSRui Paulo 				conn->server_random, server_params,
7655b9c547cSRui Paulo 				server_params_end - server_params, hash);
766780fb4a2SCy Schubert 			pos += 2;
7675b9c547cSRui Paulo #else /* CONFIG_TLSV12 */
7685b9c547cSRui Paulo 			goto fail;
7695b9c547cSRui Paulo #endif /* CONFIG_TLSV12 */
7705b9c547cSRui Paulo 		} else {
7715b9c547cSRui Paulo 			hlen = tls_key_x_server_params_hash(
7725b9c547cSRui Paulo 				conn->rl.tls_version, conn->client_random,
7735b9c547cSRui Paulo 				conn->server_random, server_params,
774*a90b9d01SCy Schubert 				server_params_end - server_params, hash,
775*a90b9d01SCy Schubert 				sizeof(hash));
7765b9c547cSRui Paulo 		}
7775b9c547cSRui Paulo 
7785b9c547cSRui Paulo 		if (hlen < 0)
7795b9c547cSRui Paulo 			goto fail;
7805b9c547cSRui Paulo 		wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerKeyExchange hash",
7815b9c547cSRui Paulo 			    hash, hlen);
7825b9c547cSRui Paulo 
7835b9c547cSRui Paulo 		if (tls_verify_signature(conn->rl.tls_version,
7845b9c547cSRui Paulo 					 conn->server_rsa_key,
7855b9c547cSRui Paulo 					 hash, hlen, pos, end - pos,
7865b9c547cSRui Paulo 					 &alert) < 0)
7875b9c547cSRui Paulo 			goto fail;
7885b9c547cSRui Paulo 	}
78939beb93cSSam Leffler 
79039beb93cSSam Leffler 	return 0;
79139beb93cSSam Leffler 
79239beb93cSSam Leffler fail:
79339beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed");
79439beb93cSSam Leffler 	tlsv1_client_free_dh(conn);
79539beb93cSSam Leffler 	return -1;
79639beb93cSSam Leffler }
79739beb93cSSam Leffler 
79839beb93cSSam Leffler 
799780fb4a2SCy Schubert static enum tls_ocsp_result
tls_process_certificate_status_ocsp_response(struct tlsv1_client * conn,const u8 * pos,size_t len)800780fb4a2SCy Schubert tls_process_certificate_status_ocsp_response(struct tlsv1_client *conn,
801780fb4a2SCy Schubert 					     const u8 *pos, size_t len)
802780fb4a2SCy Schubert {
803780fb4a2SCy Schubert 	const u8 *end = pos + len;
804780fb4a2SCy Schubert 	u32 ocsp_resp_len;
805780fb4a2SCy Schubert 
806780fb4a2SCy Schubert 	/* opaque OCSPResponse<1..2^24-1>; */
807780fb4a2SCy Schubert 	if (end - pos < 3) {
808780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "TLSv1: Too short OCSPResponse");
809780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
810780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
811780fb4a2SCy Schubert 	}
812780fb4a2SCy Schubert 	ocsp_resp_len = WPA_GET_BE24(pos);
813780fb4a2SCy Schubert 	pos += 3;
814780fb4a2SCy Schubert 	if (end - pos < ocsp_resp_len) {
815780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "TLSv1: Truncated OCSPResponse");
816780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
817780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
818780fb4a2SCy Schubert 	}
819780fb4a2SCy Schubert 
820780fb4a2SCy Schubert 	return tls_process_ocsp_response(conn, pos, ocsp_resp_len);
821780fb4a2SCy Schubert }
822780fb4a2SCy Schubert 
823780fb4a2SCy Schubert 
tls_process_certificate_status(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)824780fb4a2SCy Schubert static int tls_process_certificate_status(struct tlsv1_client *conn, u8 ct,
825780fb4a2SCy Schubert 					   const u8 *in_data, size_t *in_len)
826780fb4a2SCy Schubert {
827780fb4a2SCy Schubert 	const u8 *pos, *end;
828780fb4a2SCy Schubert 	size_t left, len;
829780fb4a2SCy Schubert 	u8 type, status_type;
830780fb4a2SCy Schubert 	enum tls_ocsp_result res;
831780fb4a2SCy Schubert 	struct x509_certificate *cert;
832780fb4a2SCy Schubert 	int depth;
833780fb4a2SCy Schubert 
834780fb4a2SCy Schubert 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
835780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
836780fb4a2SCy Schubert 			   "TLSv1: Expected Handshake; received content type 0x%x",
837780fb4a2SCy Schubert 			   ct);
838780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
839780fb4a2SCy Schubert 			  TLS_ALERT_UNEXPECTED_MESSAGE);
840780fb4a2SCy Schubert 		return -1;
841780fb4a2SCy Schubert 	}
842780fb4a2SCy Schubert 
843780fb4a2SCy Schubert 	pos = in_data;
844780fb4a2SCy Schubert 	left = *in_len;
845780fb4a2SCy Schubert 
846780fb4a2SCy Schubert 	if (left < 4) {
847780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
848780fb4a2SCy Schubert 			   "TLSv1: Too short CertificateStatus (left=%lu)",
849780fb4a2SCy Schubert 			   (unsigned long) left);
850780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
851780fb4a2SCy Schubert 		return -1;
852780fb4a2SCy Schubert 	}
853780fb4a2SCy Schubert 
854780fb4a2SCy Schubert 	type = *pos++;
855780fb4a2SCy Schubert 	len = WPA_GET_BE24(pos);
856780fb4a2SCy Schubert 	pos += 3;
857780fb4a2SCy Schubert 	left -= 4;
858780fb4a2SCy Schubert 
859780fb4a2SCy Schubert 	if (len > left) {
860780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
861780fb4a2SCy Schubert 			   "TLSv1: Mismatch in CertificateStatus length (len=%lu != left=%lu)",
862780fb4a2SCy Schubert 			   (unsigned long) len, (unsigned long) left);
863780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
864780fb4a2SCy Schubert 		return -1;
865780fb4a2SCy Schubert 	}
866780fb4a2SCy Schubert 
867780fb4a2SCy Schubert 	end = pos + len;
868780fb4a2SCy Schubert 
869780fb4a2SCy Schubert 	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS) {
870780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
871780fb4a2SCy Schubert 			   "TLSv1: Received unexpected handshake message %d (expected CertificateStatus)",
872780fb4a2SCy Schubert 			   type);
873780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
874780fb4a2SCy Schubert 			  TLS_ALERT_UNEXPECTED_MESSAGE);
875780fb4a2SCy Schubert 		return -1;
876780fb4a2SCy Schubert 	}
877780fb4a2SCy Schubert 
878780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateStatus");
879780fb4a2SCy Schubert 
880780fb4a2SCy Schubert 	/*
881780fb4a2SCy Schubert 	 * struct {
882780fb4a2SCy Schubert 	 *     CertificateStatusType status_type;
883780fb4a2SCy Schubert 	 *     select (status_type) {
884780fb4a2SCy Schubert 	 *         case ocsp: OCSPResponse;
885780fb4a2SCy Schubert 	 *         case ocsp_multi: OCSPResponseList;
886780fb4a2SCy Schubert 	 *     } response;
887780fb4a2SCy Schubert 	 * } CertificateStatus;
888780fb4a2SCy Schubert 	 */
889780fb4a2SCy Schubert 	if (end - pos < 1) {
890780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "TLSv1: Too short CertificateStatus");
891780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
892780fb4a2SCy Schubert 		return -1;
893780fb4a2SCy Schubert 	}
894780fb4a2SCy Schubert 	status_type = *pos++;
895780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatus status_type %u",
896780fb4a2SCy Schubert 		   status_type);
897780fb4a2SCy Schubert 
898780fb4a2SCy Schubert 	if (status_type == 1 /* ocsp */) {
899780fb4a2SCy Schubert 		res = tls_process_certificate_status_ocsp_response(
900780fb4a2SCy Schubert 			conn, pos, end - pos);
901780fb4a2SCy Schubert 	} else if (status_type == 2 /* ocsp_multi */) {
902780fb4a2SCy Schubert 		int good = 0, revoked = 0;
903780fb4a2SCy Schubert 		u32 resp_len;
904780fb4a2SCy Schubert 
905780fb4a2SCy Schubert 		res = TLS_OCSP_NO_RESPONSE;
906780fb4a2SCy Schubert 
907780fb4a2SCy Schubert 		/*
908780fb4a2SCy Schubert 		 * opaque OCSPResponse<0..2^24-1>;
909780fb4a2SCy Schubert 		 *
910780fb4a2SCy Schubert 		 * struct {
911780fb4a2SCy Schubert 		 *   OCSPResponse ocsp_response_list<1..2^24-1>;
912780fb4a2SCy Schubert 		 * } OCSPResponseList;
913780fb4a2SCy Schubert 		 */
914780fb4a2SCy Schubert 		if (end - pos < 3) {
915780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
916780fb4a2SCy Schubert 				   "TLSv1: Truncated OCSPResponseList");
917780fb4a2SCy Schubert 			res = TLS_OCSP_INVALID;
918780fb4a2SCy Schubert 			goto done;
919780fb4a2SCy Schubert 		}
920780fb4a2SCy Schubert 		resp_len = WPA_GET_BE24(pos);
921780fb4a2SCy Schubert 		pos += 3;
922780fb4a2SCy Schubert 		if (end - pos < resp_len) {
923780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
924780fb4a2SCy Schubert 				   "TLSv1: Truncated OCSPResponseList(len=%u)",
925780fb4a2SCy Schubert 				   resp_len);
926780fb4a2SCy Schubert 			res = TLS_OCSP_INVALID;
927780fb4a2SCy Schubert 			goto done;
928780fb4a2SCy Schubert 		}
929780fb4a2SCy Schubert 		end = pos + resp_len;
930780fb4a2SCy Schubert 
931780fb4a2SCy Schubert 		while (end - pos >= 3) {
932780fb4a2SCy Schubert 			resp_len = WPA_GET_BE24(pos);
933780fb4a2SCy Schubert 			pos += 3;
934780fb4a2SCy Schubert 			if (resp_len > end - pos) {
935780fb4a2SCy Schubert 				wpa_printf(MSG_DEBUG,
936780fb4a2SCy Schubert 					   "TLSv1: Truncated OCSPResponse(len=%u; left=%d) in ocsp_multi",
937780fb4a2SCy Schubert 					   resp_len, (int) (end - pos));
938780fb4a2SCy Schubert 				res = TLS_OCSP_INVALID;
939780fb4a2SCy Schubert 				break;
940780fb4a2SCy Schubert 			}
941780fb4a2SCy Schubert 			if (!resp_len)
942780fb4a2SCy Schubert 				continue; /* Skip an empty response */
943780fb4a2SCy Schubert 			res = tls_process_certificate_status_ocsp_response(
944780fb4a2SCy Schubert 				conn, pos - 3, resp_len + 3);
945780fb4a2SCy Schubert 			if (res == TLS_OCSP_REVOKED)
946780fb4a2SCy Schubert 				revoked++;
947780fb4a2SCy Schubert 			else if (res == TLS_OCSP_GOOD)
948780fb4a2SCy Schubert 				good++;
949780fb4a2SCy Schubert 			pos += resp_len;
950780fb4a2SCy Schubert 		}
951780fb4a2SCy Schubert 
952780fb4a2SCy Schubert 		if (revoked)
953780fb4a2SCy Schubert 			res = TLS_OCSP_REVOKED;
954780fb4a2SCy Schubert 		else if (good)
955780fb4a2SCy Schubert 			res = TLS_OCSP_GOOD;
956780fb4a2SCy Schubert 	} else {
957780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
958780fb4a2SCy Schubert 			   "TLSv1: Ignore unsupported CertificateStatus");
959780fb4a2SCy Schubert 		goto skip;
960780fb4a2SCy Schubert 	}
961780fb4a2SCy Schubert 
962780fb4a2SCy Schubert done:
963780fb4a2SCy Schubert 	if (res == TLS_OCSP_REVOKED) {
964780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
965780fb4a2SCy Schubert 			  TLS_ALERT_CERTIFICATE_REVOKED);
966780fb4a2SCy Schubert 		for (cert = conn->server_cert, depth = 0; cert;
967780fb4a2SCy Schubert 		     cert = cert->next, depth++) {
968780fb4a2SCy Schubert 			if (cert->ocsp_revoked) {
969780fb4a2SCy Schubert 				tls_cert_chain_failure_event(
970780fb4a2SCy Schubert 					conn, depth, cert, TLS_FAIL_REVOKED,
971780fb4a2SCy Schubert 					"certificate revoked");
972780fb4a2SCy Schubert 			}
973780fb4a2SCy Schubert 		}
974780fb4a2SCy Schubert 		return -1;
975780fb4a2SCy Schubert 	}
976780fb4a2SCy Schubert 
977780fb4a2SCy Schubert 	if (conn->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
978780fb4a2SCy Schubert 		/*
979780fb4a2SCy Schubert 		 * Verify that each certificate on the chain that is not part
980780fb4a2SCy Schubert 		 * of the trusted certificates has a good status. If not,
981780fb4a2SCy Schubert 		 * terminate handshake.
982780fb4a2SCy Schubert 		 */
983780fb4a2SCy Schubert 		for (cert = conn->server_cert, depth = 0; cert;
984780fb4a2SCy Schubert 		     cert = cert->next, depth++) {
985780fb4a2SCy Schubert 			if (!cert->ocsp_good) {
986780fb4a2SCy Schubert 				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
987780fb4a2SCy Schubert 					  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
988780fb4a2SCy Schubert 				tls_cert_chain_failure_event(
989780fb4a2SCy Schubert 					conn, depth, cert,
990780fb4a2SCy Schubert 					TLS_FAIL_UNSPECIFIED,
991780fb4a2SCy Schubert 					"bad certificate status response");
992780fb4a2SCy Schubert 				return -1;
993780fb4a2SCy Schubert 			}
994780fb4a2SCy Schubert 			if (cert->issuer_trusted)
995780fb4a2SCy Schubert 				break;
996780fb4a2SCy Schubert 		}
997780fb4a2SCy Schubert 	}
998780fb4a2SCy Schubert 
999780fb4a2SCy Schubert 	if ((conn->flags & TLS_CONN_REQUIRE_OCSP) && res != TLS_OCSP_GOOD) {
1000780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1001780fb4a2SCy Schubert 			  res == TLS_OCSP_INVALID ? TLS_ALERT_DECODE_ERROR :
1002780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
1003780fb4a2SCy Schubert 		if (conn->server_cert)
1004780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
1005780fb4a2SCy Schubert 				conn, 0, conn->server_cert,
1006780fb4a2SCy Schubert 				TLS_FAIL_UNSPECIFIED,
1007780fb4a2SCy Schubert 				"bad certificate status response");
1008780fb4a2SCy Schubert 		return -1;
1009780fb4a2SCy Schubert 	}
1010780fb4a2SCy Schubert 
1011780fb4a2SCy Schubert 	conn->ocsp_resp_received = 1;
1012780fb4a2SCy Schubert 
1013780fb4a2SCy Schubert skip:
1014780fb4a2SCy Schubert 	*in_len = end - in_data;
1015780fb4a2SCy Schubert 
1016780fb4a2SCy Schubert 	conn->state = SERVER_KEY_EXCHANGE;
1017780fb4a2SCy Schubert 
1018780fb4a2SCy Schubert 	return 0;
1019780fb4a2SCy Schubert }
1020780fb4a2SCy Schubert 
1021780fb4a2SCy Schubert 
tls_process_server_key_exchange(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)102239beb93cSSam Leffler static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
102339beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len)
102439beb93cSSam Leffler {
102539beb93cSSam Leffler 	const u8 *pos, *end;
102639beb93cSSam Leffler 	size_t left, len;
102739beb93cSSam Leffler 	u8 type;
102839beb93cSSam Leffler 	const struct tls_cipher_suite *suite;
102939beb93cSSam Leffler 
103039beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
103139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
103239beb93cSSam Leffler 			   "received content type 0x%x", ct);
103339beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
103439beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
103539beb93cSSam Leffler 		return -1;
103639beb93cSSam Leffler 	}
103739beb93cSSam Leffler 
103839beb93cSSam Leffler 	pos = in_data;
103939beb93cSSam Leffler 	left = *in_len;
104039beb93cSSam Leffler 
104139beb93cSSam Leffler 	if (left < 4) {
104239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange "
104339beb93cSSam Leffler 			   "(Left=%lu)", (unsigned long) left);
104439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
104539beb93cSSam Leffler 		return -1;
104639beb93cSSam Leffler 	}
104739beb93cSSam Leffler 
104839beb93cSSam Leffler 	type = *pos++;
104939beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
105039beb93cSSam Leffler 	pos += 3;
105139beb93cSSam Leffler 	left -= 4;
105239beb93cSSam Leffler 
105339beb93cSSam Leffler 	if (len > left) {
105439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange "
105539beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
105639beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
105739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
105839beb93cSSam Leffler 		return -1;
105939beb93cSSam Leffler 	}
106039beb93cSSam Leffler 
106139beb93cSSam Leffler 	end = pos + len;
106239beb93cSSam Leffler 
1063780fb4a2SCy Schubert 	if ((conn->flags & TLS_CONN_REQUEST_OCSP) &&
1064780fb4a2SCy Schubert 	    type == TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS)
1065780fb4a2SCy Schubert 		return tls_process_certificate_status(conn, ct, in_data,
1066780fb4a2SCy Schubert 						      in_len);
106739beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
106839beb93cSSam Leffler 		return tls_process_certificate_request(conn, ct, in_data,
106939beb93cSSam Leffler 						       in_len);
107039beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
107139beb93cSSam Leffler 		return tls_process_server_hello_done(conn, ct, in_data,
107239beb93cSSam Leffler 						     in_len);
107339beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) {
107439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
107539beb93cSSam Leffler 			   "message %d (expected ServerKeyExchange/"
1076780fb4a2SCy Schubert 			   "CertificateRequest/ServerHelloDone%s)", type,
1077780fb4a2SCy Schubert 			   (conn->flags & TLS_CONN_REQUEST_OCSP) ?
1078780fb4a2SCy Schubert 			   "/CertificateStatus" : "");
107939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
108039beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
108139beb93cSSam Leffler 		return -1;
108239beb93cSSam Leffler 	}
108339beb93cSSam Leffler 
108439beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange");
108539beb93cSSam Leffler 
108639beb93cSSam Leffler 	if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) {
108739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed "
108839beb93cSSam Leffler 			   "with the selected cipher suite");
108939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
109039beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
109139beb93cSSam Leffler 		return -1;
109239beb93cSSam Leffler 	}
109339beb93cSSam Leffler 
109439beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len);
109539beb93cSSam Leffler 	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
10965b9c547cSRui Paulo 	if (suite && (suite->key_exchange == TLS_KEY_X_DH_anon ||
10975b9c547cSRui Paulo 		      suite->key_exchange == TLS_KEY_X_DHE_RSA)) {
10985b9c547cSRui Paulo 		if (tlsv1_process_diffie_hellman(conn, pos, len,
10995b9c547cSRui Paulo 						 suite->key_exchange) < 0) {
110039beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
110139beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
110239beb93cSSam Leffler 			return -1;
110339beb93cSSam Leffler 		}
110439beb93cSSam Leffler 	} else {
110539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange");
110639beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
110739beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
110839beb93cSSam Leffler 		return -1;
110939beb93cSSam Leffler 	}
111039beb93cSSam Leffler 
111139beb93cSSam Leffler 	*in_len = end - in_data;
111239beb93cSSam Leffler 
111339beb93cSSam Leffler 	conn->state = SERVER_CERTIFICATE_REQUEST;
111439beb93cSSam Leffler 
111539beb93cSSam Leffler 	return 0;
111639beb93cSSam Leffler }
111739beb93cSSam Leffler 
111839beb93cSSam Leffler 
tls_process_certificate_request(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)111939beb93cSSam Leffler static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
112039beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len)
112139beb93cSSam Leffler {
112239beb93cSSam Leffler 	const u8 *pos, *end;
112339beb93cSSam Leffler 	size_t left, len;
112439beb93cSSam Leffler 	u8 type;
112539beb93cSSam Leffler 
112639beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
112739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
112839beb93cSSam Leffler 			   "received content type 0x%x", ct);
112939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
113039beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
113139beb93cSSam Leffler 		return -1;
113239beb93cSSam Leffler 	}
113339beb93cSSam Leffler 
113439beb93cSSam Leffler 	pos = in_data;
113539beb93cSSam Leffler 	left = *in_len;
113639beb93cSSam Leffler 
113739beb93cSSam Leffler 	if (left < 4) {
113839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest "
113939beb93cSSam Leffler 			   "(left=%lu)", (unsigned long) left);
114039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
114139beb93cSSam Leffler 		return -1;
114239beb93cSSam Leffler 	}
114339beb93cSSam Leffler 
114439beb93cSSam Leffler 	type = *pos++;
114539beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
114639beb93cSSam Leffler 	pos += 3;
114739beb93cSSam Leffler 	left -= 4;
114839beb93cSSam Leffler 
114939beb93cSSam Leffler 	if (len > left) {
115039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest "
115139beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
115239beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
115339beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
115439beb93cSSam Leffler 		return -1;
115539beb93cSSam Leffler 	}
115639beb93cSSam Leffler 
115739beb93cSSam Leffler 	end = pos + len;
115839beb93cSSam Leffler 
115939beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
116039beb93cSSam Leffler 		return tls_process_server_hello_done(conn, ct, in_data,
116139beb93cSSam Leffler 						     in_len);
116239beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) {
116339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
116439beb93cSSam Leffler 			   "message %d (expected CertificateRequest/"
116539beb93cSSam Leffler 			   "ServerHelloDone)", type);
116639beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
116739beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
116839beb93cSSam Leffler 		return -1;
116939beb93cSSam Leffler 	}
117039beb93cSSam Leffler 
117139beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest");
117239beb93cSSam Leffler 
117339beb93cSSam Leffler 	conn->certificate_requested = 1;
117439beb93cSSam Leffler 
117539beb93cSSam Leffler 	*in_len = end - in_data;
117639beb93cSSam Leffler 
117739beb93cSSam Leffler 	conn->state = SERVER_HELLO_DONE;
117839beb93cSSam Leffler 
117939beb93cSSam Leffler 	return 0;
118039beb93cSSam Leffler }
118139beb93cSSam Leffler 
118239beb93cSSam Leffler 
tls_process_server_hello_done(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)118339beb93cSSam Leffler static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
118439beb93cSSam Leffler 					 const u8 *in_data, size_t *in_len)
118539beb93cSSam Leffler {
118639beb93cSSam Leffler 	const u8 *pos, *end;
118739beb93cSSam Leffler 	size_t left, len;
118839beb93cSSam Leffler 	u8 type;
118939beb93cSSam Leffler 
119039beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
119139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
119239beb93cSSam Leffler 			   "received content type 0x%x", ct);
119339beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
119439beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
119539beb93cSSam Leffler 		return -1;
119639beb93cSSam Leffler 	}
119739beb93cSSam Leffler 
119839beb93cSSam Leffler 	pos = in_data;
119939beb93cSSam Leffler 	left = *in_len;
120039beb93cSSam Leffler 
120139beb93cSSam Leffler 	if (left < 4) {
120239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone "
120339beb93cSSam Leffler 			   "(left=%lu)", (unsigned long) left);
120439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
120539beb93cSSam Leffler 		return -1;
120639beb93cSSam Leffler 	}
120739beb93cSSam Leffler 
120839beb93cSSam Leffler 	type = *pos++;
120939beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
121039beb93cSSam Leffler 	pos += 3;
121139beb93cSSam Leffler 	left -= 4;
121239beb93cSSam Leffler 
121339beb93cSSam Leffler 	if (len > left) {
121439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone "
121539beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
121639beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
121739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
121839beb93cSSam Leffler 		return -1;
121939beb93cSSam Leffler 	}
122039beb93cSSam Leffler 	end = pos + len;
122139beb93cSSam Leffler 
122239beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) {
122339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
122439beb93cSSam Leffler 			   "message %d (expected ServerHelloDone)", type);
122539beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
122639beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
122739beb93cSSam Leffler 		return -1;
122839beb93cSSam Leffler 	}
122939beb93cSSam Leffler 
123039beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone");
123139beb93cSSam Leffler 
1232780fb4a2SCy Schubert 	if ((conn->flags & TLS_CONN_REQUIRE_OCSP) &&
1233780fb4a2SCy Schubert 	    !conn->ocsp_resp_received) {
1234780fb4a2SCy Schubert 		wpa_printf(MSG_INFO,
1235780fb4a2SCy Schubert 			   "TLSv1: No OCSP response received - reject handshake");
1236780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1237780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
1238780fb4a2SCy Schubert 		return -1;
1239780fb4a2SCy Schubert 	}
1240780fb4a2SCy Schubert 
124139beb93cSSam Leffler 	*in_len = end - in_data;
124239beb93cSSam Leffler 
124339beb93cSSam Leffler 	conn->state = CLIENT_KEY_EXCHANGE;
124439beb93cSSam Leffler 
124539beb93cSSam Leffler 	return 0;
124639beb93cSSam Leffler }
124739beb93cSSam Leffler 
124839beb93cSSam Leffler 
tls_process_server_change_cipher_spec(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)124939beb93cSSam Leffler static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn,
125039beb93cSSam Leffler 						 u8 ct, const u8 *in_data,
125139beb93cSSam Leffler 						 size_t *in_len)
125239beb93cSSam Leffler {
125339beb93cSSam Leffler 	const u8 *pos;
125439beb93cSSam Leffler 	size_t left;
125539beb93cSSam Leffler 
125639beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
125739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
125839beb93cSSam Leffler 			   "received content type 0x%x", ct);
125939beb93cSSam Leffler 		if (conn->use_session_ticket) {
126039beb93cSSam Leffler 			int res;
126139beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Server may have "
126239beb93cSSam Leffler 				   "rejected SessionTicket");
126339beb93cSSam Leffler 			conn->use_session_ticket = 0;
126439beb93cSSam Leffler 
126539beb93cSSam Leffler 			/* Notify upper layers that SessionTicket failed */
126639beb93cSSam Leffler 			res = conn->session_ticket_cb(
126739beb93cSSam Leffler 				conn->session_ticket_cb_ctx, NULL, 0, NULL,
126839beb93cSSam Leffler 				NULL, NULL);
126939beb93cSSam Leffler 			if (res < 0) {
127039beb93cSSam Leffler 				wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket "
127139beb93cSSam Leffler 					   "callback indicated failure");
127239beb93cSSam Leffler 				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
127339beb93cSSam Leffler 					  TLS_ALERT_HANDSHAKE_FAILURE);
127439beb93cSSam Leffler 				return -1;
127539beb93cSSam Leffler 			}
127639beb93cSSam Leffler 
127739beb93cSSam Leffler 			conn->state = SERVER_CERTIFICATE;
127839beb93cSSam Leffler 			return tls_process_certificate(conn, ct, in_data,
127939beb93cSSam Leffler 						       in_len);
128039beb93cSSam Leffler 		}
128139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
128239beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
128339beb93cSSam Leffler 		return -1;
128439beb93cSSam Leffler 	}
128539beb93cSSam Leffler 
128639beb93cSSam Leffler 	pos = in_data;
128739beb93cSSam Leffler 	left = *in_len;
128839beb93cSSam Leffler 
128939beb93cSSam Leffler 	if (left < 1) {
129039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec");
129139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
129239beb93cSSam Leffler 		return -1;
129339beb93cSSam Leffler 	}
129439beb93cSSam Leffler 
129539beb93cSSam Leffler 	if (*pos != TLS_CHANGE_CIPHER_SPEC) {
129639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
129739beb93cSSam Leffler 			   "received data 0x%x", *pos);
129839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
129939beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
130039beb93cSSam Leffler 		return -1;
130139beb93cSSam Leffler 	}
130239beb93cSSam Leffler 
130339beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec");
130439beb93cSSam Leffler 	if (tlsv1_record_change_read_cipher(&conn->rl) < 0) {
130539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher "
130639beb93cSSam Leffler 			   "for record layer");
130739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
130839beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
130939beb93cSSam Leffler 		return -1;
131039beb93cSSam Leffler 	}
131139beb93cSSam Leffler 
131239beb93cSSam Leffler 	*in_len = pos + 1 - in_data;
131339beb93cSSam Leffler 
131439beb93cSSam Leffler 	conn->state = SERVER_FINISHED;
131539beb93cSSam Leffler 
131639beb93cSSam Leffler 	return 0;
131739beb93cSSam Leffler }
131839beb93cSSam Leffler 
131939beb93cSSam Leffler 
tls_process_server_finished(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)132039beb93cSSam Leffler static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct,
132139beb93cSSam Leffler 				       const u8 *in_data, size_t *in_len)
132239beb93cSSam Leffler {
132339beb93cSSam Leffler 	const u8 *pos, *end;
132439beb93cSSam Leffler 	size_t left, len, hlen;
132539beb93cSSam Leffler 	u8 verify_data[TLS_VERIFY_DATA_LEN];
132639beb93cSSam Leffler 	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
132739beb93cSSam Leffler 
132839beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
132939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; "
133039beb93cSSam Leffler 			   "received content type 0x%x", ct);
133139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
133239beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
133339beb93cSSam Leffler 		return -1;
133439beb93cSSam Leffler 	}
133539beb93cSSam Leffler 
133639beb93cSSam Leffler 	pos = in_data;
133739beb93cSSam Leffler 	left = *in_len;
133839beb93cSSam Leffler 
133939beb93cSSam Leffler 	if (left < 4) {
134039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for "
134139beb93cSSam Leffler 			   "Finished",
134239beb93cSSam Leffler 			   (unsigned long) left);
134339beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
134439beb93cSSam Leffler 			  TLS_ALERT_DECODE_ERROR);
134539beb93cSSam Leffler 		return -1;
134639beb93cSSam Leffler 	}
134739beb93cSSam Leffler 
134839beb93cSSam Leffler 	if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) {
134939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received "
135039beb93cSSam Leffler 			   "type 0x%x", pos[0]);
135139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
135239beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
135339beb93cSSam Leffler 		return -1;
135439beb93cSSam Leffler 	}
135539beb93cSSam Leffler 
135639beb93cSSam Leffler 	len = WPA_GET_BE24(pos + 1);
135739beb93cSSam Leffler 
135839beb93cSSam Leffler 	pos += 4;
135939beb93cSSam Leffler 	left -= 4;
136039beb93cSSam Leffler 
136139beb93cSSam Leffler 	if (len > left) {
136239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished "
136339beb93cSSam Leffler 			   "(len=%lu > left=%lu)",
136439beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
136539beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
136639beb93cSSam Leffler 			  TLS_ALERT_DECODE_ERROR);
136739beb93cSSam Leffler 		return -1;
136839beb93cSSam Leffler 	}
136939beb93cSSam Leffler 	end = pos + len;
137039beb93cSSam Leffler 	if (len != TLS_VERIFY_DATA_LEN) {
137139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length "
137239beb93cSSam Leffler 			   "in Finished: %lu (expected %d)",
137339beb93cSSam Leffler 			   (unsigned long) len, TLS_VERIFY_DATA_LEN);
137439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
137539beb93cSSam Leffler 			  TLS_ALERT_DECODE_ERROR);
137639beb93cSSam Leffler 		return -1;
137739beb93cSSam Leffler 	}
137839beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished",
137939beb93cSSam Leffler 		    pos, TLS_VERIFY_DATA_LEN);
138039beb93cSSam Leffler 
1381f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
1382f05cddf9SRui Paulo 	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
1383f05cddf9SRui Paulo 		hlen = SHA256_MAC_LEN;
1384f05cddf9SRui Paulo 		if (conn->verify.sha256_server == NULL ||
1385f05cddf9SRui Paulo 		    crypto_hash_finish(conn->verify.sha256_server, hash, &hlen)
1386f05cddf9SRui Paulo 		    < 0) {
1387f05cddf9SRui Paulo 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1388f05cddf9SRui Paulo 				  TLS_ALERT_INTERNAL_ERROR);
1389f05cddf9SRui Paulo 			conn->verify.sha256_server = NULL;
1390f05cddf9SRui Paulo 			return -1;
1391f05cddf9SRui Paulo 		}
1392f05cddf9SRui Paulo 		conn->verify.sha256_server = NULL;
1393f05cddf9SRui Paulo 	} else {
1394f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
1395f05cddf9SRui Paulo 
139639beb93cSSam Leffler 	hlen = MD5_MAC_LEN;
139739beb93cSSam Leffler 	if (conn->verify.md5_server == NULL ||
139839beb93cSSam Leffler 	    crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) {
139939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
140039beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
140139beb93cSSam Leffler 		conn->verify.md5_server = NULL;
140239beb93cSSam Leffler 		crypto_hash_finish(conn->verify.sha1_server, NULL, NULL);
140339beb93cSSam Leffler 		conn->verify.sha1_server = NULL;
140439beb93cSSam Leffler 		return -1;
140539beb93cSSam Leffler 	}
140639beb93cSSam Leffler 	conn->verify.md5_server = NULL;
140739beb93cSSam Leffler 	hlen = SHA1_MAC_LEN;
140839beb93cSSam Leffler 	if (conn->verify.sha1_server == NULL ||
140939beb93cSSam Leffler 	    crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN,
141039beb93cSSam Leffler 			       &hlen) < 0) {
141139beb93cSSam Leffler 		conn->verify.sha1_server = NULL;
141239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
141339beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
141439beb93cSSam Leffler 		return -1;
141539beb93cSSam Leffler 	}
141639beb93cSSam Leffler 	conn->verify.sha1_server = NULL;
1417f05cddf9SRui Paulo 	hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
141839beb93cSSam Leffler 
1419f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
1420f05cddf9SRui Paulo 	}
1421f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
1422f05cddf9SRui Paulo 
1423f05cddf9SRui Paulo 	if (tls_prf(conn->rl.tls_version,
1424f05cddf9SRui Paulo 		    conn->master_secret, TLS_MASTER_SECRET_LEN,
1425f05cddf9SRui Paulo 		    "server finished", hash, hlen,
142639beb93cSSam Leffler 		    verify_data, TLS_VERIFY_DATA_LEN)) {
142739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data");
142839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
142939beb93cSSam Leffler 			  TLS_ALERT_DECRYPT_ERROR);
143039beb93cSSam Leffler 		return -1;
143139beb93cSSam Leffler 	}
143239beb93cSSam Leffler 	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
143339beb93cSSam Leffler 			verify_data, TLS_VERIFY_DATA_LEN);
143439beb93cSSam Leffler 
14355b9c547cSRui Paulo 	if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
143639beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data");
14375b9c547cSRui Paulo 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
14385b9c547cSRui Paulo 			  TLS_ALERT_DECRYPT_ERROR);
143939beb93cSSam Leffler 		return -1;
144039beb93cSSam Leffler 	}
144139beb93cSSam Leffler 
144239beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received Finished");
144339beb93cSSam Leffler 
144439beb93cSSam Leffler 	*in_len = end - in_data;
144539beb93cSSam Leffler 
144639beb93cSSam Leffler 	conn->state = (conn->session_resumed || conn->use_session_ticket) ?
144739beb93cSSam Leffler 		CHANGE_CIPHER_SPEC : ACK_FINISHED;
144839beb93cSSam Leffler 
144939beb93cSSam Leffler 	return 0;
145039beb93cSSam Leffler }
145139beb93cSSam Leffler 
145239beb93cSSam Leffler 
tls_process_application_data(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len,u8 ** out_data,size_t * out_len)145339beb93cSSam Leffler static int tls_process_application_data(struct tlsv1_client *conn, u8 ct,
145439beb93cSSam Leffler 					const u8 *in_data, size_t *in_len,
145539beb93cSSam Leffler 					u8 **out_data, size_t *out_len)
145639beb93cSSam Leffler {
145739beb93cSSam Leffler 	const u8 *pos;
145839beb93cSSam Leffler 	size_t left;
145939beb93cSSam Leffler 
146039beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
146139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; "
146239beb93cSSam Leffler 			   "received content type 0x%x", ct);
146339beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
146439beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
146539beb93cSSam Leffler 		return -1;
146639beb93cSSam Leffler 	}
146739beb93cSSam Leffler 
146839beb93cSSam Leffler 	pos = in_data;
146939beb93cSSam Leffler 	left = *in_len;
147039beb93cSSam Leffler 
147139beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake",
147239beb93cSSam Leffler 		    pos, left);
147339beb93cSSam Leffler 
147439beb93cSSam Leffler 	*out_data = os_malloc(left);
147539beb93cSSam Leffler 	if (*out_data) {
147639beb93cSSam Leffler 		os_memcpy(*out_data, pos, left);
147739beb93cSSam Leffler 		*out_len = left;
147839beb93cSSam Leffler 	}
147939beb93cSSam Leffler 
148039beb93cSSam Leffler 	return 0;
148139beb93cSSam Leffler }
148239beb93cSSam Leffler 
148339beb93cSSam Leffler 
tlsv1_client_process_handshake(struct tlsv1_client * conn,u8 ct,const u8 * buf,size_t * len,u8 ** out_data,size_t * out_len)148439beb93cSSam Leffler int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct,
148539beb93cSSam Leffler 				   const u8 *buf, size_t *len,
148639beb93cSSam Leffler 				   u8 **out_data, size_t *out_len)
148739beb93cSSam Leffler {
148839beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_ALERT) {
148939beb93cSSam Leffler 		if (*len < 2) {
149039beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow");
149139beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
149239beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
149339beb93cSSam Leffler 			return -1;
149439beb93cSSam Leffler 		}
149539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
149639beb93cSSam Leffler 			   buf[0], buf[1]);
149739beb93cSSam Leffler 		*len = 2;
149839beb93cSSam Leffler 		conn->state = FAILED;
149939beb93cSSam Leffler 		return -1;
150039beb93cSSam Leffler 	}
150139beb93cSSam Leffler 
150239beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 &&
150339beb93cSSam Leffler 	    buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) {
150439beb93cSSam Leffler 		size_t hr_len = WPA_GET_BE24(buf + 1);
150539beb93cSSam Leffler 		if (hr_len > *len - 4) {
150639beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow");
150739beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
150839beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
150939beb93cSSam Leffler 			return -1;
151039beb93cSSam Leffler 		}
151139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest");
151239beb93cSSam Leffler 		*len = 4 + hr_len;
151339beb93cSSam Leffler 		return 0;
151439beb93cSSam Leffler 	}
151539beb93cSSam Leffler 
151639beb93cSSam Leffler 	switch (conn->state) {
151739beb93cSSam Leffler 	case SERVER_HELLO:
151839beb93cSSam Leffler 		if (tls_process_server_hello(conn, ct, buf, len))
151939beb93cSSam Leffler 			return -1;
152039beb93cSSam Leffler 		break;
152139beb93cSSam Leffler 	case SERVER_CERTIFICATE:
152239beb93cSSam Leffler 		if (tls_process_certificate(conn, ct, buf, len))
152339beb93cSSam Leffler 			return -1;
152439beb93cSSam Leffler 		break;
152539beb93cSSam Leffler 	case SERVER_KEY_EXCHANGE:
152639beb93cSSam Leffler 		if (tls_process_server_key_exchange(conn, ct, buf, len))
152739beb93cSSam Leffler 			return -1;
152839beb93cSSam Leffler 		break;
152939beb93cSSam Leffler 	case SERVER_CERTIFICATE_REQUEST:
153039beb93cSSam Leffler 		if (tls_process_certificate_request(conn, ct, buf, len))
153139beb93cSSam Leffler 			return -1;
153239beb93cSSam Leffler 		break;
153339beb93cSSam Leffler 	case SERVER_HELLO_DONE:
153439beb93cSSam Leffler 		if (tls_process_server_hello_done(conn, ct, buf, len))
153539beb93cSSam Leffler 			return -1;
153639beb93cSSam Leffler 		break;
153739beb93cSSam Leffler 	case SERVER_CHANGE_CIPHER_SPEC:
153839beb93cSSam Leffler 		if (tls_process_server_change_cipher_spec(conn, ct, buf, len))
153939beb93cSSam Leffler 			return -1;
154039beb93cSSam Leffler 		break;
154139beb93cSSam Leffler 	case SERVER_FINISHED:
154239beb93cSSam Leffler 		if (tls_process_server_finished(conn, ct, buf, len))
154339beb93cSSam Leffler 			return -1;
154439beb93cSSam Leffler 		break;
154539beb93cSSam Leffler 	case ACK_FINISHED:
154639beb93cSSam Leffler 		if (out_data &&
154739beb93cSSam Leffler 		    tls_process_application_data(conn, ct, buf, len, out_data,
154839beb93cSSam Leffler 						 out_len))
154939beb93cSSam Leffler 			return -1;
155039beb93cSSam Leffler 		break;
155139beb93cSSam Leffler 	default:
155239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d "
155339beb93cSSam Leffler 			   "while processing received message",
155439beb93cSSam Leffler 			   conn->state);
155539beb93cSSam Leffler 		return -1;
155639beb93cSSam Leffler 	}
155739beb93cSSam Leffler 
155839beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
155939beb93cSSam Leffler 		tls_verify_hash_add(&conn->verify, buf, *len);
156039beb93cSSam Leffler 
156139beb93cSSam Leffler 	return 0;
156239beb93cSSam Leffler }
1563