xref: /freebsd/contrib/wpa/src/tls/tlsv1_client_read.c (revision c1d255d3ffdbe447de3ab875bf4e7d7accc5bfc5)
139beb93cSSam Leffler /*
239beb93cSSam Leffler  * TLSv1 client - read handshake message
3780fb4a2SCy Schubert  * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
739beb93cSSam Leffler  */
839beb93cSSam Leffler 
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler 
1139beb93cSSam Leffler #include "common.h"
12e28a4053SRui Paulo #include "crypto/md5.h"
13e28a4053SRui Paulo #include "crypto/sha1.h"
14f05cddf9SRui Paulo #include "crypto/sha256.h"
15e28a4053SRui Paulo #include "crypto/tls.h"
1639beb93cSSam Leffler #include "x509v3.h"
1739beb93cSSam Leffler #include "tlsv1_common.h"
1839beb93cSSam Leffler #include "tlsv1_record.h"
1939beb93cSSam Leffler #include "tlsv1_client.h"
2039beb93cSSam Leffler #include "tlsv1_client_i.h"
2139beb93cSSam Leffler 
2239beb93cSSam Leffler static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
2339beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len);
2439beb93cSSam Leffler static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
2539beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len);
2639beb93cSSam Leffler static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
2739beb93cSSam Leffler 					 const u8 *in_data, size_t *in_len);
2839beb93cSSam Leffler 
2939beb93cSSam Leffler 
30780fb4a2SCy Schubert static int tls_version_disabled(struct tlsv1_client *conn, u16 ver)
31780fb4a2SCy Schubert {
32780fb4a2SCy Schubert 	return (((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
33780fb4a2SCy Schubert 		 ver == TLS_VERSION_1) ||
34780fb4a2SCy Schubert 		((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
35780fb4a2SCy Schubert 		 ver == TLS_VERSION_1_1) ||
36780fb4a2SCy Schubert 		((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
37780fb4a2SCy Schubert 		 ver == TLS_VERSION_1_2));
38780fb4a2SCy Schubert }
39780fb4a2SCy Schubert 
40780fb4a2SCy Schubert 
41780fb4a2SCy Schubert static int tls_process_server_hello_extensions(struct tlsv1_client *conn,
42780fb4a2SCy Schubert 					       const u8 *pos, size_t len)
43780fb4a2SCy Schubert {
44780fb4a2SCy Schubert 	const u8 *end = pos + len;
45780fb4a2SCy Schubert 
46780fb4a2SCy Schubert 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello extensions",
47780fb4a2SCy Schubert 		    pos, len);
48780fb4a2SCy Schubert 	while (pos < end) {
49780fb4a2SCy Schubert 		u16 ext, elen;
50780fb4a2SCy Schubert 
51780fb4a2SCy Schubert 		if (end - pos < 4) {
52780fb4a2SCy Schubert 			wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension header");
53780fb4a2SCy Schubert 			return -1;
54780fb4a2SCy Schubert 		}
55780fb4a2SCy Schubert 
56780fb4a2SCy Schubert 		ext = WPA_GET_BE16(pos);
57780fb4a2SCy Schubert 		pos += 2;
58780fb4a2SCy Schubert 		elen = WPA_GET_BE16(pos);
59780fb4a2SCy Schubert 		pos += 2;
60780fb4a2SCy Schubert 
61780fb4a2SCy Schubert 		if (elen > end - pos) {
62780fb4a2SCy Schubert 			wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension");
63780fb4a2SCy Schubert 			return -1;
64780fb4a2SCy Schubert 		}
65780fb4a2SCy Schubert 
66780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "TLSv1: ServerHello ExtensionType %u",
67780fb4a2SCy Schubert 			   ext);
68780fb4a2SCy Schubert 		wpa_hexdump(MSG_DEBUG, "TLSv1: ServerHello extension data",
69780fb4a2SCy Schubert 			    pos, elen);
70780fb4a2SCy Schubert 
71780fb4a2SCy Schubert 		pos += elen;
72780fb4a2SCy Schubert 	}
73780fb4a2SCy Schubert 
74780fb4a2SCy Schubert 	return 0;
75780fb4a2SCy Schubert }
76780fb4a2SCy Schubert 
77780fb4a2SCy Schubert 
7839beb93cSSam Leffler static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct,
7939beb93cSSam Leffler 				    const u8 *in_data, size_t *in_len)
8039beb93cSSam Leffler {
8139beb93cSSam Leffler 	const u8 *pos, *end;
8239beb93cSSam Leffler 	size_t left, len, i;
8339beb93cSSam Leffler 	u16 cipher_suite;
84f05cddf9SRui Paulo 	u16 tls_version;
8539beb93cSSam Leffler 
8639beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
8739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
8839beb93cSSam Leffler 			   "received content type 0x%x", ct);
8939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
9039beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
9139beb93cSSam Leffler 		return -1;
9239beb93cSSam Leffler 	}
9339beb93cSSam Leffler 
9439beb93cSSam Leffler 	pos = in_data;
9539beb93cSSam Leffler 	left = *in_len;
9639beb93cSSam Leffler 
9739beb93cSSam Leffler 	if (left < 4)
9839beb93cSSam Leffler 		goto decode_error;
9939beb93cSSam Leffler 
10039beb93cSSam Leffler 	/* HandshakeType msg_type */
10139beb93cSSam Leffler 	if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) {
10239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
10339beb93cSSam Leffler 			   "message %d (expected ServerHello)", *pos);
10439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
10539beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
10639beb93cSSam Leffler 		return -1;
10739beb93cSSam Leffler 	}
10839beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello");
10939beb93cSSam Leffler 	pos++;
11039beb93cSSam Leffler 	/* uint24 length */
11139beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
11239beb93cSSam Leffler 	pos += 3;
11339beb93cSSam Leffler 	left -= 4;
11439beb93cSSam Leffler 
11539beb93cSSam Leffler 	if (len > left)
11639beb93cSSam Leffler 		goto decode_error;
11739beb93cSSam Leffler 
11839beb93cSSam Leffler 	/* body - ServerHello */
11939beb93cSSam Leffler 
12039beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len);
12139beb93cSSam Leffler 	end = pos + len;
12239beb93cSSam Leffler 
12339beb93cSSam Leffler 	/* ProtocolVersion server_version */
12439beb93cSSam Leffler 	if (end - pos < 2)
12539beb93cSSam Leffler 		goto decode_error;
126f05cddf9SRui Paulo 	tls_version = WPA_GET_BE16(pos);
127780fb4a2SCy Schubert 	if (!tls_version_ok(tls_version) ||
128780fb4a2SCy Schubert 	    tls_version_disabled(conn, tls_version)) {
12939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "
130f05cddf9SRui Paulo 			   "ServerHello %u.%u", pos[0], pos[1]);
13139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
13239beb93cSSam Leffler 			  TLS_ALERT_PROTOCOL_VERSION);
13339beb93cSSam Leffler 		return -1;
13439beb93cSSam Leffler 	}
13539beb93cSSam Leffler 	pos += 2;
13639beb93cSSam Leffler 
137f05cddf9SRui Paulo 	wpa_printf(MSG_DEBUG, "TLSv1: Using TLS v%s",
138f05cddf9SRui Paulo 		   tls_version_str(tls_version));
139f05cddf9SRui Paulo 	conn->rl.tls_version = tls_version;
140f05cddf9SRui Paulo 
14139beb93cSSam Leffler 	/* Random random */
14239beb93cSSam Leffler 	if (end - pos < TLS_RANDOM_LEN)
14339beb93cSSam Leffler 		goto decode_error;
14439beb93cSSam Leffler 
14539beb93cSSam Leffler 	os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN);
14639beb93cSSam Leffler 	pos += TLS_RANDOM_LEN;
14739beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random",
14839beb93cSSam Leffler 		    conn->server_random, TLS_RANDOM_LEN);
14939beb93cSSam Leffler 
15039beb93cSSam Leffler 	/* SessionID session_id */
15139beb93cSSam Leffler 	if (end - pos < 1)
15239beb93cSSam Leffler 		goto decode_error;
15339beb93cSSam Leffler 	if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN)
15439beb93cSSam Leffler 		goto decode_error;
15539beb93cSSam Leffler 	if (conn->session_id_len && conn->session_id_len == *pos &&
15639beb93cSSam Leffler 	    os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) {
15739beb93cSSam Leffler 		pos += 1 + conn->session_id_len;
15839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session");
15939beb93cSSam Leffler 		conn->session_resumed = 1;
16039beb93cSSam Leffler 	} else {
16139beb93cSSam Leffler 		conn->session_id_len = *pos;
16239beb93cSSam Leffler 		pos++;
16339beb93cSSam Leffler 		os_memcpy(conn->session_id, pos, conn->session_id_len);
16439beb93cSSam Leffler 		pos += conn->session_id_len;
16539beb93cSSam Leffler 	}
16639beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id",
16739beb93cSSam Leffler 		    conn->session_id, conn->session_id_len);
16839beb93cSSam Leffler 
16939beb93cSSam Leffler 	/* CipherSuite cipher_suite */
17039beb93cSSam Leffler 	if (end - pos < 2)
17139beb93cSSam Leffler 		goto decode_error;
17239beb93cSSam Leffler 	cipher_suite = WPA_GET_BE16(pos);
17339beb93cSSam Leffler 	pos += 2;
17439beb93cSSam Leffler 	for (i = 0; i < conn->num_cipher_suites; i++) {
17539beb93cSSam Leffler 		if (cipher_suite == conn->cipher_suites[i])
17639beb93cSSam Leffler 			break;
17739beb93cSSam Leffler 	}
17839beb93cSSam Leffler 	if (i == conn->num_cipher_suites) {
17939beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
18039beb93cSSam Leffler 			   "cipher suite 0x%04x", cipher_suite);
18139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
18239beb93cSSam Leffler 			  TLS_ALERT_ILLEGAL_PARAMETER);
18339beb93cSSam Leffler 		return -1;
18439beb93cSSam Leffler 	}
18539beb93cSSam Leffler 
18639beb93cSSam Leffler 	if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) {
18739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different "
18839beb93cSSam Leffler 			   "cipher suite for a resumed connection (0x%04x != "
18939beb93cSSam Leffler 			   "0x%04x)", cipher_suite, conn->prev_cipher_suite);
19039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
19139beb93cSSam Leffler 			  TLS_ALERT_ILLEGAL_PARAMETER);
19239beb93cSSam Leffler 		return -1;
19339beb93cSSam Leffler 	}
19439beb93cSSam Leffler 
19539beb93cSSam Leffler 	if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) {
19639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for "
19739beb93cSSam Leffler 			   "record layer");
19839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
19939beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
20039beb93cSSam Leffler 		return -1;
20139beb93cSSam Leffler 	}
20239beb93cSSam Leffler 
20339beb93cSSam Leffler 	conn->prev_cipher_suite = cipher_suite;
20439beb93cSSam Leffler 
20539beb93cSSam Leffler 	/* CompressionMethod compression_method */
20639beb93cSSam Leffler 	if (end - pos < 1)
20739beb93cSSam Leffler 		goto decode_error;
20839beb93cSSam Leffler 	if (*pos != TLS_COMPRESSION_NULL) {
20939beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
21039beb93cSSam Leffler 			   "compression 0x%02x", *pos);
21139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
21239beb93cSSam Leffler 			  TLS_ALERT_ILLEGAL_PARAMETER);
21339beb93cSSam Leffler 		return -1;
21439beb93cSSam Leffler 	}
21539beb93cSSam Leffler 	pos++;
21639beb93cSSam Leffler 
217780fb4a2SCy Schubert 	if (end - pos >= 2) {
218780fb4a2SCy Schubert 		u16 ext_len;
219780fb4a2SCy Schubert 
220780fb4a2SCy Schubert 		ext_len = WPA_GET_BE16(pos);
221780fb4a2SCy Schubert 		pos += 2;
222780fb4a2SCy Schubert 		if (end - pos < ext_len) {
223780fb4a2SCy Schubert 			wpa_printf(MSG_INFO,
224780fb4a2SCy Schubert 				   "TLSv1: Invalid ServerHello extension length: %u (left: %u)",
225780fb4a2SCy Schubert 				   ext_len, (unsigned int) (end - pos));
226780fb4a2SCy Schubert 			goto decode_error;
227780fb4a2SCy Schubert 		}
228780fb4a2SCy Schubert 
229780fb4a2SCy Schubert 		if (tls_process_server_hello_extensions(conn, pos, ext_len))
230780fb4a2SCy Schubert 			goto decode_error;
231780fb4a2SCy Schubert 		pos += ext_len;
232780fb4a2SCy Schubert 	}
233780fb4a2SCy Schubert 
23439beb93cSSam Leffler 	if (end != pos) {
23539beb93cSSam Leffler 		wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the "
23639beb93cSSam Leffler 			    "end of ServerHello", pos, end - pos);
23739beb93cSSam Leffler 		goto decode_error;
23839beb93cSSam Leffler 	}
23939beb93cSSam Leffler 
24039beb93cSSam Leffler 	if (conn->session_ticket_included && conn->session_ticket_cb) {
24139beb93cSSam Leffler 		/* TODO: include SessionTicket extension if one was included in
24239beb93cSSam Leffler 		 * ServerHello */
24339beb93cSSam Leffler 		int res = conn->session_ticket_cb(
24439beb93cSSam Leffler 			conn->session_ticket_cb_ctx, NULL, 0,
24539beb93cSSam Leffler 			conn->client_random, conn->server_random,
24639beb93cSSam Leffler 			conn->master_secret);
24739beb93cSSam Leffler 		if (res < 0) {
24839beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback "
24939beb93cSSam Leffler 				   "indicated failure");
25039beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
25139beb93cSSam Leffler 				  TLS_ALERT_HANDSHAKE_FAILURE);
25239beb93cSSam Leffler 			return -1;
25339beb93cSSam Leffler 		}
25439beb93cSSam Leffler 		conn->use_session_ticket = !!res;
25539beb93cSSam Leffler 	}
25639beb93cSSam Leffler 
25739beb93cSSam Leffler 	if ((conn->session_resumed || conn->use_session_ticket) &&
25839beb93cSSam Leffler 	    tls_derive_keys(conn, NULL, 0)) {
25939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
26039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
26139beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
26239beb93cSSam Leffler 		return -1;
26339beb93cSSam Leffler 	}
26439beb93cSSam Leffler 
26539beb93cSSam Leffler 	*in_len = end - in_data;
26639beb93cSSam Leffler 
26739beb93cSSam Leffler 	conn->state = (conn->session_resumed || conn->use_session_ticket) ?
26839beb93cSSam Leffler 		SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE;
26939beb93cSSam Leffler 
27039beb93cSSam Leffler 	return 0;
27139beb93cSSam Leffler 
27239beb93cSSam Leffler decode_error:
27339beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello");
27439beb93cSSam Leffler 	tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
27539beb93cSSam Leffler 	return -1;
27639beb93cSSam Leffler }
27739beb93cSSam Leffler 
27839beb93cSSam Leffler 
279780fb4a2SCy Schubert static void tls_peer_cert_event(struct tlsv1_client *conn, int depth,
280780fb4a2SCy Schubert 				struct x509_certificate *cert)
281780fb4a2SCy Schubert {
282780fb4a2SCy Schubert 	union tls_event_data ev;
283780fb4a2SCy Schubert 	struct wpabuf *cert_buf = NULL;
284780fb4a2SCy Schubert #ifdef CONFIG_SHA256
285780fb4a2SCy Schubert 	u8 hash[32];
286780fb4a2SCy Schubert #endif /* CONFIG_SHA256 */
287780fb4a2SCy Schubert 	char subject[128];
288780fb4a2SCy Schubert 
289780fb4a2SCy Schubert 	if (!conn->event_cb)
290780fb4a2SCy Schubert 		return;
291780fb4a2SCy Schubert 
292780fb4a2SCy Schubert 	os_memset(&ev, 0, sizeof(ev));
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 
315*c1d255d3SCy Schubert 	if (cert->extensions_present & X509_EXT_CERTIFICATE_POLICY) {
316*c1d255d3SCy Schubert 		if (cert->certificate_policy & X509_EXT_CERT_POLICY_TOD_STRICT)
317*c1d255d3SCy Schubert 			ev.peer_cert.tod = 1;
318*c1d255d3SCy Schubert 		else if (cert->certificate_policy &
319*c1d255d3SCy Schubert 			 X509_EXT_CERT_POLICY_TOD_TOFU)
320*c1d255d3SCy Schubert 			ev.peer_cert.tod = 2;
321*c1d255d3SCy Schubert 	}
322*c1d255d3SCy 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 
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 
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,
543*c1d255d3SCy 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 
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 
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,
7745b9c547cSRui Paulo 				server_params_end - server_params, hash);
7755b9c547cSRui Paulo 		}
7765b9c547cSRui Paulo 
7775b9c547cSRui Paulo 		if (hlen < 0)
7785b9c547cSRui Paulo 			goto fail;
7795b9c547cSRui Paulo 		wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerKeyExchange hash",
7805b9c547cSRui Paulo 			    hash, hlen);
7815b9c547cSRui Paulo 
7825b9c547cSRui Paulo 		if (tls_verify_signature(conn->rl.tls_version,
7835b9c547cSRui Paulo 					 conn->server_rsa_key,
7845b9c547cSRui Paulo 					 hash, hlen, pos, end - pos,
7855b9c547cSRui Paulo 					 &alert) < 0)
7865b9c547cSRui Paulo 			goto fail;
7875b9c547cSRui Paulo 	}
78839beb93cSSam Leffler 
78939beb93cSSam Leffler 	return 0;
79039beb93cSSam Leffler 
79139beb93cSSam Leffler fail:
79239beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed");
79339beb93cSSam Leffler 	tlsv1_client_free_dh(conn);
79439beb93cSSam Leffler 	return -1;
79539beb93cSSam Leffler }
79639beb93cSSam Leffler 
79739beb93cSSam Leffler 
798780fb4a2SCy Schubert static enum tls_ocsp_result
799780fb4a2SCy Schubert tls_process_certificate_status_ocsp_response(struct tlsv1_client *conn,
800780fb4a2SCy Schubert 					     const u8 *pos, size_t len)
801780fb4a2SCy Schubert {
802780fb4a2SCy Schubert 	const u8 *end = pos + len;
803780fb4a2SCy Schubert 	u32 ocsp_resp_len;
804780fb4a2SCy Schubert 
805780fb4a2SCy Schubert 	/* opaque OCSPResponse<1..2^24-1>; */
806780fb4a2SCy Schubert 	if (end - pos < 3) {
807780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "TLSv1: Too short OCSPResponse");
808780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
809780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
810780fb4a2SCy Schubert 	}
811780fb4a2SCy Schubert 	ocsp_resp_len = WPA_GET_BE24(pos);
812780fb4a2SCy Schubert 	pos += 3;
813780fb4a2SCy Schubert 	if (end - pos < ocsp_resp_len) {
814780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "TLSv1: Truncated OCSPResponse");
815780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
816780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
817780fb4a2SCy Schubert 	}
818780fb4a2SCy Schubert 
819780fb4a2SCy Schubert 	return tls_process_ocsp_response(conn, pos, ocsp_resp_len);
820780fb4a2SCy Schubert }
821780fb4a2SCy Schubert 
822780fb4a2SCy Schubert 
823780fb4a2SCy Schubert static int tls_process_certificate_status(struct tlsv1_client *conn, u8 ct,
824780fb4a2SCy Schubert 					   const u8 *in_data, size_t *in_len)
825780fb4a2SCy Schubert {
826780fb4a2SCy Schubert 	const u8 *pos, *end;
827780fb4a2SCy Schubert 	size_t left, len;
828780fb4a2SCy Schubert 	u8 type, status_type;
829780fb4a2SCy Schubert 	enum tls_ocsp_result res;
830780fb4a2SCy Schubert 	struct x509_certificate *cert;
831780fb4a2SCy Schubert 	int depth;
832780fb4a2SCy Schubert 
833780fb4a2SCy Schubert 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
834780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
835780fb4a2SCy Schubert 			   "TLSv1: Expected Handshake; received content type 0x%x",
836780fb4a2SCy Schubert 			   ct);
837780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
838780fb4a2SCy Schubert 			  TLS_ALERT_UNEXPECTED_MESSAGE);
839780fb4a2SCy Schubert 		return -1;
840780fb4a2SCy Schubert 	}
841780fb4a2SCy Schubert 
842780fb4a2SCy Schubert 	pos = in_data;
843780fb4a2SCy Schubert 	left = *in_len;
844780fb4a2SCy Schubert 
845780fb4a2SCy Schubert 	if (left < 4) {
846780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
847780fb4a2SCy Schubert 			   "TLSv1: Too short CertificateStatus (left=%lu)",
848780fb4a2SCy Schubert 			   (unsigned long) left);
849780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
850780fb4a2SCy Schubert 		return -1;
851780fb4a2SCy Schubert 	}
852780fb4a2SCy Schubert 
853780fb4a2SCy Schubert 	type = *pos++;
854780fb4a2SCy Schubert 	len = WPA_GET_BE24(pos);
855780fb4a2SCy Schubert 	pos += 3;
856780fb4a2SCy Schubert 	left -= 4;
857780fb4a2SCy Schubert 
858780fb4a2SCy Schubert 	if (len > left) {
859780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
860780fb4a2SCy Schubert 			   "TLSv1: Mismatch in CertificateStatus length (len=%lu != left=%lu)",
861780fb4a2SCy Schubert 			   (unsigned long) len, (unsigned long) left);
862780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
863780fb4a2SCy Schubert 		return -1;
864780fb4a2SCy Schubert 	}
865780fb4a2SCy Schubert 
866780fb4a2SCy Schubert 	end = pos + len;
867780fb4a2SCy Schubert 
868780fb4a2SCy Schubert 	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS) {
869780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
870780fb4a2SCy Schubert 			   "TLSv1: Received unexpected handshake message %d (expected CertificateStatus)",
871780fb4a2SCy Schubert 			   type);
872780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
873780fb4a2SCy Schubert 			  TLS_ALERT_UNEXPECTED_MESSAGE);
874780fb4a2SCy Schubert 		return -1;
875780fb4a2SCy Schubert 	}
876780fb4a2SCy Schubert 
877780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateStatus");
878780fb4a2SCy Schubert 
879780fb4a2SCy Schubert 	/*
880780fb4a2SCy Schubert 	 * struct {
881780fb4a2SCy Schubert 	 *     CertificateStatusType status_type;
882780fb4a2SCy Schubert 	 *     select (status_type) {
883780fb4a2SCy Schubert 	 *         case ocsp: OCSPResponse;
884780fb4a2SCy Schubert 	 *         case ocsp_multi: OCSPResponseList;
885780fb4a2SCy Schubert 	 *     } response;
886780fb4a2SCy Schubert 	 * } CertificateStatus;
887780fb4a2SCy Schubert 	 */
888780fb4a2SCy Schubert 	if (end - pos < 1) {
889780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "TLSv1: Too short CertificateStatus");
890780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
891780fb4a2SCy Schubert 		return -1;
892780fb4a2SCy Schubert 	}
893780fb4a2SCy Schubert 	status_type = *pos++;
894780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatus status_type %u",
895780fb4a2SCy Schubert 		   status_type);
896780fb4a2SCy Schubert 
897780fb4a2SCy Schubert 	if (status_type == 1 /* ocsp */) {
898780fb4a2SCy Schubert 		res = tls_process_certificate_status_ocsp_response(
899780fb4a2SCy Schubert 			conn, pos, end - pos);
900780fb4a2SCy Schubert 	} else if (status_type == 2 /* ocsp_multi */) {
901780fb4a2SCy Schubert 		int good = 0, revoked = 0;
902780fb4a2SCy Schubert 		u32 resp_len;
903780fb4a2SCy Schubert 
904780fb4a2SCy Schubert 		res = TLS_OCSP_NO_RESPONSE;
905780fb4a2SCy Schubert 
906780fb4a2SCy Schubert 		/*
907780fb4a2SCy Schubert 		 * opaque OCSPResponse<0..2^24-1>;
908780fb4a2SCy Schubert 		 *
909780fb4a2SCy Schubert 		 * struct {
910780fb4a2SCy Schubert 		 *   OCSPResponse ocsp_response_list<1..2^24-1>;
911780fb4a2SCy Schubert 		 * } OCSPResponseList;
912780fb4a2SCy Schubert 		 */
913780fb4a2SCy Schubert 		if (end - pos < 3) {
914780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
915780fb4a2SCy Schubert 				   "TLSv1: Truncated OCSPResponseList");
916780fb4a2SCy Schubert 			res = TLS_OCSP_INVALID;
917780fb4a2SCy Schubert 			goto done;
918780fb4a2SCy Schubert 		}
919780fb4a2SCy Schubert 		resp_len = WPA_GET_BE24(pos);
920780fb4a2SCy Schubert 		pos += 3;
921780fb4a2SCy Schubert 		if (end - pos < resp_len) {
922780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
923780fb4a2SCy Schubert 				   "TLSv1: Truncated OCSPResponseList(len=%u)",
924780fb4a2SCy Schubert 				   resp_len);
925780fb4a2SCy Schubert 			res = TLS_OCSP_INVALID;
926780fb4a2SCy Schubert 			goto done;
927780fb4a2SCy Schubert 		}
928780fb4a2SCy Schubert 		end = pos + resp_len;
929780fb4a2SCy Schubert 
930780fb4a2SCy Schubert 		while (end - pos >= 3) {
931780fb4a2SCy Schubert 			resp_len = WPA_GET_BE24(pos);
932780fb4a2SCy Schubert 			pos += 3;
933780fb4a2SCy Schubert 			if (resp_len > end - pos) {
934780fb4a2SCy Schubert 				wpa_printf(MSG_DEBUG,
935780fb4a2SCy Schubert 					   "TLSv1: Truncated OCSPResponse(len=%u; left=%d) in ocsp_multi",
936780fb4a2SCy Schubert 					   resp_len, (int) (end - pos));
937780fb4a2SCy Schubert 				res = TLS_OCSP_INVALID;
938780fb4a2SCy Schubert 				break;
939780fb4a2SCy Schubert 			}
940780fb4a2SCy Schubert 			if (!resp_len)
941780fb4a2SCy Schubert 				continue; /* Skip an empty response */
942780fb4a2SCy Schubert 			res = tls_process_certificate_status_ocsp_response(
943780fb4a2SCy Schubert 				conn, pos - 3, resp_len + 3);
944780fb4a2SCy Schubert 			if (res == TLS_OCSP_REVOKED)
945780fb4a2SCy Schubert 				revoked++;
946780fb4a2SCy Schubert 			else if (res == TLS_OCSP_GOOD)
947780fb4a2SCy Schubert 				good++;
948780fb4a2SCy Schubert 			pos += resp_len;
949780fb4a2SCy Schubert 		}
950780fb4a2SCy Schubert 
951780fb4a2SCy Schubert 		if (revoked)
952780fb4a2SCy Schubert 			res = TLS_OCSP_REVOKED;
953780fb4a2SCy Schubert 		else if (good)
954780fb4a2SCy Schubert 			res = TLS_OCSP_GOOD;
955780fb4a2SCy Schubert 	} else {
956780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
957780fb4a2SCy Schubert 			   "TLSv1: Ignore unsupported CertificateStatus");
958780fb4a2SCy Schubert 		goto skip;
959780fb4a2SCy Schubert 	}
960780fb4a2SCy Schubert 
961780fb4a2SCy Schubert done:
962780fb4a2SCy Schubert 	if (res == TLS_OCSP_REVOKED) {
963780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
964780fb4a2SCy Schubert 			  TLS_ALERT_CERTIFICATE_REVOKED);
965780fb4a2SCy Schubert 		for (cert = conn->server_cert, depth = 0; cert;
966780fb4a2SCy Schubert 		     cert = cert->next, depth++) {
967780fb4a2SCy Schubert 			if (cert->ocsp_revoked) {
968780fb4a2SCy Schubert 				tls_cert_chain_failure_event(
969780fb4a2SCy Schubert 					conn, depth, cert, TLS_FAIL_REVOKED,
970780fb4a2SCy Schubert 					"certificate revoked");
971780fb4a2SCy Schubert 			}
972780fb4a2SCy Schubert 		}
973780fb4a2SCy Schubert 		return -1;
974780fb4a2SCy Schubert 	}
975780fb4a2SCy Schubert 
976780fb4a2SCy Schubert 	if (conn->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
977780fb4a2SCy Schubert 		/*
978780fb4a2SCy Schubert 		 * Verify that each certificate on the chain that is not part
979780fb4a2SCy Schubert 		 * of the trusted certificates has a good status. If not,
980780fb4a2SCy Schubert 		 * terminate handshake.
981780fb4a2SCy Schubert 		 */
982780fb4a2SCy Schubert 		for (cert = conn->server_cert, depth = 0; cert;
983780fb4a2SCy Schubert 		     cert = cert->next, depth++) {
984780fb4a2SCy Schubert 			if (!cert->ocsp_good) {
985780fb4a2SCy Schubert 				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
986780fb4a2SCy Schubert 					  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
987780fb4a2SCy Schubert 				tls_cert_chain_failure_event(
988780fb4a2SCy Schubert 					conn, depth, cert,
989780fb4a2SCy Schubert 					TLS_FAIL_UNSPECIFIED,
990780fb4a2SCy Schubert 					"bad certificate status response");
991780fb4a2SCy Schubert 				return -1;
992780fb4a2SCy Schubert 			}
993780fb4a2SCy Schubert 			if (cert->issuer_trusted)
994780fb4a2SCy Schubert 				break;
995780fb4a2SCy Schubert 		}
996780fb4a2SCy Schubert 	}
997780fb4a2SCy Schubert 
998780fb4a2SCy Schubert 	if ((conn->flags & TLS_CONN_REQUIRE_OCSP) && res != TLS_OCSP_GOOD) {
999780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1000780fb4a2SCy Schubert 			  res == TLS_OCSP_INVALID ? TLS_ALERT_DECODE_ERROR :
1001780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
1002780fb4a2SCy Schubert 		if (conn->server_cert)
1003780fb4a2SCy Schubert 			tls_cert_chain_failure_event(
1004780fb4a2SCy Schubert 				conn, 0, conn->server_cert,
1005780fb4a2SCy Schubert 				TLS_FAIL_UNSPECIFIED,
1006780fb4a2SCy Schubert 				"bad certificate status response");
1007780fb4a2SCy Schubert 		return -1;
1008780fb4a2SCy Schubert 	}
1009780fb4a2SCy Schubert 
1010780fb4a2SCy Schubert 	conn->ocsp_resp_received = 1;
1011780fb4a2SCy Schubert 
1012780fb4a2SCy Schubert skip:
1013780fb4a2SCy Schubert 	*in_len = end - in_data;
1014780fb4a2SCy Schubert 
1015780fb4a2SCy Schubert 	conn->state = SERVER_KEY_EXCHANGE;
1016780fb4a2SCy Schubert 
1017780fb4a2SCy Schubert 	return 0;
1018780fb4a2SCy Schubert }
1019780fb4a2SCy Schubert 
1020780fb4a2SCy Schubert 
102139beb93cSSam Leffler static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
102239beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len)
102339beb93cSSam Leffler {
102439beb93cSSam Leffler 	const u8 *pos, *end;
102539beb93cSSam Leffler 	size_t left, len;
102639beb93cSSam Leffler 	u8 type;
102739beb93cSSam Leffler 	const struct tls_cipher_suite *suite;
102839beb93cSSam Leffler 
102939beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
103039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
103139beb93cSSam Leffler 			   "received content type 0x%x", ct);
103239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
103339beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
103439beb93cSSam Leffler 		return -1;
103539beb93cSSam Leffler 	}
103639beb93cSSam Leffler 
103739beb93cSSam Leffler 	pos = in_data;
103839beb93cSSam Leffler 	left = *in_len;
103939beb93cSSam Leffler 
104039beb93cSSam Leffler 	if (left < 4) {
104139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange "
104239beb93cSSam Leffler 			   "(Left=%lu)", (unsigned long) left);
104339beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
104439beb93cSSam Leffler 		return -1;
104539beb93cSSam Leffler 	}
104639beb93cSSam Leffler 
104739beb93cSSam Leffler 	type = *pos++;
104839beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
104939beb93cSSam Leffler 	pos += 3;
105039beb93cSSam Leffler 	left -= 4;
105139beb93cSSam Leffler 
105239beb93cSSam Leffler 	if (len > left) {
105339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange "
105439beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
105539beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
105639beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
105739beb93cSSam Leffler 		return -1;
105839beb93cSSam Leffler 	}
105939beb93cSSam Leffler 
106039beb93cSSam Leffler 	end = pos + len;
106139beb93cSSam Leffler 
1062780fb4a2SCy Schubert 	if ((conn->flags & TLS_CONN_REQUEST_OCSP) &&
1063780fb4a2SCy Schubert 	    type == TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS)
1064780fb4a2SCy Schubert 		return tls_process_certificate_status(conn, ct, in_data,
1065780fb4a2SCy Schubert 						      in_len);
106639beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
106739beb93cSSam Leffler 		return tls_process_certificate_request(conn, ct, in_data,
106839beb93cSSam Leffler 						       in_len);
106939beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
107039beb93cSSam Leffler 		return tls_process_server_hello_done(conn, ct, in_data,
107139beb93cSSam Leffler 						     in_len);
107239beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) {
107339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
107439beb93cSSam Leffler 			   "message %d (expected ServerKeyExchange/"
1075780fb4a2SCy Schubert 			   "CertificateRequest/ServerHelloDone%s)", type,
1076780fb4a2SCy Schubert 			   (conn->flags & TLS_CONN_REQUEST_OCSP) ?
1077780fb4a2SCy Schubert 			   "/CertificateStatus" : "");
107839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
107939beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
108039beb93cSSam Leffler 		return -1;
108139beb93cSSam Leffler 	}
108239beb93cSSam Leffler 
108339beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange");
108439beb93cSSam Leffler 
108539beb93cSSam Leffler 	if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) {
108639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed "
108739beb93cSSam Leffler 			   "with the selected cipher suite");
108839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
108939beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
109039beb93cSSam Leffler 		return -1;
109139beb93cSSam Leffler 	}
109239beb93cSSam Leffler 
109339beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len);
109439beb93cSSam Leffler 	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
10955b9c547cSRui Paulo 	if (suite && (suite->key_exchange == TLS_KEY_X_DH_anon ||
10965b9c547cSRui Paulo 		      suite->key_exchange == TLS_KEY_X_DHE_RSA)) {
10975b9c547cSRui Paulo 		if (tlsv1_process_diffie_hellman(conn, pos, len,
10985b9c547cSRui Paulo 						 suite->key_exchange) < 0) {
109939beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
110039beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
110139beb93cSSam Leffler 			return -1;
110239beb93cSSam Leffler 		}
110339beb93cSSam Leffler 	} else {
110439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange");
110539beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
110639beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
110739beb93cSSam Leffler 		return -1;
110839beb93cSSam Leffler 	}
110939beb93cSSam Leffler 
111039beb93cSSam Leffler 	*in_len = end - in_data;
111139beb93cSSam Leffler 
111239beb93cSSam Leffler 	conn->state = SERVER_CERTIFICATE_REQUEST;
111339beb93cSSam Leffler 
111439beb93cSSam Leffler 	return 0;
111539beb93cSSam Leffler }
111639beb93cSSam Leffler 
111739beb93cSSam Leffler 
111839beb93cSSam Leffler static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
111939beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len)
112039beb93cSSam Leffler {
112139beb93cSSam Leffler 	const u8 *pos, *end;
112239beb93cSSam Leffler 	size_t left, len;
112339beb93cSSam Leffler 	u8 type;
112439beb93cSSam Leffler 
112539beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
112639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
112739beb93cSSam Leffler 			   "received content type 0x%x", ct);
112839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
112939beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
113039beb93cSSam Leffler 		return -1;
113139beb93cSSam Leffler 	}
113239beb93cSSam Leffler 
113339beb93cSSam Leffler 	pos = in_data;
113439beb93cSSam Leffler 	left = *in_len;
113539beb93cSSam Leffler 
113639beb93cSSam Leffler 	if (left < 4) {
113739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest "
113839beb93cSSam Leffler 			   "(left=%lu)", (unsigned long) left);
113939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
114039beb93cSSam Leffler 		return -1;
114139beb93cSSam Leffler 	}
114239beb93cSSam Leffler 
114339beb93cSSam Leffler 	type = *pos++;
114439beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
114539beb93cSSam Leffler 	pos += 3;
114639beb93cSSam Leffler 	left -= 4;
114739beb93cSSam Leffler 
114839beb93cSSam Leffler 	if (len > left) {
114939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest "
115039beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
115139beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
115239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
115339beb93cSSam Leffler 		return -1;
115439beb93cSSam Leffler 	}
115539beb93cSSam Leffler 
115639beb93cSSam Leffler 	end = pos + len;
115739beb93cSSam Leffler 
115839beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
115939beb93cSSam Leffler 		return tls_process_server_hello_done(conn, ct, in_data,
116039beb93cSSam Leffler 						     in_len);
116139beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) {
116239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
116339beb93cSSam Leffler 			   "message %d (expected CertificateRequest/"
116439beb93cSSam Leffler 			   "ServerHelloDone)", type);
116539beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
116639beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
116739beb93cSSam Leffler 		return -1;
116839beb93cSSam Leffler 	}
116939beb93cSSam Leffler 
117039beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest");
117139beb93cSSam Leffler 
117239beb93cSSam Leffler 	conn->certificate_requested = 1;
117339beb93cSSam Leffler 
117439beb93cSSam Leffler 	*in_len = end - in_data;
117539beb93cSSam Leffler 
117639beb93cSSam Leffler 	conn->state = SERVER_HELLO_DONE;
117739beb93cSSam Leffler 
117839beb93cSSam Leffler 	return 0;
117939beb93cSSam Leffler }
118039beb93cSSam Leffler 
118139beb93cSSam Leffler 
118239beb93cSSam Leffler static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
118339beb93cSSam Leffler 					 const u8 *in_data, size_t *in_len)
118439beb93cSSam Leffler {
118539beb93cSSam Leffler 	const u8 *pos, *end;
118639beb93cSSam Leffler 	size_t left, len;
118739beb93cSSam Leffler 	u8 type;
118839beb93cSSam Leffler 
118939beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
119039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
119139beb93cSSam Leffler 			   "received content type 0x%x", ct);
119239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
119339beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
119439beb93cSSam Leffler 		return -1;
119539beb93cSSam Leffler 	}
119639beb93cSSam Leffler 
119739beb93cSSam Leffler 	pos = in_data;
119839beb93cSSam Leffler 	left = *in_len;
119939beb93cSSam Leffler 
120039beb93cSSam Leffler 	if (left < 4) {
120139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone "
120239beb93cSSam Leffler 			   "(left=%lu)", (unsigned long) left);
120339beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
120439beb93cSSam Leffler 		return -1;
120539beb93cSSam Leffler 	}
120639beb93cSSam Leffler 
120739beb93cSSam Leffler 	type = *pos++;
120839beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
120939beb93cSSam Leffler 	pos += 3;
121039beb93cSSam Leffler 	left -= 4;
121139beb93cSSam Leffler 
121239beb93cSSam Leffler 	if (len > left) {
121339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone "
121439beb93cSSam Leffler 			   "length (len=%lu != left=%lu)",
121539beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
121639beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
121739beb93cSSam Leffler 		return -1;
121839beb93cSSam Leffler 	}
121939beb93cSSam Leffler 	end = pos + len;
122039beb93cSSam Leffler 
122139beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) {
122239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
122339beb93cSSam Leffler 			   "message %d (expected ServerHelloDone)", type);
122439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
122539beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
122639beb93cSSam Leffler 		return -1;
122739beb93cSSam Leffler 	}
122839beb93cSSam Leffler 
122939beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone");
123039beb93cSSam Leffler 
1231780fb4a2SCy Schubert 	if ((conn->flags & TLS_CONN_REQUIRE_OCSP) &&
1232780fb4a2SCy Schubert 	    !conn->ocsp_resp_received) {
1233780fb4a2SCy Schubert 		wpa_printf(MSG_INFO,
1234780fb4a2SCy Schubert 			   "TLSv1: No OCSP response received - reject handshake");
1235780fb4a2SCy Schubert 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1236780fb4a2SCy Schubert 			  TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
1237780fb4a2SCy Schubert 		return -1;
1238780fb4a2SCy Schubert 	}
1239780fb4a2SCy Schubert 
124039beb93cSSam Leffler 	*in_len = end - in_data;
124139beb93cSSam Leffler 
124239beb93cSSam Leffler 	conn->state = CLIENT_KEY_EXCHANGE;
124339beb93cSSam Leffler 
124439beb93cSSam Leffler 	return 0;
124539beb93cSSam Leffler }
124639beb93cSSam Leffler 
124739beb93cSSam Leffler 
124839beb93cSSam Leffler static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn,
124939beb93cSSam Leffler 						 u8 ct, const u8 *in_data,
125039beb93cSSam Leffler 						 size_t *in_len)
125139beb93cSSam Leffler {
125239beb93cSSam Leffler 	const u8 *pos;
125339beb93cSSam Leffler 	size_t left;
125439beb93cSSam Leffler 
125539beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
125639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
125739beb93cSSam Leffler 			   "received content type 0x%x", ct);
125839beb93cSSam Leffler 		if (conn->use_session_ticket) {
125939beb93cSSam Leffler 			int res;
126039beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Server may have "
126139beb93cSSam Leffler 				   "rejected SessionTicket");
126239beb93cSSam Leffler 			conn->use_session_ticket = 0;
126339beb93cSSam Leffler 
126439beb93cSSam Leffler 			/* Notify upper layers that SessionTicket failed */
126539beb93cSSam Leffler 			res = conn->session_ticket_cb(
126639beb93cSSam Leffler 				conn->session_ticket_cb_ctx, NULL, 0, NULL,
126739beb93cSSam Leffler 				NULL, NULL);
126839beb93cSSam Leffler 			if (res < 0) {
126939beb93cSSam Leffler 				wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket "
127039beb93cSSam Leffler 					   "callback indicated failure");
127139beb93cSSam Leffler 				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
127239beb93cSSam Leffler 					  TLS_ALERT_HANDSHAKE_FAILURE);
127339beb93cSSam Leffler 				return -1;
127439beb93cSSam Leffler 			}
127539beb93cSSam Leffler 
127639beb93cSSam Leffler 			conn->state = SERVER_CERTIFICATE;
127739beb93cSSam Leffler 			return tls_process_certificate(conn, ct, in_data,
127839beb93cSSam Leffler 						       in_len);
127939beb93cSSam Leffler 		}
128039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
128139beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
128239beb93cSSam Leffler 		return -1;
128339beb93cSSam Leffler 	}
128439beb93cSSam Leffler 
128539beb93cSSam Leffler 	pos = in_data;
128639beb93cSSam Leffler 	left = *in_len;
128739beb93cSSam Leffler 
128839beb93cSSam Leffler 	if (left < 1) {
128939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec");
129039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
129139beb93cSSam Leffler 		return -1;
129239beb93cSSam Leffler 	}
129339beb93cSSam Leffler 
129439beb93cSSam Leffler 	if (*pos != TLS_CHANGE_CIPHER_SPEC) {
129539beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
129639beb93cSSam Leffler 			   "received data 0x%x", *pos);
129739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
129839beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
129939beb93cSSam Leffler 		return -1;
130039beb93cSSam Leffler 	}
130139beb93cSSam Leffler 
130239beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec");
130339beb93cSSam Leffler 	if (tlsv1_record_change_read_cipher(&conn->rl) < 0) {
130439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher "
130539beb93cSSam Leffler 			   "for record layer");
130639beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
130739beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
130839beb93cSSam Leffler 		return -1;
130939beb93cSSam Leffler 	}
131039beb93cSSam Leffler 
131139beb93cSSam Leffler 	*in_len = pos + 1 - in_data;
131239beb93cSSam Leffler 
131339beb93cSSam Leffler 	conn->state = SERVER_FINISHED;
131439beb93cSSam Leffler 
131539beb93cSSam Leffler 	return 0;
131639beb93cSSam Leffler }
131739beb93cSSam Leffler 
131839beb93cSSam Leffler 
131939beb93cSSam Leffler static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct,
132039beb93cSSam Leffler 				       const u8 *in_data, size_t *in_len)
132139beb93cSSam Leffler {
132239beb93cSSam Leffler 	const u8 *pos, *end;
132339beb93cSSam Leffler 	size_t left, len, hlen;
132439beb93cSSam Leffler 	u8 verify_data[TLS_VERIFY_DATA_LEN];
132539beb93cSSam Leffler 	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
132639beb93cSSam Leffler 
132739beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
132839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; "
132939beb93cSSam Leffler 			   "received content type 0x%x", ct);
133039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
133139beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
133239beb93cSSam Leffler 		return -1;
133339beb93cSSam Leffler 	}
133439beb93cSSam Leffler 
133539beb93cSSam Leffler 	pos = in_data;
133639beb93cSSam Leffler 	left = *in_len;
133739beb93cSSam Leffler 
133839beb93cSSam Leffler 	if (left < 4) {
133939beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for "
134039beb93cSSam Leffler 			   "Finished",
134139beb93cSSam Leffler 			   (unsigned long) left);
134239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
134339beb93cSSam Leffler 			  TLS_ALERT_DECODE_ERROR);
134439beb93cSSam Leffler 		return -1;
134539beb93cSSam Leffler 	}
134639beb93cSSam Leffler 
134739beb93cSSam Leffler 	if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) {
134839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received "
134939beb93cSSam Leffler 			   "type 0x%x", pos[0]);
135039beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
135139beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
135239beb93cSSam Leffler 		return -1;
135339beb93cSSam Leffler 	}
135439beb93cSSam Leffler 
135539beb93cSSam Leffler 	len = WPA_GET_BE24(pos + 1);
135639beb93cSSam Leffler 
135739beb93cSSam Leffler 	pos += 4;
135839beb93cSSam Leffler 	left -= 4;
135939beb93cSSam Leffler 
136039beb93cSSam Leffler 	if (len > left) {
136139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished "
136239beb93cSSam Leffler 			   "(len=%lu > left=%lu)",
136339beb93cSSam Leffler 			   (unsigned long) len, (unsigned long) left);
136439beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
136539beb93cSSam Leffler 			  TLS_ALERT_DECODE_ERROR);
136639beb93cSSam Leffler 		return -1;
136739beb93cSSam Leffler 	}
136839beb93cSSam Leffler 	end = pos + len;
136939beb93cSSam Leffler 	if (len != TLS_VERIFY_DATA_LEN) {
137039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length "
137139beb93cSSam Leffler 			   "in Finished: %lu (expected %d)",
137239beb93cSSam Leffler 			   (unsigned long) len, TLS_VERIFY_DATA_LEN);
137339beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
137439beb93cSSam Leffler 			  TLS_ALERT_DECODE_ERROR);
137539beb93cSSam Leffler 		return -1;
137639beb93cSSam Leffler 	}
137739beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished",
137839beb93cSSam Leffler 		    pos, TLS_VERIFY_DATA_LEN);
137939beb93cSSam Leffler 
1380f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
1381f05cddf9SRui Paulo 	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
1382f05cddf9SRui Paulo 		hlen = SHA256_MAC_LEN;
1383f05cddf9SRui Paulo 		if (conn->verify.sha256_server == NULL ||
1384f05cddf9SRui Paulo 		    crypto_hash_finish(conn->verify.sha256_server, hash, &hlen)
1385f05cddf9SRui Paulo 		    < 0) {
1386f05cddf9SRui Paulo 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1387f05cddf9SRui Paulo 				  TLS_ALERT_INTERNAL_ERROR);
1388f05cddf9SRui Paulo 			conn->verify.sha256_server = NULL;
1389f05cddf9SRui Paulo 			return -1;
1390f05cddf9SRui Paulo 		}
1391f05cddf9SRui Paulo 		conn->verify.sha256_server = NULL;
1392f05cddf9SRui Paulo 	} else {
1393f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
1394f05cddf9SRui Paulo 
139539beb93cSSam Leffler 	hlen = MD5_MAC_LEN;
139639beb93cSSam Leffler 	if (conn->verify.md5_server == NULL ||
139739beb93cSSam Leffler 	    crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) {
139839beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
139939beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
140039beb93cSSam Leffler 		conn->verify.md5_server = NULL;
140139beb93cSSam Leffler 		crypto_hash_finish(conn->verify.sha1_server, NULL, NULL);
140239beb93cSSam Leffler 		conn->verify.sha1_server = NULL;
140339beb93cSSam Leffler 		return -1;
140439beb93cSSam Leffler 	}
140539beb93cSSam Leffler 	conn->verify.md5_server = NULL;
140639beb93cSSam Leffler 	hlen = SHA1_MAC_LEN;
140739beb93cSSam Leffler 	if (conn->verify.sha1_server == NULL ||
140839beb93cSSam Leffler 	    crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN,
140939beb93cSSam Leffler 			       &hlen) < 0) {
141039beb93cSSam Leffler 		conn->verify.sha1_server = NULL;
141139beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
141239beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
141339beb93cSSam Leffler 		return -1;
141439beb93cSSam Leffler 	}
141539beb93cSSam Leffler 	conn->verify.sha1_server = NULL;
1416f05cddf9SRui Paulo 	hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
141739beb93cSSam Leffler 
1418f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
1419f05cddf9SRui Paulo 	}
1420f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
1421f05cddf9SRui Paulo 
1422f05cddf9SRui Paulo 	if (tls_prf(conn->rl.tls_version,
1423f05cddf9SRui Paulo 		    conn->master_secret, TLS_MASTER_SECRET_LEN,
1424f05cddf9SRui Paulo 		    "server finished", hash, hlen,
142539beb93cSSam Leffler 		    verify_data, TLS_VERIFY_DATA_LEN)) {
142639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data");
142739beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
142839beb93cSSam Leffler 			  TLS_ALERT_DECRYPT_ERROR);
142939beb93cSSam Leffler 		return -1;
143039beb93cSSam Leffler 	}
143139beb93cSSam Leffler 	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
143239beb93cSSam Leffler 			verify_data, TLS_VERIFY_DATA_LEN);
143339beb93cSSam Leffler 
14345b9c547cSRui Paulo 	if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
143539beb93cSSam Leffler 		wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data");
14365b9c547cSRui Paulo 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
14375b9c547cSRui Paulo 			  TLS_ALERT_DECRYPT_ERROR);
143839beb93cSSam Leffler 		return -1;
143939beb93cSSam Leffler 	}
144039beb93cSSam Leffler 
144139beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: Received Finished");
144239beb93cSSam Leffler 
144339beb93cSSam Leffler 	*in_len = end - in_data;
144439beb93cSSam Leffler 
144539beb93cSSam Leffler 	conn->state = (conn->session_resumed || conn->use_session_ticket) ?
144639beb93cSSam Leffler 		CHANGE_CIPHER_SPEC : ACK_FINISHED;
144739beb93cSSam Leffler 
144839beb93cSSam Leffler 	return 0;
144939beb93cSSam Leffler }
145039beb93cSSam Leffler 
145139beb93cSSam Leffler 
145239beb93cSSam Leffler static int tls_process_application_data(struct tlsv1_client *conn, u8 ct,
145339beb93cSSam Leffler 					const u8 *in_data, size_t *in_len,
145439beb93cSSam Leffler 					u8 **out_data, size_t *out_len)
145539beb93cSSam Leffler {
145639beb93cSSam Leffler 	const u8 *pos;
145739beb93cSSam Leffler 	size_t left;
145839beb93cSSam Leffler 
145939beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
146039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; "
146139beb93cSSam Leffler 			   "received content type 0x%x", ct);
146239beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
146339beb93cSSam Leffler 			  TLS_ALERT_UNEXPECTED_MESSAGE);
146439beb93cSSam Leffler 		return -1;
146539beb93cSSam Leffler 	}
146639beb93cSSam Leffler 
146739beb93cSSam Leffler 	pos = in_data;
146839beb93cSSam Leffler 	left = *in_len;
146939beb93cSSam Leffler 
147039beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake",
147139beb93cSSam Leffler 		    pos, left);
147239beb93cSSam Leffler 
147339beb93cSSam Leffler 	*out_data = os_malloc(left);
147439beb93cSSam Leffler 	if (*out_data) {
147539beb93cSSam Leffler 		os_memcpy(*out_data, pos, left);
147639beb93cSSam Leffler 		*out_len = left;
147739beb93cSSam Leffler 	}
147839beb93cSSam Leffler 
147939beb93cSSam Leffler 	return 0;
148039beb93cSSam Leffler }
148139beb93cSSam Leffler 
148239beb93cSSam Leffler 
148339beb93cSSam Leffler int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct,
148439beb93cSSam Leffler 				   const u8 *buf, size_t *len,
148539beb93cSSam Leffler 				   u8 **out_data, size_t *out_len)
148639beb93cSSam Leffler {
148739beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_ALERT) {
148839beb93cSSam Leffler 		if (*len < 2) {
148939beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow");
149039beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
149139beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
149239beb93cSSam Leffler 			return -1;
149339beb93cSSam Leffler 		}
149439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
149539beb93cSSam Leffler 			   buf[0], buf[1]);
149639beb93cSSam Leffler 		*len = 2;
149739beb93cSSam Leffler 		conn->state = FAILED;
149839beb93cSSam Leffler 		return -1;
149939beb93cSSam Leffler 	}
150039beb93cSSam Leffler 
150139beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 &&
150239beb93cSSam Leffler 	    buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) {
150339beb93cSSam Leffler 		size_t hr_len = WPA_GET_BE24(buf + 1);
150439beb93cSSam Leffler 		if (hr_len > *len - 4) {
150539beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow");
150639beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
150739beb93cSSam Leffler 				  TLS_ALERT_DECODE_ERROR);
150839beb93cSSam Leffler 			return -1;
150939beb93cSSam Leffler 		}
151039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest");
151139beb93cSSam Leffler 		*len = 4 + hr_len;
151239beb93cSSam Leffler 		return 0;
151339beb93cSSam Leffler 	}
151439beb93cSSam Leffler 
151539beb93cSSam Leffler 	switch (conn->state) {
151639beb93cSSam Leffler 	case SERVER_HELLO:
151739beb93cSSam Leffler 		if (tls_process_server_hello(conn, ct, buf, len))
151839beb93cSSam Leffler 			return -1;
151939beb93cSSam Leffler 		break;
152039beb93cSSam Leffler 	case SERVER_CERTIFICATE:
152139beb93cSSam Leffler 		if (tls_process_certificate(conn, ct, buf, len))
152239beb93cSSam Leffler 			return -1;
152339beb93cSSam Leffler 		break;
152439beb93cSSam Leffler 	case SERVER_KEY_EXCHANGE:
152539beb93cSSam Leffler 		if (tls_process_server_key_exchange(conn, ct, buf, len))
152639beb93cSSam Leffler 			return -1;
152739beb93cSSam Leffler 		break;
152839beb93cSSam Leffler 	case SERVER_CERTIFICATE_REQUEST:
152939beb93cSSam Leffler 		if (tls_process_certificate_request(conn, ct, buf, len))
153039beb93cSSam Leffler 			return -1;
153139beb93cSSam Leffler 		break;
153239beb93cSSam Leffler 	case SERVER_HELLO_DONE:
153339beb93cSSam Leffler 		if (tls_process_server_hello_done(conn, ct, buf, len))
153439beb93cSSam Leffler 			return -1;
153539beb93cSSam Leffler 		break;
153639beb93cSSam Leffler 	case SERVER_CHANGE_CIPHER_SPEC:
153739beb93cSSam Leffler 		if (tls_process_server_change_cipher_spec(conn, ct, buf, len))
153839beb93cSSam Leffler 			return -1;
153939beb93cSSam Leffler 		break;
154039beb93cSSam Leffler 	case SERVER_FINISHED:
154139beb93cSSam Leffler 		if (tls_process_server_finished(conn, ct, buf, len))
154239beb93cSSam Leffler 			return -1;
154339beb93cSSam Leffler 		break;
154439beb93cSSam Leffler 	case ACK_FINISHED:
154539beb93cSSam Leffler 		if (out_data &&
154639beb93cSSam Leffler 		    tls_process_application_data(conn, ct, buf, len, out_data,
154739beb93cSSam Leffler 						 out_len))
154839beb93cSSam Leffler 			return -1;
154939beb93cSSam Leffler 		break;
155039beb93cSSam Leffler 	default:
155139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d "
155239beb93cSSam Leffler 			   "while processing received message",
155339beb93cSSam Leffler 			   conn->state);
155439beb93cSSam Leffler 		return -1;
155539beb93cSSam Leffler 	}
155639beb93cSSam Leffler 
155739beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
155839beb93cSSam Leffler 		tls_verify_hash_add(&conn->verify, buf, *len);
155939beb93cSSam Leffler 
156039beb93cSSam Leffler 	return 0;
156139beb93cSSam Leffler }
1562