139beb93cSSam Leffler /*
239beb93cSSam Leffler  * TLSv1 server - read handshake message
35b9c547cSRui Paulo  * Copyright (c) 2006-2014, 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_server.h"
2039beb93cSSam Leffler #include "tlsv1_server_i.h"
2139beb93cSSam Leffler 
2239beb93cSSam Leffler 
2339beb93cSSam Leffler static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct,
2439beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len);
2539beb93cSSam Leffler static int tls_process_change_cipher_spec(struct tlsv1_server *conn,
2639beb93cSSam Leffler 					  u8 ct, const u8 *in_data,
2739beb93cSSam Leffler 					  size_t *in_len);
2839beb93cSSam Leffler 
2939beb93cSSam Leffler 
testing_cipher_suite_filter(struct tlsv1_server * conn,u16 suite)305b9c547cSRui Paulo static int testing_cipher_suite_filter(struct tlsv1_server *conn, u16 suite)
315b9c547cSRui Paulo {
325b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS
335b9c547cSRui Paulo 	if ((conn->test_flags &
345b9c547cSRui Paulo 	     (TLS_BREAK_SRV_KEY_X_HASH | TLS_BREAK_SRV_KEY_X_SIGNATURE |
355b9c547cSRui Paulo 	      TLS_DHE_PRIME_511B | TLS_DHE_PRIME_767B | TLS_DHE_PRIME_15 |
365b9c547cSRui Paulo 	      TLS_DHE_PRIME_58B | TLS_DHE_NON_PRIME)) &&
375b9c547cSRui Paulo 	    suite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 &&
385b9c547cSRui Paulo 	    suite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA &&
395b9c547cSRui Paulo 	    suite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 &&
405b9c547cSRui Paulo 	    suite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA &&
415b9c547cSRui Paulo 	    suite != TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
425b9c547cSRui Paulo 		return 1;
435b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */
445b9c547cSRui Paulo 
455b9c547cSRui Paulo 	return 0;
465b9c547cSRui Paulo }
475b9c547cSRui Paulo 
485b9c547cSRui Paulo 
tls_process_status_request_item(struct tlsv1_server * conn,const u8 * req,size_t req_len)49780fb4a2SCy Schubert static void tls_process_status_request_item(struct tlsv1_server *conn,
50780fb4a2SCy Schubert 					    const u8 *req, size_t req_len)
51780fb4a2SCy Schubert {
52780fb4a2SCy Schubert 	const u8 *pos, *end;
53780fb4a2SCy Schubert 	u8 status_type;
54780fb4a2SCy Schubert 
55780fb4a2SCy Schubert 	pos = req;
56780fb4a2SCy Schubert 	end = req + req_len;
57780fb4a2SCy Schubert 
58780fb4a2SCy Schubert 	/*
59780fb4a2SCy Schubert 	 * RFC 6961, 2.2:
60780fb4a2SCy Schubert 	 * struct {
61780fb4a2SCy Schubert 	 *   CertificateStatusType status_type;
62780fb4a2SCy Schubert 	 *   uint16 request_length;
63780fb4a2SCy Schubert 	 *   select (status_type) {
64780fb4a2SCy Schubert 	 *     case ocsp: OCSPStatusRequest;
65780fb4a2SCy Schubert 	 *     case ocsp_multi: OCSPStatusRequest;
66780fb4a2SCy Schubert 	 *   } request;
67780fb4a2SCy Schubert 	 * } CertificateStatusRequestItemV2;
68780fb4a2SCy Schubert 	 *
69780fb4a2SCy Schubert 	 * enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType;
70780fb4a2SCy Schubert 	 */
71780fb4a2SCy Schubert 
72780fb4a2SCy Schubert 	if (end - pos < 1)
73780fb4a2SCy Schubert 		return; /* Truncated data */
74780fb4a2SCy Schubert 
75780fb4a2SCy Schubert 	status_type = *pos++;
76780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatusType %u", status_type);
77780fb4a2SCy Schubert 	if (status_type != 1 && status_type != 2)
78780fb4a2SCy Schubert 		return; /* Unsupported status type */
79780fb4a2SCy Schubert 	/*
80780fb4a2SCy Schubert 	 * For now, only OCSP stapling is supported, so ignore the specific
81780fb4a2SCy Schubert 	 * request, if any.
82780fb4a2SCy Schubert 	 */
83780fb4a2SCy Schubert 	wpa_hexdump(MSG_DEBUG, "TLSv1: OCSPStatusRequest", pos, end - pos);
84780fb4a2SCy Schubert 
85780fb4a2SCy Schubert 	if (status_type == 2)
86780fb4a2SCy Schubert 		conn->status_request_multi = 1;
87780fb4a2SCy Schubert }
88780fb4a2SCy Schubert 
89780fb4a2SCy Schubert 
tls_process_status_request_v2(struct tlsv1_server * conn,const u8 * ext,size_t ext_len)90780fb4a2SCy Schubert static void tls_process_status_request_v2(struct tlsv1_server *conn,
91780fb4a2SCy Schubert 					  const u8 *ext, size_t ext_len)
92780fb4a2SCy Schubert {
93780fb4a2SCy Schubert 	const u8 *pos, *end;
94780fb4a2SCy Schubert 
95780fb4a2SCy Schubert 	conn->status_request_v2 = 1;
96780fb4a2SCy Schubert 
97780fb4a2SCy Schubert 	pos = ext;
98780fb4a2SCy Schubert 	end = ext + ext_len;
99780fb4a2SCy Schubert 
100780fb4a2SCy Schubert 	/*
101780fb4a2SCy Schubert 	 * RFC 6961, 2.2:
102780fb4a2SCy Schubert 	 * struct {
103780fb4a2SCy Schubert 	 *   CertificateStatusRequestItemV2
104780fb4a2SCy Schubert 	 *                    certificate_status_req_list<1..2^16-1>;
105780fb4a2SCy Schubert 	 * } CertificateStatusRequestListV2;
106780fb4a2SCy Schubert 	 */
107780fb4a2SCy Schubert 
108780fb4a2SCy Schubert 	while (end - pos >= 2) {
109780fb4a2SCy Schubert 		u16 len;
110780fb4a2SCy Schubert 
111780fb4a2SCy Schubert 		len = WPA_GET_BE16(pos);
112780fb4a2SCy Schubert 		pos += 2;
113780fb4a2SCy Schubert 		if (len > end - pos)
114780fb4a2SCy Schubert 			break; /* Truncated data */
115780fb4a2SCy Schubert 		tls_process_status_request_item(conn, pos, len);
116780fb4a2SCy Schubert 		pos += len;
117780fb4a2SCy Schubert 	}
118780fb4a2SCy Schubert }
119780fb4a2SCy Schubert 
120780fb4a2SCy Schubert 
tls_process_client_hello(struct tlsv1_server * conn,u8 ct,const u8 * in_data,size_t * in_len)12139beb93cSSam Leffler static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct,
12239beb93cSSam Leffler 				    const u8 *in_data, size_t *in_len)
12339beb93cSSam Leffler {
12439beb93cSSam Leffler 	const u8 *pos, *end, *c;
12539beb93cSSam Leffler 	size_t left, len, i, j;
12639beb93cSSam Leffler 	u16 cipher_suite;
12739beb93cSSam Leffler 	u16 num_suites;
12839beb93cSSam Leffler 	int compr_null_found;
1293157ba21SRui Paulo 	u16 ext_type, ext_len;
13039beb93cSSam Leffler 
13139beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
1325b9c547cSRui Paulo 		tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x",
1335b9c547cSRui Paulo 				 ct);
13439beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
13539beb93cSSam Leffler 				   TLS_ALERT_UNEXPECTED_MESSAGE);
13639beb93cSSam Leffler 		return -1;
13739beb93cSSam Leffler 	}
13839beb93cSSam Leffler 
13939beb93cSSam Leffler 	pos = in_data;
14039beb93cSSam Leffler 	left = *in_len;
14139beb93cSSam Leffler 
142*4bc52338SCy Schubert 	if (left < 4) {
143*4bc52338SCy Schubert 		tlsv1_server_log(conn,
144*4bc52338SCy Schubert 				 "Truncated handshake message (expected ClientHello)");
14539beb93cSSam Leffler 		goto decode_error;
146*4bc52338SCy Schubert 	}
14739beb93cSSam Leffler 
14839beb93cSSam Leffler 	/* HandshakeType msg_type */
14939beb93cSSam Leffler 	if (*pos != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) {
1505b9c547cSRui Paulo 		tlsv1_server_log(conn, "Received unexpected handshake message %d (expected ClientHello)",
1515b9c547cSRui Paulo 				 *pos);
15239beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
15339beb93cSSam Leffler 				   TLS_ALERT_UNEXPECTED_MESSAGE);
15439beb93cSSam Leffler 		return -1;
15539beb93cSSam Leffler 	}
1565b9c547cSRui Paulo 	tlsv1_server_log(conn, "Received ClientHello");
15739beb93cSSam Leffler 	pos++;
15839beb93cSSam Leffler 	/* uint24 length */
15939beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
16039beb93cSSam Leffler 	pos += 3;
16139beb93cSSam Leffler 	left -= 4;
16239beb93cSSam Leffler 
163*4bc52338SCy Schubert 	if (len > left) {
164*4bc52338SCy Schubert 		tlsv1_server_log(conn,
165*4bc52338SCy Schubert 				 "Truncated ClientHello (len=%d left=%d)",
166*4bc52338SCy Schubert 				 (int) len, (int) left);
16739beb93cSSam Leffler 		goto decode_error;
168*4bc52338SCy Schubert 	}
16939beb93cSSam Leffler 
17039beb93cSSam Leffler 	/* body - ClientHello */
17139beb93cSSam Leffler 
17239beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello", pos, len);
17339beb93cSSam Leffler 	end = pos + len;
17439beb93cSSam Leffler 
17539beb93cSSam Leffler 	/* ProtocolVersion client_version */
176*4bc52338SCy Schubert 	if (end - pos < 2) {
177*4bc52338SCy Schubert 		tlsv1_server_log(conn, "Truncated ClientHello/client_version");
17839beb93cSSam Leffler 		goto decode_error;
179*4bc52338SCy Schubert 	}
18039beb93cSSam Leffler 	conn->client_version = WPA_GET_BE16(pos);
1815b9c547cSRui Paulo 	tlsv1_server_log(conn, "Client version %d.%d",
1825b9c547cSRui Paulo 			 conn->client_version >> 8,
1835b9c547cSRui Paulo 			 conn->client_version & 0xff);
184f05cddf9SRui Paulo 	if (conn->client_version < TLS_VERSION_1) {
1855b9c547cSRui Paulo 		tlsv1_server_log(conn, "Unexpected protocol version in ClientHello %u.%u",
186f05cddf9SRui Paulo 				 conn->client_version >> 8,
187f05cddf9SRui Paulo 				 conn->client_version & 0xff);
18839beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
18939beb93cSSam Leffler 				   TLS_ALERT_PROTOCOL_VERSION);
19039beb93cSSam Leffler 		return -1;
19139beb93cSSam Leffler 	}
19239beb93cSSam Leffler 	pos += 2;
19339beb93cSSam Leffler 
194f05cddf9SRui Paulo 	if (TLS_VERSION == TLS_VERSION_1)
195f05cddf9SRui Paulo 		conn->rl.tls_version = TLS_VERSION_1;
196f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
197f05cddf9SRui Paulo 	else if (conn->client_version >= TLS_VERSION_1_2)
198f05cddf9SRui Paulo 		conn->rl.tls_version = TLS_VERSION_1_2;
199f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
200f05cddf9SRui Paulo 	else if (conn->client_version > TLS_VERSION_1_1)
201f05cddf9SRui Paulo 		conn->rl.tls_version = TLS_VERSION_1_1;
202f05cddf9SRui Paulo 	else
203f05cddf9SRui Paulo 		conn->rl.tls_version = conn->client_version;
2045b9c547cSRui Paulo 	tlsv1_server_log(conn, "Using TLS v%s",
205f05cddf9SRui Paulo 			 tls_version_str(conn->rl.tls_version));
206f05cddf9SRui Paulo 
20739beb93cSSam Leffler 	/* Random random */
208*4bc52338SCy Schubert 	if (end - pos < TLS_RANDOM_LEN) {
209*4bc52338SCy Schubert 		tlsv1_server_log(conn, "Truncated ClientHello/client_random");
21039beb93cSSam Leffler 		goto decode_error;
211*4bc52338SCy Schubert 	}
21239beb93cSSam Leffler 
21339beb93cSSam Leffler 	os_memcpy(conn->client_random, pos, TLS_RANDOM_LEN);
21439beb93cSSam Leffler 	pos += TLS_RANDOM_LEN;
21539beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random",
21639beb93cSSam Leffler 		    conn->client_random, TLS_RANDOM_LEN);
21739beb93cSSam Leffler 
21839beb93cSSam Leffler 	/* SessionID session_id */
219*4bc52338SCy Schubert 	if (end - pos < 1) {
220*4bc52338SCy Schubert 		tlsv1_server_log(conn, "Truncated ClientHello/session_id len");
22139beb93cSSam Leffler 		goto decode_error;
222*4bc52338SCy Schubert 	}
223*4bc52338SCy Schubert 	if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) {
224*4bc52338SCy Schubert 		tlsv1_server_log(conn, "Truncated ClientHello/session_id");
22539beb93cSSam Leffler 		goto decode_error;
226*4bc52338SCy Schubert 	}
22739beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client session_id", pos + 1, *pos);
22839beb93cSSam Leffler 	pos += 1 + *pos;
22939beb93cSSam Leffler 	/* TODO: add support for session resumption */
23039beb93cSSam Leffler 
23139beb93cSSam Leffler 	/* CipherSuite cipher_suites<2..2^16-1> */
232*4bc52338SCy Schubert 	if (end - pos < 2) {
233*4bc52338SCy Schubert 		tlsv1_server_log(conn,
234*4bc52338SCy Schubert 				 "Truncated ClientHello/cipher_suites len");
23539beb93cSSam Leffler 		goto decode_error;
236*4bc52338SCy Schubert 	}
23739beb93cSSam Leffler 	num_suites = WPA_GET_BE16(pos);
23839beb93cSSam Leffler 	pos += 2;
239*4bc52338SCy Schubert 	if (end - pos < num_suites) {
240*4bc52338SCy Schubert 		tlsv1_server_log(conn, "Truncated ClientHello/cipher_suites");
24139beb93cSSam Leffler 		goto decode_error;
242*4bc52338SCy Schubert 	}
24339beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client cipher suites",
24439beb93cSSam Leffler 		    pos, num_suites);
245*4bc52338SCy Schubert 	if (num_suites & 1) {
246*4bc52338SCy Schubert 		tlsv1_server_log(conn, "Odd len ClientHello/cipher_suites");
24739beb93cSSam Leffler 		goto decode_error;
248*4bc52338SCy Schubert 	}
24939beb93cSSam Leffler 	num_suites /= 2;
25039beb93cSSam Leffler 
25139beb93cSSam Leffler 	cipher_suite = 0;
25239beb93cSSam Leffler 	for (i = 0; !cipher_suite && i < conn->num_cipher_suites; i++) {
2535b9c547cSRui Paulo 		if (testing_cipher_suite_filter(conn, conn->cipher_suites[i]))
2545b9c547cSRui Paulo 			continue;
25539beb93cSSam Leffler 		c = pos;
25639beb93cSSam Leffler 		for (j = 0; j < num_suites; j++) {
25739beb93cSSam Leffler 			u16 tmp = WPA_GET_BE16(c);
25839beb93cSSam Leffler 			c += 2;
25939beb93cSSam Leffler 			if (!cipher_suite && tmp == conn->cipher_suites[i]) {
26039beb93cSSam Leffler 				cipher_suite = tmp;
26139beb93cSSam Leffler 				break;
26239beb93cSSam Leffler 			}
26339beb93cSSam Leffler 		}
26439beb93cSSam Leffler 	}
26539beb93cSSam Leffler 	pos += num_suites * 2;
26639beb93cSSam Leffler 	if (!cipher_suite) {
2675b9c547cSRui Paulo 		tlsv1_server_log(conn, "No supported cipher suite available");
26839beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
26939beb93cSSam Leffler 				   TLS_ALERT_ILLEGAL_PARAMETER);
27039beb93cSSam Leffler 		return -1;
27139beb93cSSam Leffler 	}
27239beb93cSSam Leffler 
27339beb93cSSam Leffler 	if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) {
27439beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for "
27539beb93cSSam Leffler 			   "record layer");
27639beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
27739beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
27839beb93cSSam Leffler 		return -1;
27939beb93cSSam Leffler 	}
28039beb93cSSam Leffler 
28139beb93cSSam Leffler 	conn->cipher_suite = cipher_suite;
28239beb93cSSam Leffler 
28339beb93cSSam Leffler 	/* CompressionMethod compression_methods<1..2^8-1> */
284*4bc52338SCy Schubert 	if (end - pos < 1) {
285*4bc52338SCy Schubert 		tlsv1_server_log(conn,
286*4bc52338SCy Schubert 				 "Truncated ClientHello/compression_methods len");
28739beb93cSSam Leffler 		goto decode_error;
288*4bc52338SCy Schubert 	}
28939beb93cSSam Leffler 	num_suites = *pos++;
290*4bc52338SCy Schubert 	if (end - pos < num_suites) {
291*4bc52338SCy Schubert 		tlsv1_server_log(conn,
292*4bc52338SCy Schubert 				 "Truncated ClientHello/compression_methods");
29339beb93cSSam Leffler 		goto decode_error;
294*4bc52338SCy Schubert 	}
29539beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client compression_methods",
29639beb93cSSam Leffler 		    pos, num_suites);
29739beb93cSSam Leffler 	compr_null_found = 0;
29839beb93cSSam Leffler 	for (i = 0; i < num_suites; i++) {
29939beb93cSSam Leffler 		if (*pos++ == TLS_COMPRESSION_NULL)
30039beb93cSSam Leffler 			compr_null_found = 1;
30139beb93cSSam Leffler 	}
30239beb93cSSam Leffler 	if (!compr_null_found) {
3035b9c547cSRui Paulo 		tlsv1_server_log(conn, "Client does not accept NULL compression");
30439beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
30539beb93cSSam Leffler 				   TLS_ALERT_ILLEGAL_PARAMETER);
30639beb93cSSam Leffler 		return -1;
30739beb93cSSam Leffler 	}
30839beb93cSSam Leffler 
30939beb93cSSam Leffler 	if (end - pos == 1) {
3105b9c547cSRui Paulo 		tlsv1_server_log(conn, "Unexpected extra octet in the end of ClientHello: 0x%02x",
3115b9c547cSRui Paulo 				 *pos);
31239beb93cSSam Leffler 		goto decode_error;
31339beb93cSSam Leffler 	}
31439beb93cSSam Leffler 
31539beb93cSSam Leffler 	if (end - pos >= 2) {
31639beb93cSSam Leffler 		/* Extension client_hello_extension_list<0..2^16-1> */
31739beb93cSSam Leffler 		ext_len = WPA_GET_BE16(pos);
31839beb93cSSam Leffler 		pos += 2;
31939beb93cSSam Leffler 
3205b9c547cSRui Paulo 		tlsv1_server_log(conn, "%u bytes of ClientHello extensions",
3215b9c547cSRui Paulo 				 ext_len);
32239beb93cSSam Leffler 		if (end - pos != ext_len) {
3235b9c547cSRui Paulo 			tlsv1_server_log(conn, "Invalid ClientHello extension list length %u (expected %u)",
3243157ba21SRui Paulo 					 ext_len, (unsigned int) (end - pos));
32539beb93cSSam Leffler 			goto decode_error;
32639beb93cSSam Leffler 		}
32739beb93cSSam Leffler 
32839beb93cSSam Leffler 		/*
32939beb93cSSam Leffler 		 * struct {
33039beb93cSSam Leffler 		 *   ExtensionType extension_type (0..65535)
33139beb93cSSam Leffler 		 *   opaque extension_data<0..2^16-1>
33239beb93cSSam Leffler 		 * } Extension;
33339beb93cSSam Leffler 		 */
33439beb93cSSam Leffler 
33539beb93cSSam Leffler 		while (pos < end) {
33639beb93cSSam Leffler 			if (end - pos < 2) {
3375b9c547cSRui Paulo 				tlsv1_server_log(conn, "Invalid extension_type field");
33839beb93cSSam Leffler 				goto decode_error;
33939beb93cSSam Leffler 			}
34039beb93cSSam Leffler 
34139beb93cSSam Leffler 			ext_type = WPA_GET_BE16(pos);
34239beb93cSSam Leffler 			pos += 2;
34339beb93cSSam Leffler 
34439beb93cSSam Leffler 			if (end - pos < 2) {
3455b9c547cSRui Paulo 				tlsv1_server_log(conn, "Invalid extension_data length field");
34639beb93cSSam Leffler 				goto decode_error;
34739beb93cSSam Leffler 			}
34839beb93cSSam Leffler 
34939beb93cSSam Leffler 			ext_len = WPA_GET_BE16(pos);
35039beb93cSSam Leffler 			pos += 2;
35139beb93cSSam Leffler 
35239beb93cSSam Leffler 			if (end - pos < ext_len) {
3535b9c547cSRui Paulo 				tlsv1_server_log(conn, "Invalid extension_data field");
35439beb93cSSam Leffler 				goto decode_error;
35539beb93cSSam Leffler 			}
35639beb93cSSam Leffler 
3575b9c547cSRui Paulo 			tlsv1_server_log(conn, "ClientHello Extension type %u",
3585b9c547cSRui Paulo 					 ext_type);
35939beb93cSSam Leffler 			wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello "
36039beb93cSSam Leffler 				    "Extension data", pos, ext_len);
36139beb93cSSam Leffler 
36239beb93cSSam Leffler 			if (ext_type == TLS_EXT_SESSION_TICKET) {
36339beb93cSSam Leffler 				os_free(conn->session_ticket);
36439beb93cSSam Leffler 				conn->session_ticket = os_malloc(ext_len);
36539beb93cSSam Leffler 				if (conn->session_ticket) {
36639beb93cSSam Leffler 					os_memcpy(conn->session_ticket, pos,
36739beb93cSSam Leffler 						  ext_len);
36839beb93cSSam Leffler 					conn->session_ticket_len = ext_len;
36939beb93cSSam Leffler 				}
370780fb4a2SCy Schubert 			} else if (ext_type == TLS_EXT_STATUS_REQUEST) {
371780fb4a2SCy Schubert 				conn->status_request = 1;
372780fb4a2SCy Schubert 			} else if (ext_type == TLS_EXT_STATUS_REQUEST_V2) {
373780fb4a2SCy Schubert 				tls_process_status_request_v2(conn, pos,
374780fb4a2SCy Schubert 							      ext_len);
37539beb93cSSam Leffler 			}
37639beb93cSSam Leffler 
37739beb93cSSam Leffler 			pos += ext_len;
37839beb93cSSam Leffler 		}
37939beb93cSSam Leffler 	}
38039beb93cSSam Leffler 
38139beb93cSSam Leffler 	*in_len = end - in_data;
38239beb93cSSam Leffler 
3835b9c547cSRui Paulo 	tlsv1_server_log(conn, "ClientHello OK - proceed to ServerHello");
38439beb93cSSam Leffler 	conn->state = SERVER_HELLO;
38539beb93cSSam Leffler 
38639beb93cSSam Leffler 	return 0;
38739beb93cSSam Leffler 
38839beb93cSSam Leffler decode_error:
3895b9c547cSRui Paulo 	tlsv1_server_log(conn, "Failed to decode ClientHello");
39039beb93cSSam Leffler 	tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
39139beb93cSSam Leffler 			   TLS_ALERT_DECODE_ERROR);
39239beb93cSSam Leffler 	return -1;
39339beb93cSSam Leffler }
39439beb93cSSam Leffler 
39539beb93cSSam Leffler 
tls_process_certificate(struct tlsv1_server * conn,u8 ct,const u8 * in_data,size_t * in_len)39639beb93cSSam Leffler static int tls_process_certificate(struct tlsv1_server *conn, u8 ct,
39739beb93cSSam Leffler 				   const u8 *in_data, size_t *in_len)
39839beb93cSSam Leffler {
39939beb93cSSam Leffler 	const u8 *pos, *end;
40039beb93cSSam Leffler 	size_t left, len, list_len, cert_len, idx;
40139beb93cSSam Leffler 	u8 type;
40239beb93cSSam Leffler 	struct x509_certificate *chain = NULL, *last = NULL, *cert;
40339beb93cSSam Leffler 	int reason;
40439beb93cSSam Leffler 
40539beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
4065b9c547cSRui Paulo 		tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x",
4075b9c547cSRui Paulo 				 ct);
40839beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
40939beb93cSSam Leffler 				   TLS_ALERT_UNEXPECTED_MESSAGE);
41039beb93cSSam Leffler 		return -1;
41139beb93cSSam Leffler 	}
41239beb93cSSam Leffler 
41339beb93cSSam Leffler 	pos = in_data;
41439beb93cSSam Leffler 	left = *in_len;
41539beb93cSSam Leffler 
41639beb93cSSam Leffler 	if (left < 4) {
4175b9c547cSRui Paulo 		tlsv1_server_log(conn, "Too short Certificate message (len=%lu)",
4185b9c547cSRui Paulo 				 (unsigned long) left);
41939beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
42039beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
42139beb93cSSam Leffler 		return -1;
42239beb93cSSam Leffler 	}
42339beb93cSSam Leffler 
42439beb93cSSam Leffler 	type = *pos++;
42539beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
42639beb93cSSam Leffler 	pos += 3;
42739beb93cSSam Leffler 	left -= 4;
42839beb93cSSam Leffler 
42939beb93cSSam Leffler 	if (len > left) {
4305b9c547cSRui Paulo 		tlsv1_server_log(conn, "Unexpected Certificate message length (len=%lu != left=%lu)",
43139beb93cSSam Leffler 				 (unsigned long) len, (unsigned long) left);
43239beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
43339beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
43439beb93cSSam Leffler 		return -1;
43539beb93cSSam Leffler 	}
43639beb93cSSam Leffler 
43739beb93cSSam Leffler 	if (type == TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) {
43839beb93cSSam Leffler 		if (conn->verify_peer) {
4395b9c547cSRui Paulo 			tlsv1_server_log(conn, "Client did not include Certificate");
44039beb93cSSam Leffler 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
44139beb93cSSam Leffler 					   TLS_ALERT_UNEXPECTED_MESSAGE);
44239beb93cSSam Leffler 			return -1;
44339beb93cSSam Leffler 		}
44439beb93cSSam Leffler 
44539beb93cSSam Leffler 		return tls_process_client_key_exchange(conn, ct, in_data,
44639beb93cSSam Leffler 						       in_len);
44739beb93cSSam Leffler 	}
44839beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) {
4495b9c547cSRui Paulo 		tlsv1_server_log(conn, "Received unexpected handshake message %d (expected Certificate/ClientKeyExchange)",
4505b9c547cSRui Paulo 				 type);
45139beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
45239beb93cSSam Leffler 				   TLS_ALERT_UNEXPECTED_MESSAGE);
45339beb93cSSam Leffler 		return -1;
45439beb93cSSam Leffler 	}
45539beb93cSSam Leffler 
4565b9c547cSRui Paulo 	tlsv1_server_log(conn, "Received Certificate (certificate_list len %lu)",
45739beb93cSSam Leffler 			 (unsigned long) len);
45839beb93cSSam Leffler 
45939beb93cSSam Leffler 	/*
46039beb93cSSam Leffler 	 * opaque ASN.1Cert<2^24-1>;
46139beb93cSSam Leffler 	 *
46239beb93cSSam Leffler 	 * struct {
46339beb93cSSam Leffler 	 *     ASN.1Cert certificate_list<1..2^24-1>;
46439beb93cSSam Leffler 	 * } Certificate;
46539beb93cSSam Leffler 	 */
46639beb93cSSam Leffler 
46739beb93cSSam Leffler 	end = pos + len;
46839beb93cSSam Leffler 
46939beb93cSSam Leffler 	if (end - pos < 3) {
4705b9c547cSRui Paulo 		tlsv1_server_log(conn, "Too short Certificate (left=%lu)",
4715b9c547cSRui Paulo 				 (unsigned long) left);
47239beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
47339beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
47439beb93cSSam Leffler 		return -1;
47539beb93cSSam Leffler 	}
47639beb93cSSam Leffler 
47739beb93cSSam Leffler 	list_len = WPA_GET_BE24(pos);
47839beb93cSSam Leffler 	pos += 3;
47939beb93cSSam Leffler 
48039beb93cSSam Leffler 	if ((size_t) (end - pos) != list_len) {
4815b9c547cSRui Paulo 		tlsv1_server_log(conn, "Unexpected certificate_list length (len=%lu left=%lu)",
48239beb93cSSam Leffler 				 (unsigned long) list_len,
48339beb93cSSam Leffler 				 (unsigned long) (end - pos));
48439beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
48539beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
48639beb93cSSam Leffler 		return -1;
48739beb93cSSam Leffler 	}
48839beb93cSSam Leffler 
48939beb93cSSam Leffler 	idx = 0;
49039beb93cSSam Leffler 	while (pos < end) {
49139beb93cSSam Leffler 		if (end - pos < 3) {
4925b9c547cSRui Paulo 			tlsv1_server_log(conn, "Failed to parse certificate_list");
49339beb93cSSam Leffler 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
49439beb93cSSam Leffler 					   TLS_ALERT_DECODE_ERROR);
49539beb93cSSam Leffler 			x509_certificate_chain_free(chain);
49639beb93cSSam Leffler 			return -1;
49739beb93cSSam Leffler 		}
49839beb93cSSam Leffler 
49939beb93cSSam Leffler 		cert_len = WPA_GET_BE24(pos);
50039beb93cSSam Leffler 		pos += 3;
50139beb93cSSam Leffler 
50239beb93cSSam Leffler 		if ((size_t) (end - pos) < cert_len) {
5035b9c547cSRui Paulo 			tlsv1_server_log(conn, "Unexpected certificate length (len=%lu left=%lu)",
50439beb93cSSam Leffler 					 (unsigned long) cert_len,
50539beb93cSSam Leffler 					 (unsigned long) (end - pos));
50639beb93cSSam Leffler 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
50739beb93cSSam Leffler 					   TLS_ALERT_DECODE_ERROR);
50839beb93cSSam Leffler 			x509_certificate_chain_free(chain);
50939beb93cSSam Leffler 			return -1;
51039beb93cSSam Leffler 		}
51139beb93cSSam Leffler 
5125b9c547cSRui Paulo 		tlsv1_server_log(conn, "Certificate %lu (len %lu)",
51339beb93cSSam Leffler 				 (unsigned long) idx, (unsigned long) cert_len);
51439beb93cSSam Leffler 
51539beb93cSSam Leffler 		if (idx == 0) {
51639beb93cSSam Leffler 			crypto_public_key_free(conn->client_rsa_key);
51739beb93cSSam Leffler 			if (tls_parse_cert(pos, cert_len,
51839beb93cSSam Leffler 					   &conn->client_rsa_key)) {
5195b9c547cSRui Paulo 				tlsv1_server_log(conn, "Failed to parse the certificate");
52039beb93cSSam Leffler 				tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
52139beb93cSSam Leffler 						   TLS_ALERT_BAD_CERTIFICATE);
52239beb93cSSam Leffler 				x509_certificate_chain_free(chain);
52339beb93cSSam Leffler 				return -1;
52439beb93cSSam Leffler 			}
52539beb93cSSam Leffler 		}
52639beb93cSSam Leffler 
52739beb93cSSam Leffler 		cert = x509_certificate_parse(pos, cert_len);
52839beb93cSSam Leffler 		if (cert == NULL) {
5295b9c547cSRui Paulo 			tlsv1_server_log(conn, "Failed to parse the certificate");
53039beb93cSSam Leffler 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
53139beb93cSSam Leffler 					   TLS_ALERT_BAD_CERTIFICATE);
53239beb93cSSam Leffler 			x509_certificate_chain_free(chain);
53339beb93cSSam Leffler 			return -1;
53439beb93cSSam Leffler 		}
53539beb93cSSam Leffler 
53639beb93cSSam Leffler 		if (last == NULL)
53739beb93cSSam Leffler 			chain = cert;
53839beb93cSSam Leffler 		else
53939beb93cSSam Leffler 			last->next = cert;
54039beb93cSSam Leffler 		last = cert;
54139beb93cSSam Leffler 
54239beb93cSSam Leffler 		idx++;
54339beb93cSSam Leffler 		pos += cert_len;
54439beb93cSSam Leffler 	}
54539beb93cSSam Leffler 
54639beb93cSSam Leffler 	if (x509_certificate_chain_validate(conn->cred->trusted_certs, chain,
547f05cddf9SRui Paulo 					    &reason, 0) < 0) {
54839beb93cSSam Leffler 		int tls_reason;
5495b9c547cSRui Paulo 		tlsv1_server_log(conn, "Server certificate chain validation failed (reason=%d)",
5505b9c547cSRui Paulo 				 reason);
55139beb93cSSam Leffler 		switch (reason) {
55239beb93cSSam Leffler 		case X509_VALIDATE_BAD_CERTIFICATE:
55339beb93cSSam Leffler 			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
55439beb93cSSam Leffler 			break;
55539beb93cSSam Leffler 		case X509_VALIDATE_UNSUPPORTED_CERTIFICATE:
55639beb93cSSam Leffler 			tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE;
55739beb93cSSam Leffler 			break;
55839beb93cSSam Leffler 		case X509_VALIDATE_CERTIFICATE_REVOKED:
55939beb93cSSam Leffler 			tls_reason = TLS_ALERT_CERTIFICATE_REVOKED;
56039beb93cSSam Leffler 			break;
56139beb93cSSam Leffler 		case X509_VALIDATE_CERTIFICATE_EXPIRED:
56239beb93cSSam Leffler 			tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
56339beb93cSSam Leffler 			break;
56439beb93cSSam Leffler 		case X509_VALIDATE_CERTIFICATE_UNKNOWN:
56539beb93cSSam Leffler 			tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN;
56639beb93cSSam Leffler 			break;
56739beb93cSSam Leffler 		case X509_VALIDATE_UNKNOWN_CA:
56839beb93cSSam Leffler 			tls_reason = TLS_ALERT_UNKNOWN_CA;
56939beb93cSSam Leffler 			break;
57039beb93cSSam Leffler 		default:
57139beb93cSSam Leffler 			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
57239beb93cSSam Leffler 			break;
57339beb93cSSam Leffler 		}
57439beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason);
57539beb93cSSam Leffler 		x509_certificate_chain_free(chain);
57639beb93cSSam Leffler 		return -1;
57739beb93cSSam Leffler 	}
57839beb93cSSam Leffler 
579780fb4a2SCy Schubert 	if (chain && (chain->extensions_present & X509_EXT_EXT_KEY_USAGE) &&
580780fb4a2SCy Schubert 	    !(chain->ext_key_usage &
581780fb4a2SCy Schubert 	      (X509_EXT_KEY_USAGE_ANY | X509_EXT_KEY_USAGE_CLIENT_AUTH))) {
582780fb4a2SCy Schubert 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
583780fb4a2SCy Schubert 				   TLS_ALERT_BAD_CERTIFICATE);
584780fb4a2SCy Schubert 		x509_certificate_chain_free(chain);
585780fb4a2SCy Schubert 		return -1;
586780fb4a2SCy Schubert 	}
587780fb4a2SCy Schubert 
58839beb93cSSam Leffler 	x509_certificate_chain_free(chain);
58939beb93cSSam Leffler 
59039beb93cSSam Leffler 	*in_len = end - in_data;
59139beb93cSSam Leffler 
59239beb93cSSam Leffler 	conn->state = CLIENT_KEY_EXCHANGE;
59339beb93cSSam Leffler 
59439beb93cSSam Leffler 	return 0;
59539beb93cSSam Leffler }
59639beb93cSSam Leffler 
59739beb93cSSam Leffler 
tls_process_client_key_exchange_rsa(struct tlsv1_server * conn,const u8 * pos,const u8 * end)59839beb93cSSam Leffler static int tls_process_client_key_exchange_rsa(
59939beb93cSSam Leffler 	struct tlsv1_server *conn, const u8 *pos, const u8 *end)
60039beb93cSSam Leffler {
60139beb93cSSam Leffler 	u8 *out;
60239beb93cSSam Leffler 	size_t outlen, outbuflen;
60339beb93cSSam Leffler 	u16 encr_len;
60439beb93cSSam Leffler 	int res;
60539beb93cSSam Leffler 	int use_random = 0;
60639beb93cSSam Leffler 
60739beb93cSSam Leffler 	if (end - pos < 2) {
60839beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
60939beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
61039beb93cSSam Leffler 		return -1;
61139beb93cSSam Leffler 	}
61239beb93cSSam Leffler 
61339beb93cSSam Leffler 	encr_len = WPA_GET_BE16(pos);
61439beb93cSSam Leffler 	pos += 2;
615f05cddf9SRui Paulo 	if (pos + encr_len > end) {
6165b9c547cSRui Paulo 		tlsv1_server_log(conn, "Invalid ClientKeyExchange format: encr_len=%u left=%u",
617f05cddf9SRui Paulo 				 encr_len, (unsigned int) (end - pos));
618f05cddf9SRui Paulo 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
619f05cddf9SRui Paulo 				   TLS_ALERT_DECODE_ERROR);
620f05cddf9SRui Paulo 		return -1;
621f05cddf9SRui Paulo 	}
62239beb93cSSam Leffler 
62339beb93cSSam Leffler 	outbuflen = outlen = end - pos;
62439beb93cSSam Leffler 	out = os_malloc(outlen >= TLS_PRE_MASTER_SECRET_LEN ?
62539beb93cSSam Leffler 			outlen : TLS_PRE_MASTER_SECRET_LEN);
62639beb93cSSam Leffler 	if (out == NULL) {
62739beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
62839beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
62939beb93cSSam Leffler 		return -1;
63039beb93cSSam Leffler 	}
63139beb93cSSam Leffler 
63239beb93cSSam Leffler 	/*
63339beb93cSSam Leffler 	 * struct {
63439beb93cSSam Leffler 	 *   ProtocolVersion client_version;
63539beb93cSSam Leffler 	 *   opaque random[46];
63639beb93cSSam Leffler 	 * } PreMasterSecret;
63739beb93cSSam Leffler 	 *
63839beb93cSSam Leffler 	 * struct {
63939beb93cSSam Leffler 	 *   public-key-encrypted PreMasterSecret pre_master_secret;
64039beb93cSSam Leffler 	 * } EncryptedPreMasterSecret;
64139beb93cSSam Leffler 	 */
64239beb93cSSam Leffler 
64339beb93cSSam Leffler 	/*
64439beb93cSSam Leffler 	 * Note: To avoid Bleichenbacher attack, we do not report decryption or
64539beb93cSSam Leffler 	 * parsing errors from EncryptedPreMasterSecret processing to the
64639beb93cSSam Leffler 	 * client. Instead, a random pre-master secret is used to force the
64739beb93cSSam Leffler 	 * handshake to fail.
64839beb93cSSam Leffler 	 */
64939beb93cSSam Leffler 
65039beb93cSSam Leffler 	if (crypto_private_key_decrypt_pkcs1_v15(conn->cred->key,
651f05cddf9SRui Paulo 						 pos, encr_len,
65239beb93cSSam Leffler 						 out, &outlen) < 0) {
65339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt "
654f05cddf9SRui Paulo 			   "PreMasterSecret (encr_len=%u outlen=%lu)",
655f05cddf9SRui Paulo 			   encr_len, (unsigned long) outlen);
65639beb93cSSam Leffler 		use_random = 1;
65739beb93cSSam Leffler 	}
65839beb93cSSam Leffler 
659f05cddf9SRui Paulo 	if (!use_random && outlen != TLS_PRE_MASTER_SECRET_LEN) {
6605b9c547cSRui Paulo 		tlsv1_server_log(conn, "Unexpected PreMasterSecret length %lu",
6615b9c547cSRui Paulo 				 (unsigned long) outlen);
66239beb93cSSam Leffler 		use_random = 1;
66339beb93cSSam Leffler 	}
66439beb93cSSam Leffler 
665f05cddf9SRui Paulo 	if (!use_random && WPA_GET_BE16(out) != conn->client_version) {
6665b9c547cSRui Paulo 		tlsv1_server_log(conn, "Client version in ClientKeyExchange does not match with version in ClientHello");
66739beb93cSSam Leffler 		use_random = 1;
66839beb93cSSam Leffler 	}
66939beb93cSSam Leffler 
67039beb93cSSam Leffler 	if (use_random) {
67139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Using random premaster secret "
67239beb93cSSam Leffler 			   "to avoid revealing information about private key");
67339beb93cSSam Leffler 		outlen = TLS_PRE_MASTER_SECRET_LEN;
67439beb93cSSam Leffler 		if (os_get_random(out, outlen)) {
67539beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random "
67639beb93cSSam Leffler 				   "data");
67739beb93cSSam Leffler 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
67839beb93cSSam Leffler 					   TLS_ALERT_INTERNAL_ERROR);
67939beb93cSSam Leffler 			os_free(out);
68039beb93cSSam Leffler 			return -1;
68139beb93cSSam Leffler 		}
68239beb93cSSam Leffler 	}
68339beb93cSSam Leffler 
68439beb93cSSam Leffler 	res = tlsv1_server_derive_keys(conn, out, outlen);
68539beb93cSSam Leffler 
68639beb93cSSam Leffler 	/* Clear the pre-master secret since it is not needed anymore */
68739beb93cSSam Leffler 	os_memset(out, 0, outbuflen);
68839beb93cSSam Leffler 	os_free(out);
68939beb93cSSam Leffler 
69039beb93cSSam Leffler 	if (res) {
69139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
69239beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
69339beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
69439beb93cSSam Leffler 		return -1;
69539beb93cSSam Leffler 	}
69639beb93cSSam Leffler 
69739beb93cSSam Leffler 	return 0;
69839beb93cSSam Leffler }
69939beb93cSSam Leffler 
70039beb93cSSam Leffler 
tls_process_client_key_exchange_dh(struct tlsv1_server * conn,const u8 * pos,const u8 * end)7015b9c547cSRui Paulo static int tls_process_client_key_exchange_dh(
70239beb93cSSam Leffler 	struct tlsv1_server *conn, const u8 *pos, const u8 *end)
70339beb93cSSam Leffler {
70439beb93cSSam Leffler 	const u8 *dh_yc;
70539beb93cSSam Leffler 	u16 dh_yc_len;
70639beb93cSSam Leffler 	u8 *shared;
70739beb93cSSam Leffler 	size_t shared_len;
70839beb93cSSam Leffler 	int res;
7095b9c547cSRui Paulo 	const u8 *dh_p;
7105b9c547cSRui Paulo 	size_t dh_p_len;
71139beb93cSSam Leffler 
71239beb93cSSam Leffler 	/*
71339beb93cSSam Leffler 	 * struct {
71439beb93cSSam Leffler 	 *   select (PublicValueEncoding) {
71539beb93cSSam Leffler 	 *     case implicit: struct { };
71639beb93cSSam Leffler 	 *     case explicit: opaque dh_Yc<1..2^16-1>;
71739beb93cSSam Leffler 	 *   } dh_public;
71839beb93cSSam Leffler 	 * } ClientDiffieHellmanPublic;
71939beb93cSSam Leffler 	 */
72039beb93cSSam Leffler 
7215b9c547cSRui Paulo 	tlsv1_server_log(conn, "ClientDiffieHellmanPublic received");
72239beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientDiffieHellmanPublic",
72339beb93cSSam Leffler 		    pos, end - pos);
72439beb93cSSam Leffler 
72539beb93cSSam Leffler 	if (end == pos) {
72639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Implicit public value encoding "
72739beb93cSSam Leffler 			   "not supported");
72839beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
72939beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
73039beb93cSSam Leffler 		return -1;
73139beb93cSSam Leffler 	}
73239beb93cSSam Leffler 
73339beb93cSSam Leffler 	if (end - pos < 3) {
7345b9c547cSRui Paulo 		tlsv1_server_log(conn, "Invalid client public value length");
73539beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
73639beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
73739beb93cSSam Leffler 		return -1;
73839beb93cSSam Leffler 	}
73939beb93cSSam Leffler 
74039beb93cSSam Leffler 	dh_yc_len = WPA_GET_BE16(pos);
74139beb93cSSam Leffler 	dh_yc = pos + 2;
74239beb93cSSam Leffler 
7435b9c547cSRui Paulo 	if (dh_yc_len > end - dh_yc) {
7445b9c547cSRui Paulo 		tlsv1_server_log(conn, "Client public value overflow (length %d)",
7455b9c547cSRui Paulo 				 dh_yc_len);
74639beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
74739beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
74839beb93cSSam Leffler 		return -1;
74939beb93cSSam Leffler 	}
75039beb93cSSam Leffler 
75139beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)",
75239beb93cSSam Leffler 		    dh_yc, dh_yc_len);
75339beb93cSSam Leffler 
75439beb93cSSam Leffler 	if (conn->cred == NULL || conn->cred->dh_p == NULL ||
75539beb93cSSam Leffler 	    conn->dh_secret == NULL) {
75639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available");
75739beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
75839beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
75939beb93cSSam Leffler 		return -1;
76039beb93cSSam Leffler 	}
76139beb93cSSam Leffler 
7625b9c547cSRui Paulo 	tlsv1_server_get_dh_p(conn, &dh_p, &dh_p_len);
7635b9c547cSRui Paulo 
7645b9c547cSRui Paulo 	shared_len = dh_p_len;
76539beb93cSSam Leffler 	shared = os_malloc(shared_len);
76639beb93cSSam Leffler 	if (shared == NULL) {
76739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for "
76839beb93cSSam Leffler 			   "DH");
76939beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
77039beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
77139beb93cSSam Leffler 		return -1;
77239beb93cSSam Leffler 	}
77339beb93cSSam Leffler 
77439beb93cSSam Leffler 	/* shared = Yc^secret mod p */
77539beb93cSSam Leffler 	if (crypto_mod_exp(dh_yc, dh_yc_len, conn->dh_secret,
7765b9c547cSRui Paulo 			   conn->dh_secret_len, dh_p, dh_p_len,
77739beb93cSSam Leffler 			   shared, &shared_len)) {
77839beb93cSSam Leffler 		os_free(shared);
77939beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
78039beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
78139beb93cSSam Leffler 		return -1;
78239beb93cSSam Leffler 	}
78339beb93cSSam Leffler 	wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange",
78439beb93cSSam Leffler 			shared, shared_len);
78539beb93cSSam Leffler 
78639beb93cSSam Leffler 	os_memset(conn->dh_secret, 0, conn->dh_secret_len);
78739beb93cSSam Leffler 	os_free(conn->dh_secret);
78839beb93cSSam Leffler 	conn->dh_secret = NULL;
78939beb93cSSam Leffler 
79039beb93cSSam Leffler 	res = tlsv1_server_derive_keys(conn, shared, shared_len);
79139beb93cSSam Leffler 
79239beb93cSSam Leffler 	/* Clear the pre-master secret since it is not needed anymore */
79339beb93cSSam Leffler 	os_memset(shared, 0, shared_len);
79439beb93cSSam Leffler 	os_free(shared);
79539beb93cSSam Leffler 
79639beb93cSSam Leffler 	if (res) {
79739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
79839beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
79939beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
80039beb93cSSam Leffler 		return -1;
80139beb93cSSam Leffler 	}
80239beb93cSSam Leffler 
80339beb93cSSam Leffler 	return 0;
80439beb93cSSam Leffler }
80539beb93cSSam Leffler 
80639beb93cSSam Leffler 
tls_process_client_key_exchange(struct tlsv1_server * conn,u8 ct,const u8 * in_data,size_t * in_len)80739beb93cSSam Leffler static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct,
80839beb93cSSam Leffler 					   const u8 *in_data, size_t *in_len)
80939beb93cSSam Leffler {
81039beb93cSSam Leffler 	const u8 *pos, *end;
81139beb93cSSam Leffler 	size_t left, len;
81239beb93cSSam Leffler 	u8 type;
81339beb93cSSam Leffler 	tls_key_exchange keyx;
81439beb93cSSam Leffler 	const struct tls_cipher_suite *suite;
81539beb93cSSam Leffler 
81639beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
8175b9c547cSRui Paulo 		tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x",
8185b9c547cSRui Paulo 				 ct);
81939beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
82039beb93cSSam Leffler 				   TLS_ALERT_UNEXPECTED_MESSAGE);
82139beb93cSSam Leffler 		return -1;
82239beb93cSSam Leffler 	}
82339beb93cSSam Leffler 
82439beb93cSSam Leffler 	pos = in_data;
82539beb93cSSam Leffler 	left = *in_len;
82639beb93cSSam Leffler 
82739beb93cSSam Leffler 	if (left < 4) {
8285b9c547cSRui Paulo 		tlsv1_server_log(conn, "Too short ClientKeyExchange (Left=%lu)",
8295b9c547cSRui Paulo 				 (unsigned long) left);
83039beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
83139beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
83239beb93cSSam Leffler 		return -1;
83339beb93cSSam Leffler 	}
83439beb93cSSam Leffler 
83539beb93cSSam Leffler 	type = *pos++;
83639beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
83739beb93cSSam Leffler 	pos += 3;
83839beb93cSSam Leffler 	left -= 4;
83939beb93cSSam Leffler 
84039beb93cSSam Leffler 	if (len > left) {
8415b9c547cSRui Paulo 		tlsv1_server_log(conn, "Mismatch in ClientKeyExchange length (len=%lu != left=%lu)",
84239beb93cSSam Leffler 				 (unsigned long) len, (unsigned long) left);
84339beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
84439beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
84539beb93cSSam Leffler 		return -1;
84639beb93cSSam Leffler 	}
84739beb93cSSam Leffler 
84839beb93cSSam Leffler 	end = pos + len;
84939beb93cSSam Leffler 
85039beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) {
8515b9c547cSRui Paulo 		tlsv1_server_log(conn, "Received unexpected handshake message %d (expected ClientKeyExchange)",
8525b9c547cSRui Paulo 				 type);
85339beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
85439beb93cSSam Leffler 				   TLS_ALERT_UNEXPECTED_MESSAGE);
85539beb93cSSam Leffler 		return -1;
85639beb93cSSam Leffler 	}
85739beb93cSSam Leffler 
8585b9c547cSRui Paulo 	tlsv1_server_log(conn, "Received ClientKeyExchange");
85939beb93cSSam Leffler 
86039beb93cSSam Leffler 	wpa_hexdump(MSG_DEBUG, "TLSv1: ClientKeyExchange", pos, len);
86139beb93cSSam Leffler 
86239beb93cSSam Leffler 	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
86339beb93cSSam Leffler 	if (suite == NULL)
86439beb93cSSam Leffler 		keyx = TLS_KEY_X_NULL;
86539beb93cSSam Leffler 	else
86639beb93cSSam Leffler 		keyx = suite->key_exchange;
86739beb93cSSam Leffler 
8685b9c547cSRui Paulo 	if ((keyx == TLS_KEY_X_DH_anon || keyx == TLS_KEY_X_DHE_RSA) &&
8695b9c547cSRui Paulo 	    tls_process_client_key_exchange_dh(conn, pos, end) < 0)
87039beb93cSSam Leffler 		return -1;
87139beb93cSSam Leffler 
8725b9c547cSRui Paulo 	if (keyx != TLS_KEY_X_DH_anon && keyx != TLS_KEY_X_DHE_RSA &&
87339beb93cSSam Leffler 	    tls_process_client_key_exchange_rsa(conn, pos, end) < 0)
87439beb93cSSam Leffler 		return -1;
87539beb93cSSam Leffler 
87639beb93cSSam Leffler 	*in_len = end - in_data;
87739beb93cSSam Leffler 
87839beb93cSSam Leffler 	conn->state = CERTIFICATE_VERIFY;
87939beb93cSSam Leffler 
88039beb93cSSam Leffler 	return 0;
88139beb93cSSam Leffler }
88239beb93cSSam Leffler 
88339beb93cSSam Leffler 
tls_process_certificate_verify(struct tlsv1_server * conn,u8 ct,const u8 * in_data,size_t * in_len)88439beb93cSSam Leffler static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct,
88539beb93cSSam Leffler 					  const u8 *in_data, size_t *in_len)
88639beb93cSSam Leffler {
88739beb93cSSam Leffler 	const u8 *pos, *end;
88839beb93cSSam Leffler 	size_t left, len;
88939beb93cSSam Leffler 	u8 type;
8905b9c547cSRui Paulo 	size_t hlen;
8915b9c547cSRui Paulo 	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos;
8925b9c547cSRui Paulo 	u8 alert;
89339beb93cSSam Leffler 
89439beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
89539beb93cSSam Leffler 		if (conn->verify_peer) {
8965b9c547cSRui Paulo 			tlsv1_server_log(conn, "Client did not include CertificateVerify");
89739beb93cSSam Leffler 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
89839beb93cSSam Leffler 					   TLS_ALERT_UNEXPECTED_MESSAGE);
89939beb93cSSam Leffler 			return -1;
90039beb93cSSam Leffler 		}
90139beb93cSSam Leffler 
90239beb93cSSam Leffler 		return tls_process_change_cipher_spec(conn, ct, in_data,
90339beb93cSSam Leffler 						      in_len);
90439beb93cSSam Leffler 	}
90539beb93cSSam Leffler 
90639beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
9075b9c547cSRui Paulo 		tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x",
9085b9c547cSRui Paulo 				 ct);
90939beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
91039beb93cSSam Leffler 				   TLS_ALERT_UNEXPECTED_MESSAGE);
91139beb93cSSam Leffler 		return -1;
91239beb93cSSam Leffler 	}
91339beb93cSSam Leffler 
91439beb93cSSam Leffler 	pos = in_data;
91539beb93cSSam Leffler 	left = *in_len;
91639beb93cSSam Leffler 
91739beb93cSSam Leffler 	if (left < 4) {
9185b9c547cSRui Paulo 		tlsv1_server_log(conn, "Too short CertificateVerify message (len=%lu)",
9195b9c547cSRui Paulo 				 (unsigned long) left);
92039beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
92139beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
92239beb93cSSam Leffler 		return -1;
92339beb93cSSam Leffler 	}
92439beb93cSSam Leffler 
92539beb93cSSam Leffler 	type = *pos++;
92639beb93cSSam Leffler 	len = WPA_GET_BE24(pos);
92739beb93cSSam Leffler 	pos += 3;
92839beb93cSSam Leffler 	left -= 4;
92939beb93cSSam Leffler 
93039beb93cSSam Leffler 	if (len > left) {
9315b9c547cSRui Paulo 		tlsv1_server_log(conn, "Unexpected CertificateVerify message length (len=%lu != left=%lu)",
93239beb93cSSam Leffler 				 (unsigned long) len, (unsigned long) left);
93339beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
93439beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
93539beb93cSSam Leffler 		return -1;
93639beb93cSSam Leffler 	}
93739beb93cSSam Leffler 
93839beb93cSSam Leffler 	end = pos + len;
93939beb93cSSam Leffler 
94039beb93cSSam Leffler 	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY) {
9415b9c547cSRui Paulo 		tlsv1_server_log(conn, "Received unexpected handshake message %d (expected CertificateVerify)",
9425b9c547cSRui Paulo 				 type);
94339beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
94439beb93cSSam Leffler 				   TLS_ALERT_UNEXPECTED_MESSAGE);
94539beb93cSSam Leffler 		return -1;
94639beb93cSSam Leffler 	}
94739beb93cSSam Leffler 
9485b9c547cSRui Paulo 	tlsv1_server_log(conn, "Received CertificateVerify");
94939beb93cSSam Leffler 
95039beb93cSSam Leffler 	/*
95139beb93cSSam Leffler 	 * struct {
95239beb93cSSam Leffler 	 *   Signature signature;
95339beb93cSSam Leffler 	 * } CertificateVerify;
95439beb93cSSam Leffler 	 */
95539beb93cSSam Leffler 
95639beb93cSSam Leffler 	hpos = hash;
95739beb93cSSam Leffler 
958f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
959f05cddf9SRui Paulo 	if (conn->rl.tls_version == TLS_VERSION_1_2) {
960f05cddf9SRui Paulo 		/*
961f05cddf9SRui Paulo 		 * RFC 5246, 4.7:
962f05cddf9SRui Paulo 		 * TLS v1.2 adds explicit indication of the used signature and
963f05cddf9SRui Paulo 		 * hash algorithms.
964f05cddf9SRui Paulo 		 *
965f05cddf9SRui Paulo 		 * struct {
966f05cddf9SRui Paulo 		 *   HashAlgorithm hash;
967f05cddf9SRui Paulo 		 *   SignatureAlgorithm signature;
968f05cddf9SRui Paulo 		 * } SignatureAndHashAlgorithm;
969f05cddf9SRui Paulo 		 */
970f05cddf9SRui Paulo 		if (end - pos < 2) {
971f05cddf9SRui Paulo 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
972f05cddf9SRui Paulo 					   TLS_ALERT_DECODE_ERROR);
973f05cddf9SRui Paulo 			return -1;
974f05cddf9SRui Paulo 		}
975f05cddf9SRui Paulo 		if (pos[0] != TLS_HASH_ALG_SHA256 ||
976f05cddf9SRui Paulo 		    pos[1] != TLS_SIGN_ALG_RSA) {
977f05cddf9SRui Paulo 			wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/"
978f05cddf9SRui Paulo 				   "signature(%u) algorithm",
979f05cddf9SRui Paulo 				   pos[0], pos[1]);
980f05cddf9SRui Paulo 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
981f05cddf9SRui Paulo 					   TLS_ALERT_INTERNAL_ERROR);
982f05cddf9SRui Paulo 			return -1;
983f05cddf9SRui Paulo 		}
984f05cddf9SRui Paulo 		pos += 2;
985f05cddf9SRui Paulo 
986f05cddf9SRui Paulo 		hlen = SHA256_MAC_LEN;
987f05cddf9SRui Paulo 		if (conn->verify.sha256_cert == NULL ||
988f05cddf9SRui Paulo 		    crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) <
989f05cddf9SRui Paulo 		    0) {
990f05cddf9SRui Paulo 			conn->verify.sha256_cert = NULL;
991f05cddf9SRui Paulo 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
992f05cddf9SRui Paulo 					   TLS_ALERT_INTERNAL_ERROR);
993f05cddf9SRui Paulo 			return -1;
994f05cddf9SRui Paulo 		}
995f05cddf9SRui Paulo 		conn->verify.sha256_cert = NULL;
996f05cddf9SRui Paulo 	} else {
997f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
998f05cddf9SRui Paulo 
99939beb93cSSam Leffler 	hlen = MD5_MAC_LEN;
100039beb93cSSam Leffler 	if (conn->verify.md5_cert == NULL ||
10015b9c547cSRui Paulo 	    crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) {
100239beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
100339beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
100439beb93cSSam Leffler 		conn->verify.md5_cert = NULL;
100539beb93cSSam Leffler 		crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL);
100639beb93cSSam Leffler 		conn->verify.sha1_cert = NULL;
100739beb93cSSam Leffler 		return -1;
100839beb93cSSam Leffler 	}
100939beb93cSSam Leffler 	hpos += MD5_MAC_LEN;
101039beb93cSSam Leffler 
101139beb93cSSam Leffler 	conn->verify.md5_cert = NULL;
101239beb93cSSam Leffler 	hlen = SHA1_MAC_LEN;
101339beb93cSSam Leffler 	if (conn->verify.sha1_cert == NULL ||
101439beb93cSSam Leffler 	    crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) {
101539beb93cSSam Leffler 		conn->verify.sha1_cert = NULL;
101639beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
101739beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
101839beb93cSSam Leffler 		return -1;
101939beb93cSSam Leffler 	}
102039beb93cSSam Leffler 	conn->verify.sha1_cert = NULL;
102139beb93cSSam Leffler 
102239beb93cSSam Leffler 	hlen += MD5_MAC_LEN;
102339beb93cSSam Leffler 
1024f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
1025f05cddf9SRui Paulo 	}
1026f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
1027f05cddf9SRui Paulo 
102839beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen);
102939beb93cSSam Leffler 
10305b9c547cSRui Paulo 	if (tls_verify_signature(conn->rl.tls_version, conn->client_rsa_key,
10315b9c547cSRui Paulo 				 hash, hlen, pos, end - pos, &alert) < 0) {
10325b9c547cSRui Paulo 		tlsv1_server_log(conn, "Invalid Signature in CertificateVerify");
10335b9c547cSRui Paulo 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
103439beb93cSSam Leffler 		return -1;
103539beb93cSSam Leffler 	}
103639beb93cSSam Leffler 
103739beb93cSSam Leffler 	*in_len = end - in_data;
103839beb93cSSam Leffler 
103939beb93cSSam Leffler 	conn->state = CHANGE_CIPHER_SPEC;
104039beb93cSSam Leffler 
104139beb93cSSam Leffler 	return 0;
104239beb93cSSam Leffler }
104339beb93cSSam Leffler 
104439beb93cSSam Leffler 
tls_process_change_cipher_spec(struct tlsv1_server * conn,u8 ct,const u8 * in_data,size_t * in_len)104539beb93cSSam Leffler static int tls_process_change_cipher_spec(struct tlsv1_server *conn,
104639beb93cSSam Leffler 					  u8 ct, const u8 *in_data,
104739beb93cSSam Leffler 					  size_t *in_len)
104839beb93cSSam Leffler {
104939beb93cSSam Leffler 	const u8 *pos;
105039beb93cSSam Leffler 	size_t left;
105139beb93cSSam Leffler 
105239beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
10535b9c547cSRui Paulo 		tlsv1_server_log(conn, "Expected ChangeCipherSpec; received content type 0x%x",
10545b9c547cSRui Paulo 				 ct);
105539beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
105639beb93cSSam Leffler 				   TLS_ALERT_UNEXPECTED_MESSAGE);
105739beb93cSSam Leffler 		return -1;
105839beb93cSSam Leffler 	}
105939beb93cSSam Leffler 
106039beb93cSSam Leffler 	pos = in_data;
106139beb93cSSam Leffler 	left = *in_len;
106239beb93cSSam Leffler 
106339beb93cSSam Leffler 	if (left < 1) {
10645b9c547cSRui Paulo 		tlsv1_server_log(conn, "Too short ChangeCipherSpec");
106539beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
106639beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
106739beb93cSSam Leffler 		return -1;
106839beb93cSSam Leffler 	}
106939beb93cSSam Leffler 
107039beb93cSSam Leffler 	if (*pos != TLS_CHANGE_CIPHER_SPEC) {
10715b9c547cSRui Paulo 		tlsv1_server_log(conn, "Expected ChangeCipherSpec; received data 0x%x",
10725b9c547cSRui Paulo 				 *pos);
107339beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
107439beb93cSSam Leffler 				   TLS_ALERT_UNEXPECTED_MESSAGE);
107539beb93cSSam Leffler 		return -1;
107639beb93cSSam Leffler 	}
107739beb93cSSam Leffler 
10785b9c547cSRui Paulo 	tlsv1_server_log(conn, "Received ChangeCipherSpec");
107939beb93cSSam Leffler 	if (tlsv1_record_change_read_cipher(&conn->rl) < 0) {
108039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher "
108139beb93cSSam Leffler 			   "for record layer");
108239beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
108339beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
108439beb93cSSam Leffler 		return -1;
108539beb93cSSam Leffler 	}
108639beb93cSSam Leffler 
108739beb93cSSam Leffler 	*in_len = pos + 1 - in_data;
108839beb93cSSam Leffler 
108939beb93cSSam Leffler 	conn->state = CLIENT_FINISHED;
109039beb93cSSam Leffler 
109139beb93cSSam Leffler 	return 0;
109239beb93cSSam Leffler }
109339beb93cSSam Leffler 
109439beb93cSSam Leffler 
tls_process_client_finished(struct tlsv1_server * conn,u8 ct,const u8 * in_data,size_t * in_len)109539beb93cSSam Leffler static int tls_process_client_finished(struct tlsv1_server *conn, u8 ct,
109639beb93cSSam Leffler 				       const u8 *in_data, size_t *in_len)
109739beb93cSSam Leffler {
109839beb93cSSam Leffler 	const u8 *pos, *end;
109939beb93cSSam Leffler 	size_t left, len, hlen;
110039beb93cSSam Leffler 	u8 verify_data[TLS_VERIFY_DATA_LEN];
110139beb93cSSam Leffler 	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
110239beb93cSSam Leffler 
11035b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS
11045b9c547cSRui Paulo 	if ((conn->test_flags &
11055b9c547cSRui Paulo 	     (TLS_BREAK_SRV_KEY_X_HASH | TLS_BREAK_SRV_KEY_X_SIGNATURE)) &&
11065b9c547cSRui Paulo 	    !conn->test_failure_reported) {
11075b9c547cSRui Paulo 		tlsv1_server_log(conn, "TEST-FAILURE: Client Finished received after invalid ServerKeyExchange");
11085b9c547cSRui Paulo 		conn->test_failure_reported = 1;
11095b9c547cSRui Paulo 	}
11105b9c547cSRui Paulo 
11115b9c547cSRui Paulo 	if ((conn->test_flags & TLS_DHE_PRIME_15) &&
11125b9c547cSRui Paulo 	    !conn->test_failure_reported) {
11135b9c547cSRui Paulo 		tlsv1_server_log(conn, "TEST-FAILURE: Client Finished received after bogus DHE \"prime\" 15");
11145b9c547cSRui Paulo 		conn->test_failure_reported = 1;
11155b9c547cSRui Paulo 	}
11165b9c547cSRui Paulo 
11175b9c547cSRui Paulo 	if ((conn->test_flags & TLS_DHE_PRIME_58B) &&
11185b9c547cSRui Paulo 	    !conn->test_failure_reported) {
11195b9c547cSRui Paulo 		tlsv1_server_log(conn, "TEST-FAILURE: Client Finished received after short 58-bit DHE prime in long container");
11205b9c547cSRui Paulo 		conn->test_failure_reported = 1;
11215b9c547cSRui Paulo 	}
11225b9c547cSRui Paulo 
11235b9c547cSRui Paulo 	if ((conn->test_flags & TLS_DHE_PRIME_511B) &&
11245b9c547cSRui Paulo 	    !conn->test_failure_reported) {
11255b9c547cSRui Paulo 		tlsv1_server_log(conn, "TEST-WARNING: Client Finished received after short 511-bit DHE prime (insecure)");
11265b9c547cSRui Paulo 		conn->test_failure_reported = 1;
11275b9c547cSRui Paulo 	}
11285b9c547cSRui Paulo 
11295b9c547cSRui Paulo 	if ((conn->test_flags & TLS_DHE_PRIME_767B) &&
11305b9c547cSRui Paulo 	    !conn->test_failure_reported) {
11315b9c547cSRui Paulo 		tlsv1_server_log(conn, "TEST-NOTE: Client Finished received after 767-bit DHE prime (relatively insecure)");
11325b9c547cSRui Paulo 		conn->test_failure_reported = 1;
11335b9c547cSRui Paulo 	}
11345b9c547cSRui Paulo 
11355b9c547cSRui Paulo 	if ((conn->test_flags & TLS_DHE_NON_PRIME) &&
11365b9c547cSRui Paulo 	    !conn->test_failure_reported) {
11375b9c547cSRui Paulo 		tlsv1_server_log(conn, "TEST-NOTE: Client Finished received after non-prime claimed as DHE prime");
11385b9c547cSRui Paulo 		conn->test_failure_reported = 1;
11395b9c547cSRui Paulo 	}
11405b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */
11415b9c547cSRui Paulo 
114239beb93cSSam Leffler 	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
11435b9c547cSRui Paulo 		tlsv1_server_log(conn, "Expected Finished; received content type 0x%x",
11445b9c547cSRui Paulo 				 ct);
114539beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
114639beb93cSSam Leffler 				   TLS_ALERT_UNEXPECTED_MESSAGE);
114739beb93cSSam Leffler 		return -1;
114839beb93cSSam Leffler 	}
114939beb93cSSam Leffler 
115039beb93cSSam Leffler 	pos = in_data;
115139beb93cSSam Leffler 	left = *in_len;
115239beb93cSSam Leffler 
115339beb93cSSam Leffler 	if (left < 4) {
11545b9c547cSRui Paulo 		tlsv1_server_log(conn, "Too short record (left=%lu) forFinished",
115539beb93cSSam Leffler 				 (unsigned long) left);
115639beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
115739beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
115839beb93cSSam Leffler 		return -1;
115939beb93cSSam Leffler 	}
116039beb93cSSam Leffler 
116139beb93cSSam Leffler 	if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) {
116239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received "
116339beb93cSSam Leffler 			   "type 0x%x", pos[0]);
116439beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
116539beb93cSSam Leffler 				   TLS_ALERT_UNEXPECTED_MESSAGE);
116639beb93cSSam Leffler 		return -1;
116739beb93cSSam Leffler 	}
116839beb93cSSam Leffler 
116939beb93cSSam Leffler 	len = WPA_GET_BE24(pos + 1);
117039beb93cSSam Leffler 
117139beb93cSSam Leffler 	pos += 4;
117239beb93cSSam Leffler 	left -= 4;
117339beb93cSSam Leffler 
117439beb93cSSam Leffler 	if (len > left) {
11755b9c547cSRui Paulo 		tlsv1_server_log(conn, "Too short buffer for Finished (len=%lu > left=%lu)",
117639beb93cSSam Leffler 				 (unsigned long) len, (unsigned long) left);
117739beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
117839beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
117939beb93cSSam Leffler 		return -1;
118039beb93cSSam Leffler 	}
118139beb93cSSam Leffler 	end = pos + len;
118239beb93cSSam Leffler 	if (len != TLS_VERIFY_DATA_LEN) {
11835b9c547cSRui Paulo 		tlsv1_server_log(conn, "Unexpected verify_data length in Finished: %lu (expected %d)",
118439beb93cSSam Leffler 				 (unsigned long) len, TLS_VERIFY_DATA_LEN);
118539beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
118639beb93cSSam Leffler 				   TLS_ALERT_DECODE_ERROR);
118739beb93cSSam Leffler 		return -1;
118839beb93cSSam Leffler 	}
118939beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished",
119039beb93cSSam Leffler 		    pos, TLS_VERIFY_DATA_LEN);
119139beb93cSSam Leffler 
1192f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
1193f05cddf9SRui Paulo 	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
1194f05cddf9SRui Paulo 		hlen = SHA256_MAC_LEN;
1195f05cddf9SRui Paulo 		if (conn->verify.sha256_client == NULL ||
1196f05cddf9SRui Paulo 		    crypto_hash_finish(conn->verify.sha256_client, hash, &hlen)
1197f05cddf9SRui Paulo 		    < 0) {
1198f05cddf9SRui Paulo 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1199f05cddf9SRui Paulo 					   TLS_ALERT_INTERNAL_ERROR);
1200f05cddf9SRui Paulo 			conn->verify.sha256_client = NULL;
1201f05cddf9SRui Paulo 			return -1;
1202f05cddf9SRui Paulo 		}
1203f05cddf9SRui Paulo 		conn->verify.sha256_client = NULL;
1204f05cddf9SRui Paulo 	} else {
1205f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
1206f05cddf9SRui Paulo 
120739beb93cSSam Leffler 	hlen = MD5_MAC_LEN;
120839beb93cSSam Leffler 	if (conn->verify.md5_client == NULL ||
120939beb93cSSam Leffler 	    crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) {
121039beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
121139beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
121239beb93cSSam Leffler 		conn->verify.md5_client = NULL;
121339beb93cSSam Leffler 		crypto_hash_finish(conn->verify.sha1_client, NULL, NULL);
121439beb93cSSam Leffler 		conn->verify.sha1_client = NULL;
121539beb93cSSam Leffler 		return -1;
121639beb93cSSam Leffler 	}
121739beb93cSSam Leffler 	conn->verify.md5_client = NULL;
121839beb93cSSam Leffler 	hlen = SHA1_MAC_LEN;
121939beb93cSSam Leffler 	if (conn->verify.sha1_client == NULL ||
122039beb93cSSam Leffler 	    crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN,
122139beb93cSSam Leffler 			       &hlen) < 0) {
122239beb93cSSam Leffler 		conn->verify.sha1_client = NULL;
122339beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
122439beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
122539beb93cSSam Leffler 		return -1;
122639beb93cSSam Leffler 	}
122739beb93cSSam Leffler 	conn->verify.sha1_client = NULL;
1228f05cddf9SRui Paulo 	hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
122939beb93cSSam Leffler 
1230f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
1231f05cddf9SRui Paulo 	}
1232f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
1233f05cddf9SRui Paulo 
1234f05cddf9SRui Paulo 	if (tls_prf(conn->rl.tls_version,
1235f05cddf9SRui Paulo 		    conn->master_secret, TLS_MASTER_SECRET_LEN,
1236f05cddf9SRui Paulo 		    "client finished", hash, hlen,
123739beb93cSSam Leffler 		    verify_data, TLS_VERIFY_DATA_LEN)) {
123839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data");
123939beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
124039beb93cSSam Leffler 				   TLS_ALERT_DECRYPT_ERROR);
124139beb93cSSam Leffler 		return -1;
124239beb93cSSam Leffler 	}
124339beb93cSSam Leffler 	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)",
124439beb93cSSam Leffler 			verify_data, TLS_VERIFY_DATA_LEN);
124539beb93cSSam Leffler 
12465b9c547cSRui Paulo 	if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
12475b9c547cSRui Paulo 		tlsv1_server_log(conn, "Mismatch in verify_data");
1248*4bc52338SCy Schubert 		conn->state = FAILED;
124939beb93cSSam Leffler 		return -1;
125039beb93cSSam Leffler 	}
125139beb93cSSam Leffler 
12525b9c547cSRui Paulo 	tlsv1_server_log(conn, "Received Finished");
125339beb93cSSam Leffler 
125439beb93cSSam Leffler 	*in_len = end - in_data;
125539beb93cSSam Leffler 
125639beb93cSSam Leffler 	if (conn->use_session_ticket) {
125739beb93cSSam Leffler 		/* Abbreviated handshake using session ticket; RFC 4507 */
12585b9c547cSRui Paulo 		tlsv1_server_log(conn, "Abbreviated handshake completed successfully");
125939beb93cSSam Leffler 		conn->state = ESTABLISHED;
126039beb93cSSam Leffler 	} else {
126139beb93cSSam Leffler 		/* Full handshake */
126239beb93cSSam Leffler 		conn->state = SERVER_CHANGE_CIPHER_SPEC;
126339beb93cSSam Leffler 	}
126439beb93cSSam Leffler 
126539beb93cSSam Leffler 	return 0;
126639beb93cSSam Leffler }
126739beb93cSSam Leffler 
126839beb93cSSam Leffler 
tlsv1_server_process_handshake(struct tlsv1_server * conn,u8 ct,const u8 * buf,size_t * len)126939beb93cSSam Leffler int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct,
127039beb93cSSam Leffler 				   const u8 *buf, size_t *len)
127139beb93cSSam Leffler {
127239beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_ALERT) {
127339beb93cSSam Leffler 		if (*len < 2) {
12745b9c547cSRui Paulo 			tlsv1_server_log(conn, "Alert underflow");
127539beb93cSSam Leffler 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
127639beb93cSSam Leffler 					   TLS_ALERT_DECODE_ERROR);
127739beb93cSSam Leffler 			return -1;
127839beb93cSSam Leffler 		}
12795b9c547cSRui Paulo 		tlsv1_server_log(conn, "Received alert %d:%d", buf[0], buf[1]);
128039beb93cSSam Leffler 		*len = 2;
128139beb93cSSam Leffler 		conn->state = FAILED;
128239beb93cSSam Leffler 		return -1;
128339beb93cSSam Leffler 	}
128439beb93cSSam Leffler 
128539beb93cSSam Leffler 	switch (conn->state) {
128639beb93cSSam Leffler 	case CLIENT_HELLO:
128739beb93cSSam Leffler 		if (tls_process_client_hello(conn, ct, buf, len))
128839beb93cSSam Leffler 			return -1;
128939beb93cSSam Leffler 		break;
129039beb93cSSam Leffler 	case CLIENT_CERTIFICATE:
129139beb93cSSam Leffler 		if (tls_process_certificate(conn, ct, buf, len))
129239beb93cSSam Leffler 			return -1;
129339beb93cSSam Leffler 		break;
129439beb93cSSam Leffler 	case CLIENT_KEY_EXCHANGE:
129539beb93cSSam Leffler 		if (tls_process_client_key_exchange(conn, ct, buf, len))
129639beb93cSSam Leffler 			return -1;
129739beb93cSSam Leffler 		break;
129839beb93cSSam Leffler 	case CERTIFICATE_VERIFY:
129939beb93cSSam Leffler 		if (tls_process_certificate_verify(conn, ct, buf, len))
130039beb93cSSam Leffler 			return -1;
130139beb93cSSam Leffler 		break;
130239beb93cSSam Leffler 	case CHANGE_CIPHER_SPEC:
130339beb93cSSam Leffler 		if (tls_process_change_cipher_spec(conn, ct, buf, len))
130439beb93cSSam Leffler 			return -1;
130539beb93cSSam Leffler 		break;
130639beb93cSSam Leffler 	case CLIENT_FINISHED:
130739beb93cSSam Leffler 		if (tls_process_client_finished(conn, ct, buf, len))
130839beb93cSSam Leffler 			return -1;
130939beb93cSSam Leffler 		break;
131039beb93cSSam Leffler 	default:
13115b9c547cSRui Paulo 		tlsv1_server_log(conn, "Unexpected state %d while processing received message",
131239beb93cSSam Leffler 				 conn->state);
131339beb93cSSam Leffler 		return -1;
131439beb93cSSam Leffler 	}
131539beb93cSSam Leffler 
131639beb93cSSam Leffler 	if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
131739beb93cSSam Leffler 		tls_verify_hash_add(&conn->verify, buf, *len);
131839beb93cSSam Leffler 
131939beb93cSSam Leffler 	return 0;
132039beb93cSSam Leffler }
1321